From: Jim Wilson Date: Mon, 17 Jun 1996 19:01:47 +0000 (-0700) Subject: (memory): Change r4100/r4300 support. X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=aa4e54c443741294237c992ee54bab3951690f6b;p=gcc.git (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 --- diff --git a/gcc/config/mips/mips.md b/gcc/config/mips/mips.md index f75e73773ed..fe58fdda774 100644 --- a/gcc/config/mips/mips.md +++ b/gcc/config/mips/mips.md @@ -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) @@ -356,6 +352,10 @@ (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) @@ -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\";