summaryrefslogtreecommitdiff
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.c78
1 files changed, 53 insertions, 25 deletions
diff --git a/gcc/config/mips/mips.c b/gcc/config/mips/mips.c
index ff72e28a35c..d3fd7097f57 100644
--- a/gcc/config/mips/mips.c
+++ b/gcc/config/mips/mips.c
@@ -2163,7 +2163,7 @@ static bool
mips16_unextended_reference_p (enum machine_mode mode, rtx base,
unsigned HOST_WIDE_INT offset)
{
- if (offset % GET_MODE_SIZE (mode) == 0)
+ if (mode != BLKmode && offset % GET_MODE_SIZE (mode) == 0)
{
if (GET_MODE_SIZE (mode) == 4 && base == stack_pointer_rtx)
return offset < 256U * GET_MODE_SIZE (mode);
@@ -2398,7 +2398,7 @@ mips_force_unary (enum machine_mode mode, enum rtx_code code, rtx op0)
/* Emit an instruction of the form (set TARGET (CODE OP0 OP1)). */
-static void
+void
mips_emit_binary (enum rtx_code code, rtx target, rtx op0, rtx op1)
{
emit_insn (gen_rtx_SET (VOIDmode, target,
@@ -3777,6 +3777,16 @@ mips_rtx_costs (rtx x, int code, int outer_code, int opno ATTRIBUTE_UNUSED,
return false;
case ZERO_EXTEND:
+ if (outer_code == SET
+ && ISA_HAS_BADDU
+ && (GET_CODE (XEXP (x, 0)) == TRUNCATE
+ || GET_CODE (XEXP (x, 0)) == SUBREG)
+ && GET_MODE (XEXP (x, 0)) == QImode
+ && GET_CODE (XEXP (XEXP (x, 0), 0)) == PLUS)
+ {
+ *total = set_src_cost (XEXP (XEXP (x, 0), 0), speed);
+ return true;
+ }
*total = mips_zero_extend_cost (mode, XEXP (x, 0));
return false;
@@ -11218,9 +11228,13 @@ mips_init_libfuncs (void)
}
/* The MIPS16 ISA does not have an encoding for "sync", so we rely
- on an external non-MIPS16 routine to implement __sync_synchronize. */
+ on an external non-MIPS16 routine to implement __sync_synchronize.
+ Similarly for the rest of the ll/sc libfuncs. */
if (TARGET_MIPS16)
- synchronize_libfunc = init_one_libfunc ("__sync_synchronize");
+ {
+ synchronize_libfunc = init_one_libfunc ("__sync_synchronize");
+ init_sync_libfuncs (UNITS_PER_WORD);
+ }
}
/* Build up a multi-insn sequence that loads label TARGET into $AT. */
@@ -15246,6 +15260,11 @@ mips_set_mips16_mode (int mips16_p)
/* MIPS16 has no BAL instruction. */
target_flags &= ~MASK_RELAX_PIC_CALLS;
+ /* The R4000 errata don't apply to any known MIPS16 cores.
+ It's simpler to make the R4000 fixes and MIPS16 mode
+ mutually exclusive. */
+ target_flags &= ~MASK_FIX_R4000;
+
if (flag_pic && !TARGET_OLDABI)
sorry ("MIPS16 PIC for ABIs other than o32 and o64");
@@ -15831,38 +15850,33 @@ mips_conditional_register_usage (void)
global_regs[CCDSP_PO_REGNUM] = 1;
global_regs[CCDSP_SC_REGNUM] = 1;
}
- else
- {
- int regno;
+ else
+ AND_COMPL_HARD_REG_SET (accessible_reg_set,
+ reg_class_contents[(int) DSP_ACC_REGS]);
- for (regno = DSP_ACC_REG_FIRST; regno <= DSP_ACC_REG_LAST; regno++)
- fixed_regs[regno] = call_used_regs[regno] = 1;
- }
if (!TARGET_HARD_FLOAT)
{
- int regno;
-
- for (regno = FP_REG_FIRST; regno <= FP_REG_LAST; regno++)
- fixed_regs[regno] = call_used_regs[regno] = 1;
- for (regno = ST_REG_FIRST; regno <= ST_REG_LAST; regno++)
- fixed_regs[regno] = call_used_regs[regno] = 1;
+ AND_COMPL_HARD_REG_SET (accessible_reg_set,
+ reg_class_contents[(int) FP_REGS]);
+ AND_COMPL_HARD_REG_SET (accessible_reg_set,
+ reg_class_contents[(int) ST_REGS]);
}
- else if (! ISA_HAS_8CC)
+ else if (!ISA_HAS_8CC)
{
- int regno;
-
/* We only have a single condition-code register. We implement
this by fixing all the condition-code registers and generating
RTL that refers directly to ST_REG_FIRST. */
- for (regno = ST_REG_FIRST; regno <= ST_REG_LAST; regno++)
- fixed_regs[regno] = call_used_regs[regno] = 1;
+ AND_COMPL_HARD_REG_SET (accessible_reg_set,
+ reg_class_contents[(int) ST_REGS]);
+ SET_HARD_REG_BIT (accessible_reg_set, FPSW_REGNUM);
+ fixed_regs[FPSW_REGNUM] = call_used_regs[FPSW_REGNUM] = 1;
}
- /* In MIPS16 mode, we permit the $t temporary registers to be used
- for reload. We prohibit the unused $s registers, since they
- are call-saved, and saving them via a MIPS16 register would
- probably waste more time than just reloading the value. */
if (TARGET_MIPS16)
{
+ /* In MIPS16 mode, we permit the $t temporary registers to be used
+ for reload. We prohibit the unused $s registers, since they
+ are call-saved, and saving them via a MIPS16 register would
+ probably waste more time than just reloading the value. */
fixed_regs[18] = call_used_regs[18] = 1;
fixed_regs[19] = call_used_regs[19] = 1;
fixed_regs[20] = call_used_regs[20] = 1;
@@ -15872,6 +15886,12 @@ mips_conditional_register_usage (void)
fixed_regs[26] = call_used_regs[26] = 1;
fixed_regs[27] = call_used_regs[27] = 1;
fixed_regs[30] = call_used_regs[30] = 1;
+
+ /* Do not allow HI and LO to be treated as register operands.
+ There are no MTHI or MTLO instructions (or any real need
+ for them) and one-way registers cannot easily be reloaded. */
+ AND_COMPL_HARD_REG_SET (operand_reg_set,
+ reg_class_contents[(int) MD_REGS]);
}
/* $f20-$f23 are call-clobbered for n64. */
if (mips_abi == ABI_64)
@@ -16057,12 +16077,20 @@ mips_mulsidi3_gen_fn (enum rtx_code ext_code)
case we still expand mulsidi3 for DMUL. */
if (ISA_HAS_DMUL3)
return signed_p ? gen_mulsidi3_64bit_dmul : NULL;
+ if (TARGET_MIPS16)
+ return (signed_p
+ ? gen_mulsidi3_64bit_mips16
+ : gen_umulsidi3_64bit_mips16);
if (TARGET_FIX_R4000)
return NULL;
return signed_p ? gen_mulsidi3_64bit : gen_umulsidi3_64bit;
}
else
{
+ if (TARGET_MIPS16)
+ return (signed_p
+ ? gen_mulsidi3_32bit_mips16
+ : gen_umulsidi3_32bit_mips16);
if (TARGET_FIX_R4000 && !ISA_HAS_DSP)
return signed_p ? gen_mulsidi3_32bit_r4000 : gen_umulsidi3_32bit_r4000;
return signed_p ? gen_mulsidi3_32bit : gen_umulsidi3_32bit;