--- gcc/config/mips/mips.md 2018/04/24 18:10:25 1.1 +++ gcc/config/mips/mips.md 2018/04/24 18:15:56 1.1.1.2 @@ -96,6 +96,10 @@ (define_asm_attributes [(set_attr "type" "multi")]) +;; whether or not generating calls to position independent functions +(define_attr "abicalls" "no,yes" + (const (symbol_ref "mips_abicalls_attr"))) + ;; ......................... @@ -109,7 +113,12 @@ (nil) (and (eq_attr "branch_likely" "yes") (and (eq_attr "dslot" "no") (eq_attr "length" "1")))]) -(define_delay (eq_attr "type" "call,jump") +(define_delay (eq_attr "type" "jump") + [(and (eq_attr "dslot" "no") (eq_attr "length" "1")) + (nil) + (nil)]) + +(define_delay (and (eq_attr "type" "call") (eq_attr "abicalls" "no")) [(and (eq_attr "dslot" "no") (eq_attr "length" "1")) (nil) (nil)]) @@ -328,7 +337,7 @@ " { if (GET_CODE (operands[2]) == CONST_INT && INTVAL (operands[2]) == -32768) - operands[2] = force_reg (SImode, operands[2]); + operands[2] = force_reg (DImode, operands[2]); operands[3] = gen_reg_rtx (SImode); }") @@ -1047,14 +1056,14 @@ move\\t%0,%z4\\n\\ (set_attr "mode" "SI") (set_attr "length" "1")]) -(define_expand "negdi3" +(define_expand "negdi2" [(parallel [(set (match_operand:DI 0 "register_operand" "=d") (neg:DI (match_operand:DI 1 "register_operand" "d"))) (clobber (match_dup 2))])] "!TARGET_DEBUG_G_MODE" "operands[2] = gen_reg_rtx (SImode);") -(define_insn "negdi3_internal" +(define_insn "negdi2_internal" [(set (match_operand:DI 0 "register_operand" "=d") (neg:DI (match_operand:DI 1 "register_operand" "d"))) (clobber (match_operand:SI 2 "register_operand" "=d"))] @@ -1475,10 +1484,14 @@ move\\t%0,%z4\\n\\ ;; ;; .................... +;; The SImode scratch register can not be shared with address regs used for +;; operand zero, because then the address in the move instruction will be +;; clobbered. We mark the scratch register as early clobbered to prevent this. + (define_insn "fix_truncdfsi2" [(set (match_operand:SI 0 "general_operand" "=d,*f,R,o") (fix:SI (match_operand:DF 1 "register_operand" "f,*f,f,f"))) - (clobber (match_scratch:SI 2 "=d,*d,d,d")) + (clobber (match_scratch:SI 2 "=d,*d,&d,&d")) (clobber (match_scratch:DF 3 "=f,*X,f,f"))] "TARGET_HARD_FLOAT" "* @@ -1503,7 +1516,7 @@ move\\t%0,%z4\\n\\ (define_insn "fix_truncsfsi2" [(set (match_operand:SI 0 "general_operand" "=d,*f,R,o") (fix:SI (match_operand:SF 1 "register_operand" "f,*f,f,f"))) - (clobber (match_scratch:SI 2 "=d,*d,d,d")) + (clobber (match_scratch:SI 2 "=d,*d,&d,&d")) (clobber (match_scratch:SF 3 "=f,*X,f,f"))] "TARGET_HARD_FLOAT" "* @@ -1660,7 +1673,7 @@ move\\t%0,%z4\\n\\ "" " { - /* Handle loads. */ + /* Handle stores. */ if (GET_CODE (operands[0]) == MEM) { rtx reg = gen_reg_rtx (SImode); @@ -4085,7 +4098,7 @@ move\\t%0,%z4\\n\\ [(call (match_operand 0 "call_insn_operand" "m") (match_operand 1 "" "i")) (clobber (match_operand:SI 2 "register_operand" "=d"))] - "!TARGET_LONG_CALLS" + "!TARGET_ABICALLS && !TARGET_LONG_CALLS" "* { register rtx target = XEXP (operands[0], 0); @@ -4110,15 +4123,62 @@ move\\t%0,%z4\\n\\ (set_attr "length" "1")]) (define_insn "call_internal2" + [(call (match_operand 0 "call_insn_operand" "m") + (match_operand 1 "" "i")) + (clobber (match_operand:SI 2 "register_operand" "=d"))] + "TARGET_ABICALLS && !TARGET_LONG_CALLS" + "* +{ + register rtx target = XEXP (operands[0], 0); + + if (GET_CODE (target) == SYMBOL_REF) + return \"jal\\t%0\"; + + else if (GET_CODE (target) == CONST_INT) + { + operands[0] = target; + return \"li\\t%^,%0\\n\\tjal\\t%2,%^\"; + } + + else + { + operands[0] = target; + if (REGNO (target) != PIC_FUNCTION_ADDR_REGNUM) + return \"move\\t%^,%0\\n\\tjal\\t%2,%^\"; + else + return \"jal\\t%2,%0\"; + } +}" + [(set_attr "type" "call") + (set_attr "mode" "none") + (set_attr "length" "2")]) + +(define_insn "call_internal3" [(call (mem:SI (match_operand:SI 0 "register_operand" "r")) (match_operand 1 "" "i")) (clobber (match_operand:SI 2 "register_operand" "=d"))] - "TARGET_LONG_CALLS" + "!TARGET_ABICALLS && TARGET_LONG_CALLS" "%*jal\\t%2,%0" [(set_attr "type" "call") (set_attr "mode" "none") (set_attr "length" "1")]) +(define_insn "call_internal4" + [(call (mem:SI (match_operand:SI 0 "register_operand" "r")) + (match_operand 1 "" "i")) + (clobber (match_operand:SI 2 "register_operand" "=d"))] + "TARGET_ABICALLS && TARGET_LONG_CALLS" + "* +{ + if (REGNO (operands[0]) != PIC_FUNCTION_ADDR_REGNUM) + return \"move\\t%^,%0\\n\\tjal\\t%2,%^\"; + else + return \"jal\\t%2,%0\"; +}" + [(set_attr "type" "call") + (set_attr "mode" "none") + (set_attr "length" "2")]) + ;; calls.c now passes a fourth argument, make saber happy @@ -4170,7 +4230,7 @@ move\\t%0,%z4\\n\\ (call (match_operand 1 "call_insn_operand" "m") (match_operand 2 "" "i"))) (clobber (match_operand:SI 3 "register_operand" "=d"))] - "!TARGET_LONG_CALLS" + "!TARGET_ABICALLS && !TARGET_LONG_CALLS" "* { register rtx target = XEXP (operands[1], 0); @@ -4196,15 +4256,64 @@ 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") + (match_operand 2 "" "i"))) + (clobber (match_operand:SI 3 "register_operand" "=d"))] + "TARGET_ABICALLS && !TARGET_LONG_CALLS" + "* +{ + register rtx target = XEXP (operands[1], 0); + + if (GET_CODE (target) == SYMBOL_REF) + return \"jal\\t%1\"; + + else if (GET_CODE (target) == CONST_INT) + { + operands[1] = target; + return \"li\\t%^,%1\\n\\tjal\\t%3,%^\"; + } + + else + { + operands[1] = target; + if (REGNO (target) != PIC_FUNCTION_ADDR_REGNUM) + return \"move\\t%^,%1\\n\\tjal\\t%3,%^\"; + else + return \"jal\\t%3,%1\"; + } +}" + [(set_attr "type" "call") + (set_attr "mode" "none") + (set_attr "length" "2")]) + +(define_insn "call_value_internal3" + [(set (match_operand 0 "register_operand" "=df") (call (mem:SI (match_operand:SI 1 "register_operand" "r")) (match_operand 2 "" "i"))) (clobber (match_operand:SI 3 "register_operand" "=d"))] - "TARGET_LONG_CALLS" + "!TARGET_ABICALLS && TARGET_LONG_CALLS" "%*jal\\t%3,%1" [(set_attr "type" "call") (set_attr "mode" "none") (set_attr "length" "1")]) +(define_insn "call_value_internal4" + [(set (match_operand 0 "register_operand" "=df") + (call (mem:SI (match_operand:SI 1 "register_operand" "r")) + (match_operand 2 "" "i"))) + (clobber (match_operand:SI 3 "register_operand" "=d"))] + "TARGET_ABICALLS && TARGET_LONG_CALLS" + "* +{ + if (REGNO (operands[1]) != PIC_FUNCTION_ADDR_REGNUM) + return \"move\\t%^,%1\\n\\tjal\\t%3,%^\"; + else + return \"jal\\t%3,%1\"; +}" + [(set_attr "type" "call") + (set_attr "mode" "none") + (set_attr "length" "2")]) + ;; Call subroutine returning any type. (define_expand "untyped_call"