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 @@
3 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)
(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" "xfer") 2 0)
......@@ -357,6 +353,10 @@
3 3)
(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")))
5 5)
(define_function_unit "imuldiv" 1 0
......@@ -868,9 +868,9 @@
;; ....................
;;
;; Vr4300 has a CPU bug where multiplies with certain operands may
;; corrupt immediately following multiplies. This is a simple fix to
;; insert NOPs.
;; Early Vr4300 silicon has a CPU bug where multiplies with certain
;; operands may corrupt immediately following multiplies. This is a
;; simple fix to insert NOPs.
(define_expand "muldf3"
[(set (match_operand:DF 0 "register_operand" "=f")
......@@ -3108,6 +3108,30 @@ move\\t%0,%z4\\n\\
(set_attr "mode" "SI")
(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
;; Unlike most other insns, the move insns can't be split with
......@@ -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
symbol in the .text section, we must use an offset from the start
of the function. */
......@@ -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
symbol in the .text section, we must use an offset from the start
of the function. */
......@@ -3406,7 +3454,7 @@ move\\t%0,%z4\\n\\
(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")
(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
&& (register_operand (operands[0], SImode)
|| register_operand (operands[1], SImode)
......@@ -3418,7 +3466,7 @@ move\\t%0,%z4\\n\\
(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")
(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
&& (register_operand (operands[0], SImode)
|| register_operand (operands[1], SImode)
......@@ -3714,8 +3762,8 @@ move\\t%0,%z4\\n\\
;; Insn generated by block moves
(define_insn "movstrsi_internal"
[(set (match_operand:BLK 0 "memory_operand" "=Ro") ;; destination
(match_operand:BLK 1 "memory_operand" "Ro")) ;; source
[(set (match_operand:BLK 0 "memory_operand" "=o") ;; destination
(match_operand:BLK 1 "memory_operand" "o")) ;; source
(clobber (match_scratch:SI 4 "=&d")) ;; temp 1
(clobber (match_scratch:SI 5 "=&d")) ;; temp 2
(clobber (match_scratch:SI 6 "=&d")) ;; temp 3
......@@ -3773,8 +3821,8 @@ move\\t%0,%z4\\n\\
"")
(define_insn "movstrsi_internal2"
[(set (match_operand:BLK 0 "memory_operand" "=Ro") ;; destination
(match_operand:BLK 1 "memory_operand" "Ro")) ;; source
[(set (match_operand:BLK 0 "memory_operand" "=o") ;; destination
(match_operand:BLK 1 "memory_operand" "o")) ;; source
(clobber (match_scratch:SI 4 "=&d")) ;; temp 1
(clobber (match_scratch:SI 5 "=&d")) ;; temp 2
(clobber (match_scratch:SI 6 "=&d")) ;; temp 3
......@@ -6277,7 +6325,7 @@ move\\t%0,%z4\\n\\
{
addr = XEXP (operands[0], 0);
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);
/* In order to pass small structures by value in registers
......@@ -6297,20 +6345,27 @@ move\\t%0,%z4\\n\\
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)));
DONE;
}
}")
(define_expand "call_internal0"
[(parallel [(call (match_operand 0 "" "")
(match_operand 1 "" ""))
(clobber (match_operand:SI 2 "" ""))])]
""
"")
(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"))
(clobber (match_operand:SI 2 "register_operand" "=d"))]
"!TARGET_ABICALLS && !TARGET_LONG_CALLS"
"*
{
register rtx target = XEXP (operands[0], 0);
register rtx target = operands[0];
if (GET_CODE (target) == SYMBOL_REF)
return \"%*jal\\t%0\";
......@@ -6332,13 +6387,13 @@ move\\t%0,%z4\\n\\
(set_attr "length" "1")])
(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"))
(clobber (match_operand:SI 2 "register_operand" "=d"))]
"TARGET_ABICALLS && !TARGET_LONG_CALLS"
"*
{
register rtx target = XEXP (operands[0], 0);
register rtx target = operands[0];
if (GET_CODE (target) == SYMBOL_REF)
return \"jal\\t%0\";
......@@ -6431,7 +6486,7 @@ move\\t%0,%z4\\n\\
{
addr = XEXP (operands[1], 0);
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);
/* In order to pass small structures by value in registers
......@@ -6455,7 +6510,7 @@ move\\t%0,%z4\\n\\
results. */
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),
operands[1], operands[2],
XEXP (XVECEXP (operands[0], 0, 1), 0),
......@@ -6463,22 +6518,30 @@ move\\t%0,%z4\\n\\
DONE;
}
emit_call_insn (gen_call_value_internal1 (operands[0], operands[1], operands[2],
gen_rtx (REG, SImode, GP_REG_FIRST + 31)));
emit_call_insn (gen_call_value_internal0 (operands[0], operands[1], operands[2],
gen_rtx (REG, Pmode, GP_REG_FIRST + 31)));
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"
[(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")))
(clobber (match_operand:SI 3 "register_operand" "=d"))]
"!TARGET_ABICALLS && !TARGET_LONG_CALLS"
"*
{
register rtx target = XEXP (operands[1], 0);
register rtx target = operands[1];
if (GET_CODE (target) == SYMBOL_REF)
return \"%*jal\\t%1\";
......@@ -6501,13 +6564,13 @@ move\\t%0,%z4\\n\\
(define_insn "call_value_internal2"
[(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")))
(clobber (match_operand:SI 3 "register_operand" "=d"))]
"TARGET_ABICALLS && !TARGET_LONG_CALLS"
"*
{
register rtx target = XEXP (operands[1], 0);
register rtx target = operands[1];
if (GET_CODE (target) == SYMBOL_REF)
return \"jal\\t%1\";
......@@ -6587,21 +6650,32 @@ move\\t%0,%z4\\n\\
(set_attr "mode" "none")
(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
;; return values.
(define_insn "call_value_multiple_internal2"
[(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")))
(set (match_operand 3 "register_operand" "=df")
(call (match_dup 1)
(call (mem (match_dup 1))
(match_dup 2)))
(clobber (match_operand:SI 4 "register_operand" "=d"))]
"TARGET_ABICALLS && !TARGET_LONG_CALLS"
"*
{
register rtx target = XEXP (operands[1], 0);
register rtx target = operands[1];
if (GET_CODE (target) == SYMBOL_REF)
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