Commit aa4e54c4 by Jim Wilson

(memory): Change r4100/r4300 support.

(imuldiv): Add r4300 support.
(high, low): New patterns.
(movsi, movdi): Add LO_SUM support.
(movsi_internal1, movsi_internal2): Use move_operand instead of
general_operand.
(movstrsi_internal, movstrsi_internal2): Delete R constraint.
(call, call_value): Pass address instead of MEM to call_insn_operand.
Call gen_call_{value_}internal0 instead of internal1.
(call_internal0, call_value_internal0, call_multiple_internal0):
New patterns.
(call_internal1, call_internal2, call_value_internal1,
call_value_internal2, call_value_multiple_internal2): Add explicit
MEM before target address.

From-SVN: r12287
parent ce57d6f4
...@@ -155,13 +155,9 @@ ...@@ -155,13 +155,9 @@
3 0) 3 0)
(define_function_unit "memory" 1 0 (define_function_unit "memory" 1 0
(and (eq_attr "type" "load") (eq_attr "cpu" "r3000,r4600,r4650")) (and (eq_attr "type" "load") (eq_attr "cpu" "r3000,r4600,r4650,r4100,r4300"))
2 0) 2 0)
(define_function_unit "memory" 1 0
(and (eq_attr "type" "load") (eq_attr "cpu" "r4100,r4300"))
1 0)
(define_function_unit "memory" 1 0 (eq_attr "type" "store") 1 0) (define_function_unit "memory" 1 0 (eq_attr "type" "store") 1 0)
(define_function_unit "memory" 1 0 (eq_attr "type" "xfer") 2 0) (define_function_unit "memory" 1 0 (eq_attr "type" "xfer") 2 0)
...@@ -357,6 +353,10 @@ ...@@ -357,6 +353,10 @@
3 3) 3 3)
(define_function_unit "imuldiv" 1 0 (define_function_unit "imuldiv" 1 0
(and (eq_attr "type" "fcmp,fabs,fneg") (eq_attr "cpu" "r4300"))
1 1)
(define_function_unit "imuldiv" 1 0
(and (eq_attr "type" "fmul") (and (eq_attr "mode" "SF") (eq_attr "cpu" "r4300"))) (and (eq_attr "type" "fmul") (and (eq_attr "mode" "SF") (eq_attr "cpu" "r4300")))
5 5) 5 5)
(define_function_unit "imuldiv" 1 0 (define_function_unit "imuldiv" 1 0
...@@ -868,9 +868,9 @@ ...@@ -868,9 +868,9 @@
;; .................... ;; ....................
;; ;;
;; Vr4300 has a CPU bug where multiplies with certain operands may ;; Early Vr4300 silicon has a CPU bug where multiplies with certain
;; corrupt immediately following multiplies. This is a simple fix to ;; operands may corrupt immediately following multiplies. This is a
;; insert NOPs. ;; simple fix to insert NOPs.
(define_expand "muldf3" (define_expand "muldf3"
[(set (match_operand:DF 0 "register_operand" "=f") [(set (match_operand:DF 0 "register_operand" "=f")
...@@ -3108,6 +3108,30 @@ move\\t%0,%z4\\n\\ ...@@ -3108,6 +3108,30 @@ move\\t%0,%z4\\n\\
(set_attr "mode" "SI") (set_attr "mode" "SI")
(set_attr "length" "2,4")]) (set_attr "length" "2,4")])
;; These two patterns support loading addresses with two instructions instead
;; of using the macro instruction la.
;; ??? mips_move_1word has support for HIGH, so this pattern may be
;; unnecessary.
(define_insn "high"
[(set (match_operand:SI 0 "register_operand" "=r")
(high:SI (match_operand:SI 1 "immediate_operand" "")))]
"mips_split_addresses"
"lui\\t%0,%%hi(%1) # high"
[(set_attr "type" "move")
(set_attr "length" "1")])
(define_insn "low"
[(set (match_operand:SI 0 "register_operand" "=r")
(lo_sum:SI (match_operand:SI 1 "register_operand" "r")
(match_operand:SI 2 "immediate_operand" "")))]
"mips_split_addresses"
"addiu\\t%0,%1,%%lo(%2) # low"
[(set_attr "type" "arith")
(set_attr "mode" "SI")
(set_attr "length" "1")])
;; 64-bit integer moves ;; 64-bit integer moves
;; Unlike most other insns, the move insns can't be split with ;; Unlike most other insns, the move insns can't be split with
...@@ -3120,6 +3144,18 @@ move\\t%0,%z4\\n\\ ...@@ -3120,6 +3144,18 @@ move\\t%0,%z4\\n\\
"" ""
" "
{ {
if (mips_split_addresses && mips_check_split (operands[1], DImode))
{
enum machine_mode mode = GET_MODE (operands[0]);
rtx tem = ((reload_in_progress | reload_completed)
? operands[0] : gen_reg_rtx (mode));
emit_insn (gen_rtx (SET, VOIDmode, tem,
gen_rtx (HIGH, mode, operands[1])));
operands[1] = gen_rtx (LO_SUM, mode, tem, operands[1]);
}
/* If we are generating embedded PIC code, and we are referring to a /* If we are generating embedded PIC code, and we are referring to a
symbol in the .text section, we must use an offset from the start symbol in the .text section, we must use an offset from the start
of the function. */ of the function. */
...@@ -3359,6 +3395,18 @@ move\\t%0,%z4\\n\\ ...@@ -3359,6 +3395,18 @@ move\\t%0,%z4\\n\\
"" ""
" "
{ {
if (mips_split_addresses && mips_check_split (operands[1], SImode))
{
enum machine_mode mode = GET_MODE (operands[0]);
rtx tem = ((reload_in_progress | reload_completed)
? operands[0] : gen_reg_rtx (mode));
emit_insn (gen_rtx (SET, VOIDmode, tem,
gen_rtx (HIGH, mode, operands[1])));
operands[1] = gen_rtx (LO_SUM, mode, tem, operands[1]);
}
/* If we are generating embedded PIC code, and we are referring to a /* If we are generating embedded PIC code, and we are referring to a
symbol in the .text section, we must use an offset from the start symbol in the .text section, we must use an offset from the start
of the function. */ of the function. */
...@@ -3406,7 +3454,7 @@ move\\t%0,%z4\\n\\ ...@@ -3406,7 +3454,7 @@ move\\t%0,%z4\\n\\
(define_insn "movsi_internal1" (define_insn "movsi_internal1"
[(set (match_operand:SI 0 "nonimmediate_operand" "=d,d,d,d,d,d,R,m,*d,*f*z,*f,*f,*f,*R,*m,*x,*x,*d,*d") [(set (match_operand:SI 0 "nonimmediate_operand" "=d,d,d,d,d,d,R,m,*d,*f*z,*f,*f,*f,*R,*m,*x,*x,*d,*d")
(match_operand:SI 1 "general_operand" "d,S,IKL,Mnis,R,m,dJ,dJ,*f*z,*d,*f,*R,*m,*f,*f,I,*d,*x,*a"))] (match_operand:SI 1 "move_operand" "d,S,IKL,Mnis,R,m,dJ,dJ,*f*z,*d,*f,*R,*m,*f,*f,I,*d,*x,*a"))]
"TARGET_DEBUG_H_MODE "TARGET_DEBUG_H_MODE
&& (register_operand (operands[0], SImode) && (register_operand (operands[0], SImode)
|| register_operand (operands[1], SImode) || register_operand (operands[1], SImode)
...@@ -3418,7 +3466,7 @@ move\\t%0,%z4\\n\\ ...@@ -3418,7 +3466,7 @@ move\\t%0,%z4\\n\\
(define_insn "movsi_internal2" (define_insn "movsi_internal2"
[(set (match_operand:SI 0 "nonimmediate_operand" "=d,d,d,d,d,d,R,m,*d,*z,*x,*d,*x,*d") [(set (match_operand:SI 0 "nonimmediate_operand" "=d,d,d,d,d,d,R,m,*d,*z,*x,*d,*x,*d")
(match_operand:SI 1 "general_operand" "d,S,IKL,Mnis,R,m,dJ,dJ,*z,*d,I,*x,*d,*a"))] (match_operand:SI 1 "move_operand" "d,S,IKL,Mnis,R,m,dJ,dJ,*z,*d,I,*x,*d,*a"))]
"!TARGET_DEBUG_H_MODE "!TARGET_DEBUG_H_MODE
&& (register_operand (operands[0], SImode) && (register_operand (operands[0], SImode)
|| register_operand (operands[1], SImode) || register_operand (operands[1], SImode)
...@@ -3714,8 +3762,8 @@ move\\t%0,%z4\\n\\ ...@@ -3714,8 +3762,8 @@ move\\t%0,%z4\\n\\
;; Insn generated by block moves ;; Insn generated by block moves
(define_insn "movstrsi_internal" (define_insn "movstrsi_internal"
[(set (match_operand:BLK 0 "memory_operand" "=Ro") ;; destination [(set (match_operand:BLK 0 "memory_operand" "=o") ;; destination
(match_operand:BLK 1 "memory_operand" "Ro")) ;; source (match_operand:BLK 1 "memory_operand" "o")) ;; source
(clobber (match_scratch:SI 4 "=&d")) ;; temp 1 (clobber (match_scratch:SI 4 "=&d")) ;; temp 1
(clobber (match_scratch:SI 5 "=&d")) ;; temp 2 (clobber (match_scratch:SI 5 "=&d")) ;; temp 2
(clobber (match_scratch:SI 6 "=&d")) ;; temp 3 (clobber (match_scratch:SI 6 "=&d")) ;; temp 3
...@@ -3773,8 +3821,8 @@ move\\t%0,%z4\\n\\ ...@@ -3773,8 +3821,8 @@ move\\t%0,%z4\\n\\
"") "")
(define_insn "movstrsi_internal2" (define_insn "movstrsi_internal2"
[(set (match_operand:BLK 0 "memory_operand" "=Ro") ;; destination [(set (match_operand:BLK 0 "memory_operand" "=o") ;; destination
(match_operand:BLK 1 "memory_operand" "Ro")) ;; source (match_operand:BLK 1 "memory_operand" "o")) ;; source
(clobber (match_scratch:SI 4 "=&d")) ;; temp 1 (clobber (match_scratch:SI 4 "=&d")) ;; temp 1
(clobber (match_scratch:SI 5 "=&d")) ;; temp 2 (clobber (match_scratch:SI 5 "=&d")) ;; temp 2
(clobber (match_scratch:SI 6 "=&d")) ;; temp 3 (clobber (match_scratch:SI 6 "=&d")) ;; temp 3
...@@ -6277,7 +6325,7 @@ move\\t%0,%z4\\n\\ ...@@ -6277,7 +6325,7 @@ move\\t%0,%z4\\n\\
{ {
addr = XEXP (operands[0], 0); addr = XEXP (operands[0], 0);
if ((GET_CODE (addr) != REG && (!CONSTANT_ADDRESS_P (addr) || TARGET_LONG_CALLS)) if ((GET_CODE (addr) != REG && (!CONSTANT_ADDRESS_P (addr) || TARGET_LONG_CALLS))
|| ! call_insn_operand (operands[0], VOIDmode)) || ! call_insn_operand (addr, VOIDmode))
XEXP (operands[0], 0) = copy_to_mode_reg (Pmode, addr); XEXP (operands[0], 0) = copy_to_mode_reg (Pmode, addr);
/* In order to pass small structures by value in registers /* In order to pass small structures by value in registers
...@@ -6297,20 +6345,27 @@ move\\t%0,%z4\\n\\ ...@@ -6297,20 +6345,27 @@ move\\t%0,%z4\\n\\
emit_insn (RTVEC_ELT (adjust, i)); emit_insn (RTVEC_ELT (adjust, i));
} }
emit_call_insn (gen_call_internal1 (operands[0], operands[1], emit_call_insn (gen_call_internal0 (operands[0], operands[1],
gen_rtx (REG, SImode, GP_REG_FIRST + 31))); gen_rtx (REG, SImode, GP_REG_FIRST + 31)));
DONE; DONE;
} }
}") }")
(define_expand "call_internal0"
[(parallel [(call (match_operand 0 "" "")
(match_operand 1 "" ""))
(clobber (match_operand:SI 2 "" ""))])]
""
"")
(define_insn "call_internal1" (define_insn "call_internal1"
[(call (match_operand 0 "call_insn_operand" "m") [(call (mem (match_operand 0 "call_insn_operand" "ri"))
(match_operand 1 "" "i")) (match_operand 1 "" "i"))
(clobber (match_operand:SI 2 "register_operand" "=d"))] (clobber (match_operand:SI 2 "register_operand" "=d"))]
"!TARGET_ABICALLS && !TARGET_LONG_CALLS" "!TARGET_ABICALLS && !TARGET_LONG_CALLS"
"* "*
{ {
register rtx target = XEXP (operands[0], 0); register rtx target = operands[0];
if (GET_CODE (target) == SYMBOL_REF) if (GET_CODE (target) == SYMBOL_REF)
return \"%*jal\\t%0\"; return \"%*jal\\t%0\";
...@@ -6332,13 +6387,13 @@ move\\t%0,%z4\\n\\ ...@@ -6332,13 +6387,13 @@ move\\t%0,%z4\\n\\
(set_attr "length" "1")]) (set_attr "length" "1")])
(define_insn "call_internal2" (define_insn "call_internal2"
[(call (match_operand 0 "call_insn_operand" "m") [(call (mem (match_operand 0 "call_insn_operand" "ri"))
(match_operand 1 "" "i")) (match_operand 1 "" "i"))
(clobber (match_operand:SI 2 "register_operand" "=d"))] (clobber (match_operand:SI 2 "register_operand" "=d"))]
"TARGET_ABICALLS && !TARGET_LONG_CALLS" "TARGET_ABICALLS && !TARGET_LONG_CALLS"
"* "*
{ {
register rtx target = XEXP (operands[0], 0); register rtx target = operands[0];
if (GET_CODE (target) == SYMBOL_REF) if (GET_CODE (target) == SYMBOL_REF)
return \"jal\\t%0\"; return \"jal\\t%0\";
...@@ -6431,7 +6486,7 @@ move\\t%0,%z4\\n\\ ...@@ -6431,7 +6486,7 @@ move\\t%0,%z4\\n\\
{ {
addr = XEXP (operands[1], 0); addr = XEXP (operands[1], 0);
if ((GET_CODE (addr) != REG && (!CONSTANT_ADDRESS_P (addr) || TARGET_LONG_CALLS)) if ((GET_CODE (addr) != REG && (!CONSTANT_ADDRESS_P (addr) || TARGET_LONG_CALLS))
|| ! call_insn_operand (operands[1], VOIDmode)) || ! call_insn_operand (addr, VOIDmode))
XEXP (operands[1], 0) = copy_to_mode_reg (Pmode, addr); XEXP (operands[1], 0) = copy_to_mode_reg (Pmode, addr);
/* In order to pass small structures by value in registers /* In order to pass small structures by value in registers
...@@ -6455,7 +6510,7 @@ move\\t%0,%z4\\n\\ ...@@ -6455,7 +6510,7 @@ move\\t%0,%z4\\n\\
results. */ results. */
if (GET_CODE (operands[0]) == PARALLEL) if (GET_CODE (operands[0]) == PARALLEL)
{ {
emit_call_insn (gen_call_value_multiple_internal2 emit_call_insn (gen_call_value_multiple_internal0
(XEXP (XVECEXP (operands[0], 0, 0), 0), (XEXP (XVECEXP (operands[0], 0, 0), 0),
operands[1], operands[2], operands[1], operands[2],
XEXP (XVECEXP (operands[0], 0, 1), 0), XEXP (XVECEXP (operands[0], 0, 1), 0),
...@@ -6463,22 +6518,30 @@ move\\t%0,%z4\\n\\ ...@@ -6463,22 +6518,30 @@ move\\t%0,%z4\\n\\
DONE; DONE;
} }
emit_call_insn (gen_call_value_internal1 (operands[0], operands[1], operands[2], emit_call_insn (gen_call_value_internal0 (operands[0], operands[1], operands[2],
gen_rtx (REG, SImode, GP_REG_FIRST + 31))); gen_rtx (REG, Pmode, GP_REG_FIRST + 31)));
DONE; DONE;
} }
}") }")
(define_expand "call_value_internal0"
[(parallel [(set (match_operand 0 "" "")
(call (match_operand 1 "" "")
(match_operand 2 "" "")))
(clobber (match_operand:SI 3 "" ""))])]
""
"")
(define_insn "call_value_internal1" (define_insn "call_value_internal1"
[(set (match_operand 0 "register_operand" "=df") [(set (match_operand 0 "register_operand" "=df")
(call (match_operand 1 "call_insn_operand" "m") (call (mem (match_operand 1 "call_insn_operand" "ri"))
(match_operand 2 "" "i"))) (match_operand 2 "" "i")))
(clobber (match_operand:SI 3 "register_operand" "=d"))] (clobber (match_operand:SI 3 "register_operand" "=d"))]
"!TARGET_ABICALLS && !TARGET_LONG_CALLS" "!TARGET_ABICALLS && !TARGET_LONG_CALLS"
"* "*
{ {
register rtx target = XEXP (operands[1], 0); register rtx target = operands[1];
if (GET_CODE (target) == SYMBOL_REF) if (GET_CODE (target) == SYMBOL_REF)
return \"%*jal\\t%1\"; return \"%*jal\\t%1\";
...@@ -6501,13 +6564,13 @@ move\\t%0,%z4\\n\\ ...@@ -6501,13 +6564,13 @@ move\\t%0,%z4\\n\\
(define_insn "call_value_internal2" (define_insn "call_value_internal2"
[(set (match_operand 0 "register_operand" "=df") [(set (match_operand 0 "register_operand" "=df")
(call (match_operand 1 "call_insn_operand" "m") (call (mem (match_operand 1 "call_insn_operand" "ri"))
(match_operand 2 "" "i"))) (match_operand 2 "" "i")))
(clobber (match_operand:SI 3 "register_operand" "=d"))] (clobber (match_operand:SI 3 "register_operand" "=d"))]
"TARGET_ABICALLS && !TARGET_LONG_CALLS" "TARGET_ABICALLS && !TARGET_LONG_CALLS"
"* "*
{ {
register rtx target = XEXP (operands[1], 0); register rtx target = operands[1];
if (GET_CODE (target) == SYMBOL_REF) if (GET_CODE (target) == SYMBOL_REF)
return \"jal\\t%1\"; return \"jal\\t%1\";
...@@ -6587,21 +6650,32 @@ move\\t%0,%z4\\n\\ ...@@ -6587,21 +6650,32 @@ move\\t%0,%z4\\n\\
(set_attr "mode" "none") (set_attr "mode" "none")
(set_attr "length" "2")]) (set_attr "length" "2")])
(define_insn "call_value_multiple_internal0"
[(parallel [(set (match_operand 0 "" "")
(call (match_operand 1 "" "")
(match_operand 2 "" "")))
(set (match_operand 3 "" "")
(call (match_dup 1)
(match_dup 2)))
(clobber (match_operand:SI 4 "" ""))])]
""
"")
;; ??? May eventually need all 6 versions of the call patterns with multiple ;; ??? May eventually need all 6 versions of the call patterns with multiple
;; return values. ;; return values.
(define_insn "call_value_multiple_internal2" (define_insn "call_value_multiple_internal2"
[(set (match_operand 0 "register_operand" "=df") [(set (match_operand 0 "register_operand" "=df")
(call (match_operand 1 "call_insn_operand" "m") (call (mem (match_operand 1 "call_insn_operand" "ri"))
(match_operand 2 "" "i"))) (match_operand 2 "" "i")))
(set (match_operand 3 "register_operand" "=df") (set (match_operand 3 "register_operand" "=df")
(call (match_dup 1) (call (mem (match_dup 1))
(match_dup 2))) (match_dup 2)))
(clobber (match_operand:SI 4 "register_operand" "=d"))] (clobber (match_operand:SI 4 "register_operand" "=d"))]
"TARGET_ABICALLS && !TARGET_LONG_CALLS" "TARGET_ABICALLS && !TARGET_LONG_CALLS"
"* "*
{ {
register rtx target = XEXP (operands[1], 0); register rtx target = operands[1];
if (GET_CODE (target) == SYMBOL_REF) if (GET_CODE (target) == SYMBOL_REF)
return \"jal\\t%1\"; return \"jal\\t%1\";
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment