aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--gcc/ChangeLog10
-rw-r--r--gcc/config/mips/mips.c13
-rw-r--r--gcc/config/mips/mips.md63
3 files changed, 81 insertions, 5 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index 0c89a86..4e9ddd5 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,3 +1,13 @@
+Mon Jun 14 15:38:43 1999 Jim Wilson <wilson@cygnus.com>
+
+ * config/mips/mips.c (mips_secondary_reload_class): Check for
+ (PLUS (SP) (REG)) and return appropriate register class.
+ * config/mips/mips.md (reload_insi): Delete predicate for operand 1.
+ Handle (PLUS (SP) (REG)).
+ (tablejump): In mips16 code, use emit_insn instead of emit_jump_insn.
+ (tablejump_mips161, tablejump_mips162): Use emit_jump_insn instead
+ of emit_insn for tablejump.
+
Mon Jun 14 17:26:40 1999 David Edelsohn <edelsohn@gnu.org>
* rs6000.c (output_prolog): RS6000_CALL_GLUE must be
diff --git a/gcc/config/mips/mips.c b/gcc/config/mips/mips.c
index 3433052..5c54dba 100644
--- a/gcc/config/mips/mips.c
+++ b/gcc/config/mips/mips.c
@@ -7234,6 +7234,19 @@ mips_secondary_reload_class (class, mode, x, in_p)
}
if (! gp_reg_p)
{
+ /* The stack pointer isn't a valid operand to an add instruction,
+ so we need to load it into M16_REGS first. This can happen as
+ a result of register elimination and form_sum converting
+ (plus reg (plus SP CONST)) to (plus (plus reg SP) CONST). We
+ need an extra register if the dest is the same as the other
+ register. In that case, we can't fix the problem by loading SP
+ into the dest first. */
+ if (GET_CODE (x) == PLUS && GET_CODE (XEXP (x, 0)) == REG
+ && GET_CODE (XEXP (x, 1)) == REG
+ && (XEXP (x, 0) == stack_pointer_rtx
+ || XEXP (x, 1) == stack_pointer_rtx))
+ return (class == M16_REGS ? M16_NA_REGS : M16_REGS);
+
if (class == M16_REGS || class == M16_NA_REGS)
return NO_REGS;
return M16_REGS;
diff --git a/gcc/config/mips/mips.md b/gcc/config/mips/mips.md
index 4e0a5b4..fb739b8 100644
--- a/gcc/config/mips/mips.md
+++ b/gcc/config/mips/mips.md
@@ -5473,9 +5473,12 @@ move\\t%0,%z4\\n\\
;; so we use a mult. ??? This is hideous, and we ought to figure out
;; something better.
+;; We use no predicate for operand1, because it may be a PLUS, and there
+;; is no convenient predicate for that.
+
(define_expand "reload_insi"
[(set (match_operand:SI 0 "register_operand" "=b")
- (match_operand:SI 1 "register_operand" "b"))
+ (match_operand:SI 1 "" "b"))
(clobber (match_operand:SI 2 "register_operand" "=&d"))]
"TARGET_MIPS16"
"
@@ -5499,6 +5502,56 @@ move\\t%0,%z4\\n\\
gen_rtx (REG, SImode, 66)))));
DONE;
}
+
+ /* If this is a plus, then this must be an add of the stack pointer against
+ either a hard register or a pseudo. */
+ if (TARGET_MIPS16 && GET_CODE (operands[1]) == PLUS)
+ {
+ rtx plus_op;
+
+ if (XEXP (operands[1], 0) == stack_pointer_rtx)
+ plus_op = XEXP (operands[1], 1);
+ else if (XEXP (operands[1], 1) == stack_pointer_rtx)
+ plus_op = XEXP (operands[1], 0);
+ else
+ abort ();
+
+ /* We should have a register now. */
+ if (GET_CODE (plus_op) != REG)
+ abort ();
+
+ if (REGNO (plus_op) < FIRST_PSEUDO_REGISTER)
+ {
+ /* We have to have at least one temporary register which is not
+ overlapping plus_op. */
+ if (! rtx_equal_p (plus_op, operands[0]))
+ {
+ emit_move_insn (operands[0], stack_pointer_rtx);
+ emit_insn (gen_addsi3 (operands[0], operands[0], plus_op));
+ }
+ else if (! rtx_equal_p (plus_op, operands[2]))
+ {
+ emit_move_insn (operands[2], stack_pointer_rtx);
+ emit_insn (gen_addsi3 (operands[0], plus_op, operands[2]));
+ }
+ else
+ abort ();
+ }
+ else
+ {
+ /* We need two registers in this case. */
+ if (! rtx_equal_p (operands[0], operands[2]))
+ {
+ emit_move_insn (operands[0], stack_pointer_rtx);
+ emit_move_insn (operands[2], plus_op);
+ emit_insn (gen_addsi3 (operands[0], operands[0], operands[2]));
+ }
+ else
+ abort ();
+ }
+ DONE;
+ }
+
/* FIXME: I don't know how to get a value into the HI register. */
emit_move_insn (operands[0], operands[1]);
DONE;
@@ -9039,9 +9092,9 @@ move\\t%0,%z4\\n\\
if (GET_MODE (operands[0]) != HImode)
abort ();
if (!(Pmode == DImode))
- emit_jump_insn (gen_tablejump_mips161 (operands[0], operands[1]));
+ emit_insn (gen_tablejump_mips161 (operands[0], operands[1]));
else
- emit_jump_insn (gen_tablejump_mips162 (operands[0], operands[1]));
+ emit_insn (gen_tablejump_mips162 (operands[0], operands[1]));
DONE;
}
@@ -9110,7 +9163,7 @@ move\\t%0,%z4\\n\\
emit_insn (gen_extendhisi2 (t1, operands[0]));
emit_move_insn (t2, gen_rtx (LABEL_REF, SImode, operands[1]));
emit_insn (gen_addsi3 (t3, t1, t2));
- emit_insn (gen_tablejump_internal1 (t3, operands[1]));
+ emit_jump_insn (gen_tablejump_internal1 (t3, operands[1]));
DONE;
}
}")
@@ -9132,7 +9185,7 @@ move\\t%0,%z4\\n\\
emit_insn (gen_extendhidi2 (t1, operands[0]));
emit_move_insn (t2, gen_rtx (LABEL_REF, DImode, operands[1]));
emit_insn (gen_adddi3 (t3, t1, t2));
- emit_insn (gen_tablejump_internal2 (t3, operands[1]));
+ emit_jump_insn (gen_tablejump_internal2 (t3, operands[1]));
DONE;
}
}")