Commit ff9350e7 by Linas Vepstas Committed by Richard Henderson

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
parent c8023011
Tue Sep 7 23:23:15 1999 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.
Tue Sep 7 22:39:18 1999 Mark Mitchell <mark@codesourcery.com> Tue Sep 7 22:39:18 1999 Mark Mitchell <mark@codesourcery.com>
* rs6000.c: Include ggc.h. * rs6000.c: Include ggc.h.
...@@ -1317,11 +1331,11 @@ Sat Aug 28 16:24:31 1999 Richard Henderson <rth@cygnus.com> ...@@ -1317,11 +1331,11 @@ Sat Aug 28 16:24:31 1999 Richard Henderson <rth@cygnus.com>
Sat Aug 28 16:20:12 1999 Richard Henderson <rth@cygnus.com> Sat Aug 28 16:20:12 1999 Richard Henderson <rth@cygnus.com>
* haifa-sched.c (sched_analyze): Clear LOG_LINKS before calling * haifa-sched.c (sched_analyze): Clear LOG_LINKS before calling
sched_analyze_insn. sched_analyze_insn.
(sched_analyze_1): Let add_dependence care for not adding dups. (sched_analyze_1): Let add_dependence care for not adding dups.
(sched_analyze_2): Likewise. (sched_analyze_2): Likewise.
(add_branch_dependences): Likewise. (add_branch_dependences): Likewise.
Sat Aug 28 15:58:16 1999 Mumit Khan <khan@xraylith.wisc.edu> Sat Aug 28 15:58:16 1999 Mumit Khan <khan@xraylith.wisc.edu>
......
...@@ -30,9 +30,47 @@ OpenEdition Hints ...@@ -30,9 +30,47 @@ OpenEdition Hints
The shell script "install" is handy for users of OpenEdition. 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 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 98.12.05 -- fix numerous MVC bugs
99.02.06 -- multiply insn sometimes not generated when needed. 99.02.06 -- multiply insn sometimes not generated when needed.
-- extendsidi bugs, bad literal values printed -- extendsidi bugs, bad literal values printed
......
...@@ -33,7 +33,7 @@ Boston, MA 02111-1307, USA. */ ...@@ -33,7 +33,7 @@ Boston, MA 02111-1307, USA. */
#include "insn-flags.h" #include "insn-flags.h"
#include "output.h" #include "output.h"
#include "insn-attr.h" #include "insn-attr.h"
#include "function.h" /* #include "function.h" */
#include "flags.h" #include "flags.h"
#include "recog.h" #include "recog.h"
...@@ -370,13 +370,13 @@ i370_short_branch (insn) ...@@ -370,13 +370,13 @@ i370_short_branch (insn)
/* The i370_label_scan() routine is supposed to loop over /* The i370_label_scan() routine is supposed to loop over
all labels and label references in a compilation unit, all labels and label references in a compilation unit,
and determine whether all label refs appear on the same 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. 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 approximate, and make the sizes of the jumps appear
farther apart then they will actually be. This makes 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) { \ #define I370_RECORD_LABEL_REF(label,addr) { \
...@@ -470,8 +470,8 @@ i370_label_scan (void) ...@@ -470,8 +470,8 @@ i370_label_scan (void)
can only lead to horrible results if this were to occur. can only lead to horrible results if this were to occur.
However, the current situation is not any worse than it was 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); debug_rtx (insn);
// abort(); // abort();
for (j=0; j < XVECLEN (body, 0); j++) for (j=0; j < XVECLEN (body, 0); j++)
...@@ -483,23 +483,30 @@ i370_label_scan (void) ...@@ -483,23 +483,30 @@ i370_label_scan (void)
} }
else else
{ {
/* The following appears during make of _eh in libgcc2.a /* XXX hack alert.
while not obviously wrong, its weird, so not obviously Compiling the execption handling (L_eh) in libgcc2.a will trip
right either ... up right here, with something that looks like
(jump_insn:HI 125 124 126 (set (pc) (set (pc) (mem:SI (plus:SI (reg/v:SI 1 r1) (const_int 4))))
(mem:SI (plus:SI (reg/v:SI 1 r1) {indirect_jump}
(const_int 4)))) 144 {indirect_jump} (nil) 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); debug_rtx (insn);
// abort(); /* abort(); */
continue; continue;
} }
} }
else
/* At this point, this jump_insn had better be a plain-old {
* ordinary one, grap the label id and go */ /* At this point, this jump_insn had better be a plain-old
if (CODE_LABEL != GET_CODE (label)) abort (); ordinary one, grap the label id and go */
I370_RECORD_LABEL_REF(label,here); if (CODE_LABEL != GET_CODE (label)) abort ();
I370_RECORD_LABEL_REF(label,here);
}
} }
/* Sometimes, we take addresses of labels and use them /* Sometimes, we take addresses of labels and use them
...@@ -1364,11 +1371,11 @@ i370_function_prolog (f, l) ...@@ -1364,11 +1371,11 @@ i370_function_prolog (f, l)
#ifdef TARGET_ELF_ABI #ifdef TARGET_ELF_ABI
/* /*
The 370_function_prolog() routine generates the current ELF ABI ES/390 prolog. 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: It performs the following steps:
-- saves the callers non-volatile registers on the callers stack. -- saves the callers non-volatile registers on the callers stack.
-- computes a new stack top and checks for room for the stack. -- subtracts stackframe size from the stack pointer.
-- initializes size and backpointer of new stack frame -- stores backpointer to old caller stack.
-- updates stack pointer to point at new frame.
XXX hack alert -- if the global var int leaf_function is non-zero, 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 then this is a leaf, and it might be possible to optimize the prologue
...@@ -1413,59 +1420,30 @@ i370_function_prolog (f, frame_size) ...@@ -1413,59 +1420,30 @@ i370_function_prolog (f, frame_size)
fprintf (f, "\t.long\t%d\n", aligned_size); fprintf (f, "\t.long\t%d\n", aligned_size);
/* FENT == function prologue entry */ /* 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); 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"); fprintf (f, "\tSTM\tr14,r12,12(sp)\n");
/* r11 points to arg list in callers stackframe; was passed in r2 */ /* r3 == saved callee stack pointer */
fprintf (f, "\tLR\tr11,r2\n"); fprintf (f, "\tLR\tr3,sp\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");
/* add callee stack length to caller top of stack */ /* 4(r15) == stackframe size */
fprintf (f, "\tALR\tr0,r2\n"); fprintf (f, "\tSL\tsp,4(,r15)\n");
/* is there enough room for this new stack frame? */ /* r11 points to arg list in callers stackframe; was passed in r2 */
fprintf (f, "\tCL\tr0,12(,rtca)\n"); fprintf (f, "\tLR\tr11,r2\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");
/* store callee stack pointer at 8(sp) */ /* store callee stack pointer at 8(sp) */
fprintf (f, "\tST\tr2,8(,sp)\n "); /* fprintf (f, "\tST\tsp,8(,r3)\n "); wasted cycles, no one uses this ... */
/* store caller sp at 4(callee_sp) */
fprintf (f, "\tST\tsp,4(,r2)\n ");
/* load calle_sp into sp */ /* backchain -- store caller sp at 4(callee_sp) */
fprintf (f, "\tLR\tsp,r2\n"); fprintf (f, "\tST\tr3,4(,sp)\n ");
fprintf (f, "\t.drop\tr15\n"); fprintf (f, "\t.drop\tr15\n");
/* place contents of the PSW into r3 /* Place contents of the PSW into r3
* that is, place the address of "." into r3 */ that is, place the address of "." into r3 */
fprintf (f, "\tBASR\tr%d,0\n", BASE_REGISTER); fprintf (f, "\tBASR\tr%d,0\n", BASE_REGISTER);
fprintf (f, "\t.using\t.,r%d\n", BASE_REGISTER); fprintf (f, "\t.using\t.,r%d\n", BASE_REGISTER);
function_first = 1; function_first = 1;
......
...@@ -187,6 +187,7 @@ extern int mvs_function_name_length; ...@@ -187,6 +187,7 @@ extern int mvs_function_name_length;
#define BASE_REGISTER 3 #define BASE_REGISTER 3
#define PAGE_REGISTER 4 #define PAGE_REGISTER 4
#ifdef TARGET_HLASM
/* 1 for registers that have pervasive standard uses and are not available /* 1 for registers that have pervasive standard uses and are not available
for the register allocator. These are registers that must have fixed, for the register allocator. These are registers that must have fixed,
valid values stored in them for the entire length of the subroutine call, valid values stored in them for the entire length of the subroutine call,
...@@ -249,6 +250,26 @@ extern int mvs_function_name_length; ...@@ -249,6 +250,26 @@ extern int mvs_function_name_length;
but can be less for certain modes in special long registers. but can be less for certain modes in special long registers.
Note that DCmode (complex double) needs two regs. 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) \ #define HARD_REGNO_NREGS(REGNO, MODE) \
((REGNO) > 15 ? \ ((REGNO) > 15 ? \
...@@ -327,7 +348,7 @@ extern int mvs_function_name_length; ...@@ -327,7 +348,7 @@ extern int mvs_function_name_length;
A_t a; a.a=1; a.b=2 a.c=3; A_t a; a.a=1; a.b=2 a.c=3;
return a; 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. the R1 points at that mem location.
*/ */
...@@ -444,7 +465,10 @@ enum reg_class ...@@ -444,7 +465,10 @@ enum reg_class
/* Define this if pushing a word on the stack makes the stack pointer a /* Define this if pushing a word on the stack makes the stack pointer a
smaller address. */ smaller address. */
/* ------------------------------------------------------------------- */
/* ================= */
#ifdef TARGET_HLASM
/* #define STACK_GROWS_DOWNWARD */ /* #define STACK_GROWS_DOWNWARD */
/* Define this if the nominal address of the stack frame is at the /* Define this if the nominal address of the stack frame is at the
...@@ -466,6 +490,29 @@ enum reg_class ...@@ -466,6 +490,29 @@ enum reg_class
/* If we generate an insn to push BYTES bytes, this says how many the stack /* 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. */ 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) */ /* #define PUSH_ROUNDING(BYTES) */
/* Accumulate the outgoing argument count so we can request the right /* Accumulate the outgoing argument count so we can request the right
...@@ -529,7 +576,7 @@ enum reg_class ...@@ -529,7 +576,7 @@ enum reg_class
#define RETURN_POPS_ARGS(FUNDECL,FUNTYPE,SIZE) 0 #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). 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; If the precise function being called is known, FUNC is its FUNCTION_DECL;
otherwise, FUNC is NULL. otherwise, FUNC is NULL.
...@@ -1559,7 +1606,7 @@ enum reg_class ...@@ -1559,7 +1606,7 @@ enum reg_class
#define ASM_DECLARE_FUNCTION_NAME(FILE, NAME, DECL) \ #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) \ if (mvs_function_name) \
free (mvs_function_name); \ free (mvs_function_name); \
...@@ -1567,7 +1614,7 @@ enum reg_class ...@@ -1567,7 +1614,7 @@ enum reg_class
} \ } \
if (!mvs_function_name) \ 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); \ mvs_function_name = (char *) xmalloc (mvs_function_name_length); \
} \ } \
if (!strcmp (NAME, "main")) \ if (!strcmp (NAME, "main")) \
......
...@@ -647,7 +647,9 @@ check_label_emit (); ...@@ -647,7 +647,9 @@ check_label_emit ();
else if (REG_P (operands[1])) else if (REG_P (operands[1]))
{ {
mvs_check_page (0, 4, 0); 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); mvs_check_page (0, 6, 0);
return \"MVC %O0(8,%R0),%W1\"; return \"MVC %O0(8,%R0),%W1\";
...@@ -1825,8 +1827,6 @@ check_label_emit (); ...@@ -1825,8 +1827,6 @@ check_label_emit ();
; ;
; floatsidf2 instruction pattern(s). ; floatsidf2 instruction pattern(s).
; ;
; Uses the float field of the TCA.
;
(define_insn "floatsidf2" (define_insn "floatsidf2"
[(set (match_operand:DF 0 "general_operand" "=f") [(set (match_operand:DF 0 "general_operand" "=f")
...@@ -1837,7 +1837,7 @@ check_label_emit (); ...@@ -1837,7 +1837,7 @@ check_label_emit ();
check_label_emit (); check_label_emit ();
CC_STATUS_INIT; CC_STATUS_INIT;
mvs_check_page (0, 16, 8); 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")] [(set_attr "length" "16")]
) )
...@@ -3021,7 +3021,7 @@ check_label_emit (); ...@@ -3021,7 +3021,7 @@ check_label_emit ();
(define_insn "" (define_insn ""
[(set (match_operand:SI 0 "r_or_s_operand" "=d,m") [(set (match_operand:SI 0 "r_or_s_operand" "=d,m")
(ior:SI (match_operand:SI 1 "r_or_s_operand" "%0,0") (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" "TARGET_CHAR_INSTRUCTIONS"
"* "*
{ {
......
...@@ -19,3 +19,10 @@ CC=c89 ...@@ -19,3 +19,10 @@ CC=c89
CLIB=-liberty CLIB=-liberty
LDFLAGS=-L../libiberty LDFLAGS=-L../libiberty
# TAR Options
# Please note that OpenEdition confuses tar and pax, and
# thus uses the non-standard options 'xpf'
TAROUTOPTS=xpf
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment