diff options
-rw-r--r-- | gcc/ChangeLog | 10 | ||||
-rw-r--r-- | gcc/config/mips/mips.c | 13 | ||||
-rw-r--r-- | gcc/config/mips/mips.md | 63 |
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; } }") |