📄 mips.md
字号:
(define_insn "*<su>mul_acc_di" [(set (match_operand:DI 0 "register_operand" "=x") (plus:DI (mult:DI (any_extend:DI (match_operand:SI 1 "register_operand" "d")) (any_extend:DI (match_operand:SI 2 "register_operand" "d"))) (match_operand:DI 3 "register_operand" "0")))] "(TARGET_MAD || ISA_HAS_MACC) && !TARGET_64BIT"{ if (TARGET_MAD) return "mad<u>\t%1,%2"; else if (TARGET_MIPS5500) return "madd<u>\t%1,%2"; else /* See comment in *macc. */ return "%[macc<u>\t%@,%1,%2%]";} [(set_attr "type" "imadd") (set_attr "mode" "SI")]);; Floating point multiply accumulate instructions.(define_insn "*madd<mode>" [(set (match_operand:ANYF 0 "register_operand" "=f") (plus:ANYF (mult:ANYF (match_operand:ANYF 1 "register_operand" "f") (match_operand:ANYF 2 "register_operand" "f")) (match_operand:ANYF 3 "register_operand" "f")))] "ISA_HAS_FP4 && TARGET_FUSED_MADD" "madd.<fmt>\t%0,%3,%1,%2" [(set_attr "type" "fmadd") (set_attr "mode" "<UNITMODE>")])(define_insn "*msub<mode>" [(set (match_operand:ANYF 0 "register_operand" "=f") (minus:ANYF (mult:ANYF (match_operand:ANYF 1 "register_operand" "f") (match_operand:ANYF 2 "register_operand" "f")) (match_operand:ANYF 3 "register_operand" "f")))] "ISA_HAS_FP4 && TARGET_FUSED_MADD" "msub.<fmt>\t%0,%3,%1,%2" [(set_attr "type" "fmadd") (set_attr "mode" "<UNITMODE>")])(define_insn "*nmadd<mode>" [(set (match_operand:ANYF 0 "register_operand" "=f") (neg:ANYF (plus:ANYF (mult:ANYF (match_operand:ANYF 1 "register_operand" "f") (match_operand:ANYF 2 "register_operand" "f")) (match_operand:ANYF 3 "register_operand" "f"))))] "ISA_HAS_NMADD_NMSUB && TARGET_FUSED_MADD && HONOR_SIGNED_ZEROS (<MODE>mode)" "nmadd.<fmt>\t%0,%3,%1,%2" [(set_attr "type" "fmadd") (set_attr "mode" "<UNITMODE>")])(define_insn "*nmadd<mode>_fastmath" [(set (match_operand:ANYF 0 "register_operand" "=f") (minus:ANYF (mult:ANYF (neg:ANYF (match_operand:ANYF 1 "register_operand" "f")) (match_operand:ANYF 2 "register_operand" "f")) (match_operand:ANYF 3 "register_operand" "f")))] "ISA_HAS_NMADD_NMSUB && TARGET_FUSED_MADD && !HONOR_SIGNED_ZEROS (<MODE>mode)" "nmadd.<fmt>\t%0,%3,%1,%2" [(set_attr "type" "fmadd") (set_attr "mode" "<UNITMODE>")])(define_insn "*nmsub<mode>" [(set (match_operand:ANYF 0 "register_operand" "=f") (neg:ANYF (minus:ANYF (mult:ANYF (match_operand:ANYF 2 "register_operand" "f") (match_operand:ANYF 3 "register_operand" "f")) (match_operand:ANYF 1 "register_operand" "f"))))] "ISA_HAS_NMADD_NMSUB && TARGET_FUSED_MADD && HONOR_SIGNED_ZEROS (<MODE>mode)" "nmsub.<fmt>\t%0,%1,%2,%3" [(set_attr "type" "fmadd") (set_attr "mode" "<UNITMODE>")])(define_insn "*nmsub<mode>_fastmath" [(set (match_operand:ANYF 0 "register_operand" "=f") (minus:ANYF (match_operand:ANYF 1 "register_operand" "f") (mult:ANYF (match_operand:ANYF 2 "register_operand" "f") (match_operand:ANYF 3 "register_operand" "f"))))] "ISA_HAS_NMADD_NMSUB && TARGET_FUSED_MADD && !HONOR_SIGNED_ZEROS (<MODE>mode)" "nmsub.<fmt>\t%0,%1,%2,%3" [(set_attr "type" "fmadd") (set_attr "mode" "<UNITMODE>")]);;;; ....................;;;; DIVISION and REMAINDER;;;; ....................;;(define_expand "div<mode>3" [(set (match_operand:ANYF 0 "register_operand") (div:ANYF (match_operand:ANYF 1 "reg_or_1_operand") (match_operand:ANYF 2 "register_operand")))] "<divide_condition>"{ if (const_1_operand (operands[1], <MODE>mode)) if (!(ISA_HAS_FP4 && flag_unsafe_math_optimizations)) operands[1] = force_reg (<MODE>mode, operands[1]);});; These patterns work around the early SB-1 rev2 core "F1" erratum:;;;; If an mfc1 or dmfc1 happens to access the floating point register;; file at the same time a long latency operation (div, sqrt, recip,;; sqrt) iterates an intermediate result back through the floating;; point register file bypass, then instead returning the correct;; register value the mfc1 or dmfc1 operation returns the intermediate;; result of the long latency operation.;;;; The workaround is to insert an unconditional 'mov' from/to the;; long latency op destination register.(define_insn "*div<mode>3" [(set (match_operand:ANYF 0 "register_operand" "=f") (div:ANYF (match_operand:ANYF 1 "register_operand" "f") (match_operand:ANYF 2 "register_operand" "f")))] "<divide_condition>"{ if (TARGET_FIX_SB1) return "div.<fmt>\t%0,%1,%2\;mov.<fmt>\t%0,%0"; else return "div.<fmt>\t%0,%1,%2";} [(set_attr "type" "fdiv") (set_attr "mode" "<UNITMODE>") (set (attr "length") (if_then_else (ne (symbol_ref "TARGET_FIX_SB1") (const_int 0)) (const_int 8) (const_int 4)))])(define_insn "*recip<mode>3" [(set (match_operand:ANYF 0 "register_operand" "=f") (div:ANYF (match_operand:ANYF 1 "const_1_operand" "") (match_operand:ANYF 2 "register_operand" "f")))] "<recip_condition> && flag_unsafe_math_optimizations"{ if (TARGET_FIX_SB1) return "recip.<fmt>\t%0,%2\;mov.<fmt>\t%0,%0"; else return "recip.<fmt>\t%0,%2";} [(set_attr "type" "frdiv") (set_attr "mode" "<UNITMODE>") (set (attr "length") (if_then_else (ne (symbol_ref "TARGET_FIX_SB1") (const_int 0)) (const_int 8) (const_int 4)))]);; VR4120 errata MD(A1): signed division instructions do not work correctly;; with negative operands. We use special libgcc functions instead.(define_insn "divmod<mode>4" [(set (match_operand:GPR 0 "register_operand" "=l") (div:GPR (match_operand:GPR 1 "register_operand" "d") (match_operand:GPR 2 "register_operand" "d"))) (set (match_operand:GPR 3 "register_operand" "=h") (mod:GPR (match_dup 1) (match_dup 2)))] "!TARGET_FIX_VR4120" { return mips_output_division ("<d>div\t$0,%1,%2", operands); } [(set_attr "type" "idiv") (set_attr "mode" "<MODE>")])(define_insn "udivmod<mode>4" [(set (match_operand:GPR 0 "register_operand" "=l") (udiv:GPR (match_operand:GPR 1 "register_operand" "d") (match_operand:GPR 2 "register_operand" "d"))) (set (match_operand:GPR 3 "register_operand" "=h") (umod:GPR (match_dup 1) (match_dup 2)))] "" { return mips_output_division ("<d>divu\t$0,%1,%2", operands); } [(set_attr "type" "idiv") (set_attr "mode" "<MODE>")]);;;; ....................;;;; SQUARE ROOT;;;; ....................;; These patterns work around the early SB-1 rev2 core "F1" erratum (see;; "*div[sd]f3" comment for details).(define_insn "sqrt<mode>2" [(set (match_operand:ANYF 0 "register_operand" "=f") (sqrt:ANYF (match_operand:ANYF 1 "register_operand" "f")))] "<sqrt_condition>"{ if (TARGET_FIX_SB1) return "sqrt.<fmt>\t%0,%1\;mov.<fmt>\t%0,%0"; else return "sqrt.<fmt>\t%0,%1";} [(set_attr "type" "fsqrt") (set_attr "mode" "<UNITMODE>") (set (attr "length") (if_then_else (ne (symbol_ref "TARGET_FIX_SB1") (const_int 0)) (const_int 8) (const_int 4)))])(define_insn "*rsqrt<mode>a" [(set (match_operand:ANYF 0 "register_operand" "=f") (div:ANYF (match_operand:ANYF 1 "const_1_operand" "") (sqrt:ANYF (match_operand:ANYF 2 "register_operand" "f"))))] "<recip_condition> && flag_unsafe_math_optimizations"{ if (TARGET_FIX_SB1) return "rsqrt.<fmt>\t%0,%2\;mov.<fmt>\t%0,%0"; else return "rsqrt.<fmt>\t%0,%2";} [(set_attr "type" "frsqrt") (set_attr "mode" "<UNITMODE>") (set (attr "length") (if_then_else (ne (symbol_ref "TARGET_FIX_SB1") (const_int 0)) (const_int 8) (const_int 4)))])(define_insn "*rsqrt<mode>b" [(set (match_operand:ANYF 0 "register_operand" "=f") (sqrt:ANYF (div:ANYF (match_operand:ANYF 1 "const_1_operand" "") (match_operand:ANYF 2 "register_operand" "f"))))] "<recip_condition> && flag_unsafe_math_optimizations"{ if (TARGET_FIX_SB1) return "rsqrt.<fmt>\t%0,%2\;mov.<fmt>\t%0,%0"; else return "rsqrt.<fmt>\t%0,%2";} [(set_attr "type" "frsqrt") (set_attr "mode" "<UNITMODE>") (set (attr "length") (if_then_else (ne (symbol_ref "TARGET_FIX_SB1") (const_int 0)) (const_int 8) (const_int 4)))]);;;; ....................;;;; ABSOLUTE VALUE;;;; ....................;; Do not use the integer abs macro instruction, since that signals an;; exception on -2147483648 (sigh).(define_insn "abs<mode>2" [(set (match_operand:GPR 0 "register_operand" "=d") (abs:GPR (match_operand:GPR 1 "register_operand" "d")))] "!TARGET_MIPS16"{ if (REGNO (operands[0]) == REGNO (operands[1]) && GENERATE_BRANCHLIKELY) return "%(bltzl\t%1,1f\;<d>subu\t%0,%.,%0\n%~1:%)"; else return "%(bgez\t%1,1f\;move\t%0,%1\;<d>subu\t%0,%.,%0\n%~1:%)";} [(set_attr "type" "multi") (set_attr "mode" "<MODE>") (set_attr "length" "12")])(define_insn "abs<mode>2" [(set (match_operand:ANYF 0 "register_operand" "=f") (abs:ANYF (match_operand:ANYF 1 "register_operand" "f")))] "" "abs.<fmt>\t%0,%1" [(set_attr "type" "fabs") (set_attr "mode" "<UNITMODE>")]);;;; ....................;;;; FIND FIRST BIT INSTRUCTION;;;; ....................;;(define_insn "ffs<mode>2" [(set (match_operand:GPR 0 "register_operand" "=&d") (ffs:GPR (match_operand:GPR 1 "register_operand" "d"))) (clobber (match_scratch:GPR 2 "=&d")) (clobber (match_scratch:GPR 3 "=&d"))] "!TARGET_MIPS16"{ if (optimize && find_reg_note (insn, REG_DEAD, operands[1])) return "%(\move\t%0,%.\;\beq\t%1,%.,2f\n\%~1:\tand\t%2,%1,0x0001\;\<d>addu\t%0,%0,1\;\beq\t%2,%.,1b\;\<d>srl\t%1,%1,1\n\%~2:%)"; return "%(\move\t%0,%.\;\move\t%3,%1\;\beq\t%3,%.,2f\n\%~1:\tand\t%2,%3,0x0001\;\<d>addu\t%0,%0,1\;\beq\t%2,%.,1b\;\<d>srl\t%3,%3,1\n\%~2:%)";} [(set_attr "type" "multi") (set_attr "mode" "<MODE>") (set_attr "length" "28")]);;;; ...................;;;; Count leading zeroes.;;;; ...................;;(define_insn "clz<mode>2" [(set (match_operand:GPR 0 "register_operand" "=d") (clz:GPR (match_operand:GPR 1 "register_operand" "d")))] "ISA_HAS_CLZ_CLO" "<d>clz\t%0,%1" [(set_attr "type" "clz") (set_attr "mode" "<MODE>")]);;;; ....................;;;; NEGATION and ONE'S COMPLEMENT;;;; ....................(define_insn "negsi2" [(set (match_operand:SI 0 "register_operand" "=d") (neg:SI (match_operand:SI 1 "register_operand" "d")))] ""{ if (TARGET_MIPS16) return "neg\t%0,%1"; else return "subu\t%0,%.,%1";} [(set_attr "type" "arith") (set_attr "mode" "SI")])(define_insn "negdi2" [(set (match_operand:DI 0 "register_operand" "=d") (neg:DI (match_operand:DI 1 "register_operand" "d")))] "TARGET_64BIT && !TARGET_MIPS16" "dsubu\t%0,%.,%1" [(set_attr "type" "arith") (set_attr "mode" "DI")])(define_insn "neg<mode>2" [(set (match_operand:ANYF 0 "register_operand" "=f") (neg:ANYF (match_operand:ANYF 1 "register_operand" "f")))] "" "neg.<fmt>\t%0,%1" [(set_attr "type" "fneg") (set_attr "mode" "<UNITMODE>")])(define_insn "one_cmpl<mode>2" [(set (match_operand:GPR 0 "register_operand" "=d") (not:GPR (match_operand:GPR 1 "register_operand" "d")))] ""{ if (TARGET_MIPS16) return "not\t%0,%1"; else return "nor\t%0,%.,%1";} [(set_attr "type" "arith") (set_attr "mode" "<MODE>")]);;;; ....................;;;; LOGICAL;;;; ....................;;;; Many of these instructions use trivial define_expands, because we;; want to use a different set of constraints when TARGET_MIPS16.(define_expand "and<mode>3" [(set (match_operand:GPR 0 "register_operand") (and:GPR (match_operand:GPR 1 "register_operand") (match_operand:GPR 2 "uns_arith_operand")))] ""{ if (TARGET_MIPS16) operands[2] = force_reg (<MODE>mode, ope
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -