aboutsummaryrefslogtreecommitdiff
path: root/gcc/config
diff options
context:
space:
mode:
authorLinas Vepstas <linas@linas.org>1999-09-07 23:23:46 -0700
committerRichard Henderson <rth@gcc.gnu.org>1999-09-07 23:23:46 -0700
commitff9350e750b579885057897bb9bc0f41b2b3d868 (patch)
tree0d6e1340a897078d64693a526d1d6789b8186c33 /gcc/config
parentc802301136abdeabc75c5818e893c439a57f0597 (diff)
downloadgcc-ff9350e750b579885057897bb9bc0f41b2b3d868.zip
gcc-ff9350e750b579885057897bb9bc0f41b2b3d868.tar.gz
gcc-ff9350e750b579885057897bb9bc0f41b2b3d868.tar.bz2
Linas Vepstas <linas@linas.org>
* README: Add section discussing status of ELF ABI. * i370.c: Fix misc spelling mistakes. (i370_label_scan): Updated notes, exception handling. (i370_function_prolog): Simplify ELF stack handling. * i370.h: (FIXED_REGISTERS): Free up r12 for ELF. (STACK_GROWS_DOWNWARD): ELF stack grows down. (ASM_DECLARE_FUNCTION_NAME): Fix crazy malloc size. * i370.md: (movdi): Add notes. (floatsidf2): Use stack not rtca for scratch float area. (iorsi3): Correct operand constraints. * x-oe: Restore TAROUTOPTS which are used by pax. From-SVN: r29185
Diffstat (limited to 'gcc/config')
-rw-r--r--gcc/config/i370/README40
-rw-r--r--gcc/config/i370/i370.c106
-rw-r--r--gcc/config/i370/i370.h55
-rw-r--r--gcc/config/i370/i370.md10
-rw-r--r--gcc/config/i370/x-oe7
5 files changed, 144 insertions, 74 deletions
diff --git a/gcc/config/i370/README b/gcc/config/i370/README
index 5bf99f5..56c6342 100644
--- a/gcc/config/i370/README
+++ b/gcc/config/i370/README
@@ -30,9 +30,47 @@ OpenEdition Hints
The shell script "install" is handy for users of OpenEdition.
+The ELF ABI
+-----------
+This compiler, in conjunction with the gas/binutils assembler, defines
+a defacto ELF-based ABI for the ESA/390 architecture. Be warned: this
+ABI has several major faults. It should be fixed. As it is fixed,
+it is subject to change without warning. You should not commit to major
+software systems without further exploring and fixing these problems.
+Here are some of the problems:
+
+-- No support for shared libraries or dynamically loadable objects.
+ This is because the compiler currently places address literals in
+ the text section. Although the GAS assembler supports a syntax for
+ USING that will place address literals in the data section, this forces
+ the use of two base registers, one for branches and one for the literal
+ pool. Work is needed to redesign the function prologue, epilogue and the
+ base register reloads to minimize the currently excessive use of reserved
+ registers.
+
+ I beleive the best solution would be to add a toc or plt, and extending
+ the meaning of the USING directive to encompass this. This would
+ allow the continued use of the human-readable and familiar practice
+ of using =A() and =F'' to denote address literals, as opposed to more
+ difficult jump-table notation.
+
+-- the stackframe is almost twice as big as it needs to be.
+
+-- currently, r15 is used to return 32-bit values. Because this is the
+ last register, it prevents 64-bit ints and small structures from being
+ returned in registers, forcing return in memory. It would be more
+ efficient to use r14 to return 32-bit values, and r14+r15 to return
+ 64-bit values.
+
+-- all arguments are currently passed in memory. It would be more efficient
+ to pass arguments in registers.
+
+
+
+
ChangeLog
---------
-Oct98-Dec98 -- add ELF back end; work on getting ABI more or less correct.
+Oct98-Dec98 -- add ELF back end; work on getting ABI more or less functional.
98.12.05 -- fix numerous MVC bugs
99.02.06 -- multiply insn sometimes not generated when needed.
-- extendsidi bugs, bad literal values printed
diff --git a/gcc/config/i370/i370.c b/gcc/config/i370/i370.c
index d9954e3..c999b58 100644
--- a/gcc/config/i370/i370.c
+++ b/gcc/config/i370/i370.c
@@ -33,7 +33,7 @@ Boston, MA 02111-1307, USA. */
#include "insn-flags.h"
#include "output.h"
#include "insn-attr.h"
-#include "function.h"
+/* #include "function.h" */
#include "flags.h"
#include "recog.h"
@@ -370,13 +370,13 @@ i370_short_branch (insn)
/* The i370_label_scan() routine is supposed to loop over
all labels and label references in a compilation unit,
and determine whether all label refs appear on the same
- code page as the label. If they do, thenm we can avoid
+ code page as the label. If they do, then we can avoid
a reload of the base register for that label.
- Note that the instruciton addresses used here are only
+ Note that the instruction addresses used here are only
approximate, and make the sizes of the jumps appear
farther apart then they will actually be. This makes
- this code far more conservative than it needed to be.
+ this code far more conservative than it needs to be.
*/
#define I370_RECORD_LABEL_REF(label,addr) { \
@@ -470,8 +470,8 @@ i370_label_scan (void)
can only lead to horrible results if this were to occur.
However, the current situation is not any worse than it was
- last week, and so we punt for now.
- */
+ last week, and so we punt for now. */
+
debug_rtx (insn);
// abort();
for (j=0; j < XVECLEN (body, 0); j++)
@@ -483,23 +483,30 @@ i370_label_scan (void)
}
else
{
-/* The following appears during make of _eh in libgcc2.a
- while not obviously wrong, its weird, so not obviously
- right either ...
- (jump_insn:HI 125 124 126 (set (pc)
- (mem:SI (plus:SI (reg/v:SI 1 r1)
- (const_int 4)))) 144 {indirect_jump} (nil)
- */
+/* XXX hack alert.
+ Compiling the execption handling (L_eh) in libgcc2.a will trip
+ up right here, with something that looks like
+ (set (pc) (mem:SI (plus:SI (reg/v:SI 1 r1) (const_int 4))))
+ {indirect_jump}
+ I'm not sure of what leads up to this, but it looks like
+ the makings of a long jump which will surely get us into trouble
+ because the base & page registers don't get reloaded. For now
+ I'm not sure of what to do ... again we punt ... we are not worse
+ off than yesterday. */
+
+ /* print_rtl_single (stdout, insn); */
debug_rtx (insn);
-// abort();
+ /* abort(); */
continue;
}
}
-
- /* At this point, this jump_insn had better be a plain-old
- * ordinary one, grap the label id and go */
- if (CODE_LABEL != GET_CODE (label)) abort ();
- I370_RECORD_LABEL_REF(label,here);
+ else
+ {
+ /* At this point, this jump_insn had better be a plain-old
+ ordinary one, grap the label id and go */
+ if (CODE_LABEL != GET_CODE (label)) abort ();
+ I370_RECORD_LABEL_REF(label,here);
+ }
}
/* Sometimes, we take addresses of labels and use them
@@ -1364,11 +1371,11 @@ i370_function_prolog (f, l)
#ifdef TARGET_ELF_ABI
/*
The 370_function_prolog() routine generates the current ELF ABI ES/390 prolog.
+ It implements a stack that grows downward.
It performs the following steps:
-- saves the callers non-volatile registers on the callers stack.
- -- computes a new stack top and checks for room for the stack.
- -- initializes size and backpointer of new stack frame
- -- updates stack pointer to point at new frame.
+ -- subtracts stackframe size from the stack pointer.
+ -- stores backpointer to old caller stack.
XXX hack alert -- if the global var int leaf_function is non-zero,
then this is a leaf, and it might be possible to optimize the prologue
@@ -1413,59 +1420,30 @@ i370_function_prolog (f, frame_size)
fprintf (f, "\t.long\t%d\n", aligned_size);
/* FENT == function prologue entry */
- fprintf (f, ".LFENT%03d:\n\t.balign 2\n", /* FENT%03d DS 0H */
+ fprintf (f, "\t.balign 2\n.LFENT%03d:\n",
function_label_index);
- /* store multiple of registers 14,15,0,...12 at 12 bytes from sp */
+ /* store multiple registers 14,15,0,...12 at 12 bytes from sp */
fprintf (f, "\tSTM\tr14,r12,12(sp)\n");
- /* r11 points to arg list in callers stackframe; was passed in r2 */
- fprintf (f, "\tLR\tr11,r2\n");
-
- /* r2 == callee stack pointer ; 76(sp) == caller top of stack */
- fprintf (f, "\tL\tr2,76(,sp)\n");
-
- /* 4(r15) == callee stack length */
- fprintf (f, "\tL\tr0,4(,r15)\n");
+ /* r3 == saved callee stack pointer */
+ fprintf (f, "\tLR\tr3,sp\n");
- /* add callee stack length to caller top of stack */
- fprintf (f, "\tALR\tr0,r2\n");
+ /* 4(r15) == stackframe size */
+ fprintf (f, "\tSL\tsp,4(,r15)\n");
- /* is there enough room for this new stack frame? */
- fprintf (f, "\tCL\tr0,12(,rtca)\n");
-
- /* if we've got room, skip next 2 insns */
- fprintf (f, "\tBNH\t*+10\n");
-
- /* branch to tca to get more stack */
- fprintf (f, "\tL\tr15,116(,rtca)\n");
-
- /* go */
- fprintf (f, "\tBASR\tr14,r15\n");
-
- /* 72(sp) is something that is propagated up from the base of the stack.
- We don't use this anywhere, so we could chop this out. For the moment,
- Lets keep it; it might be handy someday ... */
- fprintf (f, "\tL\tr15,72(,sp)\n");
-
- /* store the new top-of-stack at 76(callee_stack) */
- fprintf (f, "\tSTM\tr15,r0,72(r2)\n");
-
- /* store some PL/1 compatible eyecatcher ???? why bother ??? */
- fprintf (f, "\tMVI\t0(r2),0x10\n");
+ /* r11 points to arg list in callers stackframe; was passed in r2 */
+ fprintf (f, "\tLR\tr11,r2\n");
/* store callee stack pointer at 8(sp) */
- fprintf (f, "\tST\tr2,8(,sp)\n ");
-
- /* store caller sp at 4(callee_sp) */
- fprintf (f, "\tST\tsp,4(,r2)\n ");
+ /* fprintf (f, "\tST\tsp,8(,r3)\n "); wasted cycles, no one uses this ... */
- /* load calle_sp into sp */
- fprintf (f, "\tLR\tsp,r2\n");
+ /* backchain -- store caller sp at 4(callee_sp) */
+ fprintf (f, "\tST\tr3,4(,sp)\n ");
fprintf (f, "\t.drop\tr15\n");
- /* place contents of the PSW into r3
- * that is, place the address of "." into r3 */
+ /* Place contents of the PSW into r3
+ that is, place the address of "." into r3 */
fprintf (f, "\tBASR\tr%d,0\n", BASE_REGISTER);
fprintf (f, "\t.using\t.,r%d\n", BASE_REGISTER);
function_first = 1;
diff --git a/gcc/config/i370/i370.h b/gcc/config/i370/i370.h
index 1e32e01..d87369b 100644
--- a/gcc/config/i370/i370.h
+++ b/gcc/config/i370/i370.h
@@ -187,6 +187,7 @@ extern int mvs_function_name_length;
#define BASE_REGISTER 3
#define PAGE_REGISTER 4
+#ifdef TARGET_HLASM
/* 1 for registers that have pervasive standard uses and are not available
for the register allocator. These are registers that must have fixed,
valid values stored in them for the entire length of the subroutine call,
@@ -249,6 +250,26 @@ extern int mvs_function_name_length;
but can be less for certain modes in special long registers.
Note that DCmode (complex double) needs two regs.
*/
+#endif /* TARGET_HLASM */
+
+/* ================= */
+#ifdef TARGET_ELF_ABI
+/* The Linux/ELF ABI uses the same register layout as the
+ * the MVS/OE version, with the following exceptions:
+ * -- r12 (rtca) is not used.
+ */
+
+#define FIXED_REGISTERS \
+{ 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 1, 0, 1, 1, 0, 0, 0, 0, 0 }
+/*0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19*/
+
+#define CALL_USED_REGISTERS \
+{ 1, 1, 0, 1, 1, 0, 0, 0, 0, 0, 0, 1, 0, 1, 1, 1, 1, 1, 1, 1 }
+/*0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19*/
+
+#endif /* TARGET_ELF_ABI */
+/* ================= */
+
#define HARD_REGNO_NREGS(REGNO, MODE) \
((REGNO) > 15 ? \
@@ -327,7 +348,7 @@ extern int mvs_function_name_length;
A_t a; a.a=1; a.b=2 a.c=3;
return a;
}
- In the above, the stroage for the return value is in the callers stack, and
+ In the above, the storage for the return value is in the callers stack, and
the R1 points at that mem location.
*/
@@ -444,7 +465,10 @@ enum reg_class
/* Define this if pushing a word on the stack makes the stack pointer a
smaller address. */
+/* ------------------------------------------------------------------- */
+/* ================= */
+#ifdef TARGET_HLASM
/* #define STACK_GROWS_DOWNWARD */
/* Define this if the nominal address of the stack frame is at the
@@ -466,6 +490,29 @@ enum reg_class
/* If we generate an insn to push BYTES bytes, this says how many the stack
pointer really advances by. On the 370, we have no push instruction. */
+#endif /* TARGET_HLASM */
+
+/* ================= */
+#ifdef TARGET_ELF_ABI
+
+/* With ELF/Linux, stack is placed at large virtual addrs and grows down.
+ But we want the compiler to generate posistive displacements from the
+ stack pointer, and so we make the frame lie above the stack. */
+
+#define STACK_GROWS_DOWNWARD
+/* #define FRAME_GROWS_DOWNWARD */
+
+/* Offset within stack frame to start allocating local variables at.
+ This is the offset to the BEGINNING of the first local allocated. */
+
+#define STARTING_FRAME_OFFSET \
+ (STACK_POINTER_OFFSET + current_function_outgoing_args_size)
+
+#define INITIAL_FRAME_POINTER_OFFSET(DEPTH) (DEPTH) = STARTING_FRAME_OFFSET
+
+#endif /* TARGET_ELF_ABI */
+/* ================= */
+
/* #define PUSH_ROUNDING(BYTES) */
/* Accumulate the outgoing argument count so we can request the right
@@ -529,7 +576,7 @@ enum reg_class
#define RETURN_POPS_ARGS(FUNDECL,FUNTYPE,SIZE) 0
-/* The FUNCTION_VALUE macro dDefines how to find the value returned by a
+/* The FUNCTION_VALUE macro defines how to find the value returned by a
function. VALTYPE is the data type of the value (as a tree).
If the precise function being called is known, FUNC is its FUNCTION_DECL;
otherwise, FUNC is NULL.
@@ -1559,7 +1606,7 @@ enum reg_class
#define ASM_DECLARE_FUNCTION_NAME(FILE, NAME, DECL) \
{ \
- if (strlen (NAME) * 2 > mvs_function_name_length) \
+ if (strlen (NAME) + 1 > mvs_function_name_length) \
{ \
if (mvs_function_name) \
free (mvs_function_name); \
@@ -1567,7 +1614,7 @@ enum reg_class
} \
if (!mvs_function_name) \
{ \
- mvs_function_name_length = strlen (NAME) * 2; \
+ mvs_function_name_length = strlen (NAME) * 2 + 1; \
mvs_function_name = (char *) xmalloc (mvs_function_name_length); \
} \
if (!strcmp (NAME, "main")) \
diff --git a/gcc/config/i370/i370.md b/gcc/config/i370/i370.md
index 8896f2a..a48523e 100644
--- a/gcc/config/i370/i370.md
+++ b/gcc/config/i370/i370.md
@@ -647,7 +647,9 @@ check_label_emit ();
else if (REG_P (operands[1]))
{
mvs_check_page (0, 4, 0);
- return \"STM %1,%N1,%0\";
+ /* can't use stm otherwise stm r6,r7,0(r10,r13) can happen */
+ return \"STM %1,%N1,%0\";
+ /* return \"ST %1,%0\;ST %N1,4+%0\"; */
}
mvs_check_page (0, 6, 0);
return \"MVC %O0(8,%R0),%W1\";
@@ -1825,8 +1827,6 @@ check_label_emit ();
;
; floatsidf2 instruction pattern(s).
;
-; Uses the float field of the TCA.
-;
(define_insn "floatsidf2"
[(set (match_operand:DF 0 "general_operand" "=f")
@@ -1837,7 +1837,7 @@ check_label_emit ();
check_label_emit ();
CC_STATUS_INIT;
mvs_check_page (0, 16, 8);
- return \"ST %1,508(,12)\;XI 508(12),128\;LD %0,504(,12)\;SD %0,=XL8'4E00000080000000'\";
+ return \"ST %1,144(,13)\;XI 144(13),128\;LD %0,140(,13)\;SD %0,=XL8'4E00000080000000'\";
}"
[(set_attr "length" "16")]
)
@@ -3021,7 +3021,7 @@ check_label_emit ();
(define_insn ""
[(set (match_operand:SI 0 "r_or_s_operand" "=d,m")
(ior:SI (match_operand:SI 1 "r_or_s_operand" "%0,0")
- (match_operand:SI 2 "r_or_s_operand" "g,mi")))]
+ (match_operand:SI 2 "r_or_s_operand" "g,Si")))]
"TARGET_CHAR_INSTRUCTIONS"
"*
{
diff --git a/gcc/config/i370/x-oe b/gcc/config/i370/x-oe
index 04fcfeb..b6db96a 100644
--- a/gcc/config/i370/x-oe
+++ b/gcc/config/i370/x-oe
@@ -19,3 +19,10 @@ CC=c89
CLIB=-liberty
LDFLAGS=-L../libiberty
+
+# TAR Options
+# Please note that OpenEdition confuses tar and pax, and
+# thus uses the non-standard options 'xpf'
+
+TAROUTOPTS=xpf
+