📄 mips.md
字号:
(set (match_dup 0) (plus:DI (match_dup 0) (match_dup 2)))]{ HOST_WIDE_INT val = INTVAL (operands[1]); if (val >= 0) { operands[1] = GEN_INT (0xf); operands[2] = GEN_INT (val - 0xf); } else { operands[1] = GEN_INT (- 0x10); operands[2] = GEN_INT (val + 0x10); }})(define_split [(set (match_operand:DI 0 "register_operand") (plus:DI (match_operand:DI 1 "register_operand") (match_operand:DI 2 "const_int_operand")))] "TARGET_MIPS16 && TARGET_64BIT && reload_completed && !TARGET_DEBUG_D_MODE && REG_P (operands[0]) && M16_REG_P (REGNO (operands[0])) && REG_P (operands[1]) && M16_REG_P (REGNO (operands[1])) && REGNO (operands[0]) != REGNO (operands[1]) && GET_CODE (operands[2]) == CONST_INT && ((INTVAL (operands[2]) > 0x7 && INTVAL (operands[2]) <= 0x7 + 0xf) || (INTVAL (operands[2]) < - 0x8 && INTVAL (operands[2]) >= - 0x8 - 0x10))" [(set (match_dup 0) (plus:DI (match_dup 1) (match_dup 2))) (set (match_dup 0) (plus:DI (match_dup 0) (match_dup 3)))]{ HOST_WIDE_INT val = INTVAL (operands[2]); if (val >= 0) { operands[2] = GEN_INT (0x7); operands[3] = GEN_INT (val - 0x7); } else { operands[2] = GEN_INT (- 0x8); operands[3] = GEN_INT (val + 0x8); }})(define_insn "*addsi3_extended" [(set (match_operand:DI 0 "register_operand" "=d,d") (sign_extend:DI (plus:SI (match_operand:SI 1 "register_operand" "d,d") (match_operand:SI 2 "arith_operand" "d,Q"))))] "TARGET_64BIT && !TARGET_MIPS16" "@ addu\t%0,%1,%2 addiu\t%0,%1,%2" [(set_attr "type" "arith") (set_attr "mode" "SI")]);; Split this insn so that the addiu splitters can have a crack at it.;; Use a conservative length estimate until the split.(define_insn_and_split "*addsi3_extended_mips16" [(set (match_operand:DI 0 "register_operand" "=d,d,d") (sign_extend:DI (plus:SI (match_operand:SI 1 "register_operand" "0,d,d") (match_operand:SI 2 "arith_operand" "Q,O,d"))))] "TARGET_64BIT && TARGET_MIPS16" "#" "&& reload_completed" [(set (match_dup 3) (plus:SI (match_dup 1) (match_dup 2)))] { operands[3] = gen_lowpart (SImode, operands[0]); } [(set_attr "type" "arith") (set_attr "mode" "SI") (set_attr "extended_mips16" "yes")]);;;; ....................;;;; SUBTRACTION;;;; ....................;;(define_insn "sub<mode>3" [(set (match_operand:ANYF 0 "register_operand" "=f") (minus:ANYF (match_operand:ANYF 1 "register_operand" "f") (match_operand:ANYF 2 "register_operand" "f")))] "" "sub.<fmt>\t%0,%1,%2" [(set_attr "type" "fadd") (set_attr "mode" "<UNITMODE>")])(define_insn "sub<mode>3" [(set (match_operand:GPR 0 "register_operand" "=d") (minus:GPR (match_operand:GPR 1 "register_operand" "d") (match_operand:GPR 2 "register_operand" "d")))] "" "<d>subu\t%0,%1,%2" [(set_attr "type" "arith") (set_attr "mode" "<MODE>")])(define_insn "*subsi3_extended" [(set (match_operand:DI 0 "register_operand" "=d") (sign_extend:DI (minus:SI (match_operand:SI 1 "register_operand" "d") (match_operand:SI 2 "register_operand" "d"))))] "TARGET_64BIT" "subu\t%0,%1,%2" [(set_attr "type" "arith") (set_attr "mode" "DI")]);;;; ....................;;;; MULTIPLICATION;;;; ....................;;(define_expand "mul<mode>3" [(set (match_operand:SCALARF 0 "register_operand") (mult:SCALARF (match_operand:SCALARF 1 "register_operand") (match_operand:SCALARF 2 "register_operand")))] "" "")(define_insn "*mul<mode>3" [(set (match_operand:SCALARF 0 "register_operand" "=f") (mult:SCALARF (match_operand:SCALARF 1 "register_operand" "f") (match_operand:SCALARF 2 "register_operand" "f")))] "!TARGET_4300_MUL_FIX" "mul.<fmt>\t%0,%1,%2" [(set_attr "type" "fmul") (set_attr "mode" "<MODE>")]);; Early VR4300 silicon has a CPU bug where multiplies with certain;; operands may corrupt immediately following multiplies. This is a;; simple fix to insert NOPs.(define_insn "*mul<mode>3_r4300" [(set (match_operand:SCALARF 0 "register_operand" "=f") (mult:SCALARF (match_operand:SCALARF 1 "register_operand" "f") (match_operand:SCALARF 2 "register_operand" "f")))] "TARGET_4300_MUL_FIX" "mul.<fmt>\t%0,%1,%2\;nop" [(set_attr "type" "fmul") (set_attr "mode" "<MODE>") (set_attr "length" "8")])(define_insn "mulv2sf3" [(set (match_operand:V2SF 0 "register_operand" "=f") (mult:V2SF (match_operand:V2SF 1 "register_operand" "f") (match_operand:V2SF 2 "register_operand" "f")))] "TARGET_PAIRED_SINGLE_FLOAT" "mul.ps\t%0,%1,%2" [(set_attr "type" "fmul") (set_attr "mode" "SF")]);; The original R4000 has a cpu bug. If a double-word or a variable;; shift executes while an integer multiplication is in progress, the;; shift may give an incorrect result. Avoid this by keeping the mflo;; with the mult on the R4000.;;;; From "MIPS R4000PC/SC Errata, Processor Revision 2.2 and 3.0";; (also valid for MIPS R4000MC processors):;;;; "16. R4000PC, R4000SC: Please refer to errata 28 for an update to;; this errata description.;; The following code sequence causes the R4000 to incorrectly;; execute the Double Shift Right Arithmetic 32 (dsra32);; instruction. If the dsra32 instruction is executed during an;; integer multiply, the dsra32 will only shift by the amount in;; specified in the instruction rather than the amount plus 32;; bits.;; instruction 1: mult rs,rt integer multiply;; instruction 2-12: dsra32 rd,rt,rs doubleword shift;; right arithmetic + 32;; Workaround: A dsra32 instruction placed after an integer;; multiply should not be one of the 11 instructions after the;; multiply instruction.";;;; and:;;;; "28. R4000PC, R4000SC: The text from errata 16 should be replaced by;; the following description.;; All extended shifts (shift by n+32) and variable shifts (32 and;; 64-bit versions) may produce incorrect results under the;; following conditions:;; 1) An integer multiply is currently executing;; 2) These types of shift instructions are executed immediately;; following an integer divide instruction.;; Workaround:;; 1) Make sure no integer multiply is running wihen these;; instruction are executed. If this cannot be predicted at;; compile time, then insert a "mfhi" to R0 instruction;; immediately after the integer multiply instruction. This;; will cause the integer multiply to complete before the shift;; is executed.;; 2) Separate integer divide and these two classes of shift;; instructions by another instruction or a noop.";;;; These processors have PRId values of 0x00004220 and 0x00004300,;; respectively.(define_expand "mul<mode>3" [(set (match_operand:GPR 0 "register_operand") (mult:GPR (match_operand:GPR 1 "register_operand") (match_operand:GPR 2 "register_operand")))] ""{ if (GENERATE_MULT3_<MODE>) emit_insn (gen_mul<mode>3_mult3 (operands[0], operands[1], operands[2])); else if (!TARGET_FIX_R4000) emit_insn (gen_mul<mode>3_internal (operands[0], operands[1], operands[2])); else emit_insn (gen_mul<mode>3_r4000 (operands[0], operands[1], operands[2])); DONE;})(define_insn "mulsi3_mult3" [(set (match_operand:SI 0 "register_operand" "=d,l") (mult:SI (match_operand:SI 1 "register_operand" "d,d") (match_operand:SI 2 "register_operand" "d,d"))) (clobber (match_scratch:SI 3 "=h,h")) (clobber (match_scratch:SI 4 "=l,X"))] "GENERATE_MULT3_SI"{ if (which_alternative == 1) return "mult\t%1,%2"; if (TARGET_MAD || TARGET_MIPS5400 || TARGET_MIPS5500 || TARGET_MIPS7000 || TARGET_MIPS9000 || ISA_MIPS32 || ISA_MIPS32R2 || ISA_MIPS64) return "mul\t%0,%1,%2"; return "mult\t%0,%1,%2";} [(set_attr "type" "imul3,imul") (set_attr "mode" "SI")])(define_insn "muldi3_mult3" [(set (match_operand:DI 0 "register_operand" "=d") (mult:DI (match_operand:DI 1 "register_operand" "d") (match_operand:DI 2 "register_operand" "d"))) (clobber (match_scratch:DI 3 "=h")) (clobber (match_scratch:DI 4 "=l"))] "TARGET_64BIT && GENERATE_MULT3_DI" "dmult\t%0,%1,%2" [(set_attr "type" "imul3") (set_attr "mode" "DI")]);; If a register gets allocated to LO, and we spill to memory, the reload;; will include a move from LO to a GPR. Merge it into the multiplication;; if it can set the GPR directly.;;;; Operand 0: LO;; Operand 1: GPR (1st multiplication operand);; Operand 2: GPR (2nd multiplication operand);; Operand 3: HI;; Operand 4: GPR (destination)(define_peephole2 [(parallel [(set (match_operand:SI 0 "register_operand") (mult:SI (match_operand:SI 1 "register_operand") (match_operand:SI 2 "register_operand"))) (clobber (match_operand:SI 3 "register_operand")) (clobber (scratch:SI))]) (set (match_operand:SI 4 "register_operand") (unspec [(match_dup 0) (match_dup 3)] UNSPEC_MFHILO))] "GENERATE_MULT3_SI && peep2_reg_dead_p (2, operands[0])" [(parallel [(set (match_dup 4) (mult:SI (match_dup 1) (match_dup 2))) (clobber (match_dup 3)) (clobber (match_dup 0))])])(define_insn "mul<mode>3_internal" [(set (match_operand:GPR 0 "register_operand" "=l") (mult:GPR (match_operand:GPR 1 "register_operand" "d") (match_operand:GPR 2 "register_operand" "d"))) (clobber (match_scratch:GPR 3 "=h"))] "!TARGET_FIX_R4000" "<d>mult\t%1,%2" [(set_attr "type" "imul") (set_attr "mode" "<MODE>")])(define_insn "mul<mode>3_r4000" [(set (match_operand:GPR 0 "register_operand" "=d") (mult:GPR (match_operand:GPR 1 "register_operand" "d") (match_operand:GPR 2 "register_operand" "d"))) (clobber (match_scratch:GPR 3 "=h")) (clobber (match_scratch:GPR 4 "=l"))] "TARGET_FIX_R4000" "<d>mult\t%1,%2\;mflo\t%0" [(set_attr "type" "imul") (set_attr "mode" "<MODE>") (set_attr "length" "8")]);; On the VR4120 and VR4130, it is better to use "mtlo $0; macc" instead;; of "mult; mflo". They have the same latency, but the first form gives;; us an extra cycle to compute the operands.;; Operand 0: LO;; Operand 1: GPR (1st multiplication operand);; Operand 2: GPR (2nd multiplication operand);; Operand 3: HI;; Operand 4: GPR (destination)(define_peephole2 [(parallel [(set (match_operand:SI 0 "register_operand") (mult:SI (match_operand:SI 1 "register_operand") (match_operand:SI 2 "register_operand"))) (clobber (match_operand:SI 3 "register_operand"))]) (set (match_operand:SI 4 "register_operand") (unspec:SI [(match_dup 0) (match_dup 3)] UNSPEC_MFHILO))] "ISA_HAS_MACC && !GENERATE_MULT3_SI" [(set (match_dup 0) (const_int 0)) (parallel [(set (match_dup 0) (plus:SI (mult:SI (match_dup 1) (match_dup 2)) (match_dup 0))) (set (match_dup 4) (plus:SI (mult:SI (match_dup 1) (match_dup 2)) (match_dup 0))) (clobber (match_dup 3))])]);; Multiply-accumulate patterns;; For processors that can copy the output to a general register:;;;; The all-d alternative is needed because the combiner will find this;; pattern and then register alloc/reload will move registers around to;; make them fit, and we don't want to trigger unnecessary loads to LO.;;;; The last alternative should be made slightly less desirable, but adding;; "?" to the constraint is too strong, and causes values to be loaded into;; LO even when that's more costly. For now, using "*d" mostly does the;; trick.(define_insn "*mul_acc_si" [(set (match_operand:SI 0 "register_operand" "=l,*d,*d") (plus:SI (mult:SI (match_operand:SI 1 "register_operand" "d,d,d") (match_operand:SI 2 "register_operand" "d,d,d")) (match_operand:SI 3 "register_operand" "0,l,*d"))) (clobber (match_scratch:SI 4 "=h,h,h")) (clobber (match_scratch:SI 5 "=X,3,l")) (clobber (match_scratch:SI 6 "=X,X,&d"))] "(TARGET_MIPS3900 || ISA_HAS_MADD_MSUB) && !TARGET_MIPS16"{ static const char *const madd[] = { "madd\t%1,%2", "madd\t%0,%1,%2" }; if (which_alternative == 2) return "#"; if (ISA_HAS_MADD_MSUB && which_alternative != 0) return "#"; return madd[which_alternative];} [(set_attr "type" "imadd,imadd,multi") (set_attr "mode" "SI") (set_attr "length" "4,4,8")]);; Split the above insn if we failed to get LO allocated.(define_split [(set (match_operand:SI 0 "register_operand") (plus:SI (mult:SI (match_operand:SI 1 "register_operand") (match_operand:SI 2 "register_operand")) (match_operand:SI 3 "register_operand"))) (clobber (match_scratch:SI 4)) (clobber (match_scratch:SI 5)) (clobber (match_scratch:SI 6))] "reload_completed && !TARGET_DEBUG_D_MODE && GP_REG_P (true_regnum (operands[0])) && GP_REG_P (true_regnum (operands[3]))" [(parallel [(set (match_dup 6) (mult:SI (match_dup 1) (match_dup 2))) (clobber (match_dup 4)) (clobber (match_dup 5))]) (set (match_dup 0) (plus:SI (match_dup 6) (match_dup 3)))] "");; Splitter to copy result of MADD to a general register(define_split [(set (match_operand:SI 0 "register_operand") (plus:SI (mult:SI (match_operand:SI 1 "register_operand") (match_operand:SI 2 "register_operand")) (match_operand:SI 3 "register_operand"))) (clobber (match_scratch:SI 4)) (clobber (match_scratch:SI 5)) (clobber (match_scratch:SI 6))] "reload_completed && !TARGET_DEBUG_D_MODE && GP_REG_P (true_regnum (operands[0]))
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -