|
| 1 | +if ~ defined x86.mode |
| 2 | + include 'cpu\x64.inc' |
| 3 | +end if |
| 4 | + |
| 5 | +include 'cpu\ext\avx2.inc' |
| 6 | +include 'cpu\ext\adx.inc' |
| 7 | +include 'cpu\ext\aes.inc' |
| 8 | +include 'cpu\ext\bmi2.inc' |
| 9 | +include 'cpu\ext\f16c.inc' |
| 10 | +include 'cpu\ext\fma.inc' |
| 11 | +include 'cpu\ext\movbe.inc' |
| 12 | +include 'cpu\ext\pclmulqdq.inc' |
| 13 | +include 'cpu\ext\rdrand.inc' |
| 14 | +include 'cpu\ext\rdseed.inc' |
| 15 | +; RDTSCP forces all older instructions to retire before reading the time-stamp counter. |
| 16 | +include 'cpu\ext\rdtscp.inc' ; CPUID Fn8000_0001_EDX[RDTSCP] = 1 |
| 17 | + |
| 18 | +; MOVBE, CPUID.01H:ECX.MOVBE[bit 22] |
| 19 | +; PREFETCHW CLFLUSHOPT SHA CLZERO |
| 20 | + |
| 21 | +calminstruction clzero? dest* |
| 22 | + call x86.parse_operand@dest, dest |
| 23 | + check @dest.type = 'reg' & @dest.rm = 0 & @dest.size <> 1 |
| 24 | + jyes _prefix |
| 25 | + err 'operand must be rAX' |
| 26 | + exit |
| 27 | +_prefix: |
| 28 | + call x86.store_operand_prefix, @dest.size |
| 29 | + emit 1, 0Fh |
| 30 | + emit 1, 1 |
| 31 | + emit 1, 0FCh |
| 32 | +end calminstruction |
| 33 | + |
| 34 | +calminstruction mwaitx? |
| 35 | + emit 1, 0Fh |
| 36 | + emit 1, 1 |
| 37 | + emit 1, 0FBh |
| 38 | +end calminstruction |
| 39 | + |
| 40 | +calminstruction monitorx? |
| 41 | + emit 1, 0Fh |
| 42 | + emit 1, 1 |
| 43 | + emit 1, 0FAh |
| 44 | +end calminstruction |
| 45 | + |
| 46 | + |
| 47 | +; SSE4a ; AMD-only, from K10, CPUID.80000001H:ECX.SSE4A[Bit 6] flag |
| 48 | + |
| 49 | +macro extrq? dest*,src*,sel |
| 50 | + SSE.parse_operand @dest,dest |
| 51 | + if @dest.type = 'mmreg' & @dest.size = 16 |
| 52 | + match ,sel ; 66 0F 79 /r |
| 53 | + SSE.parse_operand @src,src |
| 54 | + if @src.type = 'mmreg' & @src.size = 16 |
| 55 | + @src.opcode_prefix = 66h |
| 56 | + x86.store_instruction <0Fh,79h>,@src,@dest.rm |
| 57 | + else |
| 58 | + err 'invalid combination of operands' |
| 59 | + end if |
| 60 | + else ; xmm,ib,ib ; 66 0F 78 /0 ib ib |
| 61 | + x86.parse_operand @aux1,src |
| 62 | + x86.parse_operand @aux2,sel |
| 63 | + if @aux1.type <> 'imm' | @aux1.size and not 1 \ |
| 64 | + | @aux2.type <> 'imm' | @aux2.size and not 1 |
| 65 | + err 'invalid combination of operands' |
| 66 | + else |
| 67 | + @dest.opcode_prefix = 66h |
| 68 | + x86.store_instruction <0Fh,78h>,@dest,0,2,(@aux2.imm shl 8) or @aux1.imm |
| 69 | + end if |
| 70 | + end match |
| 71 | + else |
| 72 | + err 'invalid combination of operands' |
| 73 | + end if |
| 74 | +end macro |
| 75 | + |
| 76 | +macro insertq? dest*,src*,sel1,sel2 |
| 77 | + SSE.parse_operand @dest,dest |
| 78 | + SSE.parse_operand @src,src |
| 79 | + if @dest.type = 'mmreg' & @src.type = 'mmreg' |
| 80 | + if (@dest.size or @src.size) <> 16 |
| 81 | + err 'invalid operand size' |
| 82 | + end if |
| 83 | + match ,sel1 sel2 |
| 84 | + @src.opcode_prefix = 0F2h |
| 85 | + x86.store_instruction <0Fh,79h>,@src,@dest.rm |
| 86 | + else |
| 87 | + x86.parse_operand @aux1,sel1 |
| 88 | + x86.parse_operand @aux2,sel2 |
| 89 | + if @aux1.type <> 'imm' | @aux1.size and not 1 \ |
| 90 | + | @aux2.type <> 'imm' | @aux2.size and not 1 |
| 91 | + err 'invalid combination of operands' |
| 92 | + else |
| 93 | + @src.opcode_prefix = 0F2h |
| 94 | + x86.store_instruction <0Fh,78h>,@src,@dest.rm,2,(@aux2.imm shl 8) or @aux1.imm |
| 95 | + end if |
| 96 | + end match |
| 97 | + else |
| 98 | + err 'invalid combination of operands' |
| 99 | + end if |
| 100 | +end macro |
| 101 | + |
| 102 | +iterate instr, movntss,movntsd |
| 103 | + macro instr? dest*,src* |
| 104 | + SSE.parse_operand @dest,dest |
| 105 | + SSE.parse_operand @src,src |
| 106 | + if @dest.type = 'mem' & @dest.size = 4*% \ |
| 107 | + & @src.type = 'mmreg' & @src.size = 16 |
| 108 | + @dest.opcode_prefix = 0F4h - % |
| 109 | + x86.store_instruction <0Fh,2Bh>,@dest,@src.rm |
| 110 | + else |
| 111 | + err 'invalid combination of operands' |
| 112 | + end if |
| 113 | + end macro |
| 114 | +end iterate |
0 commit comments