?? mips.md.svn-base
字號:
(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" "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" "imul") (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])) && true_regnum (operands[3]) == LO_REGNUM" [(parallel [(set (match_dup 3) (plus:SI (mult:SI (match_dup 1) (match_dup 2)) (match_dup 3))) (clobber (match_dup 4)) (clobber (match_dup 5)) (clobber (match_dup 6))]) (set (match_dup 0) (unspec:SI [(match_dup 5) (match_dup 4)] UNSPEC_MFHILO))] "")(define_insn "*macc" [(set (match_operand:SI 0 "register_operand" "=l,d") (plus:SI (mult:SI (match_operand:SI 1 "register_operand" "d,d") (match_operand:SI 2 "register_operand" "d,d")) (match_operand:SI 3 "register_operand" "0,l"))) (clobber (match_scratch:SI 4 "=h,h")) (clobber (match_scratch:SI 5 "=X,3"))] "ISA_HAS_MACC"{ if (which_alternative == 1) return "macc\t%0,%1,%2"; else if (TARGET_MIPS5500) return "madd\t%1,%2"; else /* The VR4130 assumes that there is a two-cycle latency between a macc that "writes" to $0 and an instruction that reads from it. We avoid this by assigning to $1 instead. */ return "%[macc\t%@,%1,%2%]";} [(set_attr "type" "imadd") (set_attr "mode" "SI")])(define_insn "*msac" [(set (match_operand:SI 0 "register_operand" "=l,d") (minus:SI (match_operand:SI 1 "register_operand" "0,l") (mult:SI (match_operand:SI 2 "register_operand" "d,d") (match_operand:SI 3 "register_operand" "d,d")))) (clobber (match_scratch:SI 4 "=h,h")) (clobber (match_scratch:SI 5 "=X,1"))] "ISA_HAS_MSAC"{ if (which_alternative == 1) return "msac\t%0,%2,%3"; else if (TARGET_MIPS5500) return "msub\t%2,%3"; else return "msac\t$0,%2,%3";} [(set_attr "type" "imadd") (set_attr "mode" "SI")]);; An msac-like instruction implemented using negation and a macc.(define_insn_and_split "*msac_using_macc" [(set (match_operand:SI 0 "register_operand" "=l,d") (minus:SI (match_operand:SI 1 "register_operand" "0,l") (mult:SI (match_operand:SI 2 "register_operand" "d,d") (match_operand:SI 3 "register_operand" "d,d")))) (clobber (match_scratch:SI 4 "=h,h")) (clobber (match_scratch:SI 5 "=X,1")) (clobber (match_scratch:SI 6 "=d,d"))] "ISA_HAS_MACC && !ISA_HAS_MSAC" "#" "&& reload_completed" [(set (match_dup 6) (neg:SI (match_dup 3))) (parallel [(set (match_dup 0) (plus:SI (mult:SI (match_dup 2) (match_dup 6)) (match_dup 1))) (clobber (match_dup 4)) (clobber (match_dup 5))])] "" [(set_attr "type" "imadd") (set_attr "length" "8")]);; Patterns generated by the define_peephole2 below.(define_insn "*macc2" [(set (match_operand:SI 0 "register_operand" "=l") (plus:SI (mult:SI (match_operand:SI 1 "register_operand" "d") (match_operand:SI 2 "register_operand" "d")) (match_dup 0))) (set (match_operand:SI 3 "register_operand" "=d") (plus:SI (mult:SI (match_dup 1) (match_dup 2)) (match_dup 0))) (clobber (match_scratch:SI 4 "=h"))] "ISA_HAS_MACC && reload_completed" "macc\t%3,%1,%2" [(set_attr "type" "imadd") (set_attr "mode" "SI")])(define_insn "*msac2" [(set (match_operand:SI 0 "register_operand" "=l") (minus:SI (match_dup 0) (mult:SI (match_operand:SI 1 "register_operand" "d") (match_operand:SI 2 "register_operand" "d")))) (set (match_operand:SI 3 "register_operand" "=d") (minus:SI (match_dup 0) (mult:SI (match_dup 1) (match_dup 2)))) (clobber (match_scratch:SI 4 "=h"))] "ISA_HAS_MSAC && reload_completed" "msac\t%3,%1,%2" [(set_attr "type" "imadd") (set_attr "mode" "SI")]);; Convert macc $0,<r1>,<r2> & mflo <r3> into macc <r3>,<r1>,<r2>
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -