From ab78d4a88118834f4c46a3b96801a8575ae40735 Mon Sep 17 00:00:00 2001 From: Michael Meissner Date: Tue, 25 Aug 1992 17:39:37 +0000 Subject: [PATCH] Change MIPS fp to be at top of stack, instead of bottom; Fix calling mips-tfile with wrong .o file From-SVN: r1941 --- gcc/config/mips/mips.c | 109 +++++++++++++++++-------------------- gcc/config/mips/mips.h | 110 +++++++++++++++++++++++++++++++++----- gcc/config/mips/osfrose.h | 2 +- 3 files changed, 145 insertions(+), 76 deletions(-) diff --git a/gcc/config/mips/mips.c b/gcc/config/mips/mips.c index 4aed597e6cc..5cae65b616f 100644 --- a/gcc/config/mips/mips.c +++ b/gcc/config/mips/mips.c @@ -107,10 +107,6 @@ int mips_section_threshold = -1; /* Count the number of .file directives, so that .loc is up to date. */ int num_source_filenames = 0; -/* Count of the number of functions created so far, in order to make - unique labels for omitting the frame pointer. */ -int number_functions_processed = 0; - /* Count the number of sdb related labels are generated (to find block start and end boundaries). */ int sdb_label_count = 0; @@ -3085,11 +3081,14 @@ override_options () /* - * If the frame pointer has been eliminated, the offset for an auto - * or argument will be based on the stack pointer. But this is not - * what the debugger expects--it needs to find an offset off of the - * frame pointer (whether it exists or not). So here we turn all - * offsets into those based on the (possibly virtual) frame pointer. + * The MIPS debug format wants all automatic variables and arguments + * to be in terms of the virtual frame pointer (stack pointer before + * any adjustment in the function), while the MIPS 3.0 linker wants + * the frame pointer to be the stack pointer after the initial + * adjustment. So, we do the adjustment here. The arg pointer (which + * is eliminated) points to the virtual frame pointer, while the frame + * pointer (which may be eliminated) points to the stack pointer after + * the initial adjustments. */ int @@ -3103,7 +3102,7 @@ mips_debugger_offset (addr, offset) if (!offset) offset = INTVAL (offset2); - if (reg == stack_pointer_rtx) + if (reg == stack_pointer_rtx || reg == frame_pointer_rtx) { int frame_size = (!current_frame_info.initialized) ? compute_frame_size (get_frame_size ()) @@ -3111,13 +3110,8 @@ mips_debugger_offset (addr, offset) offset = offset - frame_size; } - - /* Any other register is, we hope, either the frame pointer, - or a pseudo equivalent to the frame pointer. (Assign_parms - copies the arg pointer to a pseudo if ARG_POINTER_REGNUM is - equal to FRAME_POINTER_REGNUM, so references off of the - arg pointer are all off a pseudo.) Seems like all we can - do is to just return OFFSET and hope for the best. */ + else if (reg != arg_pointer_rtx) + abort_with_insn (addr, "mips_debugger_offset called with non stack/frame/arg pointer."); return offset; } @@ -3415,6 +3409,9 @@ print_operand_address (file, addr) break; case REG: + if (REGNO (addr) == ARG_POINTER_REGNUM) + abort_with_insn (addr, "Arg pointer not eliminated."); + fprintf (file, "0(%s)", reg_names [REGNO (addr)]); break; @@ -3448,6 +3445,9 @@ print_operand_address (file, addr) if (!CONSTANT_P (offset)) abort_with_insn (addr, "PRINT_OPERAND_ADDRESS, illegal insn #2"); + if (REGNO (reg) == ARG_POINTER_REGNUM) + abort_with_insn (addr, "Arg pointer not eliminated."); + output_addr_const (file, offset); fprintf (file, "(%s)", reg_names [REGNO (reg)]); } @@ -3861,10 +3861,6 @@ mips_output_float (stream, value) | GP save for V.4 abi | | | +-----------------------+ - | | - | local variables | - | | - +-----------------------+ | | | fp register save | | | @@ -3874,6 +3870,10 @@ mips_output_float (stream, value) | | +-----------------------+ | | + | local variables | + | | + +-----------------------+ + | | | alloca allocations | | | +-----------------------+ @@ -3906,16 +3906,23 @@ compute_frame_size (size) int fp_inc; /* 1 or 2 depending on the size of fp regs */ int fp_bits; /* bitmask to use for each fp register */ - extra_size = MIPS_STACK_ALIGN (((TARGET_ABICALLS) ? UNITS_PER_WORD : 0) - -STARTING_FRAME_OFFSET); - - var_size = MIPS_STACK_ALIGN (size); - args_size = MIPS_STACK_ALIGN (current_function_outgoing_args_size); - total_size = var_size + args_size + extra_size; gp_reg_size = 0; fp_reg_size = 0; mask = 0; fmask = 0; + extra_size = MIPS_STACK_ALIGN (((TARGET_ABICALLS) ? UNITS_PER_WORD : 0)); + var_size = MIPS_STACK_ALIGN (size); + args_size = MIPS_STACK_ALIGN (current_function_outgoing_args_size); + + /* The MIPS 3.0 linker does not like functions that dynamically + allocate the stack and have 0 for STACK_DYNAMIC_OFFSET, since it + looks like we are trying to create a second frame pointer to the + function, so allocate some stack space to make it happy. */ + + if (args_size == 0 && current_function_calls_alloca) + args_size = 4*UNITS_PER_WORD; + + total_size = var_size + args_size + extra_size; /* Calculate space needed for gp registers. */ for (regno = GP_REG_FIRST; regno <= GP_REG_LAST; regno++) @@ -3969,14 +3976,14 @@ compute_frame_size (size) if (mask) { - unsigned long offset = args_size + gp_reg_size - UNITS_PER_WORD; + unsigned long offset = args_size + var_size + gp_reg_size - UNITS_PER_WORD; current_frame_info.gp_sp_offset = offset; current_frame_info.gp_save_offset = offset - total_size; } if (fmask) { - unsigned long offset = args_size + gp_reg_rounded + fp_reg_size - 2*UNITS_PER_WORD; + unsigned long offset = args_size + var_size + gp_reg_rounded + fp_reg_size - 2*UNITS_PER_WORD; current_frame_info.fp_sp_offset = offset; current_frame_info.fp_save_offset = offset - total_size + UNITS_PER_WORD; } @@ -4152,8 +4159,6 @@ function_prologue (file, size) int size; { int tsize = current_frame_info.total_size; - int vframe; - int vreg; ASM_OUTPUT_SOURCE_FILENAME (file, DECL_SOURCE_FILE (current_function_decl)); ASM_OUTPUT_SOURCE_LINE (file, DECL_SOURCE_LINE (current_function_decl)); @@ -4174,20 +4179,9 @@ function_prologue (file, size) if (tsize > 0 && TARGET_ABICALLS) fprintf (file, "\t.cprestore %d\n", tsize + STARTING_FRAME_OFFSET); - if (frame_pointer_needed) - { - vframe = 0; - vreg = FRAME_POINTER_REGNUM; - } - else - { - vframe = tsize; - vreg = STACK_POINTER_REGNUM; - } - fprintf (file, "\t.frame\t%s,%d,%s\t\t# vars= %d, regs= %d/%d, args = %d, extra= %d\n", - reg_names[ vreg ], - vframe, + reg_names[ (frame_pointer_needed) ? FRAME_POINTER_REGNUM : STACK_POINTER_REGNUM ], + tsize, reg_names[31 + GP_REG_FIRST], current_frame_info.var_size, current_frame_info.num_gp, @@ -4209,7 +4203,6 @@ void mips_expand_prologue () { int regno; - int size; int tsize; tree fndecl = current_function_decl; /* current... is tooo long */ tree fntype = TREE_TYPE (fndecl); @@ -4291,9 +4284,7 @@ mips_expand_prologue () } } - size = MIPS_STACK_ALIGN (get_frame_size ()); - tsize = compute_frame_size (size); - + tsize = compute_frame_size (get_frame_size ()); if (tsize > 0) { rtx tsize_rtx = GEN_INT (tsize); @@ -4310,7 +4301,7 @@ mips_expand_prologue () save_restore_insns (TRUE); if (frame_pointer_needed) - emit_insn (gen_addsi3 (frame_pointer_rtx, stack_pointer_rtx, tsize_rtx)); + emit_insn (gen_movsi (frame_pointer_rtx, stack_pointer_rtx)); } } @@ -4413,15 +4404,8 @@ function_epilogue (file, size) fprintf (file, "\tli\t%s,%d\n", t1_str, tsize); if (frame_pointer_needed) - { - char *fp_str = reg_names[FRAME_POINTER_REGNUM]; - if (tsize > 32767) - fprintf (file,"\tsubu\t%s,%s,%s\t\t# sp not trusted here\n", - sp_str, fp_str, t1_str); - else - fprintf (file,"\tsubu\t%s,%s,%d\t\t# sp not trusted here\n", - sp_str, fp_str, tsize); - } + fprintf (file, "\tmove\t%s,%s\t\t\t# sp not trusted here\n", + sp_str, reg_names[FRAME_POINTER_REGNUM]); save_restore (file, "lw", "ld", "l.d"); @@ -4489,6 +4473,10 @@ function_epilogue (file, size) int num_gp_regs = current_frame_info.gp_reg_size / 4; int num_fp_regs = current_frame_info.fp_reg_size / 8; int num_regs = num_gp_regs + num_fp_regs; + char *name = current_function_name; + + if (name[0] == '*') + name++; dslots_load_total += num_regs; @@ -4511,7 +4499,7 @@ function_epilogue (file, size) fprintf (stderr, "%-20s fp=%c leaf=%c alloca=%c setjmp=%c stack=%4ld arg=%3ld reg=%2d/%d delay=%3d/%3dL %3d/%3dJ refs=%3d/%3d/%3d", - current_function_name, + name, (frame_pointer_needed) ? 'y' : 'n', ((current_frame_info.mask & (1 << 31)) != 0) ? 'n' : 'y', (current_function_calls_alloca) ? 'y' : 'n', @@ -4545,7 +4533,6 @@ function_epilogue (file, size) mips_load_reg = (rtx)0; mips_load_reg2 = (rtx)0; current_frame_info = zero_frame_info; - number_functions_processed++; /* Restore the output file if optimizing the GP (optimizing the GP causes the text to be diverted to a tempfile, so that data decls come before @@ -4574,7 +4561,7 @@ mips_expand_epilogue () if (tsize > 0) { if (frame_pointer_needed) - emit_insn (gen_subsi3 (stack_pointer_rtx, frame_pointer_rtx, tsize_rtx)); + emit_insn (gen_movsi (stack_pointer_rtx, frame_pointer_rtx)); save_restore_insns (FALSE); diff --git a/gcc/config/mips/mips.h b/gcc/config/mips/mips.h index f51fe2b590d..fd748b43552 100644 --- a/gcc/config/mips/mips.h +++ b/gcc/config/mips/mips.h @@ -402,7 +402,7 @@ while (0) \n mips-tfile %{v*: -v} \ %{K: -I %b.o~} \ %{!K: %{save-temps: -I %b.o~}} \ - %{c:%W{o*}%{!o*:-o %b.o}}%{!c:-o %u.o} \ + %{c:%W{o*}%{!o*:-o %b.o}}%{!c:-o %U.o} \ %{.s:%i} %{!.s:%g.s}}}" #endif @@ -473,7 +473,7 @@ while (0) /* Print subsidiary information on the compiler version in use. */ -#define MIPS_VERSION "[AL 1.1, MM 23]" +#define MIPS_VERSION "[AL 1.1, MM 24]" #ifndef MACHINE_TYPE #define MACHINE_TYPE "BSD Mips" @@ -651,8 +651,12 @@ do { \ #define SDB_GENERATE_FAKE(BUFFER, NUMBER) \ sprintf ((BUFFER), ".%dfake", (NUMBER)); -/* Correct the offset of automatic variables and arguments - if the frame pointer has been eliminated. */ +/* Correct the offset of automatic variables and arguments. Note that + the MIPS debug format wants all automatic variables and arguments + to be in terms of the virtual frame pointer (stack pointer before + any adjustment in the function), while the MIPS 3.0 linker wants + the frame pointer to be the stack pointer after the initial + adjustment. */ #define DEBUGGER_AUTO_OFFSET(X) mips_debugger_offset (X, 0) #define DEBUGGER_ARG_OFFSET(OFFSET, X) mips_debugger_offset (X, OFFSET) @@ -1196,7 +1200,7 @@ extern char mips_hard_regno_mode_ok[][FIRST_PSEUDO_REGISTER]; #define FRAME_POINTER_REQUIRED (current_function_calls_alloca) /* Base register for access to arguments of the function. */ -#define ARG_POINTER_REGNUM FRAME_POINTER_REGNUM +#define ARG_POINTER_REGNUM GP_REG_FIRST /* Register in which static-chain is passed to a function. */ #define STATIC_CHAIN_REGNUM (GP_REG_FIRST + 2) @@ -1485,13 +1489,30 @@ extern enum reg_class mips_char_to_class[]; is at the high-address end of the local variables; that is, each additional local variable allocated goes at a more negative offset in the frame. */ -#define FRAME_GROWS_DOWNWARD +/* #define FRAME_GROWS_DOWNWARD */ /* Offset within stack frame to start allocating local variables at. If FRAME_GROWS_DOWNWARD, this is the offset to the END of the first local allocated. Otherwise, it is the offset to the BEGINNING of the first local allocated. */ -#define STARTING_FRAME_OFFSET (-8) +#define STARTING_FRAME_OFFSET current_function_outgoing_args_size + +/* Offset from the stack pointer register to an item dynamically + allocated on the stack, e.g., by `alloca'. + + The default value for this macro is `STACK_POINTER_OFFSET' plus the + length of the outgoing arguments. The default is correct for most + machines. See `function.c' for details. + + The MIPS 3.0 linker does not like functions that dynamically + allocate the stack and have 0 for STACK_DYNAMIC_OFFSET, since it + looks like we are trying to create a second frame pointer to the + function, so allocate some stack space to make it happy. */ + +#define STACK_DYNAMIC_OFFSET(FUNDECL) \ + ((current_function_outgoing_args_size == 0 && current_function_calls_alloca) \ + ? 4*UNITS_PER_WORD \ + : current_function_outgoing_args_size) /* Structure to be filled in by compute_frame_size with register save masks, and offsets for the current function. */ @@ -1522,8 +1543,69 @@ extern struct mips_frame_info current_frame_info; as of the start of the function body. This depends on the layout of the fixed parts of the stack frame and on how registers are saved. */ -#define INITIAL_FRAME_POINTER_OFFSET(VAR) \ - ((VAR) = compute_frame_size (get_frame_size ())) +/* #define INITIAL_FRAME_POINTER_OFFSET(VAR) \ + ((VAR) = compute_frame_size (get_frame_size ())) */ + +/* If defined, this macro specifies a table of register pairs used to + eliminate unneeded registers that point into the stack frame. If + it is not defined, the only elimination attempted by the compiler + is to replace references to the frame pointer with references to + the stack pointer. + + The definition of this macro is a list of structure + initializations, each of which specifies an original and + replacement register. + + On some machines, the position of the argument pointer is not + known until the compilation is completed. In such a case, a + separate hard register must be used for the argument pointer. + This register can be eliminated by replacing it with either the + frame pointer or the argument pointer, depending on whether or not + the frame pointer has been eliminated. + + In this case, you might specify: + #define ELIMINABLE_REGS \ + {{ARG_POINTER_REGNUM, STACK_POINTER_REGNUM}, \ + {ARG_POINTER_REGNUM, FRAME_POINTER_REGNUM}, \ + {FRAME_POINTER_REGNUM, STACK_POINTER_REGNUM}} + + Note that the elimination of the argument pointer with the stack + pointer is specified first since that is the preferred elimination. */ + +#define ELIMINABLE_REGS \ +{{ ARG_POINTER_REGNUM, STACK_POINTER_REGNUM}, \ + { ARG_POINTER_REGNUM, FRAME_POINTER_REGNUM}, \ + { FRAME_POINTER_REGNUM, STACK_POINTER_REGNUM}} + + +/* A C expression that returns non-zero if the compiler is allowed to + try to replace register number FROM-REG with register number + TO-REG. This macro need only be defined if `ELIMINABLE_REGS' is + defined, and will usually be the constant 1, since most of the + cases preventing register elimination are things that the compiler + already knows about. */ + +#define CAN_ELIMINATE(FROM, TO) \ + (!frame_pointer_needed \ + || ((FROM) == ARG_POINTER_REGNUM && (TO) == FRAME_POINTER_REGNUM)) + +/* This macro is similar to `INITIAL_FRAME_POINTER_OFFSET'. It + specifies the initial difference between the specified pair of + registers. This macro must be defined if `ELIMINABLE_REGS' is + defined. */ + +#define INITIAL_ELIMINATION_OFFSET(FROM, TO, OFFSET) \ +{ compute_frame_size (get_frame_size ()); \ + if ((FROM) == FRAME_POINTER_REGNUM && (TO) == STACK_POINTER_REGNUM) \ + (OFFSET) = 0; \ + else if ((FROM) == ARG_POINTER_REGNUM && (TO) == FRAME_POINTER_REGNUM) \ + (OFFSET) = current_frame_info.total_size; \ + else if ((FROM) == ARG_POINTER_REGNUM && (TO) == STACK_POINTER_REGNUM) \ + (OFFSET) = current_frame_info.total_size; \ + else \ + abort (); \ +} + /* If we generate an insn to push BYTES bytes, this says how many the stack pointer really advances by. @@ -1780,18 +1862,19 @@ typedef struct mips_args { (get_attr_dslot (INSN) == DSLOT_NO \ && get_attr_length (INSN) == 1 \ && ! reg_mentioned_p (stack_pointer_rtx, PATTERN (INSN)) \ - && ! reg_mentioned_p (frame_pointer_rtx, PATTERN (INSN))) + && ! reg_mentioned_p (frame_pointer_rtx, PATTERN (INSN)) \ + && ! reg_mentioned_p (arg_pointer_rtx, PATTERN (INSN))) /* Tell prologue and epilogue if register REGNO should be saved / restored. */ #define MUST_SAVE_REGISTER(regno) \ ((regs_ever_live[regno] && !call_used_regs[regno]) \ || (regno == FRAME_POINTER_REGNUM && frame_pointer_needed) \ - || (regno == 31 && regs_ever_live[31])) + || (regno == (GP_REG_FIRST + 31) && regs_ever_live[GP_REG_FIRST + 31])) /* ALIGN FRAMES on double word boundaries */ -#define MIPS_STACK_ALIGN(LOC) (((LOC)+7) & 0xfffffff8) +#define MIPS_STACK_ALIGN(LOC) (((LOC)+7) & ~7) /* Output assembler code to FILE to increment profiler label # LABELNO @@ -2918,8 +3001,7 @@ while (0) $Lb[0-9]+ Begin blocks for MIPS debug support $Lc[0-9]+ Label for use in s operation. $Le[0-9]+ End blocks for MIPS debug support - $Lp\..+ Half-pic labels. - $Ls[0-9]+ FP-SP difference if -fomit-frame-pointer */ + $Lp\..+ Half-pic labels. */ /* This is how to output the definition of a user-level label named NAME, such as the label on a static function or variable NAME. diff --git a/gcc/config/mips/osfrose.h b/gcc/config/mips/osfrose.h index e8e15d643fc..dd3f9f7ae24 100644 --- a/gcc/config/mips/osfrose.h +++ b/gcc/config/mips/osfrose.h @@ -45,7 +45,7 @@ the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */ \n mips-tfile %{v*: -v} %{d*} \ %{K: -I %b.o~} \ %{!K: %{save-temps: -I %b.o~}} \ - %{c:%W{o*}%{!o*:-o %b.o}}%{!c:-o %u.o} \ + %{c:%W{o*}%{!o*:-o %b.o}}%{!c:-o %U.o} \ %{.s:%i} %{!.s:%g.s}}}" #define CPP_SPEC "\ -- 2.30.2