--- gcc/config/mips.md 2018/04/24 17:55:12 1.1.1.2 +++ gcc/config/mips.md 2018/04/24 18:06:07 1.1.1.4 @@ -51,14 +51,13 @@ ;; fsqrt floating point square root ;; multi multiword sequence (or user asm statements) ;; nop no operation -;; pic OSF/rose half pic load (define_attr "type" - "unknown,branch,jump,call,load,store,move,xfer,hilo,arith,darith,imul,idiv,icmp,fadd,fmul,fdiv,fabs,fneg,fcmp,fcvt,fsqrt,multi,nop,pic" + "unknown,branch,jump,call,load,store,move,xfer,hilo,arith,darith,imul,idiv,icmp,fadd,fmul,fdiv,fabs,fneg,fcmp,fcvt,fsqrt,multi,nop" (const_string "unknown")) ;; Main data type used by the insn -(define_attr "mode" "unknown,none,QI,HI,SI,DI,SF,DF" (const_string "unknown")) +(define_attr "mode" "unknown,none,QI,HI,SI,DI,SF,DF,FPSW" (const_string "unknown")) ;; # instructions (4 bytes each) (define_attr "length" "" (const_int 1)) @@ -69,14 +68,19 @@ (const_string "yes") (const_string "no"))) +;; Attribute describing the processor. This attribute must match exactly +;; with the processor_type enumeration in mips.h. + ;; Attribute describing the processor -(define_attr "cpu" "default,r3000,r4000,r6000" - (const - (cond [(eq (symbol_ref "mips_cpu") (symbol_ref "PROCESSOR_DEFAULT")) (const_string "default") - (eq (symbol_ref "mips_cpu") (symbol_ref "PROCESSOR_R3000")) (const_string "r3000") - (eq (symbol_ref "mips_cpu") (symbol_ref "PROCESSOR_R4000")) (const_string "r4000") - (eq (symbol_ref "mips_cpu") (symbol_ref "PROCESSOR_R6000")) (const_string "r6000")] - (const_string "default")))) +;; (define_attr "cpu" "default,r3000,r6000,r4000" +;; (const +;; (cond [(eq (symbol_ref "mips_cpu") (symbol_ref "PROCESSOR_R3000")) (const_string "r3000") +;; (eq (symbol_ref "mips_cpu") (symbol_ref "PROCESSOR_R4000")) (const_string "r4000") +;; (eq (symbol_ref "mips_cpu") (symbol_ref "PROCESSOR_R6000")) (const_string "r6000")] +;; (const_string "default")))) + +(define_attr "cpu" "default,r3000,r6000,r4000" + (const (symbol_ref "mips_cpu_attr"))) ;; Attribute defining whether or not we can use the branch-likely instructions ;; (MIPS ISA level 2) @@ -103,7 +107,7 @@ (define_delay (eq_attr "type" "branch") [(and (eq_attr "dslot" "no") (eq_attr "length" "1")) (nil) - (eq_attr "branch_likely" "yes")]) + (and (eq_attr "branch_likely" "yes") (and (eq_attr "dslot" "no") (eq_attr "length" "1")))]) (define_delay (eq_attr "type" "call,jump") [(and (eq_attr "dslot" "no") (eq_attr "length" "1")) @@ -119,117 +123,146 @@ ;; ......................... ; (define_function_unit NAME MULTIPLICITY SIMULTANEITY -; TEST READY-DELAY BUSY-DELAY [CONFLICT-LIST]) +; TEST READY-DELAY ISSUE-DELAY [CONFLICT-LIST]) ;; Make the default case (PROCESSOR_DEFAULT) handle the worst case (define_function_unit "memory" 1 0 - (and (eq_attr "type" "load,pic") (eq_attr "cpu" "!r3000")) + (and (eq_attr "type" "load") (eq_attr "cpu" "!r3000")) 3 0) (define_function_unit "memory" 1 0 - (and (eq_attr "type" "load,pic") (eq_attr "cpu" "r3000")) + (and (eq_attr "type" "load") (eq_attr "cpu" "r3000")) 2 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 "transfer" 1 0 (eq_attr "type" "xfer") 2 0) -(define_function_unit "transfer" 1 0 (eq_attr "type" "hilo") 3 0) +(define_function_unit "addr" 1 0 (eq_attr "type" "fcmp") 2 0) + +(define_function_unit "memory" 1 0 (eq_attr "type" "xfer") 2 0) +(define_function_unit "memory" 1 0 (eq_attr "type" "hilo") 3 0) (define_function_unit "imuldiv" 1 1 (and (eq_attr "type" "imul") (eq_attr "cpu" "!r3000,r4000")) - 17 34) + 17 0) (define_function_unit "imuldiv" 1 1 (and (eq_attr "type" "imul") (eq_attr "cpu" "r3000")) - 12 24) + 12 0) (define_function_unit "imuldiv" 1 1 (and (eq_attr "type" "imul") (eq_attr "cpu" "r4000")) - 10 20) + 10 0) (define_function_unit "imuldiv" 1 1 (and (eq_attr "type" "idiv") (eq_attr "cpu" "!r3000,r4000")) - 38 76) + 38 0) (define_function_unit "imuldiv" 1 1 (and (eq_attr "type" "idiv") (eq_attr "cpu" "r3000")) - 35 70) + 35 0) (define_function_unit "imuldiv" 1 1 (and (eq_attr "type" "idiv") (eq_attr "cpu" "r4000")) - 69 138) + 69 0) (define_function_unit "adder" 1 1 (and (eq_attr "type" "fadd") (eq_attr "cpu" "!r3000,r6000")) - 4 8) + 4 0) (define_function_unit "adder" 1 1 (and (eq_attr "type" "fadd") (eq_attr "cpu" "r3000")) - 2 4) + 2 0) (define_function_unit "adder" 1 1 (and (eq_attr "type" "fadd") (eq_attr "cpu" "r6000")) - 3 6) + 3 0) -(define_function_unit "fast" 1 1 +(define_function_unit "adder" 1 1 (and (eq_attr "type" "fabs,fneg") (eq_attr "cpu" "!r3000")) - 2 4) + 2 0) -(define_function_unit "fast" 1 1 +(define_function_unit "adder" 1 1 (and (eq_attr "type" "fabs,fneg") (eq_attr "cpu" "r3000")) - 1 2) + 1 0) (define_function_unit "mult" 1 1 (and (eq_attr "type" "fmul") (and (eq_attr "mode" "SF") (eq_attr "cpu" "!r3000,r6000"))) - 7 14) + 7 0) (define_function_unit "mult" 1 1 (and (eq_attr "type" "fmul") (and (eq_attr "mode" "SF") (eq_attr "cpu" "r3000"))) - 4 8) + 4 0) (define_function_unit "mult" 1 1 (and (eq_attr "type" "fmul") (and (eq_attr "mode" "SF") (eq_attr "cpu" "r6000"))) - 5 10) + 5 0) (define_function_unit "mult" 1 1 (and (eq_attr "type" "fmul") (and (eq_attr "mode" "DF") (eq_attr "cpu" "!r3000,r6000"))) - 8 16) + 8 0) (define_function_unit "mult" 1 1 (and (eq_attr "type" "fmul") (and (eq_attr "mode" "DF") (eq_attr "cpu" "r3000"))) - 5 10) + 5 0) (define_function_unit "mult" 1 1 (and (eq_attr "type" "fmul") (and (eq_attr "mode" "DF") (eq_attr "cpu" "r6000"))) - 6 12) + 6 0) (define_function_unit "divide" 1 1 (and (eq_attr "type" "fdiv") (and (eq_attr "mode" "SF") (eq_attr "cpu" "!r3000,r6000"))) - 23 46) + 23 0) (define_function_unit "divide" 1 1 (and (eq_attr "type" "fdiv") (and (eq_attr "mode" "SF") (eq_attr "cpu" "r3000"))) - 12 24) + 12 0) (define_function_unit "divide" 1 1 (and (eq_attr "type" "fdiv") (and (eq_attr "mode" "SF") (eq_attr "cpu" "r6000"))) - 15 30) + 15 0) (define_function_unit "divide" 1 1 (and (eq_attr "type" "fdiv") (and (eq_attr "mode" "DF") (eq_attr "cpu" "!r3000,r6000"))) - 36 72) + 36 0) (define_function_unit "divide" 1 1 (and (eq_attr "type" "fdiv") (and (eq_attr "mode" "DF") (eq_attr "cpu" "r3000"))) - 19 34) + 19 0) (define_function_unit "divide" 1 1 (and (eq_attr "type" "fdiv") (and (eq_attr "mode" "DF") (eq_attr "cpu" "r6000"))) - 16 32) + 16 0) -(define_function_unit "sqrt" 1 1 (and (eq_attr "type" "fsqrt") (eq_attr "mode" "SF")) 54 108) -(define_function_unit "sqrt" 1 1 (and (eq_attr "type" "fsqrt") (eq_attr "mode" "DF")) 112 224) +(define_function_unit "divide" 1 1 (and (eq_attr "type" "fsqrt") (eq_attr "mode" "SF")) 54 0) +(define_function_unit "divide" 1 1 (and (eq_attr "type" "fsqrt") (eq_attr "mode" "DF")) 112 0) + + +;; The following functional units do not use the cpu type, and use +;; much less memory in genattrtab.c. + +;; (define_function_unit "memory" 1 0 (eq_attr "type" "load") 3 0) +;; (define_function_unit "memory" 1 0 (eq_attr "type" "store") 1 0) +;; +;; (define_function_unit "fp_comp" 1 0 (eq_attr "type" "fcmp") 2 0) +;; +;; (define_function_unit "transfer" 1 0 (eq_attr "type" "xfer") 2 0) +;; (define_function_unit "transfer" 1 0 (eq_attr "type" "hilo") 3 0) +;; +;; (define_function_unit "imuldiv" 1 1 (eq_attr "type" "imul") 17 0) +;; (define_function_unit "imuldiv" 1 1 (eq_attr "type" "idiv") 38 0) +;; +;; (define_function_unit "adder" 1 1 (eq_attr "type" "fadd") 4 0) +;; (define_function_unit "adder" 1 1 (eq_attr "type" "fabs,fneg") 2 0) +;; +;; (define_function_unit "mult" 1 1 (and (eq_attr "type" "fmul") (eq_attr "mode" "SF")) 7 0) +;; (define_function_unit "mult" 1 1 (and (eq_attr "type" "fmul") (eq_attr "mode" "DF")) 8 0) +;; +;; (define_function_unit "divide" 1 1 (and (eq_attr "type" "fdiv") (eq_attr "mode" "SF")) 23 0) +;; (define_function_unit "divide" 1 1 (and (eq_attr "type" "fdiv") (eq_attr "mode" "DF")) 36 0) +;; +;; (define_function_unit "sqrt" 1 1 (and (eq_attr "type" "fsqrt") (eq_attr "mode" "SF")) 54 0) +;; (define_function_unit "sqrt" 1 1 (and (eq_attr "type" "fsqrt") (eq_attr "mode" "DF")) 112 0) ;; @@ -260,16 +293,27 @@ (set_attr "mode" "SF") (set_attr "length" "1")]) -(define_insn "addsi3" +(define_expand "addsi3" [(set (match_operand:SI 0 "register_operand" "=d") - (plus:SI (match_operand:SI 1 "arith_operand" "%d") + (plus:SI (match_operand:SI 1 "reg_or_0_operand" "dJ") (match_operand:SI 2 "arith_operand" "dI")))] "" + " +{ + if (GET_CODE (operands[2]) == CONST_INT && INTVAL (operands[2]) == -32768) + operands[2] = force_reg (SImode, operands[2]); +}") + +(define_insn "addsi3_internal" + [(set (match_operand:SI 0 "register_operand" "=d") + (plus:SI (match_operand:SI 1 "reg_or_0_operand" "dJ") + (match_operand:SI 2 "arith_operand" "dI")))] + "GET_CODE (operands[2]) != CONST_INT || INTVAL (operands[2]) != -32768" "* { return (GET_CODE (operands[2]) == CONST_INT && INTVAL (operands[2]) < 0) - ? \"subu\\t%0,%1,%n2\" - : \"addu\\t%0,%1,%2\"; + ? \"subu\\t%0,%z1,%n2\" + : \"addu\\t%0,%z1,%2\"; }" [(set_attr "type" "arith") (set_attr "mode" "SI") @@ -281,7 +325,13 @@ (match_operand:DI 2 "arith_operand" ""))) (clobber (match_dup 3))])] "!TARGET_DEBUG_G_MODE" - "operands[3] = gen_reg_rtx (SImode);") + " +{ + if (GET_CODE (operands[2]) == CONST_INT && INTVAL (operands[2]) == -32768) + operands[2] = force_reg (SImode, operands[2]); + + operands[3] = gen_reg_rtx (SImode); +}") (define_insn "adddi3_internal_1" [(set (match_operand:DI 0 "register_operand" "=d,&d") @@ -296,16 +346,16 @@ ? \"srl\\t%3,%L0,31\;sll\\t%M0,%M0,1\;sll\\t%L0,%L1,1\;addu\\t%M0,%M0,%3\" : \"addu\\t%L0,%L1,%L2\;sltu\\t%3,%L0,%L2\;addu\\t%M0,%M1,%M2\;addu\\t%M0,%M0,%3\"; }" - [(set_attr "type" "darith,darith") - (set_attr "mode" "DI,DI") - (set_attr "length" "4,4")]) + [(set_attr "type" "darith") + (set_attr "mode" "DI") + (set_attr "length" "4")]) (define_split [(set (match_operand:DI 0 "register_operand" "") (plus:DI (match_operand:DI 1 "register_operand" "") (match_operand:DI 2 "register_operand" ""))) (clobber (match_operand:SI 3 "register_operand" ""))] - "reload_completed && !WORDS_BIG_ENDIAN && !TARGET_DEBUG_G_MODE + "reload_completed && !WORDS_BIG_ENDIAN && !TARGET_DEBUG_D_MODE && !TARGET_DEBUG_G_MODE && GET_CODE (operands[0]) == REG && GP_REG_P (REGNO (operands[0])) && GET_CODE (operands[1]) == REG && GP_REG_P (REGNO (operands[1])) && GET_CODE (operands[2]) == REG && GP_REG_P (REGNO (operands[2])) @@ -317,7 +367,7 @@ (subreg:SI (match_dup 2) 0))) (set (match_dup 3) - (ltu:CC (subreg:SI (match_dup 0) 0) + (ltu:SI (subreg:SI (match_dup 0) 0) (subreg:SI (match_dup 2) 0))) (set (subreg:SI (match_dup 0) 1) @@ -334,7 +384,7 @@ (plus:DI (match_operand:DI 1 "register_operand" "") (match_operand:DI 2 "register_operand" ""))) (clobber (match_operand:SI 3 "register_operand" ""))] - "reload_completed && WORDS_BIG_ENDIAN && !TARGET_DEBUG_G_MODE + "reload_completed && WORDS_BIG_ENDIAN && !TARGET_DEBUG_D_MODE && !TARGET_DEBUG_G_MODE && GET_CODE (operands[0]) == REG && GP_REG_P (REGNO (operands[0])) && GET_CODE (operands[1]) == REG && GP_REG_P (REGNO (operands[1])) && GET_CODE (operands[2]) == REG && GP_REG_P (REGNO (operands[2])) @@ -346,7 +396,7 @@ (subreg:SI (match_dup 2) 1))) (set (match_dup 3) - (ltu:CC (subreg:SI (match_dup 0) 1) + (ltu:SI (subreg:SI (match_dup 0) 1) (subreg:SI (match_dup 2) 1))) (set (subreg:SI (match_dup 0) 0) @@ -368,8 +418,8 @@ addu\\t%L0,%L1,%2\;sltu\\t%3,%L0,%2\;addu\\t%M0,%M1,%3 move\\t%L0,%L1\;move\\t%M0,%M1 subu\\t%L0,%L1,%n2\;sltu\\t%3,%L0,%2\;subu\\t%M0,%M1,1\;addu\\t%M0,%M0,%3" - [(set_attr "type" "darith,darith,darith") - (set_attr "mode" "DI,DI,DI") + [(set_attr "type" "darith") + (set_attr "mode" "DI") (set_attr "length" "3,2,4")]) (define_split @@ -377,7 +427,7 @@ (plus:DI (match_operand:DI 1 "register_operand" "") (match_operand:DI 2 "small_int" ""))) (clobber (match_operand:SI 3 "register_operand" "=d"))] - "reload_completed && !WORDS_BIG_ENDIAN && !TARGET_DEBUG_G_MODE + "reload_completed && !WORDS_BIG_ENDIAN && !TARGET_DEBUG_D_MODE && !TARGET_DEBUG_G_MODE && GET_CODE (operands[0]) == REG && GP_REG_P (REGNO (operands[0])) && GET_CODE (operands[1]) == REG && GP_REG_P (REGNO (operands[1])) && INTVAL (operands[2]) > 0" @@ -387,7 +437,7 @@ (match_dup 2))) (set (match_dup 3) - (ltu:CC (subreg:SI (match_dup 0) 0) + (ltu:SI (subreg:SI (match_dup 0) 0) (match_dup 2))) (set (subreg:SI (match_dup 0) 1) @@ -400,7 +450,7 @@ (plus:DI (match_operand:DI 1 "register_operand" "") (match_operand:DI 2 "small_int" ""))) (clobber (match_operand:SI 3 "register_operand" "=d"))] - "reload_completed && WORDS_BIG_ENDIAN && !TARGET_DEBUG_G_MODE + "reload_completed && WORDS_BIG_ENDIAN && !TARGET_DEBUG_D_MODE && !TARGET_DEBUG_G_MODE && GET_CODE (operands[0]) == REG && GP_REG_P (REGNO (operands[0])) && GET_CODE (operands[1]) == REG && GP_REG_P (REGNO (operands[1])) && INTVAL (operands[2]) > 0" @@ -410,7 +460,7 @@ (match_dup 2))) (set (match_dup 3) - (ltu:CC (subreg:SI (match_dup 0) 1) + (ltu:SI (subreg:SI (match_dup 0) 1) (match_dup 2))) (set (subreg:SI (match_dup 0) 0) @@ -446,11 +496,22 @@ (set_attr "mode" "SF") (set_attr "length" "1")]) -(define_insn "subsi3" +(define_expand "subsi3" [(set (match_operand:SI 0 "register_operand" "=d") (minus:SI (match_operand:SI 1 "reg_or_0_operand" "dJ") (match_operand:SI 2 "arith_operand" "dI")))] "" + " +{ + if (GET_CODE (operands[2]) == CONST_INT && INTVAL (operands[2]) == -32768) + operands[2] = force_reg (SImode, operands[2]); +}") + +(define_insn "subsi3_internal" + [(set (match_operand:SI 0 "register_operand" "=d") + (minus:SI (match_operand:SI 1 "reg_or_0_operand" "dJ") + (match_operand:SI 2 "arith_operand" "dI")))] + "GET_CODE (operands[2]) != CONST_INT || INTVAL (operands[2]) != -32768" "* { return (GET_CODE (operands[2]) == CONST_INT && INTVAL (operands[2]) < 0) @@ -485,13 +546,13 @@ (minus:DI (match_operand:DI 1 "register_operand" "") (match_operand:DI 2 "register_operand" ""))) (clobber (match_operand:SI 3 "register_operand" ""))] - "reload_completed && !WORDS_BIG_ENDIAN && !TARGET_DEBUG_G_MODE + "reload_completed && !WORDS_BIG_ENDIAN && !TARGET_DEBUG_D_MODE && !TARGET_DEBUG_G_MODE && GET_CODE (operands[0]) == REG && GP_REG_P (REGNO (operands[0])) && GET_CODE (operands[1]) == REG && GP_REG_P (REGNO (operands[1])) && GET_CODE (operands[2]) == REG && GP_REG_P (REGNO (operands[2]))" [(set (match_dup 3) - (ltu:CC (subreg:SI (match_dup 1) 0) + (ltu:SI (subreg:SI (match_dup 1) 0) (subreg:SI (match_dup 2) 0))) (set (subreg:SI (match_dup 0) 0) @@ -512,13 +573,13 @@ (minus:DI (match_operand:DI 1 "register_operand" "") (match_operand:DI 2 "register_operand" ""))) (clobber (match_operand:SI 3 "register_operand" ""))] - "reload_completed && WORDS_BIG_ENDIAN && !TARGET_DEBUG_G_MODE + "reload_completed && WORDS_BIG_ENDIAN && !TARGET_DEBUG_D_MODE && !TARGET_DEBUG_G_MODE && GET_CODE (operands[0]) == REG && GP_REG_P (REGNO (operands[0])) && GET_CODE (operands[1]) == REG && GP_REG_P (REGNO (operands[1])) && GET_CODE (operands[2]) == REG && GP_REG_P (REGNO (operands[2]))" [(set (match_dup 3) - (ltu:CC (subreg:SI (match_dup 1) 1) + (ltu:SI (subreg:SI (match_dup 1) 1) (subreg:SI (match_dup 2) 1))) (set (subreg:SI (match_dup 0) 1) @@ -544,8 +605,8 @@ sltu\\t%3,%L1,%2\;subu\\t%L0,%L1,%2\;subu\\t%M0,%M1,%3 move\\t%L0,%L1\;move\\t%M0,%M1 sltu\\t%3,%L1,%2\;subu\\t%L0,%L1,%2\;subu\\t%M0,%M1,1\;subu\\t%M0,%M0,%3" - [(set_attr "type" "darith,darith,darith") - (set_attr "mode" "DI,DI,DI") + [(set_attr "type" "darith") + (set_attr "mode" "DI") (set_attr "length" "3,2,4")]) (define_split @@ -553,13 +614,13 @@ (minus:DI (match_operand:DI 1 "register_operand" "") (match_operand:DI 2 "small_int" ""))) (clobber (match_operand:SI 3 "register_operand" ""))] - "reload_completed && !WORDS_BIG_ENDIAN && !TARGET_DEBUG_G_MODE + "reload_completed && !WORDS_BIG_ENDIAN && !TARGET_DEBUG_D_MODE && !TARGET_DEBUG_G_MODE && GET_CODE (operands[0]) == REG && GP_REG_P (REGNO (operands[0])) && GET_CODE (operands[1]) == REG && GP_REG_P (REGNO (operands[1])) && INTVAL (operands[2]) > 0" [(set (match_dup 3) - (ltu:CC (subreg:SI (match_dup 1) 0) + (ltu:SI (subreg:SI (match_dup 1) 0) (match_dup 2))) (set (subreg:SI (match_dup 0) 0) @@ -576,13 +637,13 @@ (minus:DI (match_operand:DI 1 "register_operand" "") (match_operand:DI 2 "small_int" ""))) (clobber (match_operand:SI 3 "register_operand" ""))] - "reload_completed && WORDS_BIG_ENDIAN && !TARGET_DEBUG_G_MODE + "reload_completed && WORDS_BIG_ENDIAN && !TARGET_DEBUG_D_MODE && !TARGET_DEBUG_G_MODE && GET_CODE (operands[0]) == REG && GP_REG_P (REGNO (operands[0])) && GET_CODE (operands[1]) == REG && GP_REG_P (REGNO (operands[1])) && INTVAL (operands[2]) > 0" [(set (match_dup 3) - (ltu:CC (subreg:SI (match_dup 1) 1) + (ltu:SI (subreg:SI (match_dup 1) 1) (match_dup 2))) (set (subreg:SI (match_dup 0) 1) @@ -651,7 +712,7 @@ (match_operand:SI 2 "register_operand" ""))) (clobber (reg:SI 64)) (clobber (reg:SI 65))] - "" + "!TARGET_DEBUG_D_MODE" [(parallel [(set (reg:SI 65) ;; low register (mult:SI (match_dup 1) (match_dup 2))) @@ -752,15 +813,15 @@ ;; 65 is the multiply/divide lo register (define_insn "divmodsi4" - [(parallel [(set (match_operand:SI 0 "register_operand" "=d") - (div:SI (match_operand:SI 1 "register_operand" "d") - (match_operand:SI 2 "register_operand" "d"))) - (set (match_operand:SI 3 "register_operand" "=d") - (mod:SI (match_dup 1) - (match_dup 2))) - (clobber (reg:SI 64)) - (clobber (reg:SI 65))])] - "optimize && !TARGET_DEBUG_C_MODE" + [(set (match_operand:SI 0 "register_operand" "=d") + (div:SI (match_operand:SI 1 "register_operand" "d") + (match_operand:SI 2 "register_operand" "d"))) + (set (match_operand:SI 3 "register_operand" "=d") + (mod:SI (match_dup 1) + (match_dup 2))) + (clobber (reg:SI 64)) + (clobber (reg:SI 65))] + "optimize" "* { if (find_reg_note (insn, REG_UNUSED, operands[3])) @@ -776,15 +837,15 @@ (set_attr "length" "13")]) ;; various tests for dividing by 0 and such (define_insn "udivmodsi4" - [(parallel [(set (match_operand:SI 0 "register_operand" "=d") - (udiv:SI (match_operand:SI 1 "register_operand" "d") - (match_operand:SI 2 "register_operand" "d"))) - (set (match_operand:SI 3 "register_operand" "=d") - (umod:SI (match_dup 1) - (match_dup 2))) - (clobber (reg:SI 64)) - (clobber (reg:SI 65))])] - "optimize && !TARGET_DEBUG_C_MODE" + [(set (match_operand:SI 0 "register_operand" "=d") + (udiv:SI (match_operand:SI 1 "register_operand" "d") + (match_operand:SI 2 "register_operand" "d"))) + (set (match_operand:SI 3 "register_operand" "=d") + (umod:SI (match_dup 1) + (match_dup 2))) + (clobber (reg:SI 64)) + (clobber (reg:SI 65))] + "optimize" "* { if (find_reg_note (insn, REG_UNUSED, operands[3])) @@ -805,7 +866,7 @@ (match_operand:SI 2 "register_operand" "d"))) (clobber (reg:SI 64)) (clobber (reg:SI 65))] - "!optimize || TARGET_DEBUG_C_MODE" + "!optimize" "div\\t%0,%1,%2" [(set_attr "type" "idiv") (set_attr "mode" "SI") @@ -817,7 +878,7 @@ (match_operand:SI 2 "register_operand" "d"))) (clobber (reg:SI 64)) (clobber (reg:SI 65))] - "!optimize || TARGET_DEBUG_C_MODE" + "!optimize" "rem\\t%0,%1,%2" [(set_attr "type" "idiv") (set_attr "mode" "SI") @@ -829,7 +890,7 @@ (match_operand:SI 2 "register_operand" "d"))) (clobber (reg:SI 64)) (clobber (reg:SI 65))] - "!optimize || TARGET_DEBUG_C_MODE" + "!optimize" "divu\\t%0,%1,%2" [(set_attr "type" "idiv") (set_attr "mode" "SI") @@ -841,7 +902,7 @@ (match_operand:SI 2 "register_operand" "d"))) (clobber (reg:SI 64)) (clobber (reg:SI 65))] - "!optimize || TARGET_DEBUG_C_MODE" + "!optimize" "remu\\t%0,%1,%2" [(set_attr "type" "idiv") (set_attr "mode" "SI") @@ -932,8 +993,8 @@ (define_insn "ffssi2" [(set (match_operand:SI 0 "register_operand" "=&d") (ffs:SI (match_operand:SI 1 "register_operand" "d"))) - (clobber (match_scratch:SI 2 "d")) - (clobber (match_scratch:SI 3 "d"))] + (clobber (match_scratch:SI 2 "=&d")) + (clobber (match_scratch:SI 3 "=&d"))] "" "* { @@ -1054,7 +1115,7 @@ move\\t%0,%z4\\n\\ (define_split [(set (match_operand:DI 0 "register_operand" "") (not:DI (match_operand:DI 1 "register_operand" "")))] - "reload_completed && !TARGET_DEBUG_G_MODE + "reload_completed && !TARGET_DEBUG_D_MODE && !TARGET_DEBUG_G_MODE && GET_CODE (operands[0]) == REG && GP_REG_P (REGNO (operands[0])) && GET_CODE (operands[1]) == REG && GP_REG_P (REGNO (operands[1]))" @@ -1090,7 +1151,7 @@ move\\t%0,%z4\\n\\ [(set (match_operand:DI 0 "register_operand" "") (not:DI (ior:DI (match_operand:DI 1 "register_operand" "") (match_operand:DI 2 "register_operand" ""))))] - "reload_completed && !TARGET_DEBUG_G_MODE + "reload_completed && !TARGET_DEBUG_D_MODE && !TARGET_DEBUG_G_MODE && GET_CODE (operands[0]) == REG && GP_REG_P (REGNO (operands[0])) && GET_CODE (operands[1]) == REG && GP_REG_P (REGNO (operands[1])) && GET_CODE (operands[2]) == REG && GP_REG_P (REGNO (operands[2]))" @@ -1108,24 +1169,17 @@ move\\t%0,%z4\\n\\ ;; .................... ;; -;; Be more liberal in allowing logical operations than the machine actually -;; supports. This causes better code to be generated for bitfields, since -;; the optimizer can fold things together, at the expense of not moving the -;; constant out of loops. - (define_insn "andsi3" - [(set (match_operand:SI 0 "register_operand" "=d,d,?d,?d") - (and:SI (match_operand:SI 1 "arith32_operand" "%d,d,d,d") - (match_operand:SI 2 "arith32_operand" "d,K,I,M")))] + [(set (match_operand:SI 0 "register_operand" "=d,d") + (and:SI (match_operand:SI 1 "uns_arith_operand" "%d,d") + (match_operand:SI 2 "uns_arith_operand" "d,K")))] "" "@ and\\t%0,%1,%2 - andi\\t%0,%1,%x2 - %[li\\t%@,%X2\;and\\t%0,%1,%@%] - %[li\\t%@,%X2\;and\\t%0,%1,%@%]" - [(set_attr "type" "arith,arith,multi,multi") - (set_attr "mode" "SI,SI,SI,SI") - (set_attr "length" "1,1,2,3")]) + andi\\t%0,%1,%x2" + [(set_attr "type" "arith") + (set_attr "mode" "SI") + (set_attr "length" "1")]) (define_insn "anddi3" [(set (match_operand:DI 0 "register_operand" "=d") @@ -1141,7 +1195,7 @@ move\\t%0,%z4\\n\\ [(set (match_operand:DI 0 "register_operand" "") (and:DI (match_operand:DI 1 "register_operand" "") (match_operand:DI 2 "register_operand" "")))] - "reload_completed && !TARGET_DEBUG_G_MODE + "reload_completed && !TARGET_DEBUG_D_MODE && !TARGET_DEBUG_G_MODE && GET_CODE (operands[0]) == REG && GP_REG_P (REGNO (operands[0])) && GET_CODE (operands[1]) == REG && GP_REG_P (REGNO (operands[1])) && GET_CODE (operands[2]) == REG && GP_REG_P (REGNO (operands[2]))" @@ -1151,18 +1205,16 @@ move\\t%0,%z4\\n\\ "") (define_insn "iorsi3" - [(set (match_operand:SI 0 "register_operand" "=d,d,?d,?d") - (ior:SI (match_operand:SI 1 "arith32_operand" "%d,d,d,d") - (match_operand:SI 2 "arith32_operand" "d,K,I,M")))] + [(set (match_operand:SI 0 "register_operand" "=d,d") + (ior:SI (match_operand:SI 1 "uns_arith_operand" "%d,d") + (match_operand:SI 2 "uns_arith_operand" "d,K")))] "" "@ or\\t%0,%1,%2 - ori\\t%0,%1,%x2 - %[li\\t%@,%X2\;or\\t%0,%1,%@%] - %[li\\t%@,%X2\;or\\t%0,%1,%@%]" - [(set_attr "type" "arith,arith,multi,multi") - (set_attr "mode" "SI,SI,SI,SI") - (set_attr "length" "1,1,2,3")]) + ori\\t%0,%1,%x2" + [(set_attr "type" "arith") + (set_attr "mode" "SI") + (set_attr "length" "1")]) (define_insn "iordi3" [(set (match_operand:DI 0 "register_operand" "=d") @@ -1178,7 +1230,7 @@ move\\t%0,%z4\\n\\ [(set (match_operand:DI 0 "register_operand" "") (ior:DI (match_operand:DI 1 "register_operand" "") (match_operand:DI 2 "register_operand" "")))] - "reload_completed && !TARGET_DEBUG_G_MODE + "reload_completed && !TARGET_DEBUG_D_MODE && !TARGET_DEBUG_G_MODE && GET_CODE (operands[0]) == REG && GP_REG_P (REGNO (operands[0])) && GET_CODE (operands[1]) == REG && GP_REG_P (REGNO (operands[1])) && GET_CODE (operands[2]) == REG && GP_REG_P (REGNO (operands[2]))" @@ -1188,18 +1240,16 @@ move\\t%0,%z4\\n\\ "") (define_insn "xorsi3" - [(set (match_operand:SI 0 "register_operand" "=d,d,?d,?d") - (xor:SI (match_operand:SI 1 "arith32_operand" "%d,d,d,d") - (match_operand:SI 2 "arith32_operand" "d,K,I,M")))] + [(set (match_operand:SI 0 "register_operand" "=d,d") + (xor:SI (match_operand:SI 1 "uns_arith_operand" "%d,d") + (match_operand:SI 2 "uns_arith_operand" "d,K")))] "" "@ xor\\t%0,%1,%2 - xori\\t%0,%1,%x2 - %[li\\t%@,%X2\;xor\\t%0,%1,%@%] - %[li\\t%@,%X2\;xor\\t%0,%1,%@%]" - [(set_attr "type" "arith,arith,multi,multi") - (set_attr "mode" "SI,SI,SI,SI") - (set_attr "length" "1,1,2,3")]) + xori\\t%0,%1,%x2" + [(set_attr "type" "arith") + (set_attr "mode" "SI") + (set_attr "length" "1")]) (define_insn "xordi3" [(set (match_operand:DI 0 "register_operand" "=d") @@ -1215,7 +1265,7 @@ move\\t%0,%z4\\n\\ [(set (match_operand:DI 0 "register_operand" "") (xor:DI (match_operand:DI 1 "register_operand" "") (match_operand:DI 2 "register_operand" "")))] - "reload_completed && !TARGET_DEBUG_G_MODE + "reload_completed && !TARGET_DEBUG_D_MODE && !TARGET_DEBUG_G_MODE && GET_CODE (operands[0]) == REG && GP_REG_P (REGNO (operands[0])) && GET_CODE (operands[1]) == REG && GP_REG_P (REGNO (operands[1])) && GET_CODE (operands[2]) == REG && GP_REG_P (REGNO (operands[2]))" @@ -1265,7 +1315,7 @@ move\\t%0,%z4\\n\\ return mips_move_1word (operands, insn, TRUE); }" [(set_attr "type" "arith,load,load") - (set_attr "mode" "SI,SI,SI") + (set_attr "mode" "SI") (set_attr "length" "1,1,2")]) (define_insn "zero_extendqihi2" @@ -1280,7 +1330,7 @@ move\\t%0,%z4\\n\\ return mips_move_1word (operands, insn, TRUE); }" [(set_attr "type" "arith,load,load") - (set_attr "mode" "HI,HI,HI") + (set_attr "mode" "HI") (set_attr "length" "1,1,2")]) (define_insn "zero_extendqisi2" @@ -1295,7 +1345,7 @@ move\\t%0,%z4\\n\\ return mips_move_1word (operands, insn, TRUE); }" [(set_attr "type" "arith,load,load") - (set_attr "mode" "SI,SI,SI") + (set_attr "mode" "SI") (set_attr "length" "1,1,2")]) @@ -1340,8 +1390,8 @@ move\\t%0,%z4\\n\\ (sign_extend:SI (match_operand:HI 1 "memory_operand" "R,m")))] "" "* return mips_move_1word (operands, insn, FALSE);" - [(set_attr "type" "load,load") - (set_attr "mode" "SI,SI") + [(set_attr "type" "load") + (set_attr "mode" "SI") (set_attr "length" "1,2")]) (define_expand "extendqihi2" @@ -1371,8 +1421,8 @@ move\\t%0,%z4\\n\\ (sign_extend:HI (match_operand:QI 1 "memory_operand" "R,m")))] "" "* return mips_move_1word (operands, insn, FALSE);" - [(set_attr "type" "load,load") - (set_attr "mode" "SI,SI") + [(set_attr "type" "load") + (set_attr "mode" "SI") (set_attr "length" "1,2")]) @@ -1402,8 +1452,8 @@ move\\t%0,%z4\\n\\ (sign_extend:SI (match_operand:QI 1 "memory_operand" "R,m")))] "" "* return mips_move_1word (operands, insn, FALSE);" - [(set_attr "type" "load,load") - (set_attr "mode" "SI,SI") + [(set_attr "type" "load") + (set_attr "mode" "SI") (set_attr "length" "1,2")]) @@ -1425,11 +1475,11 @@ move\\t%0,%z4\\n\\ ;; ;; .................... -(define_insn "fix_truncdfsi2_internal" +(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_operand:SI 2 "register_operand" "d,*d,d,d")) - (clobber (match_operand:DF 3 "register_operand" "f,*f,f,f"))] + (clobber (match_scratch:SI 2 "=d,*d,d,d")) + (clobber (match_scratch:DF 3 "=f,*X,f,f"))] "TARGET_HARD_FLOAT" "* { @@ -1445,30 +1495,16 @@ move\\t%0,%z4\\n\\ output_asm_insn (mips_move_1word (xoperands, insn, FALSE), xoperands); return \"\"; }" - [(set_attr "type" "fcvt,fcvt,fcvt,fcvt") - (set_attr "mode" "DF,DF,DF,DF") - (set_attr "length" "14,12,13,14")]) - - -(define_expand "fix_truncdfsi2" - [(parallel [(set (match_operand:SI 0 "register_operand" "=d") - (fix:SI (match_operand:DF 1 "register_operand" "f"))) - (clobber (match_dup 2)) - (clobber (match_dup 3))])] - "TARGET_HARD_FLOAT" - " -{ - operands[2] = gen_reg_rtx (SImode); /* gp reg that saves FP status bits */ - operands[3] = gen_reg_rtx (DFmode); /* fp reg that gets the conversion */ + [(set_attr "type" "fcvt") + (set_attr "mode" "DF") + (set_attr "length" "11,9,10,11")]) - /* Fall through and generate default code */ -}") -(define_insn "fix_truncsfsi2_internal" +(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_operand:SI 2 "register_operand" "d,*d,d,d")) - (clobber (match_operand:SF 3 "register_operand" "f,*f,f,f"))] + (clobber (match_scratch:SI 2 "=d,*d,d,d")) + (clobber (match_scratch:SF 3 "=f,*X,f,f"))] "TARGET_HARD_FLOAT" "* { @@ -1484,43 +1520,44 @@ move\\t%0,%z4\\n\\ output_asm_insn (mips_move_1word (xoperands, insn, FALSE), xoperands); return \"\"; }" - [(set_attr "type" "fcvt,fcvt,fcvt,fcvt") - (set_attr "mode" "SF,SF,SF,SF") - (set_attr "length" "14,12,13,14")]) + [(set_attr "type" "fcvt") + (set_attr "mode" "SF") + (set_attr "length" "11,9,10,11")]) -(define_expand "fix_truncsfsi2" - [(parallel [(set (match_operand:SI 0 "register_operand" "=f") - (fix:SI (match_operand:SF 1 "register_operand" "f"))) - (clobber (match_dup 2)) - (clobber (match_dup 3))])] +(define_insn "floatsidf2" + [(set (match_operand:DF 0 "register_operand" "=f,f,f") + (float:DF (match_operand:SI 1 "nonimmediate_operand" "d,R,m")))] "TARGET_HARD_FLOAT" - " + "* { - operands[2] = gen_reg_rtx (SImode); /* gp reg that saves FP status bits */ - operands[3] = gen_reg_rtx (SFmode); /* fp reg that gets the conversion */ - - /* Fall through and generate default code */ -}") + dslots_load_total++; + if (GET_CODE (operands[1]) == MEM) + return \"l.s\\t%0,%1%#\;cvt.d.w\\t%0,%0\"; - -(define_insn "floatsidf2" - [(set (match_operand:DF 0 "register_operand" "=f") - (float:DF (match_operand:SI 1 "register_operand" "d")))] - "TARGET_HARD_FLOAT" - "mtc1\\t%1,%0\;cvt.d.w\\t%0,%0" + return \"mtc1\\t%1,%0%#\;cvt.d.w\\t%0,%0\"; +}" [(set_attr "type" "fcvt") (set_attr "mode" "DF") - (set_attr "length" "13")]) + (set_attr "length" "3,4,3")]) + (define_insn "floatsisf2" - [(set (match_operand:SF 0 "register_operand" "=f") - (float:SF (match_operand:SI 1 "register_operand" "d")))] + [(set (match_operand:SF 0 "register_operand" "=f,f,f") + (float:SF (match_operand:SI 1 "nonimmediate_operand" "d,R,m")))] "TARGET_HARD_FLOAT" - "mtc1\\t%1,%0\;cvt.s.w\\t%0,%0" + "* +{ + dslots_load_total++; + if (GET_CODE (operands[1]) == MEM) + return \"l.s\\t%0,%1%#\;cvt.s.w\\t%0,%0\"; + + return \"mtc1\\t%1,%0%#\;cvt.s.w\\t%0,%0\"; +}" [(set_attr "type" "fcvt") (set_attr "mode" "SF") - (set_attr "length" "13")]) + (set_attr "length" "3,4,3")]) + (define_expand "fixuns_truncdfsi2" [(set (match_operand:SI 0 "register_operand" "") @@ -1537,7 +1574,6 @@ move\\t%0,%z4\\n\\ if (reg1) /* turn off complaints about unreached code */ { - extern rtx gen_cmpdf (); emit_move_insn (reg1, immed_real_const_1 (offset, DFmode)); do_pending_stack_adjust (); @@ -1565,6 +1601,7 @@ move\\t%0,%z4\\n\\ } }") + (define_expand "fixuns_truncsfsi2" [(set (match_operand:SI 0 "register_operand" "") (unsigned_fix:SI (match_operand:SF 1 "register_operand" "")))] @@ -1580,7 +1617,6 @@ move\\t%0,%z4\\n\\ if (reg1) /* turn off complaints about unreached code */ { - extern rtx gen_cmpsf (); emit_move_insn (reg1, immed_real_const_1 (offset, SFmode)); do_pending_stack_adjust (); @@ -1624,15 +1660,18 @@ move\\t%0,%z4\\n\\ "" " { - extern rtx force_reg (); - extern rtx gen_movsi_ulw (); - extern rtx gen_movsi (); - - if (GET_CODE (operands[0]) == MEM && !reg_or_0_operand (operands[1], SImode)) + /* Handle loads. */ + if (GET_CODE (operands[0]) == MEM) { rtx reg = gen_reg_rtx (SImode); + rtx insn = emit_insn (gen_movsi_ulw (reg, operands[1])); + rtx addr = XEXP (operands[0], 0); + if (CONSTANT_P (addr)) + REG_NOTES (insn) = gen_rtx (EXPR_LIST, REG_EQUIV, addr, REG_NOTES (insn)); + + if (reg_or_0_operand (operands[1], SImode)) + DONE; - emit_insn (gen_movsi_ulw (reg, operands[1])); operands[1] = reg; } @@ -1653,7 +1692,6 @@ move\\t%0,%z4\\n\\ "" "* { - extern rtx eliminate_constant_term (); enum rtx_code code; char *ret; rtx offset; @@ -1695,7 +1733,7 @@ move\\t%0,%z4\\n\\ return mips_fill_delay_slot (ret, DELAY_LOAD, operands, insn); }" [(set_attr "type" "load,load,move,arith") - (set_attr "mode" "SI,SI,SI,SI") + (set_attr "mode" "SI") (set_attr "length" "2,4,1,2")]) (define_insn "movsi_usw" @@ -1704,7 +1742,6 @@ move\\t%0,%z4\\n\\ "" "* { - extern rtx eliminate_constant_term (); rtx offset = const0_rtx; rtx addr = XEXP (operands[0], 0); rtx mem_addr = eliminate_constant_term (addr, &offset); @@ -1733,29 +1770,51 @@ move\\t%0,%z4\\n\\ return \"usw\\t%z1,%0\"; }" - [(set_attr "type" "load,load") - (set_attr "mode" "SI,SI") + [(set_attr "type" "store") + (set_attr "mode" "SI") (set_attr "length" "2,4")]) + ;; 64-bit integer moves ;; Unlike most other insns, the move insns can't be split with ;; different predicates, because register spilling and other parts of ;; the compiler, have memoized the insn number already. -(define_insn "movdi" +(define_expand "movdi" + [(set (match_operand:DI 0 "nonimmediate_operand" "") + (match_operand:DI 1 "general_operand" ""))] + "" + " +{ + if ((reload_in_progress | reload_completed) == 0 + && !register_operand (operands[0], DImode) + && !register_operand (operands[1], DImode) + && (GET_CODE (operands[1]) != CONST_INT || INTVAL (operands[1]) != 0) + && operands[1] != CONST0_RTX (DImode)) + { + rtx temp = force_reg (DImode, operands[1]); + emit_move_insn (operands[0], temp); + DONE; + } +}") + +(define_insn "movdi_internal" [(set (match_operand:DI 0 "nonimmediate_operand" "=d,d,d,d,R,o,*d,*x") (match_operand:DI 1 "general_operand" "d,iF,R,o,d,d,*x,*d"))] - "" + "register_operand (operands[0], DImode) + || register_operand (operands[1], DImode) + || (GET_CODE (operands[1]) == CONST_INT && INTVAL (operands[1]) == 0) + || operands[1] == CONST0_RTX (DImode)" "* return mips_move_2words (operands, insn); " [(set_attr "type" "move,arith,load,load,store,store,hilo,hilo") - (set_attr "mode" "DI,DI,DI,DI,DI,DI,DI,DI") + (set_attr "mode" "DI") (set_attr "length" "2,4,2,4,2,4,2,2")]) (define_split [(set (match_operand:DI 0 "register_operand" "") (match_operand:DI 1 "register_operand" ""))] - "reload_completed && !TARGET_DEBUG_G_MODE + "reload_completed && !TARGET_DEBUG_D_MODE && !TARGET_DEBUG_G_MODE && GET_CODE (operands[0]) == REG && GP_REG_P (REGNO (operands[0])) && GET_CODE (operands[1]) == REG && GP_REG_P (REGNO (operands[1]))" @@ -1769,7 +1828,7 @@ move\\t%0,%z4\\n\\ (define_split [(set (match_operand:SI 0 "register_operand" "") (match_operand:SI 1 "large_int" ""))] - "" + "!TARGET_DEBUG_D_MODE" [(set (match_dup 0) (match_dup 2)) (set (match_dup 0) @@ -1785,14 +1844,50 @@ move\\t%0,%z4\\n\\ ;; different predicates, because register spilling and other parts of ;; the compiler, have memoized the insn number already. -(define_insn "movsi" - [(set (match_operand:SI 0 "nonimmediate_operand" "=d,d,d,d,d,d,R,m,*d,*fs,*f,*f,*f,*R,*m,*x,*d") - (match_operand:SI 1 "general_operand" "d,S,IKL,Mnis,R,m,dJ,dJ,*fs,*d,*f,*R,*m,*f,*f,*d,*x"))] +(define_expand "movsi" + [(set (match_operand:SI 0 "nonimmediate_operand" "") + (match_operand:SI 1 "general_operand" ""))] "" + " +{ + if ((reload_in_progress | reload_completed) == 0 + && !register_operand (operands[0], SImode) + && !register_operand (operands[1], SImode) + && (GET_CODE (operands[1]) != CONST_INT || INTVAL (operands[1]) != 0)) + { + rtx temp = force_reg (SImode, operands[1]); + emit_move_insn (operands[0], temp); + DONE; + } +}") + +;; The difference between these two is whether or not ints are allowed +;; in FP registers (off by default, use -mdebugh to enable). + +(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,*d") + (match_operand:SI 1 "general_operand" "d,S,IKL,Mnis,R,m,dJ,dJ,*f*z,*d,*f,*R,*m,*f,*f,*d,*x"))] + "TARGET_DEBUG_H_MODE + && (register_operand (operands[0], SImode) + || register_operand (operands[1], SImode) + || (GET_CODE (operands[1]) == CONST_INT && INTVAL (operands[1]) == 0))" "* return mips_move_1word (operands, insn, TRUE);" - [(set_attr "type" "move,pic,arith,arith,load,load,store,store,xfer,xfer,move,load,load,store,store,hilo,hilo") - (set_attr "mode" "SI,SI,SI,SI,SI,SI,SI,SI,SI,SI,SI,SI,SI,SI,SI,SI,SI") - (set_attr "length" "1,4,1,2,1,2,1,2,1,1,1,1,2,1,2,1,1")]) + [(set_attr "type" "move,load,arith,arith,load,load,store,store,xfer,xfer,move,load,load,store,store,hilo,hilo") + (set_attr "mode" "SI") + (set_attr "length" "1,2,1,2,1,2,1,2,1,1,1,1,2,1,2,1,1")]) + +(define_insn "movsi_internal2" + [(set (match_operand:SI 0 "nonimmediate_operand" "=d,d,d,d,d,d,R,m,*d,*z,*d,*x") + (match_operand:SI 1 "general_operand" "d,S,IKL,Mnis,R,m,dJ,dJ,*z,*d,*x,*d"))] + "!TARGET_DEBUG_H_MODE + && (register_operand (operands[0], SImode) + || register_operand (operands[1], SImode) + || (GET_CODE (operands[1]) == CONST_INT && INTVAL (operands[1]) == 0))" + "* return mips_move_1word (operands, insn, TRUE);" + [(set_attr "type" "move,load,arith,arith,load,load,store,store,xfer,xfer,hilo,hilo") + (set_attr "mode" "SI") + (set_attr "length" "1,2,1,2,1,2,1,2,1,1,1,1")]) + ;; 16-bit Integer moves @@ -1801,15 +1896,51 @@ move\\t%0,%z4\\n\\ ;; the compiler, have memoized the insn number already. ;; Unsigned loads are used because BYTE_LOADS_ZERO_EXTEND is defined -(define_insn "movhi" - [(set (match_operand:HI 0 "nonimmediate_operand" "=d,d,d,d,R,m,*d,*f,*f,*x,*d") - (match_operand:HI 1 "general_operand" "d,IK,R,m,dJ,dJ,*fs,*d,*f,*d,*x"))] +(define_expand "movhi" + [(set (match_operand:HI 0 "nonimmediate_operand" "") + (match_operand:HI 1 "general_operand" ""))] "" + " +{ + if ((reload_in_progress | reload_completed) == 0 + && !register_operand (operands[0], HImode) + && !register_operand (operands[1], HImode) + && (GET_CODE (operands[1]) != CONST_INT || INTVAL (operands[1]) != 0)) + { + rtx temp = force_reg (HImode, operands[1]); + emit_move_insn (operands[0], temp); + DONE; + } +}") + +;; The difference between these two is whether or not ints are allowed +;; in FP registers (off by default, use -mdebugh to enable). + +(define_insn "movhi_internal1" + [(set (match_operand:HI 0 "nonimmediate_operand" "=d,d,d,d,R,m,*d,*f,*f*z,*x,*d") + (match_operand:HI 1 "general_operand" "d,IK,R,m,dJ,dJ,*f*z,*d,*f,*d,*x"))] + "TARGET_DEBUG_H_MODE + && (register_operand (operands[0], HImode) + || register_operand (operands[1], HImode) + || (GET_CODE (operands[1]) == CONST_INT && INTVAL (operands[1]) == 0))" "* return mips_move_1word (operands, insn, TRUE);" [(set_attr "type" "move,arith,load,load,store,store,xfer,xfer,move,hilo,hilo") - (set_attr "mode" "HI,HI,HI,HI,HI,HI,HI,HI,HI,HI,HI") + (set_attr "mode" "HI") (set_attr "length" "1,1,1,2,1,2,1,1,1,1,1")]) +(define_insn "movhi_internal2" + [(set (match_operand:HI 0 "nonimmediate_operand" "=d,d,d,d,R,m,*d,*z,*x,*d") + (match_operand:HI 1 "general_operand" "d,IK,R,m,dJ,dJ,*z,*d,*d,*x"))] + "!TARGET_DEBUG_H_MODE + && (register_operand (operands[0], HImode) + || register_operand (operands[1], HImode) + || (GET_CODE (operands[1]) == CONST_INT && INTVAL (operands[1]) == 0))" + "* return mips_move_1word (operands, insn, TRUE);" + [(set_attr "type" "move,arith,load,load,store,store,xfer,xfer,hilo,hilo") + (set_attr "mode" "HI") + (set_attr "length" "1,1,1,2,1,2,1,1,1,1")]) + + ;; 8-bit Integer moves ;; Unlike most other insns, the move insns can't be split with @@ -1817,42 +1948,149 @@ move\\t%0,%z4\\n\\ ;; the compiler, have memoized the insn number already. ;; Unsigned loads are used because BYTE_LOADS_ZERO_EXTEND is defined -(define_insn "movqi" - [(set (match_operand:QI 0 "nonimmediate_operand" "=d,d,d,d,R,m,*d,*f,*f,*x,*d") - (match_operand:QI 1 "general_operand" "d,IK,R,m,dJ,dJ,*fs,*d,*f,*d,*x"))] +(define_expand "movqi" + [(set (match_operand:QI 0 "nonimmediate_operand" "") + (match_operand:QI 1 "general_operand" ""))] "" + " +{ + if ((reload_in_progress | reload_completed) == 0 + && !register_operand (operands[0], QImode) + && !register_operand (operands[1], QImode) + && (GET_CODE (operands[1]) != CONST_INT || INTVAL (operands[1]) != 0)) + { + rtx temp = force_reg (QImode, operands[1]); + emit_move_insn (operands[0], temp); + DONE; + } +}") + +;; The difference between these two is whether or not ints are allowed +;; in FP registers (off by default, use -mdebugh to enable). + +(define_insn "movqi_internal1" + [(set (match_operand:QI 0 "nonimmediate_operand" "=d,d,d,d,R,m,*d,*f*z,*f,*x,*d") + (match_operand:QI 1 "general_operand" "d,IK,R,m,dJ,dJ,*f*z,*d,*f,*d,*x"))] + "TARGET_DEBUG_H_MODE + && (register_operand (operands[0], QImode) + || register_operand (operands[1], QImode) + || (GET_CODE (operands[1]) == CONST_INT && INTVAL (operands[1]) == 0))" "* return mips_move_1word (operands, insn, TRUE);" [(set_attr "type" "move,arith,load,load,store,store,xfer,xfer,move,hilo,hilo") - (set_attr "mode" "QI,QI,QI,QI,QI,QI,QI,QI,QI,QI,QI") + (set_attr "mode" "QI") (set_attr "length" "1,1,1,2,1,2,1,1,1,1,1")]) +(define_insn "movqi_internal2" + [(set (match_operand:QI 0 "nonimmediate_operand" "=d,d,d,d,R,m,*d,*z,*x,*d") + (match_operand:QI 1 "general_operand" "d,IK,R,m,dJ,dJ,*z,*d,*d,*x"))] + "!TARGET_DEBUG_H_MODE + && (register_operand (operands[0], QImode) + || register_operand (operands[1], QImode) + || (GET_CODE (operands[1]) == CONST_INT && INTVAL (operands[1]) == 0))" + "* return mips_move_1word (operands, insn, TRUE);" + [(set_attr "type" "move,arith,load,load,store,store,xfer,xfer,hilo,hilo") + (set_attr "mode" "QI") + (set_attr "length" "1,1,1,2,1,2,1,1,1,1")]) + ;; 32-bit floating point moves -(define_insn "movsf" - [(set (match_operand:SF 0 "nonimmediate_operand" "=f,f,f,f,R,m,*f,*d,*d,*d,*d,*R,*m") - (match_operand:SF 1 "general_operand" "f,G,R,Em,fG,fG,*d,*f,*Gd,*R,*Em,*d,*d"))] +(define_expand "movsf" + [(set (match_operand:SF 0 "nonimmediate_operand" "") + (match_operand:SF 1 "general_operand" ""))] "" + " +{ + if ((reload_in_progress | reload_completed) == 0 + && !register_operand (operands[0], SFmode) + && !register_operand (operands[1], SFmode) + && (GET_CODE (operands[1]) != CONST_INT || INTVAL (operands[1]) != 0) + && operands[1] != CONST0_RTX (SFmode)) + { + rtx temp = force_reg (SFmode, operands[1]); + emit_move_insn (operands[0], temp); + DONE; + } +}") + +(define_insn "movsf_internal1" + [(set (match_operand:SF 0 "nonimmediate_operand" "=f,f,f,f,R,m,*f,*d,*d,*d,*d,*R,*m") + (match_operand:SF 1 "general_operand" "f,G,R,Em,fG,fG,*d,*f,*G*d,*R,*E*m,*d,*d"))] + "TARGET_HARD_FLOAT + && (register_operand (operands[0], SFmode) + || register_operand (operands[1], SFmode) + || (GET_CODE (operands[1]) == CONST_INT && INTVAL (operands[1]) == 0) + || operands[1] == CONST0_RTX (SFmode))" "* return mips_move_1word (operands, insn, FALSE);" [(set_attr "type" "move,xfer,load,load,store,store,xfer,xfer,move,load,load,store,store") - (set_attr "mode" "SF,SF,SF,SF,SF,SF,SF,SF,SF,SF,SF,SF,SF") + (set_attr "mode" "SF") (set_attr "length" "1,1,1,2,1,2,1,1,1,1,2,1,2")]) + +(define_insn "movsf_internal2" + [(set (match_operand:SF 0 "nonimmediate_operand" "=d,d,d,R,m") + (match_operand:SF 1 "general_operand" " Gd,R,Em,d,d"))] + "TARGET_SOFT_FLOAT + && (register_operand (operands[0], SFmode) + || register_operand (operands[1], SFmode) + || (GET_CODE (operands[1]) == CONST_INT && INTVAL (operands[1]) == 0) + || operands[1] == CONST0_RTX (SFmode))" + "* return mips_move_1word (operands, insn, FALSE);" + [(set_attr "type" "move,load,load,store,store") + (set_attr "mode" "SF") + (set_attr "length" "1,1,2,1,2")]) + + ;; 64-bit floating point moves -(define_insn "movdf" - [(set (match_operand:DF 0 "nonimmediate_operand" "=f,f,f,R,o,f,*f,*d,*d,*d,*d,*R,*o") - (match_operand:DF 1 "general_operand" "f,R,o,fG,fG,E,*d,*f,*dG,*R,*oE,*d,*d"))] +(define_expand "movdf" + [(set (match_operand:DF 0 "nonimmediate_operand" "") + (match_operand:DF 1 "general_operand" ""))] "" + " +{ + if ((reload_in_progress | reload_completed) == 0 + && !register_operand (operands[0], DFmode) + && !register_operand (operands[1], DFmode) + && (GET_CODE (operands[1]) != CONST_INT || INTVAL (operands[1]) != 0) + && operands[1] != CONST0_RTX (DFmode)) + { + rtx temp = force_reg (DFmode, operands[1]); + emit_move_insn (operands[0], temp); + DONE; + } +}") + +(define_insn "movdf_internal1" + [(set (match_operand:DF 0 "nonimmediate_operand" "=f,f,f,R,o,f,*f,*d,*d,*d,*d,*R,*o") + (match_operand:DF 1 "general_operand" "f,R,o,fG,fG,E,*d,*f,*d*G,*R,*o*E,*d,*d"))] + "TARGET_HARD_FLOAT + && (register_operand (operands[0], DFmode) + || register_operand (operands[1], DFmode) + || (GET_CODE (operands[1]) == CONST_INT && INTVAL (operands[1]) == 0) + || operands[1] == CONST0_RTX (DFmode))" "* return mips_move_2words (operands, insn); " [(set_attr "type" "move,load,load,store,store,load,xfer,xfer,move,load,load,store,store") - (set_attr "mode" "DF,DF,DF,DF,DF,DF,DF,DF,DF,DF,DF,DF,DF") + (set_attr "mode" "DF") (set_attr "length" "1,2,4,2,4,4,2,2,2,2,4,2,4")]) +(define_insn "movdf_internal2" + [(set (match_operand:DF 0 "nonimmediate_operand" "=d,d,d,R,o") + (match_operand:DF 1 "general_operand" "dG,R,oE,d,d"))] + "TARGET_SOFT_FLOAT + && (register_operand (operands[0], DFmode) + || register_operand (operands[1], DFmode) + || (GET_CODE (operands[1]) == CONST_INT && INTVAL (operands[1]) == 0) + || operands[1] == CONST0_RTX (DFmode))" + "* return mips_move_2words (operands, insn); " + [(set_attr "type" "move,load,load,store,store") + (set_attr "mode" "DF") + (set_attr "length" "2,2,4,2,4")]) + (define_split [(set (match_operand:DF 0 "register_operand" "") (match_operand:DF 1 "register_operand" ""))] - "reload_completed && !TARGET_DEBUG_G_MODE + "reload_completed && !TARGET_DEBUG_D_MODE && !TARGET_DEBUG_G_MODE && GET_CODE (operands[0]) == REG && GP_REG_P (REGNO (operands[0])) && GET_CODE (operands[1]) == REG && GP_REG_P (REGNO (operands[1]))" @@ -1860,6 +2098,7 @@ move\\t%0,%z4\\n\\ (set (subreg:SI (match_dup 0) 1) (subreg:SI (match_dup 1) 1))] "") + ;; Block moves, see mips.c for more details. ;; Argument 0 is the destination ;; Argument 1 is the source @@ -1881,6 +2120,99 @@ 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 + (clobber (match_scratch:SI 4 "=&d")) ;; temp 1 + (clobber (match_scratch:SI 5 "=&d")) ;; temp 2 + (clobber (match_scratch:SI 6 "=&d")) ;; temp 3 + (clobber (match_scratch:SI 7 "=&d")) ;; temp 4 + (use (match_operand:SI 2 "small_int" "I")) ;; # bytes to move + (use (match_operand:SI 3 "small_int" "I")) ;; alignment + (use (const_int 0))] ;; normal block move + "" + "* return output_block_move (insn, operands, 4, BLOCK_MOVE_NORMAL);" + [(set_attr "type" "multi") + (set_attr "mode" "none") + (set_attr "length" "20")]) + +;; Split a block move into 2 parts, the first part is everything +;; except for the last move, and the second part is just the last +;; store, which is exactly 1 instruction (ie, not a usw), so it can +;; fill a delay slot. This also prevents a bug in delayed branches +;; from showing up, which reuses one of the registers in our clobbers. + +(define_split + [(set (mem:BLK (match_operand:SI 0 "register_operand" "")) + (mem:BLK (match_operand:SI 1 "register_operand" ""))) + (clobber (match_operand:SI 4 "register_operand" "")) + (clobber (match_operand:SI 5 "register_operand" "")) + (clobber (match_operand:SI 6 "register_operand" "")) + (clobber (match_operand:SI 7 "register_operand" "")) + (use (match_operand:SI 2 "small_int" "")) + (use (match_operand:SI 3 "small_int" "")) + (use (const_int 0))] + + "reload_completed && !TARGET_DEBUG_D_MODE && INTVAL (operands[2]) > 0" + + ;; All but the last move + [(parallel [(set (mem:BLK (match_dup 0)) + (mem:BLK (match_dup 1))) + (clobber (match_dup 4)) + (clobber (match_dup 5)) + (clobber (match_dup 6)) + (clobber (match_dup 7)) + (use (match_dup 2)) + (use (match_dup 3)) + (use (const_int 1))]) + + ;; The last store, so it can fill a delay slot + (parallel [(set (mem:BLK (match_dup 0)) + (mem:BLK (match_dup 1))) + (clobber (match_dup 4)) + (clobber (match_dup 5)) + (clobber (match_dup 6)) + (clobber (match_dup 7)) + (use (match_dup 2)) + (use (match_dup 3)) + (use (const_int 2))])] + + "") + +(define_insn "movstrsi_internal2" + [(set (match_operand:BLK 0 "memory_operand" "=Ro") ;; destination + (match_operand:BLK 1 "memory_operand" "Ro")) ;; 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 + (clobber (match_scratch:SI 7 "=&d")) ;; temp 4 + (use (match_operand:SI 2 "small_int" "I")) ;; # bytes to move + (use (match_operand:SI 3 "small_int" "I")) ;; alignment + (use (const_int 1))] ;; all but last store + "" + "* return output_block_move (insn, operands, 4, BLOCK_MOVE_NOT_LAST);" + [(set_attr "type" "multi") + (set_attr "mode" "none") + (set_attr "length" "20")]) + +(define_insn "movstrsi_internal3" + [(set (match_operand:BLK 0 "memory_operand" "=Ro") ;; destination + (match_operand:BLK 1 "memory_operand" "Ro")) ;; 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 + (clobber (match_scratch:SI 7 "=&d")) ;; temp 4 + (use (match_operand:SI 2 "small_int" "I")) ;; # bytes to move + (use (match_operand:SI 3 "small_int" "I")) ;; alignment + (use (const_int 2))] ;; just last store of block mvoe + "" + "* return output_block_move (insn, operands, 4, BLOCK_MOVE_LAST);" + [(set_attr "type" "store") + (set_attr "mode" "none") + (set_attr "length" "1")]) + ;; ;; .................... @@ -1916,7 +2248,7 @@ move\\t%0,%z4\\n\\ (define_insn "ashldi3_internal" - [(set (match_operand:DI 0 "register_operand" "=d") + [(set (match_operand:DI 0 "register_operand" "=&d") (ashift:DI (match_operand:DI 1 "register_operand" "d") (match_operand:SI 2 "register_operand" "d"))) (clobber (match_operand:SI 3 "register_operand" "=d"))] @@ -1971,7 +2303,7 @@ move\\t%0,%z4\\n\\ (ashift:DI (match_operand:DI 1 "register_operand" "") (match_operand:SI 2 "small_int" ""))) (clobber (match_operand:SI 3 "register_operand" ""))] - "reload_completed && !WORDS_BIG_ENDIAN && !TARGET_DEBUG_G_MODE + "reload_completed && !WORDS_BIG_ENDIAN && !TARGET_DEBUG_D_MODE && !TARGET_DEBUG_G_MODE && GET_CODE (operands[0]) == REG && REGNO (operands[0]) < FIRST_PSEUDO_REGISTER && GET_CODE (operands[1]) == REG && REGNO (operands[1]) < FIRST_PSEUDO_REGISTER && (INTVAL (operands[2]) & 32) != 0" @@ -1987,7 +2319,7 @@ move\\t%0,%z4\\n\\ (ashift:DI (match_operand:DI 1 "register_operand" "") (match_operand:SI 2 "small_int" ""))) (clobber (match_operand:SI 3 "register_operand" ""))] - "reload_completed && WORDS_BIG_ENDIAN && !TARGET_DEBUG_G_MODE + "reload_completed && WORDS_BIG_ENDIAN && !TARGET_DEBUG_D_MODE && !TARGET_DEBUG_G_MODE && GET_CODE (operands[0]) == REG && REGNO (operands[0]) < FIRST_PSEUDO_REGISTER && GET_CODE (operands[1]) == REG && REGNO (operands[1]) < FIRST_PSEUDO_REGISTER && (INTVAL (operands[2]) & 32) != 0" @@ -2026,7 +2358,7 @@ move\\t%0,%z4\\n\\ (ashift:DI (match_operand:DI 1 "register_operand" "") (match_operand:SI 2 "small_int" ""))) (clobber (match_operand:SI 3 "register_operand" ""))] - "reload_completed && !WORDS_BIG_ENDIAN && !TARGET_DEBUG_G_MODE + "reload_completed && !WORDS_BIG_ENDIAN && !TARGET_DEBUG_D_MODE && !TARGET_DEBUG_G_MODE && GET_CODE (operands[0]) == REG && REGNO (operands[0]) < FIRST_PSEUDO_REGISTER && GET_CODE (operands[1]) == REG && REGNO (operands[1]) < FIRST_PSEUDO_REGISTER && (INTVAL (operands[2]) & 63) < 32 @@ -2060,7 +2392,7 @@ move\\t%0,%z4\\n\\ (ashift:DI (match_operand:DI 1 "register_operand" "") (match_operand:SI 2 "small_int" ""))) (clobber (match_operand:SI 3 "register_operand" ""))] - "reload_completed && WORDS_BIG_ENDIAN && !TARGET_DEBUG_G_MODE + "reload_completed && WORDS_BIG_ENDIAN && !TARGET_DEBUG_D_MODE && !TARGET_DEBUG_G_MODE && GET_CODE (operands[0]) == REG && REGNO (operands[0]) < FIRST_PSEUDO_REGISTER && GET_CODE (operands[1]) == REG && REGNO (operands[1]) < FIRST_PSEUDO_REGISTER && (INTVAL (operands[2]) & 63) < 32 @@ -2116,7 +2448,7 @@ move\\t%0,%z4\\n\\ (define_insn "ashrdi3_internal" - [(set (match_operand:DI 0 "register_operand" "=d") + [(set (match_operand:DI 0 "register_operand" "=&d") (ashiftrt:DI (match_operand:DI 1 "register_operand" "d") (match_operand:SI 2 "register_operand" "d"))) (clobber (match_operand:SI 3 "register_operand" "=d"))] @@ -2170,7 +2502,7 @@ move\\t%0,%z4\\n\\ (ashiftrt:DI (match_operand:DI 1 "register_operand" "") (match_operand:SI 2 "small_int" ""))) (clobber (match_operand:SI 3 "register_operand" ""))] - "reload_completed && !WORDS_BIG_ENDIAN && !TARGET_DEBUG_G_MODE + "reload_completed && !WORDS_BIG_ENDIAN && !TARGET_DEBUG_D_MODE && !TARGET_DEBUG_G_MODE && GET_CODE (operands[0]) == REG && REGNO (operands[0]) < FIRST_PSEUDO_REGISTER && GET_CODE (operands[1]) == REG && REGNO (operands[1]) < FIRST_PSEUDO_REGISTER && (INTVAL (operands[2]) & 32) != 0" @@ -2186,7 +2518,7 @@ move\\t%0,%z4\\n\\ (ashiftrt:DI (match_operand:DI 1 "register_operand" "") (match_operand:SI 2 "small_int" ""))) (clobber (match_operand:SI 3 "register_operand" ""))] - "reload_completed && WORDS_BIG_ENDIAN && !TARGET_DEBUG_G_MODE + "reload_completed && WORDS_BIG_ENDIAN && !TARGET_DEBUG_D_MODE && !TARGET_DEBUG_G_MODE && GET_CODE (operands[0]) == REG && REGNO (operands[0]) < FIRST_PSEUDO_REGISTER && GET_CODE (operands[1]) == REG && REGNO (operands[1]) < FIRST_PSEUDO_REGISTER && (INTVAL (operands[2]) & 32) != 0" @@ -2224,7 +2556,7 @@ move\\t%0,%z4\\n\\ (ashiftrt:DI (match_operand:DI 1 "register_operand" "") (match_operand:SI 2 "small_int" ""))) (clobber (match_operand:SI 3 "register_operand" ""))] - "reload_completed && !WORDS_BIG_ENDIAN && !TARGET_DEBUG_G_MODE + "reload_completed && !WORDS_BIG_ENDIAN && !TARGET_DEBUG_D_MODE && !TARGET_DEBUG_G_MODE && GET_CODE (operands[0]) == REG && REGNO (operands[0]) < FIRST_PSEUDO_REGISTER && GET_CODE (operands[1]) == REG && REGNO (operands[1]) < FIRST_PSEUDO_REGISTER && (INTVAL (operands[2]) & 63) < 32 @@ -2258,7 +2590,7 @@ move\\t%0,%z4\\n\\ (ashiftrt:DI (match_operand:DI 1 "register_operand" "") (match_operand:SI 2 "small_int" ""))) (clobber (match_operand:SI 3 "register_operand" ""))] - "reload_completed && WORDS_BIG_ENDIAN && !TARGET_DEBUG_G_MODE + "reload_completed && WORDS_BIG_ENDIAN && !TARGET_DEBUG_D_MODE && !TARGET_DEBUG_G_MODE && GET_CODE (operands[0]) == REG && REGNO (operands[0]) < FIRST_PSEUDO_REGISTER && GET_CODE (operands[1]) == REG && REGNO (operands[1]) < FIRST_PSEUDO_REGISTER && (INTVAL (operands[2]) & 63) < 32 @@ -2369,7 +2701,7 @@ move\\t%0,%z4\\n\\ (lshiftrt:DI (match_operand:DI 1 "register_operand" "") (match_operand:SI 2 "small_int" ""))) (clobber (match_operand:SI 3 "register_operand" ""))] - "reload_completed && !WORDS_BIG_ENDIAN && !TARGET_DEBUG_G_MODE + "reload_completed && !WORDS_BIG_ENDIAN && !TARGET_DEBUG_D_MODE && !TARGET_DEBUG_G_MODE && GET_CODE (operands[0]) == REG && REGNO (operands[0]) < FIRST_PSEUDO_REGISTER && GET_CODE (operands[1]) == REG && REGNO (operands[1]) < FIRST_PSEUDO_REGISTER && (INTVAL (operands[2]) & 32) != 0" @@ -2385,7 +2717,7 @@ move\\t%0,%z4\\n\\ (lshiftrt:DI (match_operand:DI 1 "register_operand" "") (match_operand:SI 2 "small_int" ""))) (clobber (match_operand:SI 3 "register_operand" ""))] - "reload_completed && WORDS_BIG_ENDIAN && !TARGET_DEBUG_G_MODE + "reload_completed && WORDS_BIG_ENDIAN && !TARGET_DEBUG_D_MODE && !TARGET_DEBUG_G_MODE && GET_CODE (operands[0]) == REG && REGNO (operands[0]) < FIRST_PSEUDO_REGISTER && GET_CODE (operands[1]) == REG && REGNO (operands[1]) < FIRST_PSEUDO_REGISTER && (INTVAL (operands[2]) & 32) != 0" @@ -2423,7 +2755,7 @@ move\\t%0,%z4\\n\\ (lshiftrt:DI (match_operand:DI 1 "register_operand" "") (match_operand:SI 2 "small_int" ""))) (clobber (match_operand:SI 3 "register_operand" ""))] - "reload_completed && !WORDS_BIG_ENDIAN && !TARGET_DEBUG_G_MODE + "reload_completed && !WORDS_BIG_ENDIAN && !TARGET_DEBUG_D_MODE && !TARGET_DEBUG_G_MODE && GET_CODE (operands[0]) == REG && REGNO (operands[0]) < FIRST_PSEUDO_REGISTER && GET_CODE (operands[1]) == REG && REGNO (operands[1]) < FIRST_PSEUDO_REGISTER && (INTVAL (operands[2]) & 63) < 32 @@ -2457,7 +2789,7 @@ move\\t%0,%z4\\n\\ (lshiftrt:DI (match_operand:DI 1 "register_operand" "") (match_operand:SI 2 "small_int" ""))) (clobber (match_operand:SI 3 "register_operand" ""))] - "reload_completed && WORDS_BIG_ENDIAN && !TARGET_DEBUG_G_MODE + "reload_completed && WORDS_BIG_ENDIAN && !TARGET_DEBUG_D_MODE && !TARGET_DEBUG_G_MODE && GET_CODE (operands[0]) == REG && REGNO (operands[0]) < FIRST_PSEUDO_REGISTER && GET_CODE (operands[1]) == REG && REGNO (operands[1]) < FIRST_PSEUDO_REGISTER && (INTVAL (operands[2]) & 63) < 32 @@ -2505,14 +2837,9 @@ move\\t%0,%z4\\n\\ ;; done, so that we can constrain things appropriately. There ;; are assumptions in the rest of GCC that break if we fold the ;; operands into the branchs for integer operations, and use cc0 -;; for floating point. -;; -;; 3) The compare define_insns then once again set branch_cmp and -;; branch_type, and the branch define_insns use them. -;; -;; 4) If a set condition code is done instead of a branch, then the -;; operands are folded into the RTL, and a separate set of cc0 is -;; not done. This allows slt's to be put into delay slots. +;; for floating point, so we use the fp status register instead. +;; If needed, an appropriate temporary is created to hold the +;; of the integer compare. (define_expand "cmpsi" [(set (cc0) @@ -2545,53 +2872,6 @@ move\\t%0,%z4\\n\\ } }") -(define_insn "cmpsi_eqne" - [(set (cc0) - (compare:CC_EQ (match_operand:SI 0 "register_operand" "dJ") - (match_operand:SI 1 "reg_or_0_operand" "dJ")))] - "" - "* -{ - branch_cmp[0] = operands[0]; - branch_cmp[1] = operands[1]; - branch_type = CMP_SI; - return \"\"; -}" - [(set_attr "type" "icmp") - (set_attr "mode" "none") - (set_attr "length" "0")]) - -(define_insn "cmpsi_zero" - [(set (cc0) - (match_operand:SI 0 "reg_or_0_operand" "dJ"))] - "" - "* -{ - branch_cmp[0] = operands[0]; - branch_cmp[1] = const0_rtx; - branch_type = CMP_SI; - return \"\"; -}" - [(set_attr "type" "icmp") - (set_attr "mode" "none") - (set_attr "length" "0")]) - -(define_insn "cmpsi_relational" - [(set (cc0) - (compare:CC (match_operand:SI 0 "register_operand" "dJ") - (match_operand:SI 1 "arith_operand" "dI")))] - "" - "* -{ - branch_cmp[0] = operands[0]; - branch_cmp[1] = operands[1]; - branch_type = CMP_SI; - return \"\"; -}" - [(set_attr "type" "icmp") - (set_attr "mode" "none") - (set_attr "length" "0")]) - (define_expand "cmpdf" [(set (cc0) (compare:CC_FP (match_operand:DF 0 "register_operand" "") @@ -2608,23 +2888,6 @@ move\\t%0,%z4\\n\\ } }") -(define_insn "cmpdf_internal" - [(set (cc0) - (compare:CC_FP (match_operand:DF 0 "register_operand" "f") - (match_operand:DF 1 "register_operand" "f")))] - "TARGET_HARD_FLOAT" - "* -{ - branch_cmp[0] = operands[0]; - branch_cmp[1] = operands[1]; - branch_type = CMP_DF; - return \"\"; -}" - [(set_attr "type" "fcmp") - (set_attr "mode" "none") - (set_attr "length" "0")]) - - (define_expand "cmpsf" [(set (cc0) (compare:CC_FP (match_operand:SF 0 "register_operand" "") @@ -2641,22 +2904,6 @@ move\\t%0,%z4\\n\\ } }") -(define_insn "cmpsf_internal" - [(set (cc0) - (compare:CC_FP (match_operand:SF 0 "register_operand" "f") - (match_operand:SF 1 "register_operand" "f")))] - "TARGET_HARD_FLOAT" - "* -{ - branch_cmp[0] = operands[0]; - branch_cmp[1] = operands[1]; - branch_type = CMP_SF; - return \"\"; -}" - [(set_attr "type" "fcmp") - (set_attr "mode" "none") - (set_attr "length" "0")]) - ;; ;; .................... @@ -2665,224 +2912,135 @@ move\\t%0,%z4\\n\\ ;; ;; .................... -;; We really can't note that integer branches clobber $at, and FP -;; branches clobber $fcr31 because if we use a parallel operation, a -;; normal insn is used to hold the value instead of jump_insn. See -;; above for cmpxx saving the operands in branch_cmp and branch_type. - -(define_insn "branch_fp_true" +(define_insn "branch_fp_ne" [(set (pc) - (if_then_else (match_operator:CC_FP 0 "fcmp_op" [(cc0) (const_int 0)]) - (label_ref (match_operand 1 "" "")) - (pc)))] + (if_then_else (ne:CC_FP (reg:CC_FP 66) + (const_int 0)) + (match_operand 0 "pc_or_label_operand" "") + (match_operand 1 "pc_or_label_operand" "")))] "" "* { - operands[2] = branch_cmp[0]; - operands[3] = branch_cmp[1]; - mips_branch_likely = (final_sequence && INSN_ANNULLED_BRANCH_P (insn)); - if (branch_type == CMP_DF) - { - switch (GET_CODE (operands[0])) - { - case EQ: return \"c.eq.d\\t%2,%3%#\;%*bc1t%?\\t%l1\"; - case NE: return \"c.eq.d\\t%2,%3%#\;%*bc1f%?\\t%l1\"; - case LT: return \"c.lt.d\\t%2,%3%#\;%*bc1t%?\\t%l1\"; - case LE: return \"c.le.d\\t%2,%3%#\;%*bc1t%?\\t%l1\"; - case GT: return \"c.lt.d\\t%3,%2%#\;%*bc1t%?\\t%l1\"; - case GE: return \"c.le.d\\t%3,%2%#\;%*bc1t%?\\t%l1\"; - } - } - - else if (branch_type == CMP_SF) - { - switch (GET_CODE (operands[0])) - { - case EQ: return \"c.eq.s\\t%2,%3%#\;%*bc1t%?\\t%l1\"; - case NE: return \"c.eq.s\\t%2,%3%#\;%*bc1f%?\\t%l1\"; - case LT: return \"c.lt.s\\t%2,%3%#\;%*bc1t%?\\t%l1\"; - case LE: return \"c.le.s\\t%2,%3%#\;%*bc1t%?\\t%l1\"; - case GT: return \"c.lt.s\\t%3,%2%#\;%*bc1t%?\\t%l1\"; - case GE: return \"c.le.s\\t%3,%2%#\;%*bc1t%?\\t%l1\"; - } - } - - abort_with_insn (insn, \"Bad floating compare/branch\"); - return (char *)0; + return (operands[0] != pc_rtx) ? \"%*bc1t%?\\t%0\" : \"%*bc1f%?\\t%1\"; }" [(set_attr "type" "branch") (set_attr "mode" "none") - (set_attr "length" "3")]) + (set_attr "length" "1")]) -(define_insn "branch_fp_false" +(define_insn "branch_fp_ne_rev" [(set (pc) - (if_then_else (match_operator:CC_FP 0 "fcmp_op" [(cc0) (const_int 0)]) - (pc) - (label_ref (match_operand 1 "" ""))))] + (if_then_else (ne:CC_REV_FP (reg:CC_REV_FP 66) + (const_int 0)) + (match_operand 0 "pc_or_label_operand" "") + (match_operand 1 "pc_or_label_operand" "")))] "" "* { - operands[2] = branch_cmp[0]; - operands[3] = branch_cmp[1]; - mips_branch_likely = (final_sequence && INSN_ANNULLED_BRANCH_P (insn)); - if (branch_type == CMP_DF) - { - switch (GET_CODE (operands[0])) - { - case EQ: return \"c.eq.d\\t%2,%3%#\;%*bc1f%?\\t%l1\"; - case NE: return \"c.eq.d\\t%2,%3%#\;%*bc1t%?\\t%l1\"; - case LT: return \"c.lt.d\\t%2,%3%#\;%*bc1f%?\\t%l1\"; - case LE: return \"c.le.d\\t%2,%3%#\;%*bc1f%?\\t%l1\"; - case GT: return \"c.lt.d\\t%3,%2%#\;%*bc1f%?\\t%l1\"; - case GE: return \"c.le.d\\t%3,%2%#\;%*bc1f%?\\t%l1\"; - } - } - - else if (branch_type == CMP_SF) - { - switch (GET_CODE (operands[0])) - { - case EQ: return \"c.eq.s\\t%2,%3%#\;%*bc1f%?\\t%l1\"; - case NE: return \"c.eq.s\\t%2,%3%#\;%*bc1t%?\\t%l1\"; - case LT: return \"c.lt.s\\t%2,%3%#\;%*bc1f%?\\t%l1\"; - case LE: return \"c.le.s\\t%2,%3%#\;%*bc1f%?\\t%l1\"; - case GT: return \"c.lt.s\\t%3,%2%#\;%*bc1f%?\\t%l1\"; - case GE: return \"c.le.s\\t%3,%2%#\;%*bc1f%?\\t%l1\"; - } - } - - abort_with_insn (insn, \"Bad floating compare/branch\"); - return (char *)0; + return (operands[0] != pc_rtx) ? \"%*bc1f%?\\t%0\" : \"%*bc1t%?\\t%1\"; }" [(set_attr "type" "branch") (set_attr "mode" "none") - (set_attr "length" "3")]) - + (set_attr "length" "1")]) -(define_insn "branch_eqne_true" +(define_insn "branch_fp_eq" [(set (pc) - (if_then_else (match_operator:CC_EQ 0 "equality_op" [(cc0) (const_int 0)]) - (label_ref (match_operand 1 "" "")) - (pc)))] + (if_then_else (eq:CC_FP (reg:CC_FP 66) + (const_int 0)) + (match_operand 0 "pc_or_label_operand" "") + (match_operand 1 "pc_or_label_operand" "")))] "" "* { mips_branch_likely = (final_sequence && INSN_ANNULLED_BRANCH_P (insn)); - operands[2] = branch_cmp[0]; - operands[3] = branch_cmp[1]; - return \"%*b%C0%?\\t%z2,%z3,%1\"; + return (operands[0] != pc_rtx) ? \"%*bc1f%?\\t%0\" : \"%*bc1t%?\\t%1\"; }" [(set_attr "type" "branch") (set_attr "mode" "none") (set_attr "length" "1")]) -(define_insn "branch_eqne_false" +(define_insn "branch_fp_eq_rev" [(set (pc) - (if_then_else (match_operator:CC_EQ 0 "equality_op" [(cc0) (const_int 0)]) - (pc) - (label_ref (match_operand 1 "" ""))))] + (if_then_else (eq:CC_REV_FP (reg:CC_REV_FP 66) + (const_int 0)) + (match_operand 0 "pc_or_label_operand" "") + (match_operand 1 "pc_or_label_operand" "")))] "" "* { mips_branch_likely = (final_sequence && INSN_ANNULLED_BRANCH_P (insn)); - operands[2] = branch_cmp[0]; - operands[3] = branch_cmp[1]; - return \"%*b%N0%?\\t%z2,%z3,%1\"; + return (operands[0] != pc_rtx) ? \"%*bc1t%?\\t%0\" : \"%*bc1f%?\\t%1\"; }" [(set_attr "type" "branch") (set_attr "mode" "none") (set_attr "length" "1")]) -(define_insn "branch_zero_true" + +(define_insn "branch_zero" [(set (pc) - (if_then_else (match_operator:CC_0 0 "cmp_op" [(cc0) (const_int 0)]) - (label_ref (match_operand 1 "" "")) - (pc)))] + (if_then_else (match_operator:SI 0 "cmp_op" + [(match_operand:SI 1 "register_operand" "d") + (const_int 0)]) + (match_operand 2 "pc_or_label_operand" "") + (match_operand 3 "pc_or_label_operand" "")))] "" "* { mips_branch_likely = (final_sequence && INSN_ANNULLED_BRANCH_P (insn)); - operands[2] = branch_cmp[0]; + if (operands[2] != pc_rtx) + { /* normal jump */ + switch (GET_CODE (operands[0])) + { + case EQ: return \"%*beq%?\\t%z1,%.,%2\"; + case NE: return \"%*bne%?\\t%z1,%.,%2\"; + case GTU: return \"%*bne%?\\t%z1,%.,%2\"; + case LEU: return \"%*beq%?\\t%z1,%.,%2\"; + case GEU: return \"%*j\\t%2\"; + case LTU: return \"%*bne%?\\t%.,%.,%2\"; + } - switch (GET_CODE (operands[0])) - { - case EQ: return \"%*beq%?\\t%z2,%.,%1\"; - case NE: return \"%*bne%?\\t%z2,%.,%1\"; - case GTU: return \"%*bne%?\\t%z2,%.,%1\"; - case LEU: return \"%*beq%?\\t%z2,%.,%1\"; - case GEU: return \"%*j\\t%1\"; - case LTU: return \"#%*bltuz\\t%z2,%1\"; + return \"%*b%C0z%?\\t%z1,%2\"; } + else + { /* inverted jump */ + switch (GET_CODE (operands[0])) + { + case EQ: return \"%*bne%?\\t%z1,%.,%3\"; + case NE: return \"%*beq%?\\t%z1,%.,%3\"; + case GTU: return \"%*beq%?\\t%z1,%.,%3\"; + case LEU: return \"%*bne%?\\t%z1,%.,%3\"; + case GEU: return \"%*beq%?\\t%.,%.,%3\"; + case LTU: return \"%*j\\t%3\"; + } - return \"%*b%C0z%?\\t%z2,%1\"; -}" - [(set_attr "type" "branch") - (set_attr "mode" "none") - (set_attr "length" "1")]) - -(define_insn "branch_zero_false" - [(set (pc) - (if_then_else (match_operator:CC_0 0 "cmp_op" [(cc0) (const_int 0)]) - (pc) - (label_ref (match_operand 1 "" ""))))] - "" - "* -{ - mips_branch_likely = (final_sequence && INSN_ANNULLED_BRANCH_P (insn)); - operands[2] = branch_cmp[0]; - switch (GET_CODE (operands[0])) - { - case EQ: return \"%*bne%?\\t%z2,%.,%1\"; - case NE: return \"%*beq%?\\t%z2,%.,%1\"; - case GTU: return \"%*beq%?\\t%z2,%.,%1\"; - case LEU: return \"%*bne\\t%z2,%.,%1\"; - case GEU: return \"#%*bgeuz\\t%z2,%1\"; - case LTU: return \"%*j\\t%1\"; + return \"%*b%N0z%?\\t%z1,%3\"; } - - return \"%*b%N0z%?\\t%z2,%1\"; }" [(set_attr "type" "branch") (set_attr "mode" "none") (set_attr "length" "1")]) -(define_insn "branch_relop_true" - [(set (pc) - (if_then_else (match_operator:CC 0 "cmp2_op" [(cc0) (const_int 0)]) - (label_ref (match_operand 1 "" "")) - (pc)))] - "" - "* -{ - mips_branch_likely = (final_sequence && INSN_ANNULLED_BRANCH_P (insn)); - operands[2] = branch_cmp[0]; - operands[3] = branch_cmp[1]; - return \"%&b%C0%?\\t%z2,%z3,%1%!\"; -}" - [(set_attr "type" "branch") - (set_attr "mode" "none") - (set_attr "length" "2")]) - -(define_insn "branch_relop_false" +(define_insn "branch_equality" [(set (pc) - (if_then_else (match_operator:CC 0 "cmp2_op" [(cc0) (const_int 0)]) - (pc) - (label_ref (match_operand 1 "" ""))))] + (if_then_else (match_operator:SI 0 "equality_op" + [(match_operand:SI 1 "register_operand" "d") + (match_operand:SI 2 "register_operand" "d")]) + (match_operand 3 "pc_or_label_operand" "") + (match_operand 4 "pc_or_label_operand" "")))] "" "* { mips_branch_likely = (final_sequence && INSN_ANNULLED_BRANCH_P (insn)); - operands[2] = branch_cmp[0]; - operands[3] = branch_cmp[1]; - - return \"%&b%N0%?\\t%z2,%z3,%1%!\"; + return (operands[3] != pc_rtx) + ? \"%*b%C0%?\\t%z1,%z2,%3\" + : \"%*b%N0%?\\t%z1,%z2,%4\"; }" [(set_attr "type" "branch") (set_attr "mode" "none") - (set_attr "length" "2")]) + (set_attr "length" "1")]) + (define_expand "beq" [(set (pc) @@ -3055,13 +3213,11 @@ move\\t%0,%z4\\n\\ (define_expand "seq" [(set (match_operand:SI 0 "register_operand" "=d") - (eq:CC_EQ (match_dup 1) - (match_dup 2)))] + (eq:SI (match_dup 1) + (match_dup 2)))] "" " { - extern rtx force_reg (); - if (branch_type != CMP_SI) FAIL; @@ -3069,47 +3225,62 @@ move\\t%0,%z4\\n\\ operands[1] = branch_cmp[0]; operands[2] = branch_cmp[1]; + if (!TARGET_DEBUG_C_MODE) + { + gen_int_relational (EQ, operands[0], operands[1], operands[2], (int *)0); + DONE; + } + if (GET_CODE (operands[2]) == CONST_INT && INTVAL (operands[2]) < 0) operands[2] = force_reg (SImode, operands[2]); /* fall through and generate default code */ }") -(define_insn "seq_si" - [(set (match_operand:SI 0 "register_operand" "=d,d,d") - (eq:CC_EQ (match_operand:SI 1 "register_operand" "%d,d,d") - (match_operand:SI 2 "uns_arith_operand" "J,d,K")))] + +(define_insn "seq_si_zero" + [(set (match_operand:SI 0 "register_operand" "=d") + (eq:SI (match_operand:SI 1 "register_operand" "d") + (const_int 0)))] "" + "sltu\\t%0,%1,1" + [(set_attr "type" "arith") + (set_attr "mode" "SI") + (set_attr "length" "1")]) + +(define_insn "seq_si" + [(set (match_operand:SI 0 "register_operand" "=d,d") + (eq:SI (match_operand:SI 1 "register_operand" "%d,d") + (match_operand:SI 2 "uns_arith_operand" "d,K")))] + "TARGET_DEBUG_C_MODE" "@ - sltu\\t%0,%1,1 xor\\t%0,%1,%2\;sltu\\t%0,%0,1 - xori\\t%0,%1,%x2\;sltu\\t%0,%0,1" - [(set_attr "type" "arith,arith,arith") - (set_attr "mode" "SI,SI,SI") - (set_attr "length" "1,2,2")]) + xori\\t%0,%1,%2\;sltu\\t%0,%0,1" + [(set_attr "type" "arith") + (set_attr "mode" "SI") + (set_attr "length" "2")]) (define_split [(set (match_operand:SI 0 "register_operand" "") - (eq:CC_EQ (match_operand:SI 1 "register_operand" "") - (match_operand:SI 2 "uns_arith_operand" "")))] - "GET_CODE (operands[2]) != CONST_INT || INTVAL (operands[2]) != 0" + (eq:SI (match_operand:SI 1 "register_operand" "") + (match_operand:SI 2 "uns_arith_operand" "")))] + "TARGET_DEBUG_C_MODE && !TARGET_DEBUG_D_MODE + && (GET_CODE (operands[2]) != CONST_INT || INTVAL (operands[2]) != 0)" [(set (match_dup 0) (xor:SI (match_dup 1) (match_dup 2))) (set (match_dup 0) - (ltu:CC (match_dup 0) + (ltu:SI (match_dup 0) (const_int 1)))] "") (define_expand "sne" [(set (match_operand:SI 0 "register_operand" "=d") - (ne:CC_EQ (match_dup 1) - (match_dup 2)))] + (ne:SI (match_dup 1) + (match_dup 2)))] "" " { - extern rtx force_reg (); - if (branch_type != CMP_SI) FAIL; @@ -3117,53 +3288,61 @@ move\\t%0,%z4\\n\\ operands[1] = branch_cmp[0]; operands[2] = branch_cmp[1]; + if (!TARGET_DEBUG_C_MODE) + { + gen_int_relational (NE, operands[0], operands[1], operands[2], (int *)0); + DONE; + } + if (GET_CODE (operands[2]) == CONST_INT && INTVAL (operands[2]) < 0) operands[2] = force_reg (SImode, operands[2]); /* fall through and generate default code */ }") -(define_insn "sne_si" - [(set (match_operand:SI 0 "register_operand" "=d,d,d") - (ne:CC_EQ (match_operand:SI 1 "register_operand" "%d,d,d") - (match_operand:SI 2 "uns_arith_operand" "J,d,K")))] +(define_insn "sne_si_zero" + [(set (match_operand:SI 0 "register_operand" "=d") + (ne:SI (match_operand:SI 1 "register_operand" "d") + (const_int 0)))] "" - "* -{ - if (GET_CODE (operands[2]) != CONST_INT) - return \"xor\\t%0,%1,%2\;sltu\\t%0,%.,%0\"; - - if (INTVAL (operands[2]) == 0) - return \"sltu\\t%0,%.,%1\"; + "sltu\\t%0,%.,%1" + [(set_attr "type" "arith") + (set_attr "mode" "SI") + (set_attr "length" "1")]) - return \"xori\\t%0,%1,%x2\;sltu\\t%0,%.,%0\"; -}" - [(set_attr "type" "arith,arith,arith") - (set_attr "mode" "SI,SI,SI") - (set_attr "length" "1,2,2")]) +(define_insn "sne_si" + [(set (match_operand:SI 0 "register_operand" "=d,d") + (ne:SI (match_operand:SI 1 "register_operand" "%d,d") + (match_operand:SI 2 "uns_arith_operand" "d,K")))] + "TARGET_DEBUG_C_MODE" + "@ + xor\\t%0,%1,%2\;sltu\\t%0,%.,%0 + xori\\t%0,%1,%x2\;sltu\\t%0,%.,%0" + [(set_attr "type" "arith") + (set_attr "mode" "SI") + (set_attr "length" "2")]) (define_split [(set (match_operand:SI 0 "register_operand" "") - (ne:CC_EQ (match_operand:SI 1 "register_operand" "") - (match_operand:SI 2 "uns_arith_operand" "")))] - "GET_CODE (operands[2]) != CONST_INT || INTVAL (operands[2]) != 0" + (ne:SI (match_operand:SI 1 "register_operand" "") + (match_operand:SI 2 "uns_arith_operand" "")))] + "TARGET_DEBUG_C_MODE && !TARGET_DEBUG_D_MODE + && (GET_CODE (operands[2]) != CONST_INT || INTVAL (operands[2]) != 0)" [(set (match_dup 0) (xor:SI (match_dup 1) (match_dup 2))) (set (match_dup 0) - (gtu:CC (match_dup 0) + (gtu:SI (match_dup 0) (const_int 0)))] "") (define_expand "sgt" [(set (match_operand:SI 0 "register_operand" "=d") - (gt:CC (match_dup 1) + (gt:SI (match_dup 1) (match_dup 2)))] "" " { - extern rtx force_reg (); - if (branch_type != CMP_SI) FAIL; @@ -3171,6 +3350,12 @@ move\\t%0,%z4\\n\\ operands[1] = branch_cmp[0]; operands[2] = branch_cmp[1]; + if (!TARGET_DEBUG_C_MODE) + { + gen_int_relational (GT, operands[0], operands[1], operands[2], (int *)0); + DONE; + } + if (GET_CODE (operands[2]) == CONST_INT && INTVAL (operands[2]) != 0) operands[2] = force_reg (SImode, operands[2]); @@ -3179,7 +3364,7 @@ move\\t%0,%z4\\n\\ (define_insn "sgt_si" [(set (match_operand:SI 0 "register_operand" "=d") - (gt:CC (match_operand:SI 1 "register_operand" "d") + (gt:SI (match_operand:SI 1 "register_operand" "d") (match_operand:SI 2 "reg_or_0_operand" "dJ")))] "" "slt\\t%0,%z2,%1" @@ -3189,7 +3374,7 @@ move\\t%0,%z4\\n\\ (define_expand "sge" [(set (match_operand:SI 0 "register_operand" "=d") - (ge:CC (match_dup 1) + (ge:SI (match_dup 1) (match_dup 2)))] "" " @@ -3201,14 +3386,20 @@ move\\t%0,%z4\\n\\ operands[1] = branch_cmp[0]; operands[2] = branch_cmp[1]; + if (!TARGET_DEBUG_C_MODE) + { + gen_int_relational (GE, operands[0], operands[1], operands[2], (int *)0); + DONE; + } + /* fall through and generate default code */ }") (define_insn "sge_si" [(set (match_operand:SI 0 "register_operand" "=d") - (ge:CC (match_operand:SI 1 "register_operand" "d") + (ge:SI (match_operand:SI 1 "register_operand" "d") (match_operand:SI 2 "arith_operand" "dI")))] - "" + "TARGET_DEBUG_C_MODE" "slt\\t%0,%1,%2\;xori\\t%0,%0,0x0001" [(set_attr "type" "arith") (set_attr "mode" "SI") @@ -3216,11 +3407,11 @@ move\\t%0,%z4\\n\\ (define_split [(set (match_operand:SI 0 "register_operand" "") - (ge:CC (match_operand:SI 1 "register_operand" "") + (ge:SI (match_operand:SI 1 "register_operand" "") (match_operand:SI 2 "arith_operand" "")))] - "" + "TARGET_DEBUG_C_MODE && !TARGET_DEBUG_D_MODE" [(set (match_dup 0) - (lt:CC (match_dup 1) + (lt:SI (match_dup 1) (match_dup 2))) (set (match_dup 0) (xor:SI (match_dup 0) @@ -3229,7 +3420,7 @@ move\\t%0,%z4\\n\\ (define_expand "slt" [(set (match_operand:SI 0 "register_operand" "=d") - (lt:CC (match_dup 1) + (lt:SI (match_dup 1) (match_dup 2)))] "" " @@ -3241,12 +3432,18 @@ move\\t%0,%z4\\n\\ operands[1] = branch_cmp[0]; operands[2] = branch_cmp[1]; + if (!TARGET_DEBUG_C_MODE) + { + gen_int_relational (LT, operands[0], operands[1], operands[2], (int *)0); + DONE; + } + /* fall through and generate default code */ }") (define_insn "slt_si" [(set (match_operand:SI 0 "register_operand" "=d") - (lt:CC (match_operand:SI 1 "register_operand" "d") + (lt:SI (match_operand:SI 1 "register_operand" "d") (match_operand:SI 2 "arith_operand" "dI")))] "" "slt\\t%0,%1,%2" @@ -3256,13 +3453,11 @@ move\\t%0,%z4\\n\\ (define_expand "sle" [(set (match_operand:SI 0 "register_operand" "=d") - (le:CC (match_dup 1) + (le:SI (match_dup 1) (match_dup 2)))] "" " { - extern rtx force_reg (); - if (branch_type != CMP_SI) FAIL; @@ -3270,31 +3465,49 @@ move\\t%0,%z4\\n\\ operands[1] = branch_cmp[0]; operands[2] = branch_cmp[1]; + if (!TARGET_DEBUG_C_MODE) + { + gen_int_relational (LE, operands[0], operands[1], operands[2], (int *)0); + DONE; + } + if (GET_CODE (operands[2]) == CONST_INT && INTVAL (operands[2]) >= 32767) operands[2] = force_reg (SImode, operands[2]); /* fall through and generate default code */ }") -(define_insn "sle_si" - [(set (match_operand:SI 0 "register_operand" "=d,d") - (le:CC (match_operand:SI 1 "register_operand" "d,d") - (match_operand:SI 2 "arith_operand" "d,I")))] - "GET_CODE (operands[2]) != CONST_INT || INTVAL (operands[2]) < 32767" - "@ - slt\\t%0,%z2,%1\;xori\\t%0,%0,0x0001 - slt\\t%0,%1,(%2+1)" - [(set_attr "type" "arith,arith") - (set_attr "mode" "SI,SI") - (set_attr "length" "2,1")]) +(define_insn "sle_si_const" + [(set (match_operand:SI 0 "register_operand" "=d") + (le:SI (match_operand:SI 1 "register_operand" "d") + (match_operand:SI 2 "small_int" "I")))] + "INTVAL (operands[2]) < 32767" + "* +{ + operands[2] = gen_rtx (CONST_INT, VOIDmode, INTVAL (operands[2])+1); + return \"slt\\t%0,%1,%2\"; +}" + [(set_attr "type" "arith") + (set_attr "mode" "SI") + (set_attr "length" "1")]) + +(define_insn "sle_si_reg" + [(set (match_operand:SI 0 "register_operand" "=d") + (le:SI (match_operand:SI 1 "register_operand" "d") + (match_operand:SI 2 "register_operand" "d")))] + "TARGET_DEBUG_C_MODE" + "slt\\t%0,%z2,%1\;xori\\t%0,%0,0x0001" + [(set_attr "type" "arith") + (set_attr "mode" "SI") + (set_attr "length" "2")]) (define_split [(set (match_operand:SI 0 "register_operand" "") - (le:CC (match_operand:SI 1 "register_operand" "") + (le:SI (match_operand:SI 1 "register_operand" "") (match_operand:SI 2 "register_operand" "")))] - "" + "TARGET_DEBUG_C_MODE && !TARGET_DEBUG_D_MODE" [(set (match_dup 0) - (lt:CC (match_dup 2) + (lt:SI (match_dup 2) (match_dup 1))) (set (match_dup 0) (xor:SI (match_dup 0) @@ -3303,13 +3516,11 @@ move\\t%0,%z4\\n\\ (define_expand "sgtu" [(set (match_operand:SI 0 "register_operand" "=d") - (gtu:CC (match_dup 1) + (gtu:SI (match_dup 1) (match_dup 2)))] "" " { - extern rtx force_reg (); - if (branch_type != CMP_SI) FAIL; @@ -3317,6 +3528,12 @@ move\\t%0,%z4\\n\\ operands[1] = branch_cmp[0]; operands[2] = branch_cmp[1]; + if (!TARGET_DEBUG_C_MODE) + { + gen_int_relational (GTU, operands[0], operands[1], operands[2], (int *)0); + DONE; + } + if (GET_CODE (operands[2]) == CONST_INT && INTVAL (operands[2]) != 0) operands[2] = force_reg (SImode, operands[2]); @@ -3325,7 +3542,7 @@ move\\t%0,%z4\\n\\ (define_insn "sgtu_si" [(set (match_operand:SI 0 "register_operand" "=d") - (gtu:CC (match_operand:SI 1 "register_operand" "d") + (gtu:SI (match_operand:SI 1 "register_operand" "d") (match_operand:SI 2 "reg_or_0_operand" "dJ")))] "" "sltu\\t%0,%z2,%1" @@ -3335,7 +3552,7 @@ move\\t%0,%z4\\n\\ (define_expand "sgeu" [(set (match_operand:SI 0 "register_operand" "=d") - (geu:CC (match_dup 1) + (geu:SI (match_dup 1) (match_dup 2)))] "" " @@ -3347,14 +3564,20 @@ move\\t%0,%z4\\n\\ operands[1] = branch_cmp[0]; operands[2] = branch_cmp[1]; + if (!TARGET_DEBUG_C_MODE) + { + gen_int_relational (GEU, operands[0], operands[1], operands[2], (int *)0); + DONE; + } + /* fall through and generate default code */ }") (define_insn "sgeu_si" [(set (match_operand:SI 0 "register_operand" "=d") - (geu:CC (match_operand:SI 1 "register_operand" "d") + (geu:SI (match_operand:SI 1 "register_operand" "d") (match_operand:SI 2 "arith_operand" "dI")))] - "" + "TARGET_DEBUG_C_MODE" "sltu\\t%0,%1,%2\;xori\\t%0,%0,0x0001" [(set_attr "type" "arith") (set_attr "mode" "SI") @@ -3362,11 +3585,11 @@ move\\t%0,%z4\\n\\ (define_split [(set (match_operand:SI 0 "register_operand" "") - (geu:CC (match_operand:SI 1 "register_operand" "") + (geu:SI (match_operand:SI 1 "register_operand" "") (match_operand:SI 2 "arith_operand" "")))] - "" + "TARGET_DEBUG_C_MODE && !TARGET_DEBUG_D_MODE" [(set (match_dup 0) - (ltu:CC (match_dup 1) + (ltu:SI (match_dup 1) (match_dup 2))) (set (match_dup 0) (xor:SI (match_dup 0) @@ -3375,7 +3598,7 @@ move\\t%0,%z4\\n\\ (define_expand "sltu" [(set (match_operand:SI 0 "register_operand" "=d") - (ltu:CC (match_dup 1) + (ltu:SI (match_dup 1) (match_dup 2)))] "" " @@ -3387,12 +3610,18 @@ move\\t%0,%z4\\n\\ operands[1] = branch_cmp[0]; operands[2] = branch_cmp[1]; + if (!TARGET_DEBUG_C_MODE) + { + gen_int_relational (LTU, operands[0], operands[1], operands[2], (int *)0); + DONE; + } + /* fall through and generate default code */ }") (define_insn "sltu_si" [(set (match_operand:SI 0 "register_operand" "=d") - (ltu:CC (match_operand:SI 1 "register_operand" "d") + (ltu:SI (match_operand:SI 1 "register_operand" "d") (match_operand:SI 2 "arith_operand" "dI")))] "" "sltu\\t%0,%1,%2" @@ -3402,13 +3631,11 @@ move\\t%0,%z4\\n\\ (define_expand "sleu" [(set (match_operand:SI 0 "register_operand" "=d") - (leu:CC (match_dup 1) + (leu:SI (match_dup 1) (match_dup 2)))] "" " { - extern rtx force_reg (); - if (branch_type != CMP_SI) FAIL; @@ -3416,31 +3643,49 @@ move\\t%0,%z4\\n\\ operands[1] = branch_cmp[0]; operands[2] = branch_cmp[1]; + if (!TARGET_DEBUG_C_MODE) + { + gen_int_relational (LEU, operands[0], operands[1], operands[2], (int *)0); + DONE; + } + if (GET_CODE (operands[2]) == CONST_INT && INTVAL (operands[2]) >= 32767) operands[2] = force_reg (SImode, operands[2]); /* fall through and generate default code */ }") -(define_insn "sleu_si" - [(set (match_operand:SI 0 "register_operand" "=d,d") - (leu:CC (match_operand:SI 1 "register_operand" "d,d") - (match_operand:SI 2 "arith_operand" "d,I")))] - "GET_CODE (operands[2]) != CONST_INT || INTVAL (operands[2]) < 32767" - "@ - sltu\\t%0,%z2,%1\;xori\\t%0,%0,0x0001 - sltu\\t%0,%1,(%2+1)" - [(set_attr "type" "arith,arith") - (set_attr "mode" "SI,SI") - (set_attr "length" "2,1")]) +(define_insn "sleu_si_const" + [(set (match_operand:SI 0 "register_operand" "=d") + (leu:SI (match_operand:SI 1 "register_operand" "d") + (match_operand:SI 2 "small_int" "I")))] + "INTVAL (operands[2]) < 32767" + "* +{ + operands[2] = gen_rtx (CONST_INT, VOIDmode, INTVAL (operands[2])+1); + return \"sltu\\t%0,%1,%2\"; +}" + [(set_attr "type" "arith") + (set_attr "mode" "SI") + (set_attr "length" "1")]) + +(define_insn "sleu_si_reg" + [(set (match_operand:SI 0 "register_operand" "=d") + (leu:SI (match_operand:SI 1 "register_operand" "d") + (match_operand:SI 2 "register_operand" "d")))] + "TARGET_DEBUG_C_MODE" + "sltu\\t%0,%z2,%1\;xori\\t%0,%0,0x0001" + [(set_attr "type" "arith") + (set_attr "mode" "SI") + (set_attr "length" "2")]) (define_split [(set (match_operand:SI 0 "register_operand" "") - (leu:CC (match_operand:SI 1 "register_operand" "") + (leu:SI (match_operand:SI 1 "register_operand" "") (match_operand:SI 2 "register_operand" "")))] - "" + "TARGET_DEBUG_C_MODE && !TARGET_DEBUG_D_MODE" [(set (match_dup 0) - (ltu:CC (match_dup 2) + (ltu:SI (match_dup 2) (match_dup 1))) (set (match_dup 0) (xor:SI (match_dup 0) @@ -3451,6 +3696,230 @@ move\\t%0,%z4\\n\\ ;; ;; .................... ;; +;; FLOATING POINT COMPARISONS +;; +;; .................... + +(define_insn "seq_df" + [(set (reg:CC_FP 66) + (eq:CC_FP (match_operand:DF 0 "register_operand" "f") + (match_operand:DF 1 "register_operand" "f")))] + "" + "* +{ + rtx xoperands[10]; + xoperands[0] = gen_rtx (REG, CC_FPmode, FPSW_REGNUM); + xoperands[1] = operands[0]; + xoperands[2] = operands[1]; + + return mips_fill_delay_slot (\"c.eq.d\\t%0,%1\", DELAY_FCMP, xoperands, insn); +}" + [(set_attr "type" "fcmp") + (set_attr "mode" "FPSW") + (set_attr "length" "1")]) + +(define_insn "sne_df" + [(set (reg:CC_REV_FP 66) + (ne:CC_REV_FP (match_operand:DF 0 "register_operand" "f") + (match_operand:DF 1 "register_operand" "f")))] + "" + "* +{ + rtx xoperands[10]; + xoperands[0] = gen_rtx (REG, CC_FPmode, FPSW_REGNUM); + xoperands[1] = operands[0]; + xoperands[2] = operands[1]; + + return mips_fill_delay_slot (\"c.eq.d\\t%0,%1\", DELAY_FCMP, xoperands, insn); +}" + [(set_attr "type" "fcmp") + (set_attr "mode" "FPSW") + (set_attr "length" "1")]) + +(define_insn "slt_df" + [(set (reg:CC_FP 66) + (lt:CC_FP (match_operand:DF 0 "register_operand" "f") + (match_operand:DF 1 "register_operand" "f")))] + "" + "* +{ + rtx xoperands[10]; + xoperands[0] = gen_rtx (REG, CC_FPmode, FPSW_REGNUM); + xoperands[1] = operands[0]; + xoperands[2] = operands[1]; + + return mips_fill_delay_slot (\"c.lt.d\\t%0,%1\", DELAY_FCMP, xoperands, insn); +}" + [(set_attr "type" "fcmp") + (set_attr "mode" "FPSW") + (set_attr "length" "1")]) + +(define_insn "sle_df" + [(set (reg:CC_FP 66) + (le:CC_FP (match_operand:DF 0 "register_operand" "f") + (match_operand:DF 1 "register_operand" "f")))] + "" + "* +{ + rtx xoperands[10]; + xoperands[0] = gen_rtx (REG, CC_FPmode, FPSW_REGNUM); + xoperands[1] = operands[0]; + xoperands[2] = operands[1]; + + return mips_fill_delay_slot (\"c.le.d\\t%0,%1\", DELAY_FCMP, xoperands, insn); +}" + [(set_attr "type" "fcmp") + (set_attr "mode" "FPSW") + (set_attr "length" "1")]) + +(define_insn "sgt_df" + [(set (reg:CC_FP 66) + (gt:CC_FP (match_operand:DF 0 "register_operand" "f") + (match_operand:DF 1 "register_operand" "f")))] + "" + "* +{ + rtx xoperands[10]; + xoperands[0] = gen_rtx (REG, CC_FPmode, FPSW_REGNUM); + xoperands[1] = operands[0]; + xoperands[2] = operands[1]; + + return mips_fill_delay_slot (\"c.lt.d\\t%1,%0\", DELAY_FCMP, xoperands, insn); +}" + [(set_attr "type" "fcmp") + (set_attr "mode" "FPSW") + (set_attr "length" "1")]) + +(define_insn "sge_df" + [(set (reg:CC_FP 66) + (ge:CC_FP (match_operand:DF 0 "register_operand" "f") + (match_operand:DF 1 "register_operand" "f")))] + "" + "* +{ + rtx xoperands[10]; + xoperands[0] = gen_rtx (REG, CC_FPmode, FPSW_REGNUM); + xoperands[1] = operands[0]; + xoperands[2] = operands[1]; + + return mips_fill_delay_slot (\"c.le.d\\t%1,%0\", DELAY_FCMP, xoperands, insn); +}" + [(set_attr "type" "fcmp") + (set_attr "mode" "FPSW") + (set_attr "length" "1")]) + +(define_insn "seq_sf" + [(set (reg:CC_FP 66) + (eq:CC_FP (match_operand:SF 0 "register_operand" "f") + (match_operand:SF 1 "register_operand" "f")))] + "" + "* +{ + rtx xoperands[10]; + xoperands[0] = gen_rtx (REG, CC_FPmode, FPSW_REGNUM); + xoperands[1] = operands[0]; + xoperands[2] = operands[1]; + + return mips_fill_delay_slot (\"c.eq.s\\t%0,%1\", DELAY_FCMP, xoperands, insn); +}" + [(set_attr "type" "fcmp") + (set_attr "mode" "FPSW") + (set_attr "length" "1")]) + +(define_insn "sne_sf" + [(set (reg:CC_REV_FP 66) + (ne:CC_REV_FP (match_operand:SF 0 "register_operand" "f") + (match_operand:SF 1 "register_operand" "f")))] + "" + "* +{ + rtx xoperands[10]; + xoperands[0] = gen_rtx (REG, CC_FPmode, FPSW_REGNUM); + xoperands[1] = operands[0]; + xoperands[2] = operands[1]; + + return mips_fill_delay_slot (\"c.eq.s\\t%0,%1\", DELAY_FCMP, xoperands, insn); +}" + [(set_attr "type" "fcmp") + (set_attr "mode" "FPSW") + (set_attr "length" "1")]) + +(define_insn "slt_sf" + [(set (reg:CC_FP 66) + (lt:CC_FP (match_operand:SF 0 "register_operand" "f") + (match_operand:SF 1 "register_operand" "f")))] + "" + "* +{ + rtx xoperands[10]; + xoperands[0] = gen_rtx (REG, CC_FPmode, FPSW_REGNUM); + xoperands[1] = operands[0]; + xoperands[2] = operands[1]; + + return mips_fill_delay_slot (\"c.lt.s\\t%0,%1\", DELAY_FCMP, xoperands, insn); +}" + [(set_attr "type" "fcmp") + (set_attr "mode" "FPSW") + (set_attr "length" "1")]) + +(define_insn "sle_sf" + [(set (reg:CC_FP 66) + (le:CC_FP (match_operand:SF 0 "register_operand" "f") + (match_operand:SF 1 "register_operand" "f")))] + "" + "* +{ + rtx xoperands[10]; + xoperands[0] = gen_rtx (REG, CC_FPmode, FPSW_REGNUM); + xoperands[1] = operands[0]; + xoperands[2] = operands[1]; + + return mips_fill_delay_slot (\"c.le.s\\t%0,%1\", DELAY_FCMP, xoperands, insn); +}" + [(set_attr "type" "fcmp") + (set_attr "mode" "FPSW") + (set_attr "length" "1")]) + +(define_insn "sgt_sf" + [(set (reg:CC_FP 66) + (gt:CC_FP (match_operand:SF 0 "register_operand" "f") + (match_operand:SF 1 "register_operand" "f")))] + "" + "* +{ + rtx xoperands[10]; + xoperands[0] = gen_rtx (REG, CC_FPmode, FPSW_REGNUM); + xoperands[1] = operands[0]; + xoperands[2] = operands[1]; + + return mips_fill_delay_slot (\"c.lt.s\\t%1,%0\", DELAY_FCMP, xoperands, insn); +}" + [(set_attr "type" "fcmp") + (set_attr "mode" "FPSW") + (set_attr "length" "1")]) + +(define_insn "sge_sf" + [(set (reg:CC_FP 66) + (ge:CC_FP (match_operand:SF 0 "register_operand" "f") + (match_operand:SF 1 "register_operand" "f")))] + "" + "* +{ + rtx xoperands[10]; + xoperands[0] = gen_rtx (REG, CC_FPmode, FPSW_REGNUM); + xoperands[1] = operands[0]; + xoperands[2] = operands[1]; + + return mips_fill_delay_slot (\"c.le.s\\t%1,%0\", DELAY_FCMP, xoperands, insn); +}" + [(set_attr "type" "fcmp") + (set_attr "mode" "FPSW") + (set_attr "length" "1")]) + + +;; +;; .................... +;; ;; UNCONDITIONAL BRANCHES ;; ;; .................... @@ -3493,14 +3962,22 @@ move\\t%0,%z4\\n\\ ;; Function return, only allow after optimization, so that we can ;; eliminate jumps to jumps if no stack space is used. -(define_insn "return" - [(return)] - "null_epilogue ()" - "* -{ - operands[0] = gen_rtx (REG, SImode, GP_REG_FIRST + 31); - return \"%*j\\t%0\"; -}" +;; (define_expand "return" +;; [(set (pc) (reg:SI 31))] +;; "simple_epilogue_p ()" +;; "") + +(define_expand "return" + [(parallel [(return) + (use (reg:SI 31))])] + "simple_epilogue_p ()" + "") + +(define_insn "return_internal" + [(parallel [(return) + (use (match_operand:SI 0 "register_operand" "d"))])] + "" + "%*j\\t%0" [(set_attr "type" "jump") (set_attr "mode" "none") (set_attr "length" "1")]) @@ -3509,6 +3986,54 @@ move\\t%0,%z4\\n\\ ;; ;; .................... ;; +;; Function prologue/epilogue +;; +;; .................... +;; + +(define_expand "prologue" + [(const_int 1)] + "" + " +{ + if (mips_isa >= 0) /* avoid unused code warnings */ + { + mips_expand_prologue (); + DONE; + } +}") + +;; Block any insns from being moved before this point, since the +;; profiling call to mcount can use various registers that aren't +;; saved or used to pass arguments. + +(define_insn "blockage" + [(unspec_volatile [(const_int 0)] 0)] + "" + "" + [(set_attr "type" "unknown") + (set_attr "mode" "none") + (set_attr "length" "0")]) + +;; At present, don't expand the epilogue, reorg.c will clobber the +;; return register in compiling gen_lowpart (emit-rtl.c). +;; +;; (define_expand "epilogue" +;; [(const_int 2)] +;; "" +;; " +;; { +;; if (mips_isa >= 0) /* avoid unused code warnings */ +;; { +;; mips_expand_epilogue (); +;; DONE; +;; } +;; }") + + +;; +;; .................... +;; ;; FUNCTION CALLS ;; ;; .................... @@ -3516,23 +4041,47 @@ move\\t%0,%z4\\n\\ ;; calls.c now passes a third argument, make saber happy (define_expand "call" - [(parallel [(call (match_operand 0 "call_memory_operand" "m") + [(parallel [(call (match_operand 0 "memory_operand" "m") (match_operand 1 "" "i")) - (clobber (match_operand 2 "" ""))])] ;; overwrite op2 with $31 + (clobber (reg:SI 31)) + (use (match_operand 2 "" "")) ;; next_arg_reg + (use (match_operand 3 "" ""))])] ;; struct_value_size_rtx "" " { rtx addr; - operands[2] = gen_rtx (REG, SImode, GP_REG_FIRST + 31); + if (operands[0]) /* eliminate unused code warnings */ + { + addr = XEXP (operands[0], 0); + if (GET_CODE (addr) != REG && !CONSTANT_ADDRESS_P (addr)) + XEXP (operands[0], 0) = force_reg (FUNCTION_MODE, addr); + + /* In order to pass small structures by value in registers + compatibly with the MIPS compiler, we need to shift the value + into the high part of the register. Function_arg has encoded + a PARALLEL rtx, holding a vector of adjustments to be made + as the next_arg_reg variable, so we split up the insns, + and emit them separately. */ + + if (operands[2] != (rtx)0 && GET_CODE (operands[2]) == PARALLEL) + { + rtvec adjust = XVEC (operands[2], 0); + int num = GET_NUM_ELEM (adjust); + int i; + + for (i = 0; i < num; i++) + emit_insn (RTVEC_ELT (adjust, i)); + } - addr = XEXP (operands[0], 0); - if (! call_memory_operand (addr, VOIDmode)) - XEXP (operands[0], 0) = force_reg (FUNCTION_MODE, addr); + emit_call_insn (gen_call_internal (operands[0], operands[1], + gen_rtx (REG, Pmode, GP_REG_FIRST + 31))); + DONE; + } }") (define_insn "call_internal" - [(call (match_operand 0 "call_memory_operand" "m") + [(call (match_operand 0 "memory_operand" "m") (match_operand 1 "" "i")) (clobber (match_operand:SI 2 "register_operand" "=d"))] "" @@ -3543,11 +4092,16 @@ move\\t%0,%z4\\n\\ 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; - operands[1] = gen_rtx (REG, SImode, GP_REG_FIRST + 31); - return \"%*jal\\t%1,%0\"; + return \"%*jal\\t%2,%0\"; } }" [(set_attr "type" "call") @@ -3558,24 +4112,49 @@ move\\t%0,%z4\\n\\ (define_expand "call_value" [(parallel [(set (match_operand 0 "register_operand" "=df") - (call (match_operand 1 "call_memory_operand" "m") + (call (match_operand 1 "memory_operand" "m") (match_operand 2 "" "i"))) - (clobber (match_operand 3 "" ""))])] ;; overwrite op3 with $31 + (clobber (reg:SI 31)) + (use (match_operand 3 "" ""))])] ;; next_arg_reg "" " { rtx addr; - operands[3] = gen_rtx (REG, SImode, GP_REG_FIRST + 31); + if (operands[0]) /* eliminate unused code warning */ + { + addr = XEXP (operands[1], 0); + if (GET_CODE (addr) != REG && !CONSTANT_ADDRESS_P (addr)) + XEXP (operands[1], 0) = force_reg (FUNCTION_MODE, addr); + + /* In order to pass small structures by value in registers + compatibly with the MIPS compiler, we need to shift the value + into the high part of the register. Function_arg has encoded + a PARALLEL rtx, holding a vector of adjustments to be made + as the next_arg_reg variable, so we split up the insns, + and emit them separately. */ + + if (operands[3] != (rtx)0 && GET_CODE (operands[3]) == PARALLEL) + { + rtvec adjust = XVEC (operands[3], 0); + int num = GET_NUM_ELEM (adjust); + int i; + + for (i = 0; i < num; i++) + emit_insn (RTVEC_ELT (adjust, i)); + } + + emit_call_insn (gen_call_value_internal (operands[0], operands[1], operands[2], + gen_rtx (REG, Pmode, GP_REG_FIRST + 31))); + + DONE; + } - addr = XEXP (operands[1], 0); - if (! call_memory_operand (addr, VOIDmode)) - XEXP (operands[1], 0) = force_reg (FUNCTION_MODE, addr); }") (define_insn "call_value_internal" [(set (match_operand 0 "register_operand" "=df") - (call (match_operand 1 "call_memory_operand" "m") + (call (match_operand 1 "memory_operand" "m") (match_operand 2 "" "i"))) (clobber (match_operand:SI 3 "register_operand" "=d"))] "" @@ -3586,11 +4165,16 @@ move\\t%0,%z4\\n\\ 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; - operands[2] = gen_rtx (REG, SImode, GP_REG_FIRST + 31); - return \"%*jal\\t%2,%1\"; + return \"%*jal\\t%3,%1\"; } }" [(set_attr "type" "call")