aboutsummaryrefslogtreecommitdiff
path: root/gcc/config/mips/mips.c
diff options
context:
space:
mode:
Diffstat (limited to 'gcc/config/mips/mips.c')
-rw-r--r--gcc/config/mips/mips.c98
1 files changed, 52 insertions, 46 deletions
diff --git a/gcc/config/mips/mips.c b/gcc/config/mips/mips.c
index a677f9392b4..b40ba3ba5fe 100644
--- a/gcc/config/mips/mips.c
+++ b/gcc/config/mips/mips.c
@@ -285,10 +285,10 @@ struct GTY(()) mips_frame_info {
HOST_WIDE_INT acc_sp_offset;
HOST_WIDE_INT cop0_sp_offset;
- /* The offset of arg_pointer_rtx from frame_pointer_rtx. */
+ /* The offset of arg_pointer_rtx from the bottom of the frame. */
HOST_WIDE_INT arg_pointer_offset;
- /* The offset of hard_frame_pointer_rtx from frame_pointer_rtx. */
+ /* The offset of hard_frame_pointer_rtx from the bottom of the frame. */
HOST_WIDE_INT hard_frame_pointer_offset;
};
@@ -2703,8 +2703,10 @@ mips_add_offset (rtx temp, rtx reg, HOST_WIDE_INT offset)
}
else
{
- /* Leave OFFSET as a 16-bit offset and put the excess in HIGH. */
- high = GEN_INT (CONST_HIGH_PART (offset));
+ /* Leave OFFSET as a 16-bit offset and put the excess in HIGH.
+ The addition inside the macro CONST_HIGH_PART may cause an
+ overflow, so we need to force a sign-extension check. */
+ high = gen_int_mode (CONST_HIGH_PART (offset), Pmode);
offset = CONST_LOW_PART (offset);
}
high = mips_force_temporary (temp, high);
@@ -2846,41 +2848,36 @@ mips_force_address (rtx x, enum machine_mode mode)
return x;
}
-/* This function is used to implement LEGITIMIZE_ADDRESS. If *XLOC can
+/* This function is used to implement LEGITIMIZE_ADDRESS. If X can
be legitimized in a way that the generic machinery might not expect,
- put the new address in *XLOC and return true. MODE is the mode of
+ return a new address, otherwise return NULL. MODE is the mode of
the memory being accessed. */
-bool
-mips_legitimize_address (rtx *xloc, enum machine_mode mode)
+static rtx
+mips_legitimize_address (rtx x, rtx oldx ATTRIBUTE_UNUSED,
+ enum machine_mode mode)
{
rtx base, addr;
HOST_WIDE_INT offset;
- if (mips_tls_symbol_p (*xloc))
- {
- *xloc = mips_legitimize_tls_address (*xloc);
- return true;
- }
+ if (mips_tls_symbol_p (x))
+ return mips_legitimize_tls_address (x);
/* See if the address can split into a high part and a LO_SUM. */
- if (mips_split_symbol (NULL, *xloc, mode, &addr))
- {
- *xloc = mips_force_address (addr, mode);
- return true;
- }
+ if (mips_split_symbol (NULL, x, mode, &addr))
+ return mips_force_address (addr, mode);
/* Handle BASE + OFFSET using mips_add_offset. */
- mips_split_plus (*xloc, &base, &offset);
+ mips_split_plus (x, &base, &offset);
if (offset != 0)
{
if (!mips_valid_base_register_p (base, mode, false))
base = copy_to_mode_reg (Pmode, base);
addr = mips_add_offset (NULL, base, offset);
- *xloc = mips_force_address (addr, mode);
- return true;
+ return mips_force_address (addr, mode);
}
- return false;
+
+ return x;
}
/* Load VALUE into DEST. TEMP is as for mips_force_temporary. */
@@ -8671,16 +8668,16 @@ mips_save_reg_p (unsigned int regno)
| | + UNITS_PER_WORD
| accumulator save area |
| |
- +-------------------------------+ <-- frame_pointer_rtx + fp_sp_offset
+ +-------------------------------+ <-- stack_pointer_rtx + fp_sp_offset
| | + UNITS_PER_HWFPVALUE
| FPR save area |
| |
- +-------------------------------+ <-- frame_pointer_rtx + gp_sp_offset
+ +-------------------------------+ <-- stack_pointer_rtx + gp_sp_offset
| | + UNITS_PER_WORD
| GPR save area |
| |
- +-------------------------------+
- | | \
+ +-------------------------------+ <-- frame_pointer_rtx with
+ | | \ -fstack-protector
| local variables | | var_size
| | /
+-------------------------------+
@@ -8688,16 +8685,17 @@ mips_save_reg_p (unsigned int regno)
| $gp save area | | cprestore_size
| | /
P +-------------------------------+ <-- hard_frame_pointer_rtx for
- | | MIPS16 code
- | outgoing stack arguments |
- | |
- +-------------------------------+
- | |
- | caller-allocated save area |
- | for register arguments |
- | |
+ | | \ MIPS16 code
+ | outgoing stack arguments | |
+ | | |
+ +-------------------------------+ | args_size
+ | | |
+ | caller-allocated save area | |
+ | for register arguments | |
+ | | /
+-------------------------------+ <-- stack_pointer_rtx
- frame_pointer_rtx
+ frame_pointer_rtx without
+ -fstack-protector
hard_frame_pointer_rtx for
non-MIPS16 code.
@@ -8742,11 +8740,11 @@ mips_compute_frame_info (void)
cfun->machine->global_pointer = mips_global_pointer ();
- /* The first STARTING_FRAME_OFFSET bytes contain the outgoing argument
- area and the $gp save slot. This area isn't needed in leaf functions,
- but if the target-independent frame size is nonzero, we're committed
- to allocating it anyway. */
- if (size == 0 && current_function_is_leaf)
+ /* The first two blocks contain the outgoing argument area and the $gp save
+ slot. This area isn't needed in leaf functions, but if the
+ target-independent frame size is nonzero, we have already committed to
+ allocating these in STARTING_FRAME_OFFSET for !FRAME_GROWS_DOWNWARD. */
+ if ((size == 0 || FRAME_GROWS_DOWNWARD) && current_function_is_leaf)
{
/* The MIPS 3.0 linker does not like functions that dynamically
allocate the stack and have 0 for STACK_DYNAMIC_OFFSET, since it
@@ -8761,7 +8759,7 @@ mips_compute_frame_info (void)
else
{
frame->args_size = crtl->outgoing_args_size;
- frame->cprestore_size = STARTING_FRAME_OFFSET - frame->args_size;
+ frame->cprestore_size = MIPS_GP_SAVE_AREA_SIZE;
}
offset = frame->args_size + frame->cprestore_size;
@@ -8940,12 +8938,16 @@ mips_initial_elimination_offset (int from, int to)
mips_compute_frame_info ();
- /* Set OFFSET to the offset from the soft frame pointer, which is also
- the offset from the end-of-prologue stack pointer. */
+ /* Set OFFSET to the offset from the end-of-prologue stack pointer. */
switch (from)
{
case FRAME_POINTER_REGNUM:
- offset = 0;
+ if (FRAME_GROWS_DOWNWARD)
+ offset = (cfun->machine->frame.args_size
+ + cfun->machine->frame.cprestore_size
+ + cfun->machine->frame.var_size);
+ else
+ offset = 0;
break;
case ARG_POINTER_REGNUM:
@@ -11642,8 +11644,9 @@ AVAIL_NON_MIPS16 (cache, TARGET_CACHE_BUILTIN)
for instruction CODE_FOR_loongson_<INSN>. FUNCTION_TYPE is a
builtin_description field. */
#define LOONGSON_BUILTIN_ALIAS(INSN, FN_NAME, FUNCTION_TYPE) \
- { CODE_FOR_loongson_ ## INSN, 0, "__builtin_loongson_" #FN_NAME, \
- MIPS_BUILTIN_DIRECT, FUNCTION_TYPE, mips_builtin_avail_loongson }
+ { CODE_FOR_loongson_ ## INSN, MIPS_FP_COND_f, \
+ "__builtin_loongson_" #FN_NAME, MIPS_BUILTIN_DIRECT, \
+ FUNCTION_TYPE, mips_builtin_avail_loongson }
/* Define a Loongson MIPS_BUILTIN_DIRECT function __builtin_loongson_<INSN>
for instruction CODE_FOR_loongson_<INSN>. FUNCTION_TYPE is a
@@ -14741,6 +14744,9 @@ mips_final_postscan_insn (FILE *file, rtx insn, rtx *opvec, int noperands)
#undef TARGET_ASM_ALIGNED_DI_OP
#define TARGET_ASM_ALIGNED_DI_OP "\t.dword\t"
+#undef TARGET_LEGITIMIZE_ADDRESS
+#define TARGET_LEGITIMIZE_ADDRESS mips_legitimize_address
+
#undef TARGET_ASM_FUNCTION_PROLOGUE
#define TARGET_ASM_FUNCTION_PROLOGUE mips_output_function_prologue
#undef TARGET_ASM_FUNCTION_EPILOGUE