aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMichael Meissner <meissner@gcc.gnu.org>1992-08-25 17:39:37 +0000
committerMichael Meissner <meissner@gcc.gnu.org>1992-08-25 17:39:37 +0000
commitab78d4a88118834f4c46a3b96801a8575ae40735 (patch)
tree409cd7da2445e9dfbd2aa86b4354e0e95fdd5080
parent8436fe35328c0c173575ad517e746e4e3a57d781 (diff)
downloadgcc-ab78d4a88118834f4c46a3b96801a8575ae40735.zip
gcc-ab78d4a88118834f4c46a3b96801a8575ae40735.tar.gz
gcc-ab78d4a88118834f4c46a3b96801a8575ae40735.tar.bz2
Change MIPS fp to be at top of stack, instead of bottom; Fix calling mips-tfile with wrong .o file
From-SVN: r1941
-rw-r--r--gcc/config/mips/mips.c109
-rw-r--r--gcc/config/mips/mips.h110
-rw-r--r--gcc/config/mips/osfrose.h2
3 files changed, 145 insertions, 76 deletions
diff --git a/gcc/config/mips/mips.c b/gcc/config/mips/mips.c
index 4aed597..5cae65b 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 f51fe2b..fd748b4 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<xx> 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 e8e15d6..dd3f9f7 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 "\