summaryrefslogtreecommitdiff
path: root/gcc/config/epiphany/epiphany.c
diff options
context:
space:
mode:
Diffstat (limited to 'gcc/config/epiphany/epiphany.c')
-rw-r--r--gcc/config/epiphany/epiphany.c90
1 files changed, 56 insertions, 34 deletions
diff --git a/gcc/config/epiphany/epiphany.c b/gcc/config/epiphany/epiphany.c
index 5520a633c1f..7d251e3d00e 100644
--- a/gcc/config/epiphany/epiphany.c
+++ b/gcc/config/epiphany/epiphany.c
@@ -335,7 +335,8 @@ epiphany_select_cc_mode (enum rtx_code op,
{
if (GET_MODE_CLASS (GET_MODE (x)) == MODE_FLOAT)
{
- if (TARGET_SOFT_CMPSF)
+ if (TARGET_SOFT_CMPSF
+ || op == ORDERED || op == UNORDERED)
{
if (op == EQ || op == NE)
return CC_FP_EQmode;
@@ -537,24 +538,47 @@ gen_compare_reg (enum machine_mode cmode, enum rtx_code code,
if (mode == CC_FP_GTEmode
&& (code == LE || code == LT || code == UNGT || code == UNGE))
{
- rtx tmp = x; x = y; y = tmp;
- code = swap_condition (code);
+ if (flag_finite_math_only
+ && ((REG_P (x) && REGNO (x) == GPR_0)
+ || (REG_P (y) && REGNO (y) == GPR_1)))
+ switch (code)
+ {
+ case LE: code = UNLE; break;
+ case LT: code = UNLT; break;
+ case UNGT: code = GT; break;
+ case UNGE: code = GE; break;
+ default: gcc_unreachable ();
+ }
+ else
+ {
+ rtx tmp = x; x = y; y = tmp;
+ code = swap_condition (code);
+ }
}
cc_reg = gen_rtx_REG (mode, CC_REGNUM);
}
if ((mode == CC_FP_EQmode || mode == CC_FP_GTEmode
|| mode == CC_FP_ORDmode || mode == CC_FP_UNEQmode)
/* mov<mode>cc might want to re-emit a comparison during ifcvt. */
- && (!REG_P (x) || REGNO (x) != 0 || !REG_P (y) || REGNO (y) != 1))
+ && (!REG_P (x) || REGNO (x) != GPR_0
+ || !REG_P (y) || REGNO (y) != GPR_1))
{
rtx reg;
+#if 0
+ /* ??? We should really do the r0/r1 clobber only during rtl expansion,
+ but just like the flag clobber of movsicc, we have to allow
+ this for ifcvt to work, on the assumption that we'll only want
+ to do this if these registers have been used before by the
+ pre-ifcvt code. */
gcc_assert (currently_expanding_to_rtl);
- reg = gen_rtx_REG (in_mode, 0);
- gcc_assert (!reg_overlap_mentioned_p (reg, y));
+#endif
+ reg = gen_rtx_REG (in_mode, GPR_0);
+ if (reg_overlap_mentioned_p (reg, y))
+ return 0;
emit_move_insn (reg, x);
x = reg;
- reg = gen_rtx_REG (in_mode, 1);
+ reg = gen_rtx_REG (in_mode, GPR_1);
emit_move_insn (reg, y);
y = reg;
}
@@ -964,7 +988,6 @@ epiphany_compute_frame_size (int size /* # of var. bytes allocated. */)
int first_slot, last_slot, first_slot_offset, last_slot_offset;
int first_slot_size;
int small_slots = 0;
- long lr_slot_offset;
var_size = size;
args_size = crtl->outgoing_args_size;
@@ -1021,7 +1044,7 @@ epiphany_compute_frame_size (int size /* # of var. bytes allocated. */)
first_slot = regno;
else if (last_slot < 0
&& (first_slot ^ regno) != 1
- && (!interrupt_p || regno > GPR_0 + 1))
+ && (!interrupt_p || regno > GPR_1))
last_slot = regno;
}
}
@@ -1116,28 +1139,6 @@ epiphany_compute_frame_size (int size /* # of var. bytes allocated. */)
}
total_size = first_slot_offset + last_slot_offset;
- lr_slot_offset
- = (frame_pointer_needed ? first_slot_offset : (long) total_size);
- if (first_slot != GPR_LR)
- {
- int stack_offset = epiphany_stack_offset - UNITS_PER_WORD;
-
- for (regno = 0; ; regno++)
- {
- if (stack_offset + UNITS_PER_WORD - first_slot_size == 0
- && first_slot >= 0)
- {
- stack_offset -= first_slot_size;
- regno--;
- }
- else if (regno == GPR_LR)
- break;
- else if TEST_HARD_REG_BIT (gmask, regno)
- stack_offset -= UNITS_PER_WORD;
- }
- lr_slot_offset += stack_offset;
- }
-
/* Save computed information. */
current_frame_info.total_size = total_size;
current_frame_info.pretend_size = pretend_size;
@@ -1150,7 +1151,6 @@ epiphany_compute_frame_size (int size /* # of var. bytes allocated. */)
current_frame_info.first_slot_offset = first_slot_offset;
current_frame_info.first_slot_size = first_slot_size;
current_frame_info.last_slot_offset = last_slot_offset;
- MACHINE_FUNCTION (cfun)->lr_slot_offset = lr_slot_offset;
current_frame_info.initialized = reload_completed;
@@ -1622,6 +1622,28 @@ epiphany_emit_save_restore (int min, int limit, rtx addr, int epilogue_p)
mem = skipped_mem;
else
mem = gen_mem (mode, addr);
+
+ /* If we are loading / storing LR, note the offset that
+ gen_reload_insi_ra requires. Since GPR_LR is even,
+ we only need to test n, even if mode is DImode. */
+ gcc_assert ((GPR_LR & 1) == 0);
+ if (n == GPR_LR)
+ {
+ long lr_slot_offset = 0;
+ rtx m_addr = XEXP (mem, 0);
+
+ if (GET_CODE (m_addr) == PLUS)
+ lr_slot_offset = INTVAL (XEXP (m_addr, 1));
+ if (frame_pointer_needed)
+ lr_slot_offset += (current_frame_info.first_slot_offset
+ - current_frame_info.total_size);
+ if (MACHINE_FUNCTION (cfun)->lr_slot_known)
+ gcc_assert (MACHINE_FUNCTION (cfun)->lr_slot_offset
+ == lr_slot_offset);
+ MACHINE_FUNCTION (cfun)->lr_slot_offset = lr_slot_offset;
+ MACHINE_FUNCTION (cfun)->lr_slot_known = 1;
+ }
+
if (!epilogue_p)
frame_move_insn (mem, reg);
else if (n >= MAX_EPIPHANY_PARM_REGS || !crtl->args.pretend_args_size)
@@ -1667,7 +1689,7 @@ epiphany_expand_prologue (void)
gen_rtx_REG (DImode, GPR_0));
frame_move_insn (gen_rtx_REG (SImode, GPR_0),
gen_rtx_REG (word_mode, STATUS_REGNUM));
- frame_move_insn (gen_rtx_REG (SImode, GPR_0+1),
+ frame_move_insn (gen_rtx_REG (SImode, GPR_1),
gen_rtx_REG (word_mode, IRET_REGNUM));
mem = gen_frame_mem (BLKmode, stack_pointer_rtx);
off = GEN_INT (-current_frame_info.first_slot_offset);
@@ -1843,7 +1865,7 @@ epiphany_expand_epilogue (int sibcall_p)
emit_move_insn (gen_rtx_REG (word_mode, STATUS_REGNUM),
gen_rtx_REG (SImode, GPR_0));
emit_move_insn (gen_rtx_REG (word_mode, IRET_REGNUM),
- gen_rtx_REG (SImode, GPR_0+1));
+ gen_rtx_REG (SImode, GPR_1));
addr = plus_constant (Pmode, stack_pointer_rtx,
- (HOST_WIDE_INT) 2 * UNITS_PER_WORD);
emit_move_insn (gen_rtx_REG (DImode, GPR_0),