diff options
Diffstat (limited to 'gcc/config/i386/i386.md')
-rw-r--r-- | gcc/config/i386/i386.md | 381 |
1 files changed, 364 insertions, 17 deletions
diff --git a/gcc/config/i386/i386.md b/gcc/config/i386/i386.md index 5119db6..3b98788 100644 --- a/gcc/config/i386/i386.md +++ b/gcc/config/i386/i386.md @@ -92,6 +92,15 @@ ;; 43 This is a `rsqsrt' operation. ;; 44 This is a `sfence' operation. ;; 45 This is a noop to prevent excessive combiner cleverness. +;; 46 This is a `femms' operation. +;; 47 This is a `prefetch' (3DNow) operation. +;; 48 This is a `prefetchw' operation. +;; 49 This is a 'pavgusb' operation. +;; 50 This is a `pfrcp' operation. +;; 51 This is a `pfrcpit1' operation. +;; 52 This is a `pfrcpit2' operation. +;; 53 This is a `pfrsqrt' operation. +;; 54 This is a `pfrsqrit1' operation. ;; Insns whose names begin with "x86_" are emitted by gen_FOO calls ;; from i386.c. @@ -17455,6 +17464,13 @@ "movq\t{%1, %0|%0, %1}" [(set_attr "type" "mmx")]) +(define_insn "movv2sf_internal" + [(set (match_operand:V2SF 0 "nonimmediate_operand" "=y,m") + (match_operand:V2SF 1 "general_operand" "ym,y"))] + "TARGET_3DNOW" + "movq\\t{%1, %0|%0, %1}" + [(set_attr "type" "mmx")]) + (define_expand "movti" [(set (match_operand:TI 0 "general_operand" "") (match_operand:TI 1 "general_operand" ""))] @@ -17641,6 +17657,40 @@ } }) +(define_expand "movv2sf" + [(set (match_operand:V2SF 0 "general_operand" "") + (match_operand:V2SF 1 "general_operand" ""))] + "TARGET_3DNOW" + " +{ + /* For constants other than zero into memory. We do not know how the + instructions used to build constants modify the upper 64 bits + of the register, once we have that information we may be able + to handle some of them more efficiently. */ + if ((reload_in_progress | reload_completed) == 0 + && register_operand (operands[0], V2SFmode) + && CONSTANT_P (operands[1])) + { + rtx addr = gen_reg_rtx (Pmode); + + emit_move_insn (addr, + XEXP (force_const_mem (V2SFmode, operands[1]), 0)); + operands[1] = gen_rtx_MEM (V2SFmode, addr); + } + + /* Make operand1 a register is it isn't already. */ + if ((reload_in_progress | reload_completed) == 0 + && !register_operand (operands[0], V2SFmode) + && !register_operand (operands[1], V2SFmode) + && (GET_CODE (operands[1]) != CONST_INT || INTVAL (operands[1]) != 0) + && operands[1] != CONST0_RTX (V2SFmode)) + { + rtx temp = force_reg (V2SFmode, operands[1]); + emit_move_insn (operands[0], temp); + DONE; + } +}") + (define_insn_and_split "*pushti" [(set (match_operand:TI 0 "push_operand" "=<") (match_operand:TI 1 "nonmemory_operand" "x"))] @@ -17707,6 +17757,17 @@ "" [(set_attr "type" "mmx")]) +(define_insn_and_split "*pushv2sf" + [(set (match_operand:V2SF 0 "push_operand" "=<") + (match_operand:V2SF 1 "nonmemory_operand" "y"))] + "TARGET_3DNOW" + "#" + "" + [(set (reg:SI 7) (plus:SI (reg:SI 7) (const_int -8))) + (set (mem:V2SF (reg:SI 7)) (match_dup 1))] + "" + [(set_attr "type" "mmx")]) + (define_insn "movti_internal" [(set (match_operand:TI 0 "nonimmediate_operand" "=x,m") (match_operand:TI 1 "general_operand" "xm,x"))] @@ -17749,7 +17810,7 @@ (define_insn "mmx_pmovmskb" [(set (match_operand:SI 0 "register_operand" "=r") (unspec:SI [(match_operand:V8QI 1 "register_operand" "y")] 33))] - "TARGET_SSE" + "TARGET_SSE || TARGET_3DNOW_A" "pmovmskb\t{%1, %0|%0, %1}" [(set_attr "type" "sse")]) @@ -17757,7 +17818,7 @@ [(set (mem:V8QI (match_operand:SI 0 "register_operand" "D")) (unspec:V8QI [(match_operand:V8QI 1 "register_operand" "y") (match_operand:V8QI 2 "register_operand" "y")] 32))] - "TARGET_SSE" + "TARGET_SSE || TARGET_3DNOW_A" ;; @@@ check ordering of operands in intel/nonintel syntax "maskmovq\t{%2, %1|%1, %2}" [(set_attr "type" "sse")]) @@ -17772,7 +17833,7 @@ (define_insn "sse_movntdi" [(set (match_operand:DI 0 "memory_operand" "=m") (unspec:DI [(match_operand:DI 1 "register_operand" "y")] 34))] - "TARGET_SSE" + "TARGET_SSE || TARGET_3DNOW_A" "movntq\t{%1, %0|%0, %1}" [(set_attr "type" "sse")]) @@ -18535,7 +18596,7 @@ (mult:V4SI (zero_extend:V4SI (match_operand:V4HI 1 "register_operand" "0")) (zero_extend:V4SI (match_operand:V4HI 2 "nonimmediate_operand" "ym"))) (const_int 16))))] - "TARGET_MMX" + "TARGET_SSE || TARGET_3DNOW_A" "pmulhuw\t{%2, %0|%0, %2}" [(set_attr "type" "mmx")]) @@ -18628,7 +18689,7 @@ (const_int 1) (const_int 1)]))) (const_int 1)))] - "TARGET_SSE" + "TARGET_SSE || TARGET_3DNOW_A" "pavgb\t{%2, %0|%0, %2}" [(set_attr "type" "sse")]) @@ -18643,7 +18704,7 @@ (const_int 1) (const_int 1)]))) (const_int 1)))] - "TARGET_SSE" + "TARGET_SSE || TARGET_3DNOW_A" "pavgw\t{%2, %0|%0, %2}" [(set_attr "type" "sse")]) @@ -18651,7 +18712,7 @@ [(set (match_operand:V8QI 0 "register_operand" "=y") (abs:V8QI (minus:V8QI (match_operand:V8QI 1 "register_operand" "0") (match_operand:V8QI 2 "nonimmediate_operand" "ym"))))] - "TARGET_SSE" + "TARGET_SSE || TARGET_3DNOW_A" "psadbw\t{%2, %0|%0, %2}" [(set_attr "type" "sse")]) @@ -18664,7 +18725,7 @@ (vec_duplicate:V4HI (truncate:HI (match_operand:SI 2 "nonimmediate_operand" "rm"))) (match_operand:SI 3 "immediate_operand" "i")))] - "TARGET_SSE" + "TARGET_SSE || TARGET_3DNOW_A" "pinsrw\t{%3, %2, %0|%0, %2, %3}" [(set_attr "type" "sse")]) @@ -18673,7 +18734,7 @@ (zero_extend:SI (vec_select:HI (match_operand:V4HI 1 "register_operand" "y") (parallel [(match_operand:SI 2 "immediate_operand" "i")]))))] - "TARGET_SSE" + "TARGET_SSE || TARGET_3DNOW_A" "pextrw\t{%2, %1, %0|%0, %1, %2}" [(set_attr "type" "sse")]) @@ -18682,7 +18743,7 @@ (unspec:V4HI [(match_operand:V4HI 1 "register_operand" "0") (match_operand:V4HI 2 "nonimmediate_operand" "ym") (match_operand:SI 3 "immediate_operand" "i")] 41))] - "TARGET_SSE" + "TARGET_SSE || TARGET_3DNOW_A" "pshufw\t{%3, %2, %0|%0, %2, %3}" [(set_attr "type" "sse")]) @@ -18744,7 +18805,7 @@ [(set (match_operand:V8QI 0 "register_operand" "=y") (umax:V8QI (match_operand:V8QI 1 "register_operand" "0") (match_operand:V8QI 2 "nonimmediate_operand" "ym")))] - "TARGET_SSE" + "TARGET_SSE || TARGET_3DNOW_A" "pmaxub\t{%2, %0|%0, %2}" [(set_attr "type" "sse")]) @@ -18752,7 +18813,7 @@ [(set (match_operand:V4HI 0 "register_operand" "=y") (smax:V4HI (match_operand:V4HI 1 "register_operand" "0") (match_operand:V4HI 2 "nonimmediate_operand" "ym")))] - "TARGET_SSE" + "TARGET_SSE || TARGET_3DNOW_A" "pmaxsw\t{%2, %0|%0, %2}" [(set_attr "type" "sse")]) @@ -18760,7 +18821,7 @@ [(set (match_operand:V8QI 0 "register_operand" "=y") (umin:V8QI (match_operand:V8QI 1 "register_operand" "0") (match_operand:V8QI 2 "nonimmediate_operand" "ym")))] - "TARGET_SSE" + "TARGET_SSE || TARGET_3DNOW_A" "pminub\t{%2, %0|%0, %2}" [(set_attr "type" "sse")]) @@ -18768,7 +18829,7 @@ [(set (match_operand:V4HI 0 "register_operand" "=y") (smin:V4HI (match_operand:V4HI 1 "register_operand" "0") (match_operand:V4HI 2 "nonimmediate_operand" "ym")))] - "TARGET_SSE" + "TARGET_SSE || TARGET_3DNOW_A" "pminsw\t{%2, %0|%0, %2}" [(set_attr "type" "sse")]) @@ -19031,7 +19092,7 @@ (define_expand "sfence" [(set (match_dup 0) (unspec:BLK [(match_dup 0)] 44))] - "TARGET_SSE" + "TARGET_SSE || TARGET_3DNOW_A" { operands[0] = gen_rtx_MEM (BLKmode, gen_rtx_SCRATCH (Pmode)); MEM_VOLATILE_P (operands[0]) = 1; @@ -19040,7 +19101,7 @@ (define_insn "*sfence_insn" [(set (match_operand:BLK 0 "" "") (unspec:BLK [(match_dup 0)] 44))] - "TARGET_SSE" + "TARGET_SSE || TARGET_3DNOW_A" "sfence" [(set_attr "type" "sse") (set_attr "memory" "unknown")]) @@ -19048,7 +19109,7 @@ (define_insn "prefetch" [(unspec [(match_operand:SI 0 "address_operand" "p") (match_operand:SI 1 "immediate_operand" "n")] 35)] - "TARGET_SSE" + "TARGET_SSE || TARGET_3DNOW_A" { switch (INTVAL (operands[1])) { @@ -19126,3 +19187,289 @@ (set_attr "memory" "store") (set_attr "modrm" "0") (set_attr "mode" "DI")]) + +;; 3Dnow! instructions + +(define_insn "addv2sf3" + [(set (match_operand:V2SF 0 "register_operand" "=y") + (plus:V2SF (match_operand:V2SF 1 "register_operand" "0") + (match_operand:V2SF 2 "nonimmediate_operand" "ym")))] + "TARGET_3DNOW" + "pfadd\\t{%2, %0|%0, %2}" + [(set_attr "type" "mmx")]) + +(define_insn "subv2sf3" + [(set (match_operand:V2SF 0 "register_operand" "=y") + (minus:V2SF (match_operand:V2SF 1 "register_operand" "0") + (match_operand:V2SF 2 "nonimmediate_operand" "ym")))] + "TARGET_3DNOW" + "pfsub\\t{%2, %0|%0, %2}" + [(set_attr "type" "mmx")]) + +(define_insn "subrv2sf3" + [(set (match_operand:V2SF 0 "register_operand" "=y") + (minus:V2SF (match_operand:V2SF 2 "nonimmediate_operand" "ym") + (match_operand:V2SF 1 "register_operand" "0")))] + "TARGET_3DNOW" + "pfsubr\\t{%2, %0|%0, %2}" + [(set_attr "type" "mmx")]) + +(define_insn "gtv2sf3" + [(set (match_operand:V2SI 0 "register_operand" "=y") + (gt:V2SI (match_operand:V2SF 1 "register_operand" "0") + (match_operand:V2SF 2 "nonimmediate_operand" "ym")))] + "TARGET_3DNOW" + "pfcmpgt\\t{%2, %0|%0, %2}" + [(set_attr "type" "mmx")]) + +(define_insn "gev2sf3" + [(set (match_operand:V2SI 0 "register_operand" "=y") + (ge:V2SI (match_operand:V2SF 1 "register_operand" "0") + (match_operand:V2SF 2 "nonimmediate_operand" "ym")))] + "TARGET_3DNOW" + "pfcmpge\\t{%2, %0|%0, %2}" + [(set_attr "type" "mmx")]) + +(define_insn "eqv2sf3" + [(set (match_operand:V2SI 0 "register_operand" "=y") + (eq:V2SI (match_operand:V2SF 1 "register_operand" "0") + (match_operand:V2SF 2 "nonimmediate_operand" "ym")))] + "TARGET_3DNOW" + "pfcmpeq\\t{%2, %0|%0, %2}" + [(set_attr "type" "mmx")]) + +(define_insn "pfmaxv2sf3" + [(set (match_operand:V2SF 0 "register_operand" "=y") + (smax:V2SF (match_operand:V2SF 1 "register_operand" "0") + (match_operand:V2SF 2 "nonimmediate_operand" "ym")))] + "TARGET_3DNOW" + "pfmax\\t{%2, %0|%0, %2}" + [(set_attr "type" "mmx")]) + +(define_insn "pfminv2sf3" + [(set (match_operand:V2SF 0 "register_operand" "=y") + (smin:V2SF (match_operand:V2SF 1 "register_operand" "0") + (match_operand:V2SF 2 "nonimmediate_operand" "ym")))] + "TARGET_3DNOW" + "pfmin\\t{%2, %0|%0, %2}" + [(set_attr "type" "mmx")]) + +(define_insn "mulv2sf3" + [(set (match_operand:V2SF 0 "register_operand" "=y") + (mult:V2SF (match_operand:V2SF 1 "register_operand" "0") + (match_operand:V2SF 2 "nonimmediate_operand" "ym")))] + "TARGET_3DNOW" + "pfmul\\t{%2, %0|%0, %2}" + [(set_attr "type" "mmx")]) + +(define_insn "femms" + [(unspec_volatile [(const_int 0)] 46) + (clobber (reg:XF 8)) + (clobber (reg:XF 9)) + (clobber (reg:XF 10)) + (clobber (reg:XF 11)) + (clobber (reg:XF 12)) + (clobber (reg:XF 13)) + (clobber (reg:XF 14)) + (clobber (reg:XF 15)) + (clobber (reg:DI 29)) + (clobber (reg:DI 30)) + (clobber (reg:DI 31)) + (clobber (reg:DI 32)) + (clobber (reg:DI 33)) + (clobber (reg:DI 34)) + (clobber (reg:DI 35)) + (clobber (reg:DI 36))] + "TARGET_3DNOW" + "femms" + [(set_attr "type" "mmx")]) + +(define_insn "prefetch_3dnow" + [(unspec [(match_operand:SI 0 "address_operand" "p")] 47)] + "TARGET_3DNOW" + "prefetch\\t%a0" + [(set_attr "type" "mmx")]) + +(define_insn "prefetchw" + [(unspec [(match_operand:SI 0 "address_operand" "p")] 48)] + "TARGET_3DNOW" + "prefetchw\\t%a0" + [(set_attr "type" "mmx")]) + +(define_insn "pf2id" + [(set (match_operand:V2SI 0 "register_operand" "=y") + (fix:V2SI (match_operand:V2SF 1 "nonimmediate_operand" "ym")))] + "TARGET_3DNOW" + "pf2id\\t{%1, %0|%0, %1}" + [(set_attr "type" "mmx")]) + +(define_insn "pf2iw" + [(set (match_operand:V2SI 0 "register_operand" "=y") + (sign_extend:V2SI + (ss_truncate:V2HI + (fix:V2SI (match_operand:V2SF 1 "nonimmediate_operand" "ym")))))] + "TARGET_3DNOW_A" + "pf2iw\\t{%1, %0|%0, %1}" + [(set_attr "type" "mmx")]) + +(define_insn "pfacc" + [(set (match_operand:V2SF 0 "register_operand" "=y") + (vec_concat:V2SF + (plus:SF + (vec_select:SF (match_operand:V2SF 1 "register_operand" "0") + (parallel [(const_int 0)])) + (vec_select:SF (match_dup 1) + (parallel [(const_int 1)]))) + (plus:SF + (vec_select:SF (match_operand:V2SF 2 "nonimmediate_operand" "y") + (parallel [(const_int 0)])) + (vec_select:SF (match_dup 2) + (parallel [(const_int 1)])))))] + "TARGET_3DNOW" + "pfacc\\t{%2, %0|%0, %2}" + [(set_attr "type" "mmx")]) + +(define_insn "pfnacc" + [(set (match_operand:V2SF 0 "register_operand" "=y") + (vec_concat:V2SF + (minus:SF + (vec_select:SF (match_operand:V2SF 1 "register_operand" "0") + (parallel [(const_int 0)])) + (vec_select:SF (match_dup 1) + (parallel [(const_int 1)]))) + (minus:SF + (vec_select:SF (match_operand:V2SF 2 "nonimmediate_operand" "y") + (parallel [(const_int 0)])) + (vec_select:SF (match_dup 2) + (parallel [(const_int 1)])))))] + "TARGET_3DNOW_A" + "pfnacc\\t{%2, %0|%0, %2}" + [(set_attr "type" "mmx")]) + +(define_insn "pfpnacc" + [(set (match_operand:V2SF 0 "register_operand" "=y") + (vec_concat:V2SF + (minus:SF + (vec_select:SF (match_operand:V2SF 1 "register_operand" "0") + (parallel [(const_int 0)])) + (vec_select:SF (match_dup 1) + (parallel [(const_int 1)]))) + (plus:SF + (vec_select:SF (match_operand:V2SF 2 "nonimmediate_operand" "y") + (parallel [(const_int 0)])) + (vec_select:SF (match_dup 2) + (parallel [(const_int 1)])))))] + "TARGET_3DNOW_A" + "pfpnacc\\t{%2, %0|%0, %2}" + [(set_attr "type" "mmx")]) + +(define_insn "pi2fw" + [(set (match_operand:V2SF 0 "register_operand" "=y") + (float:V2SF + (vec_concat:V2SI + (sign_extend:SI + (truncate:HI + (vec_select:SI (match_operand:V2SI 1 "nonimmediate_operand" "ym") + (parallel [(const_int 0)])))) + (sign_extend:SI + (truncate:HI + (vec_select:SI (match_dup 1) + (parallel [(const_int 1)])))))))] + "TARGET_3DNOW_A" + "pi2fw\\t{%1, %0|%0, %1}" + [(set_attr "type" "mmx")]) + +(define_insn "floatv2si2" + [(set (match_operand:V2SF 0 "register_operand" "=y") + (float:V2SF (match_operand:V2SI 1 "nonimmediate_operand" "ym")))] + "TARGET_3DNOW" + "pi2fd\\t{%1, %0|%0, %1}" + [(set_attr "type" "mmx")]) + +;; This insn is identical to pavgb in operation, but the opcode is +;; different. To avoid accidentally matching pavgb, use an unspec. + +(define_insn "pavgusb" + [(set (match_operand:V8QI 0 "register_operand" "=y") + (unspec:V8QI + [(match_operand:V8QI 1 "register_operand" "0") + (match_operand:V8QI 2 "nonimmediate_operand" "ym")] 49))] + "TARGET_3DNOW" + "pavgusb\\t{%2, %0|%0, %2}" + [(set_attr "type" "mmx")]) + +;; 3DNow reciprical and sqrt + +(define_insn "pfrcpv2sf2" + [(set (match_operand:V2SF 0 "register_operand" "=y") + (unspec:V2SF [(match_operand:V2SF 1 "nonimmediate_operand" "ym")] 50))] + "TARGET_3DNOW" + "pfrcp\\t{%1, %0|%0, %1}" + [(set_attr "type" "mmx")]) + +(define_insn "pfrcpit1v2sf3" + [(set (match_operand:V2SF 0 "register_operand" "=y") + (unspec:V2SF [(match_operand:V2SF 1 "register_operand" "0") + (match_operand:V2SF 2 "nonimmediate_operand" "ym")] 51))] + "TARGET_3DNOW" + "pfrcpit1\\t{%2, %0|%0, %2}" + [(set_attr "type" "mmx")]) + +(define_insn "pfrcpit2v2sf3" + [(set (match_operand:V2SF 0 "register_operand" "=y") + (unspec:V2SF [(match_operand:V2SF 1 "register_operand" "0") + (match_operand:V2SF 2 "nonimmediate_operand" "ym")] 52))] + "TARGET_3DNOW" + "pfrcpit2\\t{%2, %0|%0, %2}" + [(set_attr "type" "mmx")]) + +(define_insn "pfrsqrtv2sf2" + [(set (match_operand:V2SF 0 "register_operand" "=y") + (unspec:V2SF [(match_operand:V2SF 1 "nonimmediate_operand" "ym")] 53))] + "TARGET_3DNOW" + "pfrsqrt\\t{%1, %0|%0, %1}" + [(set_attr "type" "mmx")]) + +(define_insn "pfrsqit1v2sf3" + [(set (match_operand:V2SF 0 "register_operand" "=y") + (unspec:V2SF [(match_operand:V2SF 1 "register_operand" "0") + (match_operand:V2SF 2 "nonimmediate_operand" "ym")] 54))] + "TARGET_3DNOW" + "pfrsqit1\\t{%2, %0|%0, %2}" + [(set_attr "type" "mmx")]) + +(define_insn "pmulhrwv4hi3" + [(set (match_operand:V4HI 0 "register_operand" "=y") + (truncate:V4HI + (lshiftrt:V4SI + (plus:V4SI + (mult:V4SI + (sign_extend:V4SI + (match_operand:V4HI 1 "register_operand" "0")) + (sign_extend:V4SI + (match_operand:V4HI 2 "nonimmediate_operand" "ym"))) + (vec_const:V4SI + (parallel [(const_int 0x8000) + (const_int 0x8000) + (const_int 0x8000) + (const_int 0x8000)]))) + (const_int 16))))] + "TARGET_3DNOW" + "pmulhrw\\t{%2, %0|%0, %2}" + [(set_attr "type" "mmx")]) + +(define_insn "pswapdv2si2" + [(set (match_operand:V2SI 0 "register_operand" "=y") + (vec_select:V2SI (match_operand:V2SI 1 "nonimmediate_operand" "ym") + (parallel [(const_int 1) (const_int 0)])))] + "TARGET_3DNOW_A" + "pswapd\\t{%1, %0|%0, %1}" + [(set_attr "type" "mmx")]) + +(define_insn "pswapdv2sf2" + [(set (match_operand:V2SF 0 "register_operand" "=y") + (vec_select:V2SF (match_operand:V2SF 1 "nonimmediate_operand" "ym") + (parallel [(const_int 1) (const_int 0)])))] + "TARGET_3DNOW_A" + "pswapd\\t{%1, %0|%0, %1}" + [(set_attr "type" "mmx")]) |