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)
(and (eq_attr "type" "fadd") (eq_attr "cpu" "r4300"))
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)
;; ....................
;;
-;; 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")
(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
""
"
{
+ 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. */
""
"
{
+ 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. */
(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)
(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)
;; 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
"")
(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
{
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
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\";
(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\";
{
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
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),
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\";
(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\";
(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\";