summaryrefslogtreecommitdiff
path: root/src/common/x64/emitter.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/common/x64/emitter.cpp')
-rw-r--r--src/common/x64/emitter.cpp2614
1 files changed, 1592 insertions, 1022 deletions
diff --git a/src/common/x64/emitter.cpp b/src/common/x64/emitter.cpp
index 5662f7f86..f5930abec 100644
--- a/src/common/x64/emitter.cpp
+++ b/src/common/x64/emitter.cpp
@@ -17,188 +17,169 @@
17 17
18#include <cinttypes> 18#include <cinttypes>
19#include <cstring> 19#include <cstring>
20 20#include "abi.h"
21#include "common/assert.h" 21#include "common/assert.h"
22#include "common/logging/log.h" 22#include "common/logging/log.h"
23#include "common/memory_util.h" 23#include "common/memory_util.h"
24
25#include "abi.h"
26#include "cpu_detect.h" 24#include "cpu_detect.h"
27#include "emitter.h" 25#include "emitter.h"
28 26
29namespace Gen 27namespace Gen {
30{
31 28
32struct NormalOpDef 29struct NormalOpDef {
33{
34 u8 toRm8, toRm32, fromRm8, fromRm32, imm8, imm32, simm8, eaximm8, eaximm32, ext; 30 u8 toRm8, toRm32, fromRm8, fromRm32, imm8, imm32, simm8, eaximm8, eaximm32, ext;
35}; 31};
36 32
37// 0xCC is code for invalid combination of immediates 33// 0xCC is code for invalid combination of immediates
38static const NormalOpDef normalops[11] = 34static const NormalOpDef normalops[11] = {
39{ 35 {0x00, 0x01, 0x02, 0x03, 0x80, 0x81, 0x83, 0x04, 0x05, 0}, // ADD
40 {0x00, 0x01, 0x02, 0x03, 0x80, 0x81, 0x83, 0x04, 0x05, 0}, //ADD 36 {0x10, 0x11, 0x12, 0x13, 0x80, 0x81, 0x83, 0x14, 0x15, 2}, // ADC
41 {0x10, 0x11, 0x12, 0x13, 0x80, 0x81, 0x83, 0x14, 0x15, 2}, //ADC
42 37
43 {0x28, 0x29, 0x2A, 0x2B, 0x80, 0x81, 0x83, 0x2C, 0x2D, 5}, //SUB 38 {0x28, 0x29, 0x2A, 0x2B, 0x80, 0x81, 0x83, 0x2C, 0x2D, 5}, // SUB
44 {0x18, 0x19, 0x1A, 0x1B, 0x80, 0x81, 0x83, 0x1C, 0x1D, 3}, //SBB 39 {0x18, 0x19, 0x1A, 0x1B, 0x80, 0x81, 0x83, 0x1C, 0x1D, 3}, // SBB
45 40
46 {0x20, 0x21, 0x22, 0x23, 0x80, 0x81, 0x83, 0x24, 0x25, 4}, //AND 41 {0x20, 0x21, 0x22, 0x23, 0x80, 0x81, 0x83, 0x24, 0x25, 4}, // AND
47 {0x08, 0x09, 0x0A, 0x0B, 0x80, 0x81, 0x83, 0x0C, 0x0D, 1}, //OR 42 {0x08, 0x09, 0x0A, 0x0B, 0x80, 0x81, 0x83, 0x0C, 0x0D, 1}, // OR
48 43
49 {0x30, 0x31, 0x32, 0x33, 0x80, 0x81, 0x83, 0x34, 0x35, 6}, //XOR 44 {0x30, 0x31, 0x32, 0x33, 0x80, 0x81, 0x83, 0x34, 0x35, 6}, // XOR
50 {0x88, 0x89, 0x8A, 0x8B, 0xC6, 0xC7, 0xCC, 0xCC, 0xCC, 0}, //MOV 45 {0x88, 0x89, 0x8A, 0x8B, 0xC6, 0xC7, 0xCC, 0xCC, 0xCC, 0}, // MOV
51 46
52 {0x84, 0x85, 0x84, 0x85, 0xF6, 0xF7, 0xCC, 0xA8, 0xA9, 0}, //TEST (to == from) 47 {0x84, 0x85, 0x84, 0x85, 0xF6, 0xF7, 0xCC, 0xA8, 0xA9, 0}, // TEST (to == from)
53 {0x38, 0x39, 0x3A, 0x3B, 0x80, 0x81, 0x83, 0x3C, 0x3D, 7}, //CMP 48 {0x38, 0x39, 0x3A, 0x3B, 0x80, 0x81, 0x83, 0x3C, 0x3D, 7}, // CMP
54 49
55 {0x86, 0x87, 0x86, 0x87, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 7}, //XCHG 50 {0x86, 0x87, 0x86, 0x87, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 7}, // XCHG
56}; 51};
57 52
58enum NormalSSEOps 53enum NormalSSEOps {
59{ 54 sseCMP = 0xC2,
60 sseCMP = 0xC2, 55 sseADD = 0x58, // ADD
61 sseADD = 0x58, //ADD 56 sseSUB = 0x5C, // SUB
62 sseSUB = 0x5C, //SUB 57 sseAND = 0x54, // AND
63 sseAND = 0x54, //AND 58 sseANDN = 0x55, // ANDN
64 sseANDN = 0x55, //ANDN 59 sseOR = 0x56,
65 sseOR = 0x56, 60 sseXOR = 0x57,
66 sseXOR = 0x57, 61 sseMUL = 0x59, // MUL
67 sseMUL = 0x59, //MUL 62 sseDIV = 0x5E, // DIV
68 sseDIV = 0x5E, //DIV 63 sseMIN = 0x5D, // MIN
69 sseMIN = 0x5D, //MIN 64 sseMAX = 0x5F, // MAX
70 sseMAX = 0x5F, //MAX 65 sseCOMIS = 0x2F, // COMIS
71 sseCOMIS = 0x2F, //COMIS 66 sseUCOMIS = 0x2E, // UCOMIS
72 sseUCOMIS = 0x2E, //UCOMIS 67 sseSQRT = 0x51, // SQRT
73 sseSQRT = 0x51, //SQRT 68 sseRSQRT = 0x52, // RSQRT (NO DOUBLE PRECISION!!!)
74 sseRSQRT = 0x52, //RSQRT (NO DOUBLE PRECISION!!!) 69 sseRCP = 0x53, // RCP
75 sseRCP = 0x53, //RCP 70 sseMOVAPfromRM = 0x28, // MOVAP from RM
76 sseMOVAPfromRM = 0x28, //MOVAP from RM 71 sseMOVAPtoRM = 0x29, // MOVAP to RM
77 sseMOVAPtoRM = 0x29, //MOVAP to RM 72 sseMOVUPfromRM = 0x10, // MOVUP from RM
78 sseMOVUPfromRM = 0x10, //MOVUP from RM 73 sseMOVUPtoRM = 0x11, // MOVUP to RM
79 sseMOVUPtoRM = 0x11, //MOVUP to RM 74 sseMOVLPfromRM = 0x12,
80 sseMOVLPfromRM= 0x12, 75 sseMOVLPtoRM = 0x13,
81 sseMOVLPtoRM = 0x13, 76 sseMOVHPfromRM = 0x16,
82 sseMOVHPfromRM= 0x16, 77 sseMOVHPtoRM = 0x17,
83 sseMOVHPtoRM = 0x17, 78 sseMOVHLPS = 0x12,
84 sseMOVHLPS = 0x12, 79 sseMOVLHPS = 0x16,
85 sseMOVLHPS = 0x16,
86 sseMOVDQfromRM = 0x6F, 80 sseMOVDQfromRM = 0x6F,
87 sseMOVDQtoRM = 0x7F, 81 sseMOVDQtoRM = 0x7F,
88 sseMASKMOVDQU = 0xF7, 82 sseMASKMOVDQU = 0xF7,
89 sseLDDQU = 0xF0, 83 sseLDDQU = 0xF0,
90 sseSHUF = 0xC6, 84 sseSHUF = 0xC6,
91 sseMOVNTDQ = 0xE7, 85 sseMOVNTDQ = 0xE7,
92 sseMOVNTP = 0x2B, 86 sseMOVNTP = 0x2B,
93 sseHADD = 0x7C, 87 sseHADD = 0x7C,
94}; 88};
95 89
96 90void XEmitter::SetCodePtr(u8* ptr) {
97void XEmitter::SetCodePtr(u8 *ptr)
98{
99 code = ptr; 91 code = ptr;
100} 92}
101 93
102const u8 *XEmitter::GetCodePtr() const 94const u8* XEmitter::GetCodePtr() const {
103{
104 return code; 95 return code;
105} 96}
106 97
107u8 *XEmitter::GetWritableCodePtr() 98u8* XEmitter::GetWritableCodePtr() {
108{
109 return code; 99 return code;
110} 100}
111 101
112void XEmitter::Write8(u8 value) 102void XEmitter::Write8(u8 value) {
113{
114 *code++ = value; 103 *code++ = value;
115} 104}
116 105
117void XEmitter::Write16(u16 value) 106void XEmitter::Write16(u16 value) {
118{
119 std::memcpy(code, &value, sizeof(u16)); 107 std::memcpy(code, &value, sizeof(u16));
120 code += sizeof(u16); 108 code += sizeof(u16);
121} 109}
122 110
123void XEmitter::Write32(u32 value) 111void XEmitter::Write32(u32 value) {
124{
125 std::memcpy(code, &value, sizeof(u32)); 112 std::memcpy(code, &value, sizeof(u32));
126 code += sizeof(u32); 113 code += sizeof(u32);
127} 114}
128 115
129void XEmitter::Write64(u64 value) 116void XEmitter::Write64(u64 value) {
130{
131 std::memcpy(code, &value, sizeof(u64)); 117 std::memcpy(code, &value, sizeof(u64));
132 code += sizeof(u64); 118 code += sizeof(u64);
133} 119}
134 120
135void XEmitter::ReserveCodeSpace(int bytes) 121void XEmitter::ReserveCodeSpace(int bytes) {
136{
137 for (int i = 0; i < bytes; i++) 122 for (int i = 0; i < bytes; i++)
138 *code++ = 0xCC; 123 *code++ = 0xCC;
139} 124}
140 125
141const u8 *XEmitter::AlignCode4() 126const u8* XEmitter::AlignCode4() {
142{
143 int c = int((u64)code & 3); 127 int c = int((u64)code & 3);
144 if (c) 128 if (c)
145 ReserveCodeSpace(4-c); 129 ReserveCodeSpace(4 - c);
146 return code; 130 return code;
147} 131}
148 132
149const u8 *XEmitter::AlignCode16() 133const u8* XEmitter::AlignCode16() {
150{
151 int c = int((u64)code & 15); 134 int c = int((u64)code & 15);
152 if (c) 135 if (c)
153 ReserveCodeSpace(16-c); 136 ReserveCodeSpace(16 - c);
154 return code; 137 return code;
155} 138}
156 139
157const u8 *XEmitter::AlignCodePage() 140const u8* XEmitter::AlignCodePage() {
158{
159 int c = int((u64)code & 4095); 141 int c = int((u64)code & 4095);
160 if (c) 142 if (c)
161 ReserveCodeSpace(4096-c); 143 ReserveCodeSpace(4096 - c);
162 return code; 144 return code;
163} 145}
164 146
165// This operation modifies flags; check to see the flags are locked. 147// This operation modifies flags; check to see the flags are locked.
166// If the flags are locked, we should immediately and loudly fail before 148// If the flags are locked, we should immediately and loudly fail before
167// causing a subtle JIT bug. 149// causing a subtle JIT bug.
168void XEmitter::CheckFlags() 150void XEmitter::CheckFlags() {
169{
170 ASSERT_MSG(!flags_locked, "Attempt to modify flags while flags locked!"); 151 ASSERT_MSG(!flags_locked, "Attempt to modify flags while flags locked!");
171} 152}
172 153
173void XEmitter::WriteModRM(int mod, int reg, int rm) 154void XEmitter::WriteModRM(int mod, int reg, int rm) {
174{
175 Write8((u8)((mod << 6) | ((reg & 7) << 3) | (rm & 7))); 155 Write8((u8)((mod << 6) | ((reg & 7) << 3) | (rm & 7)));
176} 156}
177 157
178void XEmitter::WriteSIB(int scale, int index, int base) 158void XEmitter::WriteSIB(int scale, int index, int base) {
179{
180 Write8((u8)((scale << 6) | ((index & 7) << 3) | (base & 7))); 159 Write8((u8)((scale << 6) | ((index & 7) << 3) | (base & 7)));
181} 160}
182 161
183void OpArg::WriteRex(XEmitter *emit, int opBits, int bits, int customOp) const 162void OpArg::WriteRex(XEmitter* emit, int opBits, int bits, int customOp) const {
184{ 163 if (customOp == -1)
185 if (customOp == -1) customOp = operandReg; 164 customOp = operandReg;
186#ifdef ARCHITECTURE_x86_64 165#ifdef ARCHITECTURE_x86_64
187 u8 op = 0x40; 166 u8 op = 0x40;
188 // REX.W (whether operation is a 64-bit operation) 167 // REX.W (whether operation is a 64-bit operation)
189 if (opBits == 64) op |= 8; 168 if (opBits == 64)
169 op |= 8;
190 // REX.R (whether ModR/M reg field refers to R8-R15. 170 // REX.R (whether ModR/M reg field refers to R8-R15.
191 if (customOp & 8) op |= 4; 171 if (customOp & 8)
172 op |= 4;
192 // REX.X (whether ModR/M SIB index field refers to R8-R15) 173 // REX.X (whether ModR/M SIB index field refers to R8-R15)
193 if (indexReg & 8) op |= 2; 174 if (indexReg & 8)
175 op |= 2;
194 // REX.B (whether ModR/M rm or SIB base or opcode reg field refers to R8-R15) 176 // REX.B (whether ModR/M rm or SIB base or opcode reg field refers to R8-R15)
195 if (offsetOrBaseReg & 8) op |= 1; 177 if (offsetOrBaseReg & 8)
178 op |= 1;
196 // Write REX if wr have REX bits to write, or if the operation accesses 179 // Write REX if wr have REX bits to write, or if the operation accesses
197 // SIL, DIL, BPL, or SPL. 180 // SIL, DIL, BPL, or SPL.
198 if (op != 0x40 || 181 if (op != 0x40 || (scale == SCALE_NONE && bits == 8 && (offsetOrBaseReg & 0x10c) == 4) ||
199 (scale == SCALE_NONE && bits == 8 && (offsetOrBaseReg & 0x10c) == 4) || 182 (opBits == 8 && (customOp & 0x10c) == 4)) {
200 (opBits == 8 && (customOp & 0x10c) == 4))
201 {
202 emit->Write8(op); 183 emit->Write8(op);
203 // Check the operation doesn't access AH, BH, CH, or DH. 184 // Check the operation doesn't access AH, BH, CH, or DH.
204 DEBUG_ASSERT((offsetOrBaseReg & 0x100) == 0); 185 DEBUG_ASSERT((offsetOrBaseReg & 0x100) == 0);
@@ -214,8 +195,8 @@ void OpArg::WriteRex(XEmitter *emit, int opBits, int bits, int customOp) const
214#endif 195#endif
215} 196}
216 197
217void OpArg::WriteVex(XEmitter* emit, X64Reg regOp1, X64Reg regOp2, int L, int pp, int mmmmm, int W) const 198void OpArg::WriteVex(XEmitter* emit, X64Reg regOp1, X64Reg regOp2, int L, int pp, int mmmmm,
218{ 199 int W) const {
219 int R = !(regOp1 & 8); 200 int R = !(regOp1 & 8);
220 int X = !(indexReg & 8); 201 int X = !(indexReg & 8);
221 int B = !(offsetOrBaseReg & 8); 202 int B = !(offsetOrBaseReg & 8);
@@ -223,14 +204,11 @@ void OpArg::WriteVex(XEmitter* emit, X64Reg regOp1, X64Reg regOp2, int L, int pp
223 int vvvv = (regOp2 == X64Reg::INVALID_REG) ? 0xf : (regOp2 ^ 0xf); 204 int vvvv = (regOp2 == X64Reg::INVALID_REG) ? 0xf : (regOp2 ^ 0xf);
224 205
225 // do we need any VEX fields that only appear in the three-byte form? 206 // do we need any VEX fields that only appear in the three-byte form?
226 if (X == 1 && B == 1 && W == 0 && mmmmm == 1) 207 if (X == 1 && B == 1 && W == 0 && mmmmm == 1) {
227 {
228 u8 RvvvvLpp = (R << 7) | (vvvv << 3) | (L << 2) | pp; 208 u8 RvvvvLpp = (R << 7) | (vvvv << 3) | (L << 2) | pp;
229 emit->Write8(0xC5); 209 emit->Write8(0xC5);
230 emit->Write8(RvvvvLpp); 210 emit->Write8(RvvvvLpp);
231 } 211 } else {
232 else
233 {
234 u8 RXBmmmmm = (R << 7) | (X << 6) | (B << 5) | mmmmm; 212 u8 RXBmmmmm = (R << 7) | (X << 6) | (B << 5) | mmmmm;
235 u8 WvvvvLpp = (W << 7) | (vvvv << 3) | (L << 2) | pp; 213 u8 WvvvvLpp = (W << 7) | (vvvv << 3) | (L << 2) | pp;
236 emit->Write8(0xC4); 214 emit->Write8(0xC4);
@@ -239,9 +217,8 @@ void OpArg::WriteVex(XEmitter* emit, X64Reg regOp1, X64Reg regOp2, int L, int pp
239 } 217 }
240} 218}
241 219
242void OpArg::WriteRest(XEmitter *emit, int extraBytes, X64Reg _operandReg, 220void OpArg::WriteRest(XEmitter* emit, int extraBytes, X64Reg _operandReg,
243 bool warn_64bit_offset) const 221 bool warn_64bit_offset) const {
244{
245 if (_operandReg == INVALID_REG) 222 if (_operandReg == INVALID_REG)
246 _operandReg = (X64Reg)this->operandReg; 223 _operandReg = (X64Reg)this->operandReg;
247 int mod = 0; 224 int mod = 0;
@@ -249,21 +226,18 @@ void OpArg::WriteRest(XEmitter *emit, int extraBytes, X64Reg _operandReg,
249 bool SIB = false; 226 bool SIB = false;
250 int _offsetOrBaseReg = this->offsetOrBaseReg; 227 int _offsetOrBaseReg = this->offsetOrBaseReg;
251 228
252 if (scale == SCALE_RIP) //Also, on 32-bit, just an immediate address 229 if (scale == SCALE_RIP) // Also, on 32-bit, just an immediate address
253 { 230 {
254 // Oh, RIP addressing. 231 // Oh, RIP addressing.
255 _offsetOrBaseReg = 5; 232 _offsetOrBaseReg = 5;
256 emit->WriteModRM(0, _operandReg, _offsetOrBaseReg); 233 emit->WriteModRM(0, _operandReg, _offsetOrBaseReg);
257 //TODO : add some checks 234// TODO : add some checks
258#ifdef ARCHITECTURE_x86_64 235#ifdef ARCHITECTURE_x86_64
259 u64 ripAddr = (u64)emit->GetCodePtr() + 4 + extraBytes; 236 u64 ripAddr = (u64)emit->GetCodePtr() + 4 + extraBytes;
260 s64 distance = (s64)offset - (s64)ripAddr; 237 s64 distance = (s64)offset - (s64)ripAddr;
261 ASSERT_MSG( 238 ASSERT_MSG((distance < 0x80000000LL && distance >= -0x80000000LL) || !warn_64bit_offset,
262 (distance < 0x80000000LL && 239 "WriteRest: op out of range (0x%" PRIx64 " uses 0x%" PRIx64 ")", ripAddr,
263 distance >= -0x80000000LL) || 240 offset);
264 !warn_64bit_offset,
265 "WriteRest: op out of range (0x%" PRIx64 " uses 0x%" PRIx64 ")",
266 ripAddr, offset);
267 s32 offs = (s32)distance; 241 s32 offs = (s32)distance;
268 emit->Write32((u32)offs); 242 emit->Write32((u32)offs);
269#else 243#else
@@ -272,66 +246,49 @@ void OpArg::WriteRest(XEmitter *emit, int extraBytes, X64Reg _operandReg,
272 return; 246 return;
273 } 247 }
274 248
275 if (scale == 0) 249 if (scale == 0) {
276 {
277 // Oh, no memory, Just a reg. 250 // Oh, no memory, Just a reg.
278 mod = 3; //11 251 mod = 3; // 11
279 } 252 } else if (scale >= 1) {
280 else if (scale >= 1) 253 // Ah good, no scaling.
281 { 254 if (scale == SCALE_ATREG && !((_offsetOrBaseReg & 7) == 4 || (_offsetOrBaseReg & 7) == 5)) {
282 //Ah good, no scaling. 255 // Okay, we're good. No SIB necessary.
283 if (scale == SCALE_ATREG && !((_offsetOrBaseReg & 7) == 4 || (_offsetOrBaseReg & 7) == 5))
284 {
285 //Okay, we're good. No SIB necessary.
286 int ioff = (int)offset; 256 int ioff = (int)offset;
287 if (ioff == 0) 257 if (ioff == 0) {
288 {
289 mod = 0; 258 mod = 0;
259 } else if (ioff < -128 || ioff > 127) {
260 mod = 2; // 32-bit displacement
261 } else {
262 mod = 1; // 8-bit displacement
290 } 263 }
291 else if (ioff<-128 || ioff>127) 264 } else if (scale >= SCALE_NOBASE_2 && scale <= SCALE_NOBASE_8) {
292 {
293 mod = 2; //32-bit displacement
294 }
295 else
296 {
297 mod = 1; //8-bit displacement
298 }
299 }
300 else if (scale >= SCALE_NOBASE_2 && scale <= SCALE_NOBASE_8)
301 {
302 SIB = true; 265 SIB = true;
303 mod = 0; 266 mod = 0;
304 _offsetOrBaseReg = 5; 267 _offsetOrBaseReg = 5;
305 } 268 } else // if (scale != SCALE_ATREG)
306 else //if (scale != SCALE_ATREG)
307 { 269 {
308 if ((_offsetOrBaseReg & 7) == 4) //this would occupy the SIB encoding :( 270 if ((_offsetOrBaseReg & 7) == 4) // this would occupy the SIB encoding :(
309 { 271 {
310 //So we have to fake it with SIB encoding :( 272 // So we have to fake it with SIB encoding :(
311 SIB = true; 273 SIB = true;
312 } 274 }
313 275
314 if (scale >= SCALE_1 && scale < SCALE_ATREG) 276 if (scale >= SCALE_1 && scale < SCALE_ATREG) {
315 {
316 SIB = true; 277 SIB = true;
317 } 278 }
318 279
319 if (scale == SCALE_ATREG && ((_offsetOrBaseReg & 7) == 4)) 280 if (scale == SCALE_ATREG && ((_offsetOrBaseReg & 7) == 4)) {
320 {
321 SIB = true; 281 SIB = true;
322 ireg = _offsetOrBaseReg; 282 ireg = _offsetOrBaseReg;
323 } 283 }
324 284
325 //Okay, we're fine. Just disp encoding. 285 // Okay, we're fine. Just disp encoding.
326 //We need displacement. Which size? 286 // We need displacement. Which size?
327 int ioff = (int)(s64)offset; 287 int ioff = (int)(s64)offset;
328 if (ioff < -128 || ioff > 127) 288 if (ioff < -128 || ioff > 127) {
329 { 289 mod = 2; // 32-bit displacement
330 mod = 2; //32-bit displacement 290 } else {
331 } 291 mod = 1; // 8-bit displacement
332 else
333 {
334 mod = 1; //8-bit displacement
335 } 292 }
336 } 293 }
337 } 294 }
@@ -343,36 +300,55 @@ void OpArg::WriteRest(XEmitter *emit, int extraBytes, X64Reg _operandReg,
343 oreg = 4; 300 oreg = 4;
344 301
345 // TODO(ector): WTF is this if about? I don't remember writing it :-) 302 // TODO(ector): WTF is this if about? I don't remember writing it :-)
346 //if (RIP) 303 // if (RIP)
347 // oreg = 5; 304 // oreg = 5;
348 305
349 emit->WriteModRM(mod, _operandReg&7, oreg&7); 306 emit->WriteModRM(mod, _operandReg & 7, oreg & 7);
350 307
351 if (SIB) 308 if (SIB) {
352 { 309 // SIB byte
353 //SIB byte
354 int ss; 310 int ss;
355 switch (scale) 311 switch (scale) {
356 { 312 case SCALE_NONE:
357 case SCALE_NONE: _offsetOrBaseReg = 4; ss = 0; break; //RSP 313 _offsetOrBaseReg = 4;
358 case SCALE_1: ss = 0; break; 314 ss = 0;
359 case SCALE_2: ss = 1; break; 315 break; // RSP
360 case SCALE_4: ss = 2; break; 316 case SCALE_1:
361 case SCALE_8: ss = 3; break; 317 ss = 0;
362 case SCALE_NOBASE_2: ss = 1; break; 318 break;
363 case SCALE_NOBASE_4: ss = 2; break; 319 case SCALE_2:
364 case SCALE_NOBASE_8: ss = 3; break; 320 ss = 1;
365 case SCALE_ATREG: ss = 0; break; 321 break;
366 default: ASSERT_MSG(0, "Invalid scale for SIB byte"); ss = 0; break; 322 case SCALE_4:
323 ss = 2;
324 break;
325 case SCALE_8:
326 ss = 3;
327 break;
328 case SCALE_NOBASE_2:
329 ss = 1;
330 break;
331 case SCALE_NOBASE_4:
332 ss = 2;
333 break;
334 case SCALE_NOBASE_8:
335 ss = 3;
336 break;
337 case SCALE_ATREG:
338 ss = 0;
339 break;
340 default:
341 ASSERT_MSG(0, "Invalid scale for SIB byte");
342 ss = 0;
343 break;
367 } 344 }
368 emit->Write8((u8)((ss << 6) | ((ireg&7)<<3) | (_offsetOrBaseReg&7))); 345 emit->Write8((u8)((ss << 6) | ((ireg & 7) << 3) | (_offsetOrBaseReg & 7)));
369 } 346 }
370 347
371 if (mod == 1) //8-bit disp 348 if (mod == 1) // 8-bit disp
372 { 349 {
373 emit->Write8((u8)(s8)(s32)offset); 350 emit->Write8((u8)(s8)(s32)offset);
374 } 351 } else if (mod == 2 || (scale >= SCALE_NOBASE_2 && scale <= SCALE_NOBASE_8)) // 32-bit disp
375 else if (mod == 2 || (scale >= SCALE_NOBASE_2 && scale <= SCALE_NOBASE_8)) //32-bit disp
376 { 352 {
377 emit->Write32((u32)offset); 353 emit->Write32((u32)offset);
378 } 354 }
@@ -382,8 +358,7 @@ void OpArg::WriteRest(XEmitter *emit, int extraBytes, X64Reg _operandReg,
382// R = register# upper bit 358// R = register# upper bit
383// X = scale amnt upper bit 359// X = scale amnt upper bit
384// B = base register# upper bit 360// B = base register# upper bit
385void XEmitter::Rex(int w, int r, int x, int b) 361void XEmitter::Rex(int w, int r, int x, int b) {
386{
387 w = w ? 1 : 0; 362 w = w ? 1 : 0;
388 r = r ? 1 : 0; 363 r = r ? 1 : 0;
389 x = x ? 1 : 0; 364 x = x ? 1 : 0;
@@ -393,70 +368,60 @@ void XEmitter::Rex(int w, int r, int x, int b)
393 Write8(rx); 368 Write8(rx);
394} 369}
395 370
396void XEmitter::JMP(const u8* addr, bool force5Bytes) 371void XEmitter::JMP(const u8* addr, bool force5Bytes) {
397{
398 u64 fn = (u64)addr; 372 u64 fn = (u64)addr;
399 if (!force5Bytes) 373 if (!force5Bytes) {
400 {
401 s64 distance = (s64)(fn - ((u64)code + 2)); 374 s64 distance = (s64)(fn - ((u64)code + 2));
402 ASSERT_MSG(distance >= -0x80 && distance < 0x80, 375 ASSERT_MSG(distance >= -0x80 && distance < 0x80,
403 "Jump target too far away, needs force5Bytes = true"); 376 "Jump target too far away, needs force5Bytes = true");
404 //8 bits will do 377 // 8 bits will do
405 Write8(0xEB); 378 Write8(0xEB);
406 Write8((u8)(s8)distance); 379 Write8((u8)(s8)distance);
407 } 380 } else {
408 else
409 {
410 s64 distance = (s64)(fn - ((u64)code + 5)); 381 s64 distance = (s64)(fn - ((u64)code + 5));
411 382
412 ASSERT_MSG( 383 ASSERT_MSG(distance >= -0x80000000LL && distance < 0x80000000LL,
413 distance >= -0x80000000LL && distance < 0x80000000LL, 384 "Jump target too far away, needs indirect register");
414 "Jump target too far away, needs indirect register");
415 Write8(0xE9); 385 Write8(0xE9);
416 Write32((u32)(s32)distance); 386 Write32((u32)(s32)distance);
417 } 387 }
418} 388}
419 389
420void XEmitter::JMPptr(const OpArg& arg2) 390void XEmitter::JMPptr(const OpArg& arg2) {
421{
422 OpArg arg = arg2; 391 OpArg arg = arg2;
423 if (arg.IsImm()) ASSERT_MSG(0, "JMPptr - Imm argument"); 392 if (arg.IsImm())
393 ASSERT_MSG(0, "JMPptr - Imm argument");
424 arg.operandReg = 4; 394 arg.operandReg = 4;
425 arg.WriteRex(this, 0, 0); 395 arg.WriteRex(this, 0, 0);
426 Write8(0xFF); 396 Write8(0xFF);
427 arg.WriteRest(this); 397 arg.WriteRest(this);
428} 398}
429 399
430//Can be used to trap other processors, before overwriting their code 400// Can be used to trap other processors, before overwriting their code
431// not used in dolphin 401// not used in dolphin
432void XEmitter::JMPself() 402void XEmitter::JMPself() {
433{
434 Write8(0xEB); 403 Write8(0xEB);
435 Write8(0xFE); 404 Write8(0xFE);
436} 405}
437 406
438void XEmitter::CALLptr(OpArg arg) 407void XEmitter::CALLptr(OpArg arg) {
439{ 408 if (arg.IsImm())
440 if (arg.IsImm()) ASSERT_MSG(0, "CALLptr - Imm argument"); 409 ASSERT_MSG(0, "CALLptr - Imm argument");
441 arg.operandReg = 2; 410 arg.operandReg = 2;
442 arg.WriteRex(this, 0, 0); 411 arg.WriteRex(this, 0, 0);
443 Write8(0xFF); 412 Write8(0xFF);
444 arg.WriteRest(this); 413 arg.WriteRest(this);
445} 414}
446 415
447void XEmitter::CALL(const void* fnptr) 416void XEmitter::CALL(const void* fnptr) {
448{
449 u64 distance = u64(fnptr) - (u64(code) + 5); 417 u64 distance = u64(fnptr) - (u64(code) + 5);
450 ASSERT_MSG( 418 ASSERT_MSG(distance < 0x0000000080000000ULL || distance >= 0xFFFFFFFF80000000ULL,
451 distance < 0x0000000080000000ULL || 419 "CALL out of range (%p calls %p)", code, fnptr);
452 distance >= 0xFFFFFFFF80000000ULL,
453 "CALL out of range (%p calls %p)", code, fnptr);
454 Write8(0xE8); 420 Write8(0xE8);
455 Write32(u32(distance)); 421 Write32(u32(distance));
456} 422}
457 423
458FixupBranch XEmitter::CALL() 424FixupBranch XEmitter::CALL() {
459{
460 FixupBranch branch; 425 FixupBranch branch;
461 branch.type = 1; 426 branch.type = 1;
462 branch.ptr = code + 5; 427 branch.ptr = code + 5;
@@ -467,38 +432,30 @@ FixupBranch XEmitter::CALL()
467 return branch; 432 return branch;
468} 433}
469 434
470FixupBranch XEmitter::J(bool force5bytes) 435FixupBranch XEmitter::J(bool force5bytes) {
471{
472 FixupBranch branch; 436 FixupBranch branch;
473 branch.type = force5bytes ? 1 : 0; 437 branch.type = force5bytes ? 1 : 0;
474 branch.ptr = code + (force5bytes ? 5 : 2); 438 branch.ptr = code + (force5bytes ? 5 : 2);
475 if (!force5bytes) 439 if (!force5bytes) {
476 { 440 // 8 bits will do
477 //8 bits will do
478 Write8(0xEB); 441 Write8(0xEB);
479 Write8(0); 442 Write8(0);
480 } 443 } else {
481 else
482 {
483 Write8(0xE9); 444 Write8(0xE9);
484 Write32(0); 445 Write32(0);
485 } 446 }
486 return branch; 447 return branch;
487} 448}
488 449
489FixupBranch XEmitter::J_CC(CCFlags conditionCode, bool force5bytes) 450FixupBranch XEmitter::J_CC(CCFlags conditionCode, bool force5bytes) {
490{
491 FixupBranch branch; 451 FixupBranch branch;
492 branch.type = force5bytes ? 1 : 0; 452 branch.type = force5bytes ? 1 : 0;
493 branch.ptr = code + (force5bytes ? 6 : 2); 453 branch.ptr = code + (force5bytes ? 6 : 2);
494 if (!force5bytes) 454 if (!force5bytes) {
495 { 455 // 8 bits will do
496 //8 bits will do
497 Write8(0x70 + conditionCode); 456 Write8(0x70 + conditionCode);
498 Write8(0); 457 Write8(0);
499 } 458 } else {
500 else
501 {
502 Write8(0x0F); 459 Write8(0x0F);
503 Write8(0x80 + conditionCode); 460 Write8(0x80 + conditionCode);
504 Write32(0); 461 Write32(0);
@@ -506,198 +463,268 @@ FixupBranch XEmitter::J_CC(CCFlags conditionCode, bool force5bytes)
506 return branch; 463 return branch;
507} 464}
508 465
509void XEmitter::J_CC(CCFlags conditionCode, const u8* addr, bool force5bytes) 466void XEmitter::J_CC(CCFlags conditionCode, const u8* addr, bool force5bytes) {
510{
511 u64 fn = (u64)addr; 467 u64 fn = (u64)addr;
512 s64 distance = (s64)(fn - ((u64)code + 2)); 468 s64 distance = (s64)(fn - ((u64)code + 2));
513 if (distance < -0x80 || distance >= 0x80 || force5bytes) 469 if (distance < -0x80 || distance >= 0x80 || force5bytes) {
514 {
515 distance = (s64)(fn - ((u64)code + 6)); 470 distance = (s64)(fn - ((u64)code + 6));
516 ASSERT_MSG( 471 ASSERT_MSG(distance >= -0x80000000LL && distance < 0x80000000LL,
517 distance >= -0x80000000LL && distance < 0x80000000LL, 472 "Jump target too far away, needs indirect register");
518 "Jump target too far away, needs indirect register");
519 Write8(0x0F); 473 Write8(0x0F);
520 Write8(0x80 + conditionCode); 474 Write8(0x80 + conditionCode);
521 Write32((u32)(s32)distance); 475 Write32((u32)(s32)distance);
522 } 476 } else {
523 else
524 {
525 Write8(0x70 + conditionCode); 477 Write8(0x70 + conditionCode);
526 Write8((u8)(s8)distance); 478 Write8((u8)(s8)distance);
527 } 479 }
528} 480}
529 481
530void XEmitter::SetJumpTarget(const FixupBranch& branch) 482void XEmitter::SetJumpTarget(const FixupBranch& branch) {
531{ 483 if (branch.type == 0) {
532 if (branch.type == 0)
533 {
534 s64 distance = (s64)(code - branch.ptr); 484 s64 distance = (s64)(code - branch.ptr);
535 ASSERT_MSG(distance >= -0x80 && distance < 0x80, "Jump target too far away, needs force5Bytes = true"); 485 ASSERT_MSG(distance >= -0x80 && distance < 0x80,
486 "Jump target too far away, needs force5Bytes = true");
536 branch.ptr[-1] = (u8)(s8)distance; 487 branch.ptr[-1] = (u8)(s8)distance;
537 } 488 } else if (branch.type == 1) {
538 else if (branch.type == 1)
539 {
540 s64 distance = (s64)(code - branch.ptr); 489 s64 distance = (s64)(code - branch.ptr);
541 ASSERT_MSG(distance >= -0x80000000LL && distance < 0x80000000LL, "Jump target too far away, needs indirect register"); 490 ASSERT_MSG(distance >= -0x80000000LL && distance < 0x80000000LL,
491 "Jump target too far away, needs indirect register");
542 ((s32*)branch.ptr)[-1] = (s32)distance; 492 ((s32*)branch.ptr)[-1] = (s32)distance;
543 } 493 }
544} 494}
545 495
546void XEmitter::SetJumpTarget(const FixupBranch& branch, const u8* target) 496void XEmitter::SetJumpTarget(const FixupBranch& branch, const u8* target) {
547{ 497 if (branch.type == 0) {
548 if (branch.type == 0)
549 {
550 s64 distance = (s64)(target - branch.ptr); 498 s64 distance = (s64)(target - branch.ptr);
551 ASSERT_MSG(distance >= -0x80 && distance < 0x80, "Jump target too far away, needs force5Bytes = true"); 499 ASSERT_MSG(distance >= -0x80 && distance < 0x80,
500 "Jump target too far away, needs force5Bytes = true");
552 branch.ptr[-1] = (u8)(s8)distance; 501 branch.ptr[-1] = (u8)(s8)distance;
553 } 502 } else if (branch.type == 1) {
554 else if (branch.type == 1)
555 {
556 s64 distance = (s64)(target - branch.ptr); 503 s64 distance = (s64)(target - branch.ptr);
557 ASSERT_MSG(distance >= -0x80000000LL && distance < 0x80000000LL, "Jump target too far away, needs indirect register"); 504 ASSERT_MSG(distance >= -0x80000000LL && distance < 0x80000000LL,
505 "Jump target too far away, needs indirect register");
558 ((s32*)branch.ptr)[-1] = (s32)distance; 506 ((s32*)branch.ptr)[-1] = (s32)distance;
559 } 507 }
560} 508}
561 509
562//Single byte opcodes 510// Single byte opcodes
563//There is no PUSHAD/POPAD in 64-bit mode. 511// There is no PUSHAD/POPAD in 64-bit mode.
564void XEmitter::INT3() {Write8(0xCC);} 512void XEmitter::INT3() {
565void XEmitter::RET() {Write8(0xC3);} 513 Write8(0xCC);
566void XEmitter::RET_FAST() {Write8(0xF3); Write8(0xC3);} //two-byte return (rep ret) - recommended by AMD optimization manual for the case of jumping to a ret 514}
515void XEmitter::RET() {
516 Write8(0xC3);
517}
518void XEmitter::RET_FAST() {
519 Write8(0xF3);
520 Write8(0xC3);
521} // two-byte return (rep ret) - recommended by AMD optimization manual for the case of jumping to a
522 // ret
567 523
568// The first sign of decadence: optimized NOPs. 524// The first sign of decadence: optimized NOPs.
569void XEmitter::NOP(size_t size) 525void XEmitter::NOP(size_t size) {
570{
571 DEBUG_ASSERT((int)size > 0); 526 DEBUG_ASSERT((int)size > 0);
572 while (true) 527 while (true) {
573 { 528 switch (size) {
574 switch (size)
575 {
576 case 0: 529 case 0:
577 return; 530 return;
578 case 1: 531 case 1:
579 Write8(0x90); 532 Write8(0x90);
580 return; 533 return;
581 case 2: 534 case 2:
582 Write8(0x66); Write8(0x90); 535 Write8(0x66);
536 Write8(0x90);
583 return; 537 return;
584 case 3: 538 case 3:
585 Write8(0x0F); Write8(0x1F); Write8(0x00); 539 Write8(0x0F);
540 Write8(0x1F);
541 Write8(0x00);
586 return; 542 return;
587 case 4: 543 case 4:
588 Write8(0x0F); Write8(0x1F); Write8(0x40); Write8(0x00); 544 Write8(0x0F);
545 Write8(0x1F);
546 Write8(0x40);
547 Write8(0x00);
589 return; 548 return;
590 case 5: 549 case 5:
591 Write8(0x0F); Write8(0x1F); Write8(0x44); Write8(0x00); 550 Write8(0x0F);
551 Write8(0x1F);
552 Write8(0x44);
553 Write8(0x00);
592 Write8(0x00); 554 Write8(0x00);
593 return; 555 return;
594 case 6: 556 case 6:
595 Write8(0x66); Write8(0x0F); Write8(0x1F); Write8(0x44); 557 Write8(0x66);
596 Write8(0x00); Write8(0x00); 558 Write8(0x0F);
559 Write8(0x1F);
560 Write8(0x44);
561 Write8(0x00);
562 Write8(0x00);
597 return; 563 return;
598 case 7: 564 case 7:
599 Write8(0x0F); Write8(0x1F); Write8(0x80); Write8(0x00); 565 Write8(0x0F);
600 Write8(0x00); Write8(0x00); Write8(0x00); 566 Write8(0x1F);
567 Write8(0x80);
568 Write8(0x00);
569 Write8(0x00);
570 Write8(0x00);
571 Write8(0x00);
601 return; 572 return;
602 case 8: 573 case 8:
603 Write8(0x0F); Write8(0x1F); Write8(0x84); Write8(0x00); 574 Write8(0x0F);
604 Write8(0x00); Write8(0x00); Write8(0x00); Write8(0x00); 575 Write8(0x1F);
576 Write8(0x84);
577 Write8(0x00);
578 Write8(0x00);
579 Write8(0x00);
580 Write8(0x00);
581 Write8(0x00);
605 return; 582 return;
606 case 9: 583 case 9:
607 Write8(0x66); Write8(0x0F); Write8(0x1F); Write8(0x84); 584 Write8(0x66);
608 Write8(0x00); Write8(0x00); Write8(0x00); Write8(0x00); 585 Write8(0x0F);
586 Write8(0x1F);
587 Write8(0x84);
588 Write8(0x00);
589 Write8(0x00);
590 Write8(0x00);
591 Write8(0x00);
609 Write8(0x00); 592 Write8(0x00);
610 return; 593 return;
611 case 10: 594 case 10:
612 Write8(0x66); Write8(0x66); Write8(0x0F); Write8(0x1F); 595 Write8(0x66);
613 Write8(0x84); Write8(0x00); Write8(0x00); Write8(0x00); 596 Write8(0x66);
614 Write8(0x00); Write8(0x00); 597 Write8(0x0F);
598 Write8(0x1F);
599 Write8(0x84);
600 Write8(0x00);
601 Write8(0x00);
602 Write8(0x00);
603 Write8(0x00);
604 Write8(0x00);
615 return; 605 return;
616 default: 606 default:
617 // Even though x86 instructions are allowed to be up to 15 bytes long, 607 // Even though x86 instructions are allowed to be up to 15 bytes long,
618 // AMD advises against using NOPs longer than 11 bytes because they 608 // AMD advises against using NOPs longer than 11 bytes because they
619 // carry a performance penalty on CPUs older than AMD family 16h. 609 // carry a performance penalty on CPUs older than AMD family 16h.
620 Write8(0x66); Write8(0x66); Write8(0x66); Write8(0x0F); 610 Write8(0x66);
621 Write8(0x1F); Write8(0x84); Write8(0x00); Write8(0x00); 611 Write8(0x66);
622 Write8(0x00); Write8(0x00); Write8(0x00); 612 Write8(0x66);
613 Write8(0x0F);
614 Write8(0x1F);
615 Write8(0x84);
616 Write8(0x00);
617 Write8(0x00);
618 Write8(0x00);
619 Write8(0x00);
620 Write8(0x00);
623 size -= 11; 621 size -= 11;
624 continue; 622 continue;
625 } 623 }
626 } 624 }
627} 625}
628 626
629void XEmitter::PAUSE() {Write8(0xF3); NOP();} //use in tight spinloops for energy saving on some cpu 627void XEmitter::PAUSE() {
630void XEmitter::CLC() {CheckFlags(); Write8(0xF8);} //clear carry 628 Write8(0xF3);
631void XEmitter::CMC() {CheckFlags(); Write8(0xF5);} //flip carry 629 NOP();
632void XEmitter::STC() {CheckFlags(); Write8(0xF9);} //set carry 630} // use in tight spinloops for energy saving on some cpu
631void XEmitter::CLC() {
632 CheckFlags();
633 Write8(0xF8);
634} // clear carry
635void XEmitter::CMC() {
636 CheckFlags();
637 Write8(0xF5);
638} // flip carry
639void XEmitter::STC() {
640 CheckFlags();
641 Write8(0xF9);
642} // set carry
633 643
634//TODO: xchg ah, al ??? 644// TODO: xchg ah, al ???
635void XEmitter::XCHG_AHAL() 645void XEmitter::XCHG_AHAL() {
636{
637 Write8(0x86); 646 Write8(0x86);
638 Write8(0xe0); 647 Write8(0xe0);
639 // alt. 86 c4 648 // alt. 86 c4
640} 649}
641 650
642//These two can not be executed on early Intel 64-bit CPU:s, only on AMD! 651// These two can not be executed on early Intel 64-bit CPU:s, only on AMD!
643void XEmitter::LAHF() {Write8(0x9F);} 652void XEmitter::LAHF() {
644void XEmitter::SAHF() {CheckFlags(); Write8(0x9E);} 653 Write8(0x9F);
654}
655void XEmitter::SAHF() {
656 CheckFlags();
657 Write8(0x9E);
658}
645 659
646void XEmitter::PUSHF() {Write8(0x9C);} 660void XEmitter::PUSHF() {
647void XEmitter::POPF() {CheckFlags(); Write8(0x9D);} 661 Write8(0x9C);
662}
663void XEmitter::POPF() {
664 CheckFlags();
665 Write8(0x9D);
666}
648 667
649void XEmitter::LFENCE() {Write8(0x0F); Write8(0xAE); Write8(0xE8);} 668void XEmitter::LFENCE() {
650void XEmitter::MFENCE() {Write8(0x0F); Write8(0xAE); Write8(0xF0);} 669 Write8(0x0F);
651void XEmitter::SFENCE() {Write8(0x0F); Write8(0xAE); Write8(0xF8);} 670 Write8(0xAE);
671 Write8(0xE8);
672}
673void XEmitter::MFENCE() {
674 Write8(0x0F);
675 Write8(0xAE);
676 Write8(0xF0);
677}
678void XEmitter::SFENCE() {
679 Write8(0x0F);
680 Write8(0xAE);
681 Write8(0xF8);
682}
652 683
653void XEmitter::WriteSimple1Byte(int bits, u8 byte, X64Reg reg) 684void XEmitter::WriteSimple1Byte(int bits, u8 byte, X64Reg reg) {
654{
655 if (bits == 16) 685 if (bits == 16)
656 Write8(0x66); 686 Write8(0x66);
657 Rex(bits == 64, 0, 0, (int)reg >> 3); 687 Rex(bits == 64, 0, 0, (int)reg >> 3);
658 Write8(byte + ((int)reg & 7)); 688 Write8(byte + ((int)reg & 7));
659} 689}
660 690
661void XEmitter::WriteSimple2Byte(int bits, u8 byte1, u8 byte2, X64Reg reg) 691void XEmitter::WriteSimple2Byte(int bits, u8 byte1, u8 byte2, X64Reg reg) {
662{
663 if (bits == 16) 692 if (bits == 16)
664 Write8(0x66); 693 Write8(0x66);
665 Rex(bits==64, 0, 0, (int)reg >> 3); 694 Rex(bits == 64, 0, 0, (int)reg >> 3);
666 Write8(byte1); 695 Write8(byte1);
667 Write8(byte2 + ((int)reg & 7)); 696 Write8(byte2 + ((int)reg & 7));
668} 697}
669 698
670void XEmitter::CWD(int bits) 699void XEmitter::CWD(int bits) {
671{
672 if (bits == 16) 700 if (bits == 16)
673 Write8(0x66); 701 Write8(0x66);
674 Rex(bits == 64, 0, 0, 0); 702 Rex(bits == 64, 0, 0, 0);
675 Write8(0x99); 703 Write8(0x99);
676} 704}
677 705
678void XEmitter::CBW(int bits) 706void XEmitter::CBW(int bits) {
679{
680 if (bits == 8) 707 if (bits == 8)
681 Write8(0x66); 708 Write8(0x66);
682 Rex(bits == 32, 0, 0, 0); 709 Rex(bits == 32, 0, 0, 0);
683 Write8(0x98); 710 Write8(0x98);
684} 711}
685 712
686//Simple opcodes 713// Simple opcodes
687 714
715// push/pop do not need wide to be 64-bit
716void XEmitter::PUSH(X64Reg reg) {
717 WriteSimple1Byte(32, 0x50, reg);
718}
719void XEmitter::POP(X64Reg reg) {
720 WriteSimple1Byte(32, 0x58, reg);
721}
688 722
689//push/pop do not need wide to be 64-bit 723void XEmitter::PUSH(int bits, const OpArg& reg) {
690void XEmitter::PUSH(X64Reg reg) {WriteSimple1Byte(32, 0x50, reg);}
691void XEmitter::POP(X64Reg reg) {WriteSimple1Byte(32, 0x58, reg);}
692
693void XEmitter::PUSH(int bits, const OpArg& reg)
694{
695 if (reg.IsSimpleReg()) 724 if (reg.IsSimpleReg())
696 PUSH(reg.GetSimpleReg()); 725 PUSH(reg.GetSimpleReg());
697 else if (reg.IsImm()) 726 else if (reg.IsImm()) {
698 { 727 switch (reg.GetImmBits()) {
699 switch (reg.GetImmBits())
700 {
701 case 8: 728 case 8:
702 Write8(0x6A); 729 Write8(0x6A);
703 Write8((u8)(s8)reg.offset); 730 Write8((u8)(s8)reg.offset);
@@ -715,9 +742,7 @@ void XEmitter::PUSH(int bits, const OpArg& reg)
715 ASSERT_MSG(0, "PUSH - Bad imm bits"); 742 ASSERT_MSG(0, "PUSH - Bad imm bits");
716 break; 743 break;
717 } 744 }
718 } 745 } else {
719 else
720 {
721 if (bits == 16) 746 if (bits == 16)
722 Write8(0x66); 747 Write8(0x66);
723 reg.WriteRex(this, bits, bits); 748 reg.WriteRex(this, bits, bits);
@@ -726,44 +751,33 @@ void XEmitter::PUSH(int bits, const OpArg& reg)
726 } 751 }
727} 752}
728 753
729void XEmitter::POP(int /*bits*/, const OpArg& reg) 754void XEmitter::POP(int /*bits*/, const OpArg& reg) {
730{
731 if (reg.IsSimpleReg()) 755 if (reg.IsSimpleReg())
732 POP(reg.GetSimpleReg()); 756 POP(reg.GetSimpleReg());
733 else 757 else
734 ASSERT_MSG(0, "POP - Unsupported encoding"); 758 ASSERT_MSG(0, "POP - Unsupported encoding");
735} 759}
736 760
737void XEmitter::BSWAP(int bits, X64Reg reg) 761void XEmitter::BSWAP(int bits, X64Reg reg) {
738{ 762 if (bits >= 32) {
739 if (bits >= 32)
740 {
741 WriteSimple2Byte(bits, 0x0F, 0xC8, reg); 763 WriteSimple2Byte(bits, 0x0F, 0xC8, reg);
742 } 764 } else if (bits == 16) {
743 else if (bits == 16)
744 {
745 ROL(16, R(reg), Imm8(8)); 765 ROL(16, R(reg), Imm8(8));
746 } 766 } else if (bits == 8) {
747 else if (bits == 8)
748 {
749 // Do nothing - can't bswap a single byte... 767 // Do nothing - can't bswap a single byte...
750 } 768 } else {
751 else
752 {
753 ASSERT_MSG(0, "BSWAP - Wrong number of bits"); 769 ASSERT_MSG(0, "BSWAP - Wrong number of bits");
754 } 770 }
755} 771}
756 772
757// Undefined opcode - reserved 773// Undefined opcode - reserved
758// If we ever need a way to always cause a non-breakpoint hard exception... 774// If we ever need a way to always cause a non-breakpoint hard exception...
759void XEmitter::UD2() 775void XEmitter::UD2() {
760{
761 Write8(0x0F); 776 Write8(0x0F);
762 Write8(0x0B); 777 Write8(0x0B);
763} 778}
764 779
765void XEmitter::PREFETCH(PrefetchLevel level, OpArg arg) 780void XEmitter::PREFETCH(PrefetchLevel level, OpArg arg) {
766{
767 ASSERT_MSG(!arg.IsImm(), "PREFETCH - Imm argument"); 781 ASSERT_MSG(!arg.IsImm(), "PREFETCH - Imm argument");
768 arg.operandReg = (u8)level; 782 arg.operandReg = (u8)level;
769 arg.WriteRex(this, 0, 0); 783 arg.WriteRex(this, 0, 0);
@@ -772,8 +786,7 @@ void XEmitter::PREFETCH(PrefetchLevel level, OpArg arg)
772 arg.WriteRest(this); 786 arg.WriteRest(this);
773} 787}
774 788
775void XEmitter::SETcc(CCFlags flag, OpArg dest) 789void XEmitter::SETcc(CCFlags flag, OpArg dest) {
776{
777 ASSERT_MSG(!dest.IsImm(), "SETcc - Imm argument"); 790 ASSERT_MSG(!dest.IsImm(), "SETcc - Imm argument");
778 dest.operandReg = 0; 791 dest.operandReg = 0;
779 dest.WriteRex(this, 0, 8); 792 dest.WriteRex(this, 0, 8);
@@ -782,8 +795,7 @@ void XEmitter::SETcc(CCFlags flag, OpArg dest)
782 dest.WriteRest(this); 795 dest.WriteRest(this);
783} 796}
784 797
785void XEmitter::CMOVcc(int bits, X64Reg dest, OpArg src, CCFlags flag) 798void XEmitter::CMOVcc(int bits, X64Reg dest, OpArg src, CCFlags flag) {
786{
787 ASSERT_MSG(!src.IsImm(), "CMOVcc - Imm argument"); 799 ASSERT_MSG(!src.IsImm(), "CMOVcc - Imm argument");
788 ASSERT_MSG(bits != 8, "CMOVcc - 8 bits unsupported"); 800 ASSERT_MSG(bits != 8, "CMOVcc - 8 bits unsupported");
789 if (bits == 16) 801 if (bits == 16)
@@ -795,34 +807,41 @@ void XEmitter::CMOVcc(int bits, X64Reg dest, OpArg src, CCFlags flag)
795 src.WriteRest(this); 807 src.WriteRest(this);
796} 808}
797 809
798void XEmitter::WriteMulDivType(int bits, OpArg src, int ext) 810void XEmitter::WriteMulDivType(int bits, OpArg src, int ext) {
799{
800 ASSERT_MSG(!src.IsImm(), "WriteMulDivType - Imm argument"); 811 ASSERT_MSG(!src.IsImm(), "WriteMulDivType - Imm argument");
801 CheckFlags(); 812 CheckFlags();
802 src.operandReg = ext; 813 src.operandReg = ext;
803 if (bits == 16) 814 if (bits == 16)
804 Write8(0x66); 815 Write8(0x66);
805 src.WriteRex(this, bits, bits, 0); 816 src.WriteRex(this, bits, bits, 0);
806 if (bits == 8) 817 if (bits == 8) {
807 {
808 Write8(0xF6); 818 Write8(0xF6);
809 } 819 } else {
810 else
811 {
812 Write8(0xF7); 820 Write8(0xF7);
813 } 821 }
814 src.WriteRest(this); 822 src.WriteRest(this);
815} 823}
816 824
817void XEmitter::MUL(int bits, const OpArg& src) {WriteMulDivType(bits, src, 4);} 825void XEmitter::MUL(int bits, const OpArg& src) {
818void XEmitter::DIV(int bits, const OpArg& src) {WriteMulDivType(bits, src, 6);} 826 WriteMulDivType(bits, src, 4);
819void XEmitter::IMUL(int bits, const OpArg& src) {WriteMulDivType(bits, src, 5);} 827}
820void XEmitter::IDIV(int bits, const OpArg& src) {WriteMulDivType(bits, src, 7);} 828void XEmitter::DIV(int bits, const OpArg& src) {
821void XEmitter::NEG(int bits, const OpArg& src) {WriteMulDivType(bits, src, 3);} 829 WriteMulDivType(bits, src, 6);
822void XEmitter::NOT(int bits, const OpArg& src) {WriteMulDivType(bits, src, 2);} 830}
831void XEmitter::IMUL(int bits, const OpArg& src) {
832 WriteMulDivType(bits, src, 5);
833}
834void XEmitter::IDIV(int bits, const OpArg& src) {
835 WriteMulDivType(bits, src, 7);
836}
837void XEmitter::NEG(int bits, const OpArg& src) {
838 WriteMulDivType(bits, src, 3);
839}
840void XEmitter::NOT(int bits, const OpArg& src) {
841 WriteMulDivType(bits, src, 2);
842}
823 843
824void XEmitter::WriteBitSearchType(int bits, X64Reg dest, OpArg src, u8 byte2, bool rep) 844void XEmitter::WriteBitSearchType(int bits, X64Reg dest, OpArg src, u8 byte2, bool rep) {
825{
826 ASSERT_MSG(!src.IsImm(), "WriteBitSearchType - Imm argument"); 845 ASSERT_MSG(!src.IsImm(), "WriteBitSearchType - Imm argument");
827 CheckFlags(); 846 CheckFlags();
828 src.operandReg = (u8)dest; 847 src.operandReg = (u8)dest;
@@ -836,36 +855,35 @@ void XEmitter::WriteBitSearchType(int bits, X64Reg dest, OpArg src, u8 byte2, bo
836 src.WriteRest(this); 855 src.WriteRest(this);
837} 856}
838 857
839void XEmitter::MOVNTI(int bits, const OpArg& dest, X64Reg src) 858void XEmitter::MOVNTI(int bits, const OpArg& dest, X64Reg src) {
840{
841 if (bits <= 16) 859 if (bits <= 16)
842 ASSERT_MSG(0, "MOVNTI - bits<=16"); 860 ASSERT_MSG(0, "MOVNTI - bits<=16");
843 WriteBitSearchType(bits, src, dest, 0xC3); 861 WriteBitSearchType(bits, src, dest, 0xC3);
844} 862}
845 863
846void XEmitter::BSF(int bits, X64Reg dest, const OpArg& src) {WriteBitSearchType(bits,dest,src,0xBC);} // Bottom bit to top bit 864void XEmitter::BSF(int bits, X64Reg dest, const OpArg& src) {
847void XEmitter::BSR(int bits, X64Reg dest, const OpArg& src) {WriteBitSearchType(bits,dest,src,0xBD);} // Top bit to bottom bit 865 WriteBitSearchType(bits, dest, src, 0xBC);
866} // Bottom bit to top bit
867void XEmitter::BSR(int bits, X64Reg dest, const OpArg& src) {
868 WriteBitSearchType(bits, dest, src, 0xBD);
869} // Top bit to bottom bit
848 870
849void XEmitter::TZCNT(int bits, X64Reg dest, const OpArg& src) 871void XEmitter::TZCNT(int bits, X64Reg dest, const OpArg& src) {
850{
851 CheckFlags(); 872 CheckFlags();
852 if (!Common::GetCPUCaps().bmi1) 873 if (!Common::GetCPUCaps().bmi1)
853 ASSERT_MSG(0, "Trying to use BMI1 on a system that doesn't support it. Bad programmer."); 874 ASSERT_MSG(0, "Trying to use BMI1 on a system that doesn't support it. Bad programmer.");
854 WriteBitSearchType(bits, dest, src, 0xBC, true); 875 WriteBitSearchType(bits, dest, src, 0xBC, true);
855} 876}
856void XEmitter::LZCNT(int bits, X64Reg dest, const OpArg& src) 877void XEmitter::LZCNT(int bits, X64Reg dest, const OpArg& src) {
857{
858 CheckFlags(); 878 CheckFlags();
859 if (!Common::GetCPUCaps().lzcnt) 879 if (!Common::GetCPUCaps().lzcnt)
860 ASSERT_MSG(0, "Trying to use LZCNT on a system that doesn't support it. Bad programmer."); 880 ASSERT_MSG(0, "Trying to use LZCNT on a system that doesn't support it. Bad programmer.");
861 WriteBitSearchType(bits, dest, src, 0xBD, true); 881 WriteBitSearchType(bits, dest, src, 0xBD, true);
862} 882}
863 883
864void XEmitter::MOVSX(int dbits, int sbits, X64Reg dest, OpArg src) 884void XEmitter::MOVSX(int dbits, int sbits, X64Reg dest, OpArg src) {
865{
866 ASSERT_MSG(!src.IsImm(), "MOVSX - Imm argument"); 885 ASSERT_MSG(!src.IsImm(), "MOVSX - Imm argument");
867 if (dbits == sbits) 886 if (dbits == sbits) {
868 {
869 MOV(dbits, R(dest), src); 887 MOV(dbits, R(dest), src);
870 return; 888 return;
871 } 889 }
@@ -873,66 +891,49 @@ void XEmitter::MOVSX(int dbits, int sbits, X64Reg dest, OpArg src)
873 if (dbits == 16) 891 if (dbits == 16)
874 Write8(0x66); 892 Write8(0x66);
875 src.WriteRex(this, dbits, sbits); 893 src.WriteRex(this, dbits, sbits);
876 if (sbits == 8) 894 if (sbits == 8) {
877 {
878 Write8(0x0F); 895 Write8(0x0F);
879 Write8(0xBE); 896 Write8(0xBE);
880 } 897 } else if (sbits == 16) {
881 else if (sbits == 16)
882 {
883 Write8(0x0F); 898 Write8(0x0F);
884 Write8(0xBF); 899 Write8(0xBF);
885 } 900 } else if (sbits == 32 && dbits == 64) {
886 else if (sbits == 32 && dbits == 64)
887 {
888 Write8(0x63); 901 Write8(0x63);
889 } 902 } else {
890 else
891 {
892 Crash(); 903 Crash();
893 } 904 }
894 src.WriteRest(this); 905 src.WriteRest(this);
895} 906}
896 907
897void XEmitter::MOVZX(int dbits, int sbits, X64Reg dest, OpArg src) 908void XEmitter::MOVZX(int dbits, int sbits, X64Reg dest, OpArg src) {
898{
899 ASSERT_MSG(!src.IsImm(), "MOVZX - Imm argument"); 909 ASSERT_MSG(!src.IsImm(), "MOVZX - Imm argument");
900 if (dbits == sbits) 910 if (dbits == sbits) {
901 {
902 MOV(dbits, R(dest), src); 911 MOV(dbits, R(dest), src);
903 return; 912 return;
904 } 913 }
905 src.operandReg = (u8)dest; 914 src.operandReg = (u8)dest;
906 if (dbits == 16) 915 if (dbits == 16)
907 Write8(0x66); 916 Write8(0x66);
908 //the 32bit result is automatically zero extended to 64bit 917 // the 32bit result is automatically zero extended to 64bit
909 src.WriteRex(this, dbits == 64 ? 32 : dbits, sbits); 918 src.WriteRex(this, dbits == 64 ? 32 : dbits, sbits);
910 if (sbits == 8) 919 if (sbits == 8) {
911 {
912 Write8(0x0F); 920 Write8(0x0F);
913 Write8(0xB6); 921 Write8(0xB6);
914 } 922 } else if (sbits == 16) {
915 else if (sbits == 16)
916 {
917 Write8(0x0F); 923 Write8(0x0F);
918 Write8(0xB7); 924 Write8(0xB7);
919 } 925 } else if (sbits == 32 && dbits == 64) {
920 else if (sbits == 32 && dbits == 64)
921 {
922 Write8(0x8B); 926 Write8(0x8B);
923 } 927 } else {
924 else
925 {
926 ASSERT_MSG(0, "MOVZX - Invalid size"); 928 ASSERT_MSG(0, "MOVZX - Invalid size");
927 } 929 }
928 src.WriteRest(this); 930 src.WriteRest(this);
929} 931}
930 932
931void XEmitter::MOVBE(int bits, const OpArg& dest, const OpArg& src) 933void XEmitter::MOVBE(int bits, const OpArg& dest, const OpArg& src) {
932{ 934 ASSERT_MSG(Common::GetCPUCaps().movbe,
933 ASSERT_MSG(Common::GetCPUCaps().movbe, "Generating MOVBE on a system that does not support it."); 935 "Generating MOVBE on a system that does not support it.");
934 if (bits == 8) 936 if (bits == 8) {
935 {
936 MOV(bits, dest, src); 937 MOV(bits, dest, src);
937 return; 938 return;
938 } 939 }
@@ -940,71 +941,60 @@ void XEmitter::MOVBE(int bits, const OpArg& dest, const OpArg& src)
940 if (bits == 16) 941 if (bits == 16)
941 Write8(0x66); 942 Write8(0x66);
942 943
943 if (dest.IsSimpleReg()) 944 if (dest.IsSimpleReg()) {
944 {
945 ASSERT_MSG(!src.IsSimpleReg() && !src.IsImm(), "MOVBE: Loading from !mem"); 945 ASSERT_MSG(!src.IsSimpleReg() && !src.IsImm(), "MOVBE: Loading from !mem");
946 src.WriteRex(this, bits, bits, dest.GetSimpleReg()); 946 src.WriteRex(this, bits, bits, dest.GetSimpleReg());
947 Write8(0x0F); Write8(0x38); Write8(0xF0); 947 Write8(0x0F);
948 Write8(0x38);
949 Write8(0xF0);
948 src.WriteRest(this, 0, dest.GetSimpleReg()); 950 src.WriteRest(this, 0, dest.GetSimpleReg());
949 } 951 } else if (src.IsSimpleReg()) {
950 else if (src.IsSimpleReg())
951 {
952 ASSERT_MSG(!dest.IsSimpleReg() && !dest.IsImm(), "MOVBE: Storing to !mem"); 952 ASSERT_MSG(!dest.IsSimpleReg() && !dest.IsImm(), "MOVBE: Storing to !mem");
953 dest.WriteRex(this, bits, bits, src.GetSimpleReg()); 953 dest.WriteRex(this, bits, bits, src.GetSimpleReg());
954 Write8(0x0F); Write8(0x38); Write8(0xF1); 954 Write8(0x0F);
955 Write8(0x38);
956 Write8(0xF1);
955 dest.WriteRest(this, 0, src.GetSimpleReg()); 957 dest.WriteRest(this, 0, src.GetSimpleReg());
956 } 958 } else {
957 else
958 {
959 ASSERT_MSG(0, "MOVBE: Not loading or storing to mem"); 959 ASSERT_MSG(0, "MOVBE: Not loading or storing to mem");
960 } 960 }
961} 961}
962 962
963 963void XEmitter::LEA(int bits, X64Reg dest, OpArg src) {
964void XEmitter::LEA(int bits, X64Reg dest, OpArg src)
965{
966 ASSERT_MSG(!src.IsImm(), "LEA - Imm argument"); 964 ASSERT_MSG(!src.IsImm(), "LEA - Imm argument");
967 src.operandReg = (u8)dest; 965 src.operandReg = (u8)dest;
968 if (bits == 16) 966 if (bits == 16)
969 Write8(0x66); //TODO: performance warning 967 Write8(0x66); // TODO: performance warning
970 src.WriteRex(this, bits, bits); 968 src.WriteRex(this, bits, bits);
971 Write8(0x8D); 969 Write8(0x8D);
972 src.WriteRest(this, 0, INVALID_REG, bits == 64); 970 src.WriteRest(this, 0, INVALID_REG, bits == 64);
973} 971}
974 972
975//shift can be either imm8 or cl 973// shift can be either imm8 or cl
976void XEmitter::WriteShift(int bits, OpArg dest, const OpArg& shift, int ext) 974void XEmitter::WriteShift(int bits, OpArg dest, const OpArg& shift, int ext) {
977{
978 CheckFlags(); 975 CheckFlags();
979 bool writeImm = false; 976 bool writeImm = false;
980 if (dest.IsImm()) 977 if (dest.IsImm()) {
981 {
982 ASSERT_MSG(0, "WriteShift - can't shift imms"); 978 ASSERT_MSG(0, "WriteShift - can't shift imms");
983 } 979 }
984 if ((shift.IsSimpleReg() && shift.GetSimpleReg() != ECX) || (shift.IsImm() && shift.GetImmBits() != 8)) 980 if ((shift.IsSimpleReg() && shift.GetSimpleReg() != ECX) ||
985 { 981 (shift.IsImm() && shift.GetImmBits() != 8)) {
986 ASSERT_MSG(0, "WriteShift - illegal argument"); 982 ASSERT_MSG(0, "WriteShift - illegal argument");
987 } 983 }
988 dest.operandReg = ext; 984 dest.operandReg = ext;
989 if (bits == 16) 985 if (bits == 16)
990 Write8(0x66); 986 Write8(0x66);
991 dest.WriteRex(this, bits, bits, 0); 987 dest.WriteRex(this, bits, bits, 0);
992 if (shift.GetImmBits() == 8) 988 if (shift.GetImmBits() == 8) {
993 { 989 // ok an imm
994 //ok an imm
995 u8 imm = (u8)shift.offset; 990 u8 imm = (u8)shift.offset;
996 if (imm == 1) 991 if (imm == 1) {
997 {
998 Write8(bits == 8 ? 0xD0 : 0xD1); 992 Write8(bits == 8 ? 0xD0 : 0xD1);
999 } 993 } else {
1000 else
1001 {
1002 writeImm = true; 994 writeImm = true;
1003 Write8(bits == 8 ? 0xC0 : 0xC1); 995 Write8(bits == 8 ? 0xC0 : 0xC1);
1004 } 996 }
1005 } 997 } else {
1006 else
1007 {
1008 Write8(bits == 8 ? 0xD2 : 0xD3); 998 Write8(bits == 8 ? 0xD2 : 0xD3);
1009 } 999 }
1010 dest.WriteRest(this, writeImm ? 1 : 0); 1000 dest.WriteRest(this, writeImm ? 1 : 0);
@@ -1014,116 +1004,125 @@ void XEmitter::WriteShift(int bits, OpArg dest, const OpArg& shift, int ext)
1014 1004
1015// large rotates and shift are slower on intel than amd 1005// large rotates and shift are slower on intel than amd
1016// intel likes to rotate by 1, and the op is smaller too 1006// intel likes to rotate by 1, and the op is smaller too
1017void XEmitter::ROL(int bits, const OpArg& dest, const OpArg& shift) {WriteShift(bits, dest, shift, 0);} 1007void XEmitter::ROL(int bits, const OpArg& dest, const OpArg& shift) {
1018void XEmitter::ROR(int bits, const OpArg& dest, const OpArg& shift) {WriteShift(bits, dest, shift, 1);} 1008 WriteShift(bits, dest, shift, 0);
1019void XEmitter::RCL(int bits, const OpArg& dest, const OpArg& shift) {WriteShift(bits, dest, shift, 2);} 1009}
1020void XEmitter::RCR(int bits, const OpArg& dest, const OpArg& shift) {WriteShift(bits, dest, shift, 3);} 1010void XEmitter::ROR(int bits, const OpArg& dest, const OpArg& shift) {
1021void XEmitter::SHL(int bits, const OpArg& dest, const OpArg& shift) {WriteShift(bits, dest, shift, 4);} 1011 WriteShift(bits, dest, shift, 1);
1022void XEmitter::SHR(int bits, const OpArg& dest, const OpArg& shift) {WriteShift(bits, dest, shift, 5);} 1012}
1023void XEmitter::SAR(int bits, const OpArg& dest, const OpArg& shift) {WriteShift(bits, dest, shift, 7);} 1013void XEmitter::RCL(int bits, const OpArg& dest, const OpArg& shift) {
1014 WriteShift(bits, dest, shift, 2);
1015}
1016void XEmitter::RCR(int bits, const OpArg& dest, const OpArg& shift) {
1017 WriteShift(bits, dest, shift, 3);
1018}
1019void XEmitter::SHL(int bits, const OpArg& dest, const OpArg& shift) {
1020 WriteShift(bits, dest, shift, 4);
1021}
1022void XEmitter::SHR(int bits, const OpArg& dest, const OpArg& shift) {
1023 WriteShift(bits, dest, shift, 5);
1024}
1025void XEmitter::SAR(int bits, const OpArg& dest, const OpArg& shift) {
1026 WriteShift(bits, dest, shift, 7);
1027}
1024 1028
1025// index can be either imm8 or register, don't use memory destination because it's slow 1029// index can be either imm8 or register, don't use memory destination because it's slow
1026void XEmitter::WriteBitTest(int bits, const OpArg& dest, const OpArg& index, int ext) 1030void XEmitter::WriteBitTest(int bits, const OpArg& dest, const OpArg& index, int ext) {
1027{
1028 CheckFlags(); 1031 CheckFlags();
1029 if (dest.IsImm()) 1032 if (dest.IsImm()) {
1030 {
1031 ASSERT_MSG(0, "WriteBitTest - can't test imms"); 1033 ASSERT_MSG(0, "WriteBitTest - can't test imms");
1032 } 1034 }
1033 if ((index.IsImm() && index.GetImmBits() != 8)) 1035 if ((index.IsImm() && index.GetImmBits() != 8)) {
1034 {
1035 ASSERT_MSG(0, "WriteBitTest - illegal argument"); 1036 ASSERT_MSG(0, "WriteBitTest - illegal argument");
1036 } 1037 }
1037 if (bits == 16) 1038 if (bits == 16)
1038 Write8(0x66); 1039 Write8(0x66);
1039 if (index.IsImm()) 1040 if (index.IsImm()) {
1040 {
1041 dest.WriteRex(this, bits, bits); 1041 dest.WriteRex(this, bits, bits);
1042 Write8(0x0F); Write8(0xBA); 1042 Write8(0x0F);
1043 Write8(0xBA);
1043 dest.WriteRest(this, 1, (X64Reg)ext); 1044 dest.WriteRest(this, 1, (X64Reg)ext);
1044 Write8((u8)index.offset); 1045 Write8((u8)index.offset);
1045 } 1046 } else {
1046 else
1047 {
1048 X64Reg operand = index.GetSimpleReg(); 1047 X64Reg operand = index.GetSimpleReg();
1049 dest.WriteRex(this, bits, bits, operand); 1048 dest.WriteRex(this, bits, bits, operand);
1050 Write8(0x0F); Write8(0x83 + 8*ext); 1049 Write8(0x0F);
1050 Write8(0x83 + 8 * ext);
1051 dest.WriteRest(this, 1, operand); 1051 dest.WriteRest(this, 1, operand);
1052 } 1052 }
1053} 1053}
1054 1054
1055void XEmitter::BT(int bits, const OpArg& dest, const OpArg& index) {WriteBitTest(bits, dest, index, 4);} 1055void XEmitter::BT(int bits, const OpArg& dest, const OpArg& index) {
1056void XEmitter::BTS(int bits, const OpArg& dest, const OpArg& index) {WriteBitTest(bits, dest, index, 5);} 1056 WriteBitTest(bits, dest, index, 4);
1057void XEmitter::BTR(int bits, const OpArg& dest, const OpArg& index) {WriteBitTest(bits, dest, index, 6);} 1057}
1058void XEmitter::BTC(int bits, const OpArg& dest, const OpArg& index) {WriteBitTest(bits, dest, index, 7);} 1058void XEmitter::BTS(int bits, const OpArg& dest, const OpArg& index) {
1059 WriteBitTest(bits, dest, index, 5);
1060}
1061void XEmitter::BTR(int bits, const OpArg& dest, const OpArg& index) {
1062 WriteBitTest(bits, dest, index, 6);
1063}
1064void XEmitter::BTC(int bits, const OpArg& dest, const OpArg& index) {
1065 WriteBitTest(bits, dest, index, 7);
1066}
1059 1067
1060//shift can be either imm8 or cl 1068// shift can be either imm8 or cl
1061void XEmitter::SHRD(int bits, const OpArg& dest, const OpArg& src, const OpArg& shift) 1069void XEmitter::SHRD(int bits, const OpArg& dest, const OpArg& src, const OpArg& shift) {
1062{
1063 CheckFlags(); 1070 CheckFlags();
1064 if (dest.IsImm()) 1071 if (dest.IsImm()) {
1065 {
1066 ASSERT_MSG(0, "SHRD - can't use imms as destination"); 1072 ASSERT_MSG(0, "SHRD - can't use imms as destination");
1067 } 1073 }
1068 if (!src.IsSimpleReg()) 1074 if (!src.IsSimpleReg()) {
1069 {
1070 ASSERT_MSG(0, "SHRD - must use simple register as source"); 1075 ASSERT_MSG(0, "SHRD - must use simple register as source");
1071 } 1076 }
1072 if ((shift.IsSimpleReg() && shift.GetSimpleReg() != ECX) || (shift.IsImm() && shift.GetImmBits() != 8)) 1077 if ((shift.IsSimpleReg() && shift.GetSimpleReg() != ECX) ||
1073 { 1078 (shift.IsImm() && shift.GetImmBits() != 8)) {
1074 ASSERT_MSG(0, "SHRD - illegal shift"); 1079 ASSERT_MSG(0, "SHRD - illegal shift");
1075 } 1080 }
1076 if (bits == 16) 1081 if (bits == 16)
1077 Write8(0x66); 1082 Write8(0x66);
1078 X64Reg operand = src.GetSimpleReg(); 1083 X64Reg operand = src.GetSimpleReg();
1079 dest.WriteRex(this, bits, bits, operand); 1084 dest.WriteRex(this, bits, bits, operand);
1080 if (shift.GetImmBits() == 8) 1085 if (shift.GetImmBits() == 8) {
1081 { 1086 Write8(0x0F);
1082 Write8(0x0F); Write8(0xAC); 1087 Write8(0xAC);
1083 dest.WriteRest(this, 1, operand); 1088 dest.WriteRest(this, 1, operand);
1084 Write8((u8)shift.offset); 1089 Write8((u8)shift.offset);
1085 } 1090 } else {
1086 else 1091 Write8(0x0F);
1087 { 1092 Write8(0xAD);
1088 Write8(0x0F); Write8(0xAD);
1089 dest.WriteRest(this, 0, operand); 1093 dest.WriteRest(this, 0, operand);
1090 } 1094 }
1091} 1095}
1092 1096
1093void XEmitter::SHLD(int bits, const OpArg& dest, const OpArg& src, const OpArg& shift) 1097void XEmitter::SHLD(int bits, const OpArg& dest, const OpArg& src, const OpArg& shift) {
1094{
1095 CheckFlags(); 1098 CheckFlags();
1096 if (dest.IsImm()) 1099 if (dest.IsImm()) {
1097 {
1098 ASSERT_MSG(0, "SHLD - can't use imms as destination"); 1100 ASSERT_MSG(0, "SHLD - can't use imms as destination");
1099 } 1101 }
1100 if (!src.IsSimpleReg()) 1102 if (!src.IsSimpleReg()) {
1101 {
1102 ASSERT_MSG(0, "SHLD - must use simple register as source"); 1103 ASSERT_MSG(0, "SHLD - must use simple register as source");
1103 } 1104 }
1104 if ((shift.IsSimpleReg() && shift.GetSimpleReg() != ECX) || (shift.IsImm() && shift.GetImmBits() != 8)) 1105 if ((shift.IsSimpleReg() && shift.GetSimpleReg() != ECX) ||
1105 { 1106 (shift.IsImm() && shift.GetImmBits() != 8)) {
1106 ASSERT_MSG(0, "SHLD - illegal shift"); 1107 ASSERT_MSG(0, "SHLD - illegal shift");
1107 } 1108 }
1108 if (bits == 16) 1109 if (bits == 16)
1109 Write8(0x66); 1110 Write8(0x66);
1110 X64Reg operand = src.GetSimpleReg(); 1111 X64Reg operand = src.GetSimpleReg();
1111 dest.WriteRex(this, bits, bits, operand); 1112 dest.WriteRex(this, bits, bits, operand);
1112 if (shift.GetImmBits() == 8) 1113 if (shift.GetImmBits() == 8) {
1113 { 1114 Write8(0x0F);
1114 Write8(0x0F); Write8(0xA4); 1115 Write8(0xA4);
1115 dest.WriteRest(this, 1, operand); 1116 dest.WriteRest(this, 1, operand);
1116 Write8((u8)shift.offset); 1117 Write8((u8)shift.offset);
1117 } 1118 } else {
1118 else 1119 Write8(0x0F);
1119 { 1120 Write8(0xA5);
1120 Write8(0x0F); Write8(0xA5);
1121 dest.WriteRest(this, 0, operand); 1121 dest.WriteRest(this, 0, operand);
1122 } 1122 }
1123} 1123}
1124 1124
1125void OpArg::WriteSingleByteOp(XEmitter *emit, u8 op, X64Reg _operandReg, int bits) 1125void OpArg::WriteSingleByteOp(XEmitter* emit, u8 op, X64Reg _operandReg, int bits) {
1126{
1127 if (bits == 16) 1126 if (bits == 16)
1128 emit->Write8(0x66); 1127 emit->Write8(0x66);
1129 1128
@@ -1133,12 +1132,11 @@ void OpArg::WriteSingleByteOp(XEmitter *emit, u8 op, X64Reg _operandReg, int bit
1133 WriteRest(emit); 1132 WriteRest(emit);
1134} 1133}
1135 1134
1136//operand can either be immediate or register 1135// operand can either be immediate or register
1137void OpArg::WriteNormalOp(XEmitter *emit, bool toRM, NormalOp op, const OpArg& operand, int bits) const 1136void OpArg::WriteNormalOp(XEmitter* emit, bool toRM, NormalOp op, const OpArg& operand,
1138{ 1137 int bits) const {
1139 X64Reg _operandReg; 1138 X64Reg _operandReg;
1140 if (IsImm()) 1139 if (IsImm()) {
1141 {
1142 ASSERT_MSG(0, "WriteNormalOp - Imm argument, wrong order"); 1140 ASSERT_MSG(0, "WriteNormalOp - Imm argument, wrong order");
1143 } 1141 }
1144 1142
@@ -1147,27 +1145,22 @@ void OpArg::WriteNormalOp(XEmitter *emit, bool toRM, NormalOp op, const OpArg& o
1147 1145
1148 int immToWrite = 0; 1146 int immToWrite = 0;
1149 1147
1150 if (operand.IsImm()) 1148 if (operand.IsImm()) {
1151 {
1152 WriteRex(emit, bits, bits); 1149 WriteRex(emit, bits, bits);
1153 1150
1154 if (!toRM) 1151 if (!toRM) {
1155 {
1156 ASSERT_MSG(0, "WriteNormalOp - Writing to Imm (!toRM)"); 1152 ASSERT_MSG(0, "WriteNormalOp - Writing to Imm (!toRM)");
1157 } 1153 }
1158 1154
1159 if (operand.scale == SCALE_IMM8 && bits == 8) 1155 if (operand.scale == SCALE_IMM8 && bits == 8) {
1160 {
1161 // op al, imm8 1156 // op al, imm8
1162 if (!scale && offsetOrBaseReg == AL && normalops[op].eaximm8 != 0xCC) 1157 if (!scale && offsetOrBaseReg == AL && normalops[op].eaximm8 != 0xCC) {
1163 {
1164 emit->Write8(normalops[op].eaximm8); 1158 emit->Write8(normalops[op].eaximm8);
1165 emit->Write8((u8)operand.offset); 1159 emit->Write8((u8)operand.offset);
1166 return; 1160 return;
1167 } 1161 }
1168 // mov reg, imm8 1162 // mov reg, imm8
1169 if (!scale && op == nrmMOV) 1163 if (!scale && op == nrmMOV) {
1170 {
1171 emit->Write8(0xB0 + (offsetOrBaseReg & 7)); 1164 emit->Write8(0xB0 + (offsetOrBaseReg & 7));
1172 emit->Write8((u8)operand.offset); 1165 emit->Write8((u8)operand.offset);
1173 return; 1166 return;
@@ -1175,26 +1168,20 @@ void OpArg::WriteNormalOp(XEmitter *emit, bool toRM, NormalOp op, const OpArg& o
1175 // op r/m8, imm8 1168 // op r/m8, imm8
1176 emit->Write8(normalops[op].imm8); 1169 emit->Write8(normalops[op].imm8);
1177 immToWrite = 8; 1170 immToWrite = 8;
1178 } 1171 } else if ((operand.scale == SCALE_IMM16 && bits == 16) ||
1179 else if ((operand.scale == SCALE_IMM16 && bits == 16) || 1172 (operand.scale == SCALE_IMM32 && bits == 32) ||
1180 (operand.scale == SCALE_IMM32 && bits == 32) || 1173 (operand.scale == SCALE_IMM32 && bits == 64)) {
1181 (operand.scale == SCALE_IMM32 && bits == 64))
1182 {
1183 // Try to save immediate size if we can, but first check to see 1174 // Try to save immediate size if we can, but first check to see
1184 // if the instruction supports simm8. 1175 // if the instruction supports simm8.
1185 // op r/m, imm8 1176 // op r/m, imm8
1186 if (normalops[op].simm8 != 0xCC && 1177 if (normalops[op].simm8 != 0xCC &&
1187 ((operand.scale == SCALE_IMM16 && (s16)operand.offset == (s8)operand.offset) || 1178 ((operand.scale == SCALE_IMM16 && (s16)operand.offset == (s8)operand.offset) ||
1188 (operand.scale == SCALE_IMM32 && (s32)operand.offset == (s8)operand.offset))) 1179 (operand.scale == SCALE_IMM32 && (s32)operand.offset == (s8)operand.offset))) {
1189 {
1190 emit->Write8(normalops[op].simm8); 1180 emit->Write8(normalops[op].simm8);
1191 immToWrite = 8; 1181 immToWrite = 8;
1192 } 1182 } else {
1193 else
1194 {
1195 // mov reg, imm 1183 // mov reg, imm
1196 if (!scale && op == nrmMOV && bits != 64) 1184 if (!scale && op == nrmMOV && bits != 64) {
1197 {
1198 emit->Write8(0xB8 + (offsetOrBaseReg & 7)); 1185 emit->Write8(0xB8 + (offsetOrBaseReg & 7));
1199 if (bits == 16) 1186 if (bits == 16)
1200 emit->Write16((u16)operand.offset); 1187 emit->Write16((u16)operand.offset);
@@ -1203,8 +1190,7 @@ void OpArg::WriteNormalOp(XEmitter *emit, bool toRM, NormalOp op, const OpArg& o
1203 return; 1190 return;
1204 } 1191 }
1205 // op eax, imm 1192 // op eax, imm
1206 if (!scale && offsetOrBaseReg == EAX && normalops[op].eaximm32 != 0xCC) 1193 if (!scale && offsetOrBaseReg == EAX && normalops[op].eaximm32 != 0xCC) {
1207 {
1208 emit->Write8(normalops[op].eaximm32); 1194 emit->Write8(normalops[op].eaximm32);
1209 if (bits == 16) 1195 if (bits == 16)
1210 emit->Write16((u16)operand.offset); 1196 emit->Write16((u16)operand.offset);
@@ -1216,54 +1202,41 @@ void OpArg::WriteNormalOp(XEmitter *emit, bool toRM, NormalOp op, const OpArg& o
1216 emit->Write8(normalops[op].imm32); 1202 emit->Write8(normalops[op].imm32);
1217 immToWrite = bits == 16 ? 16 : 32; 1203 immToWrite = bits == 16 ? 16 : 32;
1218 } 1204 }
1219 } 1205 } else if ((operand.scale == SCALE_IMM8 && bits == 16) ||
1220 else if ((operand.scale == SCALE_IMM8 && bits == 16) || 1206 (operand.scale == SCALE_IMM8 && bits == 32) ||
1221 (operand.scale == SCALE_IMM8 && bits == 32) || 1207 (operand.scale == SCALE_IMM8 && bits == 64)) {
1222 (operand.scale == SCALE_IMM8 && bits == 64))
1223 {
1224 // op r/m, imm8 1208 // op r/m, imm8
1225 emit->Write8(normalops[op].simm8); 1209 emit->Write8(normalops[op].simm8);
1226 immToWrite = 8; 1210 immToWrite = 8;
1227 } 1211 } else if (operand.scale == SCALE_IMM64 && bits == 64) {
1228 else if (operand.scale == SCALE_IMM64 && bits == 64) 1212 if (scale) {
1229 {
1230 if (scale)
1231 {
1232 ASSERT_MSG(0, "WriteNormalOp - MOV with 64-bit imm requres register destination"); 1213 ASSERT_MSG(0, "WriteNormalOp - MOV with 64-bit imm requres register destination");
1233 } 1214 }
1234 // mov reg64, imm64 1215 // mov reg64, imm64
1235 else if (op == nrmMOV) 1216 else if (op == nrmMOV) {
1236 {
1237 emit->Write8(0xB8 + (offsetOrBaseReg & 7)); 1217 emit->Write8(0xB8 + (offsetOrBaseReg & 7));
1238 emit->Write64((u64)operand.offset); 1218 emit->Write64((u64)operand.offset);
1239 return; 1219 return;
1240 } 1220 }
1241 ASSERT_MSG(0, "WriteNormalOp - Only MOV can take 64-bit imm"); 1221 ASSERT_MSG(0, "WriteNormalOp - Only MOV can take 64-bit imm");
1242 } 1222 } else {
1243 else
1244 {
1245 ASSERT_MSG(0, "WriteNormalOp - Unhandled case"); 1223 ASSERT_MSG(0, "WriteNormalOp - Unhandled case");
1246 } 1224 }
1247 _operandReg = (X64Reg)normalops[op].ext; //pass extension in REG of ModRM 1225 _operandReg = (X64Reg)normalops[op].ext; // pass extension in REG of ModRM
1248 } 1226 } else {
1249 else
1250 {
1251 _operandReg = (X64Reg)operand.offsetOrBaseReg; 1227 _operandReg = (X64Reg)operand.offsetOrBaseReg;
1252 WriteRex(emit, bits, bits, _operandReg); 1228 WriteRex(emit, bits, bits, _operandReg);
1253 // op r/m, reg 1229 // op r/m, reg
1254 if (toRM) 1230 if (toRM) {
1255 {
1256 emit->Write8(bits == 8 ? normalops[op].toRm8 : normalops[op].toRm32); 1231 emit->Write8(bits == 8 ? normalops[op].toRm8 : normalops[op].toRm32);
1257 } 1232 }
1258 // op reg, r/m 1233 // op reg, r/m
1259 else 1234 else {
1260 {
1261 emit->Write8(bits == 8 ? normalops[op].fromRm8 : normalops[op].fromRm32); 1235 emit->Write8(bits == 8 ? normalops[op].fromRm8 : normalops[op].fromRm32);
1262 } 1236 }
1263 } 1237 }
1264 WriteRest(emit, immToWrite >> 3, _operandReg); 1238 WriteRest(emit, immToWrite >> 3, _operandReg);
1265 switch (immToWrite) 1239 switch (immToWrite) {
1266 {
1267 case 0: 1240 case 0:
1268 break; 1241 break;
1269 case 8: 1242 case 8:
@@ -1280,66 +1253,84 @@ void OpArg::WriteNormalOp(XEmitter *emit, bool toRM, NormalOp op, const OpArg& o
1280 } 1253 }
1281} 1254}
1282 1255
1283void XEmitter::WriteNormalOp(XEmitter *emit, int bits, NormalOp op, const OpArg& a1, const OpArg& a2) 1256void XEmitter::WriteNormalOp(XEmitter* emit, int bits, NormalOp op, const OpArg& a1,
1284{ 1257 const OpArg& a2) {
1285 if (a1.IsImm()) 1258 if (a1.IsImm()) {
1286 { 1259 // Booh! Can't write to an imm
1287 //Booh! Can't write to an imm
1288 ASSERT_MSG(0, "WriteNormalOp - a1 cannot be imm"); 1260 ASSERT_MSG(0, "WriteNormalOp - a1 cannot be imm");
1289 return; 1261 return;
1290 } 1262 }
1291 if (a2.IsImm()) 1263 if (a2.IsImm()) {
1292 {
1293 a1.WriteNormalOp(emit, true, op, a2, bits); 1264 a1.WriteNormalOp(emit, true, op, a2, bits);
1294 } 1265 } else {
1295 else 1266 if (a1.IsSimpleReg()) {
1296 {
1297 if (a1.IsSimpleReg())
1298 {
1299 a2.WriteNormalOp(emit, false, op, a1, bits); 1267 a2.WriteNormalOp(emit, false, op, a1, bits);
1300 } 1268 } else {
1301 else 1269 ASSERT_MSG(a2.IsSimpleReg() || a2.IsImm(),
1302 { 1270 "WriteNormalOp - a1 and a2 cannot both be memory");
1303 ASSERT_MSG(a2.IsSimpleReg() || a2.IsImm(), "WriteNormalOp - a1 and a2 cannot both be memory");
1304 a1.WriteNormalOp(emit, true, op, a2, bits); 1271 a1.WriteNormalOp(emit, true, op, a2, bits);
1305 } 1272 }
1306 } 1273 }
1307} 1274}
1308 1275
1309void XEmitter::ADD (int bits, const OpArg& a1, const OpArg& a2) {CheckFlags(); WriteNormalOp(this, bits, nrmADD, a1, a2);} 1276void XEmitter::ADD(int bits, const OpArg& a1, const OpArg& a2) {
1310void XEmitter::ADC (int bits, const OpArg& a1, const OpArg& a2) {CheckFlags(); WriteNormalOp(this, bits, nrmADC, a1, a2);} 1277 CheckFlags();
1311void XEmitter::SUB (int bits, const OpArg& a1, const OpArg& a2) {CheckFlags(); WriteNormalOp(this, bits, nrmSUB, a1, a2);} 1278 WriteNormalOp(this, bits, nrmADD, a1, a2);
1312void XEmitter::SBB (int bits, const OpArg& a1, const OpArg& a2) {CheckFlags(); WriteNormalOp(this, bits, nrmSBB, a1, a2);} 1279}
1313void XEmitter::AND (int bits, const OpArg& a1, const OpArg& a2) {CheckFlags(); WriteNormalOp(this, bits, nrmAND, a1, a2);} 1280void XEmitter::ADC(int bits, const OpArg& a1, const OpArg& a2) {
1314void XEmitter::OR (int bits, const OpArg& a1, const OpArg& a2) {CheckFlags(); WriteNormalOp(this, bits, nrmOR , a1, a2);} 1281 CheckFlags();
1315void XEmitter::XOR (int bits, const OpArg& a1, const OpArg& a2) {CheckFlags(); WriteNormalOp(this, bits, nrmXOR, a1, a2);} 1282 WriteNormalOp(this, bits, nrmADC, a1, a2);
1316void XEmitter::MOV (int bits, const OpArg& a1, const OpArg& a2) 1283}
1317{ 1284void XEmitter::SUB(int bits, const OpArg& a1, const OpArg& a2) {
1285 CheckFlags();
1286 WriteNormalOp(this, bits, nrmSUB, a1, a2);
1287}
1288void XEmitter::SBB(int bits, const OpArg& a1, const OpArg& a2) {
1289 CheckFlags();
1290 WriteNormalOp(this, bits, nrmSBB, a1, a2);
1291}
1292void XEmitter::AND(int bits, const OpArg& a1, const OpArg& a2) {
1293 CheckFlags();
1294 WriteNormalOp(this, bits, nrmAND, a1, a2);
1295}
1296void XEmitter::OR(int bits, const OpArg& a1, const OpArg& a2) {
1297 CheckFlags();
1298 WriteNormalOp(this, bits, nrmOR, a1, a2);
1299}
1300void XEmitter::XOR(int bits, const OpArg& a1, const OpArg& a2) {
1301 CheckFlags();
1302 WriteNormalOp(this, bits, nrmXOR, a1, a2);
1303}
1304void XEmitter::MOV(int bits, const OpArg& a1, const OpArg& a2) {
1318 if (a1.IsSimpleReg() && a2.IsSimpleReg() && a1.GetSimpleReg() == a2.GetSimpleReg()) 1305 if (a1.IsSimpleReg() && a2.IsSimpleReg() && a1.GetSimpleReg() == a2.GetSimpleReg())
1319 LOG_ERROR(Common, "Redundant MOV @ %p - bug in JIT?", code); 1306 LOG_ERROR(Common, "Redundant MOV @ %p - bug in JIT?", code);
1320 WriteNormalOp(this, bits, nrmMOV, a1, a2); 1307 WriteNormalOp(this, bits, nrmMOV, a1, a2);
1321} 1308}
1322void XEmitter::TEST(int bits, const OpArg& a1, const OpArg& a2) {CheckFlags(); WriteNormalOp(this, bits, nrmTEST, a1, a2);} 1309void XEmitter::TEST(int bits, const OpArg& a1, const OpArg& a2) {
1323void XEmitter::CMP (int bits, const OpArg& a1, const OpArg& a2) {CheckFlags(); WriteNormalOp(this, bits, nrmCMP, a1, a2);} 1310 CheckFlags();
1324void XEmitter::XCHG(int bits, const OpArg& a1, const OpArg& a2) {WriteNormalOp(this, bits, nrmXCHG, a1, a2);} 1311 WriteNormalOp(this, bits, nrmTEST, a1, a2);
1312}
1313void XEmitter::CMP(int bits, const OpArg& a1, const OpArg& a2) {
1314 CheckFlags();
1315 WriteNormalOp(this, bits, nrmCMP, a1, a2);
1316}
1317void XEmitter::XCHG(int bits, const OpArg& a1, const OpArg& a2) {
1318 WriteNormalOp(this, bits, nrmXCHG, a1, a2);
1319}
1325 1320
1326void XEmitter::IMUL(int bits, X64Reg regOp, const OpArg& a1, const OpArg& a2) 1321void XEmitter::IMUL(int bits, X64Reg regOp, const OpArg& a1, const OpArg& a2) {
1327{
1328 CheckFlags(); 1322 CheckFlags();
1329 if (bits == 8) 1323 if (bits == 8) {
1330 {
1331 ASSERT_MSG(0, "IMUL - illegal bit size!"); 1324 ASSERT_MSG(0, "IMUL - illegal bit size!");
1332 return; 1325 return;
1333 } 1326 }
1334 1327
1335 if (a1.IsImm()) 1328 if (a1.IsImm()) {
1336 {
1337 ASSERT_MSG(0, "IMUL - second arg cannot be imm!"); 1329 ASSERT_MSG(0, "IMUL - second arg cannot be imm!");
1338 return; 1330 return;
1339 } 1331 }
1340 1332
1341 if (!a2.IsImm()) 1333 if (!a2.IsImm()) {
1342 {
1343 ASSERT_MSG(0, "IMUL - third arg must be imm!"); 1334 ASSERT_MSG(0, "IMUL - third arg must be imm!");
1344 return; 1335 return;
1345 } 1336 }
@@ -1348,46 +1339,34 @@ void XEmitter::IMUL(int bits, X64Reg regOp, const OpArg& a1, const OpArg& a2)
1348 Write8(0x66); 1339 Write8(0x66);
1349 a1.WriteRex(this, bits, bits, regOp); 1340 a1.WriteRex(this, bits, bits, regOp);
1350 1341
1351 if (a2.GetImmBits() == 8 || 1342 if (a2.GetImmBits() == 8 || (a2.GetImmBits() == 16 && (s8)a2.offset == (s16)a2.offset) ||
1352 (a2.GetImmBits() == 16 && (s8)a2.offset == (s16)a2.offset) || 1343 (a2.GetImmBits() == 32 && (s8)a2.offset == (s32)a2.offset)) {
1353 (a2.GetImmBits() == 32 && (s8)a2.offset == (s32)a2.offset))
1354 {
1355 Write8(0x6B); 1344 Write8(0x6B);
1356 a1.WriteRest(this, 1, regOp); 1345 a1.WriteRest(this, 1, regOp);
1357 Write8((u8)a2.offset); 1346 Write8((u8)a2.offset);
1358 } 1347 } else {
1359 else
1360 {
1361 Write8(0x69); 1348 Write8(0x69);
1362 if (a2.GetImmBits() == 16 && bits == 16) 1349 if (a2.GetImmBits() == 16 && bits == 16) {
1363 {
1364 a1.WriteRest(this, 2, regOp); 1350 a1.WriteRest(this, 2, regOp);
1365 Write16((u16)a2.offset); 1351 Write16((u16)a2.offset);
1366 } 1352 } else if (a2.GetImmBits() == 32 && (bits == 32 || bits == 64)) {
1367 else if (a2.GetImmBits() == 32 && (bits == 32 || bits == 64))
1368 {
1369 a1.WriteRest(this, 4, regOp); 1353 a1.WriteRest(this, 4, regOp);
1370 Write32((u32)a2.offset); 1354 Write32((u32)a2.offset);
1371 } 1355 } else {
1372 else
1373 {
1374 ASSERT_MSG(0, "IMUL - unhandled case!"); 1356 ASSERT_MSG(0, "IMUL - unhandled case!");
1375 } 1357 }
1376 } 1358 }
1377} 1359}
1378 1360
1379void XEmitter::IMUL(int bits, X64Reg regOp, const OpArg& a) 1361void XEmitter::IMUL(int bits, X64Reg regOp, const OpArg& a) {
1380{
1381 CheckFlags(); 1362 CheckFlags();
1382 if (bits == 8) 1363 if (bits == 8) {
1383 {
1384 ASSERT_MSG(0, "IMUL - illegal bit size!"); 1364 ASSERT_MSG(0, "IMUL - illegal bit size!");
1385 return; 1365 return;
1386 } 1366 }
1387 1367
1388 if (a.IsImm()) 1368 if (a.IsImm()) {
1389 { 1369 IMUL(bits, regOp, R(regOp), a);
1390 IMUL(bits, regOp, R(regOp), a) ;
1391 return; 1370 return;
1392 } 1371 }
1393 1372
@@ -1399,9 +1378,7 @@ void XEmitter::IMUL(int bits, X64Reg regOp, const OpArg& a)
1399 a.WriteRest(this, 0, regOp); 1378 a.WriteRest(this, 0, regOp);
1400} 1379}
1401 1380
1402 1381void XEmitter::WriteSSEOp(u8 opPrefix, u16 op, X64Reg regOp, OpArg arg, int extrabytes) {
1403void XEmitter::WriteSSEOp(u8 opPrefix, u16 op, X64Reg regOp, OpArg arg, int extrabytes)
1404{
1405 if (opPrefix) 1382 if (opPrefix)
1406 Write8(opPrefix); 1383 Write8(opPrefix);
1407 arg.operandReg = regOp; 1384 arg.operandReg = regOp;
@@ -1413,13 +1390,11 @@ void XEmitter::WriteSSEOp(u8 opPrefix, u16 op, X64Reg regOp, OpArg arg, int extr
1413 arg.WriteRest(this, extrabytes); 1390 arg.WriteRest(this, extrabytes);
1414} 1391}
1415 1392
1416void XEmitter::WriteAVXOp(u8 opPrefix, u16 op, X64Reg regOp, const OpArg& arg, int extrabytes) 1393void XEmitter::WriteAVXOp(u8 opPrefix, u16 op, X64Reg regOp, const OpArg& arg, int extrabytes) {
1417{
1418 WriteAVXOp(opPrefix, op, regOp, INVALID_REG, arg, extrabytes); 1394 WriteAVXOp(opPrefix, op, regOp, INVALID_REG, arg, extrabytes);
1419} 1395}
1420 1396
1421static int GetVEXmmmmm(u16 op) 1397static int GetVEXmmmmm(u16 op) {
1422{
1423 // Currently, only 0x38 and 0x3A are used as secondary escape byte. 1398 // Currently, only 0x38 and 0x3A are used as secondary escape byte.
1424 if ((op >> 8) == 0x3A) 1399 if ((op >> 8) == 0x3A)
1425 return 3; 1400 return 3;
@@ -1429,8 +1404,7 @@ static int GetVEXmmmmm(u16 op)
1429 return 1; 1404 return 1;
1430} 1405}
1431 1406
1432static int GetVEXpp(u8 opPrefix) 1407static int GetVEXpp(u8 opPrefix) {
1433{
1434 if (opPrefix == 0x66) 1408 if (opPrefix == 0x66)
1435 return 1; 1409 return 1;
1436 if (opPrefix == 0xF3) 1410 if (opPrefix == 0xF3)
@@ -1441,21 +1415,22 @@ static int GetVEXpp(u8 opPrefix)
1441 return 0; 1415 return 0;
1442} 1416}
1443 1417
1444void XEmitter::WriteAVXOp(u8 opPrefix, u16 op, X64Reg regOp1, X64Reg regOp2, const OpArg& arg, int extrabytes) 1418void XEmitter::WriteAVXOp(u8 opPrefix, u16 op, X64Reg regOp1, X64Reg regOp2, const OpArg& arg,
1445{ 1419 int extrabytes) {
1446 if (!Common::GetCPUCaps().avx) 1420 if (!Common::GetCPUCaps().avx)
1447 ASSERT_MSG(0, "Trying to use AVX on a system that doesn't support it. Bad programmer."); 1421 ASSERT_MSG(0, "Trying to use AVX on a system that doesn't support it. Bad programmer.");
1448 int mmmmm = GetVEXmmmmm(op); 1422 int mmmmm = GetVEXmmmmm(op);
1449 int pp = GetVEXpp(opPrefix); 1423 int pp = GetVEXpp(opPrefix);
1450 // FIXME: we currently don't support 256-bit instructions, and "size" is not the vector size here 1424 // FIXME: we currently don't support 256-bit instructions, and "size" is not the vector size
1425 // here
1451 arg.WriteVex(this, regOp1, regOp2, 0, pp, mmmmm); 1426 arg.WriteVex(this, regOp1, regOp2, 0, pp, mmmmm);
1452 Write8(op & 0xFF); 1427 Write8(op & 0xFF);
1453 arg.WriteRest(this, extrabytes, regOp1); 1428 arg.WriteRest(this, extrabytes, regOp1);
1454} 1429}
1455 1430
1456// Like the above, but more general; covers GPR-based VEX operations, like BMI1/2 1431// Like the above, but more general; covers GPR-based VEX operations, like BMI1/2
1457void XEmitter::WriteVEXOp(int size, u8 opPrefix, u16 op, X64Reg regOp1, X64Reg regOp2, const OpArg& arg, int extrabytes) 1432void XEmitter::WriteVEXOp(int size, u8 opPrefix, u16 op, X64Reg regOp1, X64Reg regOp2,
1458{ 1433 const OpArg& arg, int extrabytes) {
1459 if (size != 32 && size != 64) 1434 if (size != 32 && size != 64)
1460 ASSERT_MSG(0, "VEX GPR instructions only support 32-bit and 64-bit modes!"); 1435 ASSERT_MSG(0, "VEX GPR instructions only support 32-bit and 64-bit modes!");
1461 int mmmmm = GetVEXmmmmm(op); 1436 int mmmmm = GetVEXmmmmm(op);
@@ -1465,49 +1440,50 @@ void XEmitter::WriteVEXOp(int size, u8 opPrefix, u16 op, X64Reg regOp1, X64Reg r
1465 arg.WriteRest(this, extrabytes, regOp1); 1440 arg.WriteRest(this, extrabytes, regOp1);
1466} 1441}
1467 1442
1468void XEmitter::WriteBMI1Op(int size, u8 opPrefix, u16 op, X64Reg regOp1, X64Reg regOp2, const OpArg& arg, int extrabytes) 1443void XEmitter::WriteBMI1Op(int size, u8 opPrefix, u16 op, X64Reg regOp1, X64Reg regOp2,
1469{ 1444 const OpArg& arg, int extrabytes) {
1470 CheckFlags(); 1445 CheckFlags();
1471 if (!Common::GetCPUCaps().bmi1) 1446 if (!Common::GetCPUCaps().bmi1)
1472 ASSERT_MSG(0, "Trying to use BMI1 on a system that doesn't support it. Bad programmer."); 1447 ASSERT_MSG(0, "Trying to use BMI1 on a system that doesn't support it. Bad programmer.");
1473 WriteVEXOp(size, opPrefix, op, regOp1, regOp2, arg, extrabytes); 1448 WriteVEXOp(size, opPrefix, op, regOp1, regOp2, arg, extrabytes);
1474} 1449}
1475 1450
1476void XEmitter::WriteBMI2Op(int size, u8 opPrefix, u16 op, X64Reg regOp1, X64Reg regOp2, const OpArg& arg, int extrabytes) 1451void XEmitter::WriteBMI2Op(int size, u8 opPrefix, u16 op, X64Reg regOp1, X64Reg regOp2,
1477{ 1452 const OpArg& arg, int extrabytes) {
1478 CheckFlags(); 1453 CheckFlags();
1479 if (!Common::GetCPUCaps().bmi2) 1454 if (!Common::GetCPUCaps().bmi2)
1480 ASSERT_MSG(0, "Trying to use BMI2 on a system that doesn't support it. Bad programmer."); 1455 ASSERT_MSG(0, "Trying to use BMI2 on a system that doesn't support it. Bad programmer.");
1481 WriteVEXOp(size, opPrefix, op, regOp1, regOp2, arg, extrabytes); 1456 WriteVEXOp(size, opPrefix, op, regOp1, regOp2, arg, extrabytes);
1482} 1457}
1483 1458
1484void XEmitter::MOVD_xmm(X64Reg dest, const OpArg &arg) {WriteSSEOp(0x66, 0x6E, dest, arg, 0);} 1459void XEmitter::MOVD_xmm(X64Reg dest, const OpArg& arg) {
1485void XEmitter::MOVD_xmm(const OpArg &arg, X64Reg src) {WriteSSEOp(0x66, 0x7E, src, arg, 0);} 1460 WriteSSEOp(0x66, 0x6E, dest, arg, 0);
1461}
1462void XEmitter::MOVD_xmm(const OpArg& arg, X64Reg src) {
1463 WriteSSEOp(0x66, 0x7E, src, arg, 0);
1464}
1486 1465
1487void XEmitter::MOVQ_xmm(X64Reg dest, OpArg arg) 1466void XEmitter::MOVQ_xmm(X64Reg dest, OpArg arg) {
1488{
1489#ifdef ARCHITECTURE_x86_64 1467#ifdef ARCHITECTURE_x86_64
1490 // Alternate encoding 1468 // Alternate encoding
1491 // This does not display correctly in MSVC's debugger, it thinks it's a MOVD 1469 // This does not display correctly in MSVC's debugger, it thinks it's a MOVD
1492 arg.operandReg = dest; 1470 arg.operandReg = dest;
1493 Write8(0x66); 1471 Write8(0x66);
1494 arg.WriteRex(this, 64, 0); 1472 arg.WriteRex(this, 64, 0);
1495 Write8(0x0f); 1473 Write8(0x0f);
1496 Write8(0x6E); 1474 Write8(0x6E);
1497 arg.WriteRest(this, 0); 1475 arg.WriteRest(this, 0);
1498#else 1476#else
1499 arg.operandReg = dest; 1477 arg.operandReg = dest;
1500 Write8(0xF3); 1478 Write8(0xF3);
1501 Write8(0x0f); 1479 Write8(0x0f);
1502 Write8(0x7E); 1480 Write8(0x7E);
1503 arg.WriteRest(this, 0); 1481 arg.WriteRest(this, 0);
1504#endif 1482#endif
1505} 1483}
1506 1484
1507void XEmitter::MOVQ_xmm(OpArg arg, X64Reg src) 1485void XEmitter::MOVQ_xmm(OpArg arg, X64Reg src) {
1508{ 1486 if (src > 7 || arg.IsSimpleReg()) {
1509 if (src > 7 || arg.IsSimpleReg())
1510 {
1511 // Alternate encoding 1487 // Alternate encoding
1512 // This does not display correctly in MSVC's debugger, it thinks it's a MOVD 1488 // This does not display correctly in MSVC's debugger, it thinks it's a MOVD
1513 arg.operandReg = src; 1489 arg.operandReg = src;
@@ -1516,9 +1492,7 @@ void XEmitter::MOVQ_xmm(OpArg arg, X64Reg src)
1516 Write8(0x0f); 1492 Write8(0x0f);
1517 Write8(0x7E); 1493 Write8(0x7E);
1518 arg.WriteRest(this, 0); 1494 arg.WriteRest(this, 0);
1519 } 1495 } else {
1520 else
1521 {
1522 arg.operandReg = src; 1496 arg.operandReg = src;
1523 arg.WriteRex(this, 0, 0); 1497 arg.WriteRex(this, 0, 0);
1524 Write8(0x66); 1498 Write8(0x66);
@@ -1528,8 +1502,7 @@ void XEmitter::MOVQ_xmm(OpArg arg, X64Reg src)
1528 } 1502 }
1529} 1503}
1530 1504
1531void XEmitter::WriteMXCSR(OpArg arg, int ext) 1505void XEmitter::WriteMXCSR(OpArg arg, int ext) {
1532{
1533 if (arg.IsImm() || arg.IsSimpleReg()) 1506 if (arg.IsImm() || arg.IsSimpleReg())
1534 ASSERT_MSG(0, "MXCSR - invalid operand"); 1507 ASSERT_MSG(0, "MXCSR - invalid operand");
1535 1508
@@ -1540,143 +1513,357 @@ void XEmitter::WriteMXCSR(OpArg arg, int ext)
1540 arg.WriteRest(this); 1513 arg.WriteRest(this);
1541} 1514}
1542 1515
1543void XEmitter::STMXCSR(const OpArg& memloc) {WriteMXCSR(memloc, 3);} 1516void XEmitter::STMXCSR(const OpArg& memloc) {
1544void XEmitter::LDMXCSR(const OpArg& memloc) {WriteMXCSR(memloc, 2);} 1517 WriteMXCSR(memloc, 3);
1545 1518}
1546void XEmitter::MOVNTDQ(const OpArg& arg, X64Reg regOp) {WriteSSEOp(0x66, sseMOVNTDQ, regOp, arg);} 1519void XEmitter::LDMXCSR(const OpArg& memloc) {
1547void XEmitter::MOVNTPS(const OpArg& arg, X64Reg regOp) {WriteSSEOp(0x00, sseMOVNTP, regOp, arg);} 1520 WriteMXCSR(memloc, 2);
1548void XEmitter::MOVNTPD(const OpArg& arg, X64Reg regOp) {WriteSSEOp(0x66, sseMOVNTP, regOp, arg);} 1521}
1549 1522
1550void XEmitter::ADDSS(X64Reg regOp, const OpArg& arg) {WriteSSEOp(0xF3, sseADD, regOp, arg);} 1523void XEmitter::MOVNTDQ(const OpArg& arg, X64Reg regOp) {
1551void XEmitter::ADDSD(X64Reg regOp, const OpArg& arg) {WriteSSEOp(0xF2, sseADD, regOp, arg);} 1524 WriteSSEOp(0x66, sseMOVNTDQ, regOp, arg);
1552void XEmitter::SUBSS(X64Reg regOp, const OpArg& arg) {WriteSSEOp(0xF3, sseSUB, regOp, arg);} 1525}
1553void XEmitter::SUBSD(X64Reg regOp, const OpArg& arg) {WriteSSEOp(0xF2, sseSUB, regOp, arg);} 1526void XEmitter::MOVNTPS(const OpArg& arg, X64Reg regOp) {
1554void XEmitter::CMPSS(X64Reg regOp, const OpArg& arg, u8 compare) {WriteSSEOp(0xF3, sseCMP, regOp, arg, 1); Write8(compare);} 1527 WriteSSEOp(0x00, sseMOVNTP, regOp, arg);
1555void XEmitter::CMPSD(X64Reg regOp, const OpArg& arg, u8 compare) {WriteSSEOp(0xF2, sseCMP, regOp, arg, 1); Write8(compare);} 1528}
1556void XEmitter::MULSS(X64Reg regOp, const OpArg& arg) {WriteSSEOp(0xF3, sseMUL, regOp, arg);} 1529void XEmitter::MOVNTPD(const OpArg& arg, X64Reg regOp) {
1557void XEmitter::MULSD(X64Reg regOp, const OpArg& arg) {WriteSSEOp(0xF2, sseMUL, regOp, arg);} 1530 WriteSSEOp(0x66, sseMOVNTP, regOp, arg);
1558void XEmitter::DIVSS(X64Reg regOp, const OpArg& arg) {WriteSSEOp(0xF3, sseDIV, regOp, arg);} 1531}
1559void XEmitter::DIVSD(X64Reg regOp, const OpArg& arg) {WriteSSEOp(0xF2, sseDIV, regOp, arg);} 1532
1560void XEmitter::MINSS(X64Reg regOp, const OpArg& arg) {WriteSSEOp(0xF3, sseMIN, regOp, arg);} 1533void XEmitter::ADDSS(X64Reg regOp, const OpArg& arg) {
1561void XEmitter::MINSD(X64Reg regOp, const OpArg& arg) {WriteSSEOp(0xF2, sseMIN, regOp, arg);} 1534 WriteSSEOp(0xF3, sseADD, regOp, arg);
1562void XEmitter::MAXSS(X64Reg regOp, const OpArg& arg) {WriteSSEOp(0xF3, sseMAX, regOp, arg);} 1535}
1563void XEmitter::MAXSD(X64Reg regOp, const OpArg& arg) {WriteSSEOp(0xF2, sseMAX, regOp, arg);} 1536void XEmitter::ADDSD(X64Reg regOp, const OpArg& arg) {
1564void XEmitter::SQRTSS(X64Reg regOp, const OpArg& arg) {WriteSSEOp(0xF3, sseSQRT, regOp, arg);} 1537 WriteSSEOp(0xF2, sseADD, regOp, arg);
1565void XEmitter::SQRTSD(X64Reg regOp, const OpArg& arg) {WriteSSEOp(0xF2, sseSQRT, regOp, arg);} 1538}
1566void XEmitter::RCPSS(X64Reg regOp, const OpArg& arg) {WriteSSEOp(0xF3, sseRCP, regOp, arg);} 1539void XEmitter::SUBSS(X64Reg regOp, const OpArg& arg) {
1567void XEmitter::RSQRTSS(X64Reg regOp, const OpArg& arg) {WriteSSEOp(0xF3, sseRSQRT, regOp, arg);} 1540 WriteSSEOp(0xF3, sseSUB, regOp, arg);
1568 1541}
1569void XEmitter::ADDPS(X64Reg regOp, const OpArg& arg) {WriteSSEOp(0x00, sseADD, regOp, arg);} 1542void XEmitter::SUBSD(X64Reg regOp, const OpArg& arg) {
1570void XEmitter::ADDPD(X64Reg regOp, const OpArg& arg) {WriteSSEOp(0x66, sseADD, regOp, arg);} 1543 WriteSSEOp(0xF2, sseSUB, regOp, arg);
1571void XEmitter::SUBPS(X64Reg regOp, const OpArg& arg) {WriteSSEOp(0x00, sseSUB, regOp, arg);} 1544}
1572void XEmitter::SUBPD(X64Reg regOp, const OpArg& arg) {WriteSSEOp(0x66, sseSUB, regOp, arg);} 1545void XEmitter::CMPSS(X64Reg regOp, const OpArg& arg, u8 compare) {
1573void XEmitter::CMPPS(X64Reg regOp, const OpArg& arg, u8 compare) {WriteSSEOp(0x00, sseCMP, regOp, arg, 1); Write8(compare);} 1546 WriteSSEOp(0xF3, sseCMP, regOp, arg, 1);
1574void XEmitter::CMPPD(X64Reg regOp, const OpArg& arg, u8 compare) {WriteSSEOp(0x66, sseCMP, regOp, arg, 1); Write8(compare);} 1547 Write8(compare);
1575void XEmitter::ANDPS(X64Reg regOp, const OpArg& arg) {WriteSSEOp(0x00, sseAND, regOp, arg);} 1548}
1576void XEmitter::ANDPD(X64Reg regOp, const OpArg& arg) {WriteSSEOp(0x66, sseAND, regOp, arg);} 1549void XEmitter::CMPSD(X64Reg regOp, const OpArg& arg, u8 compare) {
1577void XEmitter::ANDNPS(X64Reg regOp, const OpArg& arg) {WriteSSEOp(0x00, sseANDN, regOp, arg);} 1550 WriteSSEOp(0xF2, sseCMP, regOp, arg, 1);
1578void XEmitter::ANDNPD(X64Reg regOp, const OpArg& arg) {WriteSSEOp(0x66, sseANDN, regOp, arg);} 1551 Write8(compare);
1579void XEmitter::ORPS(X64Reg regOp, const OpArg& arg) {WriteSSEOp(0x00, sseOR, regOp, arg);} 1552}
1580void XEmitter::ORPD(X64Reg regOp, const OpArg& arg) {WriteSSEOp(0x66, sseOR, regOp, arg);} 1553void XEmitter::MULSS(X64Reg regOp, const OpArg& arg) {
1581void XEmitter::XORPS(X64Reg regOp, const OpArg& arg) {WriteSSEOp(0x00, sseXOR, regOp, arg);} 1554 WriteSSEOp(0xF3, sseMUL, regOp, arg);
1582void XEmitter::XORPD(X64Reg regOp, const OpArg& arg) {WriteSSEOp(0x66, sseXOR, regOp, arg);} 1555}
1583void XEmitter::MULPS(X64Reg regOp, const OpArg& arg) {WriteSSEOp(0x00, sseMUL, regOp, arg);} 1556void XEmitter::MULSD(X64Reg regOp, const OpArg& arg) {
1584void XEmitter::MULPD(X64Reg regOp, const OpArg& arg) {WriteSSEOp(0x66, sseMUL, regOp, arg);} 1557 WriteSSEOp(0xF2, sseMUL, regOp, arg);
1585void XEmitter::DIVPS(X64Reg regOp, const OpArg& arg) {WriteSSEOp(0x00, sseDIV, regOp, arg);} 1558}
1586void XEmitter::DIVPD(X64Reg regOp, const OpArg& arg) {WriteSSEOp(0x66, sseDIV, regOp, arg);} 1559void XEmitter::DIVSS(X64Reg regOp, const OpArg& arg) {
1587void XEmitter::MINPS(X64Reg regOp, const OpArg& arg) {WriteSSEOp(0x00, sseMIN, regOp, arg);} 1560 WriteSSEOp(0xF3, sseDIV, regOp, arg);
1588void XEmitter::MINPD(X64Reg regOp, const OpArg& arg) {WriteSSEOp(0x66, sseMIN, regOp, arg);} 1561}
1589void XEmitter::MAXPS(X64Reg regOp, const OpArg& arg) {WriteSSEOp(0x00, sseMAX, regOp, arg);} 1562void XEmitter::DIVSD(X64Reg regOp, const OpArg& arg) {
1590void XEmitter::MAXPD(X64Reg regOp, const OpArg& arg) {WriteSSEOp(0x66, sseMAX, regOp, arg);} 1563 WriteSSEOp(0xF2, sseDIV, regOp, arg);
1591void XEmitter::SQRTPS(X64Reg regOp, const OpArg& arg) {WriteSSEOp(0x00, sseSQRT, regOp, arg);} 1564}
1592void XEmitter::SQRTPD(X64Reg regOp, const OpArg& arg) {WriteSSEOp(0x66, sseSQRT, regOp, arg);} 1565void XEmitter::MINSS(X64Reg regOp, const OpArg& arg) {
1593void XEmitter::RCPPS(X64Reg regOp, const OpArg& arg) { WriteSSEOp(0x00, sseRCP, regOp, arg); } 1566 WriteSSEOp(0xF3, sseMIN, regOp, arg);
1594void XEmitter::RSQRTPS(X64Reg regOp, const OpArg& arg) {WriteSSEOp(0x00, sseRSQRT, regOp, arg);} 1567}
1595void XEmitter::SHUFPS(X64Reg regOp, const OpArg& arg, u8 shuffle) {WriteSSEOp(0x00, sseSHUF, regOp, arg,1); Write8(shuffle);} 1568void XEmitter::MINSD(X64Reg regOp, const OpArg& arg) {
1596void XEmitter::SHUFPD(X64Reg regOp, const OpArg& arg, u8 shuffle) {WriteSSEOp(0x66, sseSHUF, regOp, arg,1); Write8(shuffle);} 1569 WriteSSEOp(0xF2, sseMIN, regOp, arg);
1597 1570}
1598void XEmitter::HADDPS(X64Reg regOp, const OpArg& arg) {WriteSSEOp(0xF2, sseHADD, regOp, arg);} 1571void XEmitter::MAXSS(X64Reg regOp, const OpArg& arg) {
1599 1572 WriteSSEOp(0xF3, sseMAX, regOp, arg);
1600void XEmitter::COMISS(X64Reg regOp, const OpArg& arg) {WriteSSEOp(0x00, sseCOMIS, regOp, arg);} //weird that these should be packed 1573}
1601void XEmitter::COMISD(X64Reg regOp, const OpArg& arg) {WriteSSEOp(0x66, sseCOMIS, regOp, arg);} //ordered 1574void XEmitter::MAXSD(X64Reg regOp, const OpArg& arg) {
1602void XEmitter::UCOMISS(X64Reg regOp, const OpArg& arg) {WriteSSEOp(0x00, sseUCOMIS, regOp, arg);} //unordered 1575 WriteSSEOp(0xF2, sseMAX, regOp, arg);
1603void XEmitter::UCOMISD(X64Reg regOp, const OpArg& arg) {WriteSSEOp(0x66, sseUCOMIS, regOp, arg);} 1576}
1604 1577void XEmitter::SQRTSS(X64Reg regOp, const OpArg& arg) {
1605void XEmitter::MOVAPS(X64Reg regOp, const OpArg& arg) {WriteSSEOp(0x00, sseMOVAPfromRM, regOp, arg);} 1578 WriteSSEOp(0xF3, sseSQRT, regOp, arg);
1606void XEmitter::MOVAPD(X64Reg regOp, const OpArg& arg) {WriteSSEOp(0x66, sseMOVAPfromRM, regOp, arg);} 1579}
1607void XEmitter::MOVAPS(const OpArg& arg, X64Reg regOp) {WriteSSEOp(0x00, sseMOVAPtoRM, regOp, arg);} 1580void XEmitter::SQRTSD(X64Reg regOp, const OpArg& arg) {
1608void XEmitter::MOVAPD(const OpArg& arg, X64Reg regOp) {WriteSSEOp(0x66, sseMOVAPtoRM, regOp, arg);} 1581 WriteSSEOp(0xF2, sseSQRT, regOp, arg);
1609 1582}
1610void XEmitter::MOVUPS(X64Reg regOp, const OpArg& arg) {WriteSSEOp(0x00, sseMOVUPfromRM, regOp, arg);} 1583void XEmitter::RCPSS(X64Reg regOp, const OpArg& arg) {
1611void XEmitter::MOVUPD(X64Reg regOp, const OpArg& arg) {WriteSSEOp(0x66, sseMOVUPfromRM, regOp, arg);} 1584 WriteSSEOp(0xF3, sseRCP, regOp, arg);
1612void XEmitter::MOVUPS(const OpArg& arg, X64Reg regOp) {WriteSSEOp(0x00, sseMOVUPtoRM, regOp, arg);} 1585}
1613void XEmitter::MOVUPD(const OpArg& arg, X64Reg regOp) {WriteSSEOp(0x66, sseMOVUPtoRM, regOp, arg);} 1586void XEmitter::RSQRTSS(X64Reg regOp, const OpArg& arg) {
1614 1587 WriteSSEOp(0xF3, sseRSQRT, regOp, arg);
1615void XEmitter::MOVDQA(X64Reg regOp, const OpArg& arg) {WriteSSEOp(0x66, sseMOVDQfromRM, regOp, arg);} 1588}
1616void XEmitter::MOVDQA(const OpArg& arg, X64Reg regOp) {WriteSSEOp(0x66, sseMOVDQtoRM, regOp, arg);} 1589
1617void XEmitter::MOVDQU(X64Reg regOp, const OpArg& arg) {WriteSSEOp(0xF3, sseMOVDQfromRM, regOp, arg);} 1590void XEmitter::ADDPS(X64Reg regOp, const OpArg& arg) {
1618void XEmitter::MOVDQU(const OpArg& arg, X64Reg regOp) {WriteSSEOp(0xF3, sseMOVDQtoRM, regOp, arg);} 1591 WriteSSEOp(0x00, sseADD, regOp, arg);
1619 1592}
1620void XEmitter::MOVSS(X64Reg regOp, const OpArg& arg) {WriteSSEOp(0xF3, sseMOVUPfromRM, regOp, arg);} 1593void XEmitter::ADDPD(X64Reg regOp, const OpArg& arg) {
1621void XEmitter::MOVSD(X64Reg regOp, const OpArg& arg) {WriteSSEOp(0xF2, sseMOVUPfromRM, regOp, arg);} 1594 WriteSSEOp(0x66, sseADD, regOp, arg);
1622void XEmitter::MOVSS(const OpArg& arg, X64Reg regOp) {WriteSSEOp(0xF3, sseMOVUPtoRM, regOp, arg);} 1595}
1623void XEmitter::MOVSD(const OpArg& arg, X64Reg regOp) {WriteSSEOp(0xF2, sseMOVUPtoRM, regOp, arg);} 1596void XEmitter::SUBPS(X64Reg regOp, const OpArg& arg) {
1624 1597 WriteSSEOp(0x00, sseSUB, regOp, arg);
1625void XEmitter::MOVLPS(X64Reg regOp, const OpArg& arg) { WriteSSEOp(0x00, sseMOVLPfromRM, regOp, arg); } 1598}
1626void XEmitter::MOVLPD(X64Reg regOp, const OpArg& arg) { WriteSSEOp(0x66, sseMOVLPfromRM, regOp, arg); } 1599void XEmitter::SUBPD(X64Reg regOp, const OpArg& arg) {
1627void XEmitter::MOVLPS(const OpArg& arg, X64Reg regOp) { WriteSSEOp(0x00, sseMOVLPtoRM, regOp, arg); } 1600 WriteSSEOp(0x66, sseSUB, regOp, arg);
1628void XEmitter::MOVLPD(const OpArg& arg, X64Reg regOp) { WriteSSEOp(0x66, sseMOVLPtoRM, regOp, arg); } 1601}
1629 1602void XEmitter::CMPPS(X64Reg regOp, const OpArg& arg, u8 compare) {
1630void XEmitter::MOVHPS(X64Reg regOp, const OpArg& arg) { WriteSSEOp(0x00, sseMOVHPfromRM, regOp, arg); } 1603 WriteSSEOp(0x00, sseCMP, regOp, arg, 1);
1631void XEmitter::MOVHPD(X64Reg regOp, const OpArg& arg) { WriteSSEOp(0x66, sseMOVHPfromRM, regOp, arg); } 1604 Write8(compare);
1632void XEmitter::MOVHPS(const OpArg& arg, X64Reg regOp) { WriteSSEOp(0x00, sseMOVHPtoRM, regOp, arg); } 1605}
1633void XEmitter::MOVHPD(const OpArg& arg, X64Reg regOp) { WriteSSEOp(0x66, sseMOVHPtoRM, regOp, arg); } 1606void XEmitter::CMPPD(X64Reg regOp, const OpArg& arg, u8 compare) {
1634 1607 WriteSSEOp(0x66, sseCMP, regOp, arg, 1);
1635void XEmitter::MOVHLPS(X64Reg regOp1, X64Reg regOp2) {WriteSSEOp(0x00, sseMOVHLPS, regOp1, R(regOp2));} 1608 Write8(compare);
1636void XEmitter::MOVLHPS(X64Reg regOp1, X64Reg regOp2) {WriteSSEOp(0x00, sseMOVLHPS, regOp1, R(regOp2));} 1609}
1637 1610void XEmitter::ANDPS(X64Reg regOp, const OpArg& arg) {
1638void XEmitter::CVTPS2PD(X64Reg regOp, const OpArg& arg) {WriteSSEOp(0x00, 0x5A, regOp, arg);} 1611 WriteSSEOp(0x00, sseAND, regOp, arg);
1639void XEmitter::CVTPD2PS(X64Reg regOp, const OpArg& arg) {WriteSSEOp(0x66, 0x5A, regOp, arg);} 1612}
1640 1613void XEmitter::ANDPD(X64Reg regOp, const OpArg& arg) {
1641void XEmitter::CVTSD2SS(X64Reg regOp, const OpArg& arg) {WriteSSEOp(0xF2, 0x5A, regOp, arg);} 1614 WriteSSEOp(0x66, sseAND, regOp, arg);
1642void XEmitter::CVTSS2SD(X64Reg regOp, const OpArg& arg) {WriteSSEOp(0xF3, 0x5A, regOp, arg);} 1615}
1643void XEmitter::CVTSD2SI(X64Reg regOp, const OpArg& arg) {WriteSSEOp(0xF2, 0x2D, regOp, arg);} 1616void XEmitter::ANDNPS(X64Reg regOp, const OpArg& arg) {
1644void XEmitter::CVTSS2SI(X64Reg regOp, const OpArg& arg) {WriteSSEOp(0xF3, 0x2D, regOp, arg);} 1617 WriteSSEOp(0x00, sseANDN, regOp, arg);
1645void XEmitter::CVTSI2SD(X64Reg regOp, const OpArg& arg) {WriteSSEOp(0xF2, 0x2A, regOp, arg);} 1618}
1646void XEmitter::CVTSI2SS(X64Reg regOp, const OpArg& arg) {WriteSSEOp(0xF3, 0x2A, regOp, arg);} 1619void XEmitter::ANDNPD(X64Reg regOp, const OpArg& arg) {
1647 1620 WriteSSEOp(0x66, sseANDN, regOp, arg);
1648void XEmitter::CVTDQ2PD(X64Reg regOp, const OpArg& arg) {WriteSSEOp(0xF3, 0xE6, regOp, arg);} 1621}
1649void XEmitter::CVTDQ2PS(X64Reg regOp, const OpArg& arg) {WriteSSEOp(0x00, 0x5B, regOp, arg);} 1622void XEmitter::ORPS(X64Reg regOp, const OpArg& arg) {
1650void XEmitter::CVTPD2DQ(X64Reg regOp, const OpArg& arg) {WriteSSEOp(0xF2, 0xE6, regOp, arg);} 1623 WriteSSEOp(0x00, sseOR, regOp, arg);
1651void XEmitter::CVTPS2DQ(X64Reg regOp, const OpArg& arg) {WriteSSEOp(0x66, 0x5B, regOp, arg);} 1624}
1652 1625void XEmitter::ORPD(X64Reg regOp, const OpArg& arg) {
1653void XEmitter::CVTTSD2SI(X64Reg regOp, const OpArg& arg) {WriteSSEOp(0xF2, 0x2C, regOp, arg);} 1626 WriteSSEOp(0x66, sseOR, regOp, arg);
1654void XEmitter::CVTTSS2SI(X64Reg regOp, const OpArg& arg) {WriteSSEOp(0xF3, 0x2C, regOp, arg);} 1627}
1655void XEmitter::CVTTPS2DQ(X64Reg regOp, const OpArg& arg) {WriteSSEOp(0xF3, 0x5B, regOp, arg);} 1628void XEmitter::XORPS(X64Reg regOp, const OpArg& arg) {
1656void XEmitter::CVTTPD2DQ(X64Reg regOp, const OpArg& arg) {WriteSSEOp(0x66, 0xE6, regOp, arg);} 1629 WriteSSEOp(0x00, sseXOR, regOp, arg);
1657 1630}
1658void XEmitter::MASKMOVDQU(X64Reg dest, X64Reg src) {WriteSSEOp(0x66, sseMASKMOVDQU, dest, R(src));} 1631void XEmitter::XORPD(X64Reg regOp, const OpArg& arg) {
1659 1632 WriteSSEOp(0x66, sseXOR, regOp, arg);
1660void XEmitter::MOVMSKPS(X64Reg dest, const OpArg& arg) {WriteSSEOp(0x00, 0x50, dest, arg);} 1633}
1661void XEmitter::MOVMSKPD(X64Reg dest, const OpArg& arg) {WriteSSEOp(0x66, 0x50, dest, arg);} 1634void XEmitter::MULPS(X64Reg regOp, const OpArg& arg) {
1662 1635 WriteSSEOp(0x00, sseMUL, regOp, arg);
1663void XEmitter::LDDQU(X64Reg dest, const OpArg& arg) {WriteSSEOp(0xF2, sseLDDQU, dest, arg);} // For integer data only 1636}
1637void XEmitter::MULPD(X64Reg regOp, const OpArg& arg) {
1638 WriteSSEOp(0x66, sseMUL, regOp, arg);
1639}
1640void XEmitter::DIVPS(X64Reg regOp, const OpArg& arg) {
1641 WriteSSEOp(0x00, sseDIV, regOp, arg);
1642}
1643void XEmitter::DIVPD(X64Reg regOp, const OpArg& arg) {
1644 WriteSSEOp(0x66, sseDIV, regOp, arg);
1645}
1646void XEmitter::MINPS(X64Reg regOp, const OpArg& arg) {
1647 WriteSSEOp(0x00, sseMIN, regOp, arg);
1648}
1649void XEmitter::MINPD(X64Reg regOp, const OpArg& arg) {
1650 WriteSSEOp(0x66, sseMIN, regOp, arg);
1651}
1652void XEmitter::MAXPS(X64Reg regOp, const OpArg& arg) {
1653 WriteSSEOp(0x00, sseMAX, regOp, arg);
1654}
1655void XEmitter::MAXPD(X64Reg regOp, const OpArg& arg) {
1656 WriteSSEOp(0x66, sseMAX, regOp, arg);
1657}
1658void XEmitter::SQRTPS(X64Reg regOp, const OpArg& arg) {
1659 WriteSSEOp(0x00, sseSQRT, regOp, arg);
1660}
1661void XEmitter::SQRTPD(X64Reg regOp, const OpArg& arg) {
1662 WriteSSEOp(0x66, sseSQRT, regOp, arg);
1663}
1664void XEmitter::RCPPS(X64Reg regOp, const OpArg& arg) {
1665 WriteSSEOp(0x00, sseRCP, regOp, arg);
1666}
1667void XEmitter::RSQRTPS(X64Reg regOp, const OpArg& arg) {
1668 WriteSSEOp(0x00, sseRSQRT, regOp, arg);
1669}
1670void XEmitter::SHUFPS(X64Reg regOp, const OpArg& arg, u8 shuffle) {
1671 WriteSSEOp(0x00, sseSHUF, regOp, arg, 1);
1672 Write8(shuffle);
1673}
1674void XEmitter::SHUFPD(X64Reg regOp, const OpArg& arg, u8 shuffle) {
1675 WriteSSEOp(0x66, sseSHUF, regOp, arg, 1);
1676 Write8(shuffle);
1677}
1678
1679void XEmitter::HADDPS(X64Reg regOp, const OpArg& arg) {
1680 WriteSSEOp(0xF2, sseHADD, regOp, arg);
1681}
1682
1683void XEmitter::COMISS(X64Reg regOp, const OpArg& arg) {
1684 WriteSSEOp(0x00, sseCOMIS, regOp, arg);
1685} // weird that these should be packed
1686void XEmitter::COMISD(X64Reg regOp, const OpArg& arg) {
1687 WriteSSEOp(0x66, sseCOMIS, regOp, arg);
1688} // ordered
1689void XEmitter::UCOMISS(X64Reg regOp, const OpArg& arg) {
1690 WriteSSEOp(0x00, sseUCOMIS, regOp, arg);
1691} // unordered
1692void XEmitter::UCOMISD(X64Reg regOp, const OpArg& arg) {
1693 WriteSSEOp(0x66, sseUCOMIS, regOp, arg);
1694}
1695
1696void XEmitter::MOVAPS(X64Reg regOp, const OpArg& arg) {
1697 WriteSSEOp(0x00, sseMOVAPfromRM, regOp, arg);
1698}
1699void XEmitter::MOVAPD(X64Reg regOp, const OpArg& arg) {
1700 WriteSSEOp(0x66, sseMOVAPfromRM, regOp, arg);
1701}
1702void XEmitter::MOVAPS(const OpArg& arg, X64Reg regOp) {
1703 WriteSSEOp(0x00, sseMOVAPtoRM, regOp, arg);
1704}
1705void XEmitter::MOVAPD(const OpArg& arg, X64Reg regOp) {
1706 WriteSSEOp(0x66, sseMOVAPtoRM, regOp, arg);
1707}
1708
1709void XEmitter::MOVUPS(X64Reg regOp, const OpArg& arg) {
1710 WriteSSEOp(0x00, sseMOVUPfromRM, regOp, arg);
1711}
1712void XEmitter::MOVUPD(X64Reg regOp, const OpArg& arg) {
1713 WriteSSEOp(0x66, sseMOVUPfromRM, regOp, arg);
1714}
1715void XEmitter::MOVUPS(const OpArg& arg, X64Reg regOp) {
1716 WriteSSEOp(0x00, sseMOVUPtoRM, regOp, arg);
1717}
1718void XEmitter::MOVUPD(const OpArg& arg, X64Reg regOp) {
1719 WriteSSEOp(0x66, sseMOVUPtoRM, regOp, arg);
1720}
1721
1722void XEmitter::MOVDQA(X64Reg regOp, const OpArg& arg) {
1723 WriteSSEOp(0x66, sseMOVDQfromRM, regOp, arg);
1724}
1725void XEmitter::MOVDQA(const OpArg& arg, X64Reg regOp) {
1726 WriteSSEOp(0x66, sseMOVDQtoRM, regOp, arg);
1727}
1728void XEmitter::MOVDQU(X64Reg regOp, const OpArg& arg) {
1729 WriteSSEOp(0xF3, sseMOVDQfromRM, regOp, arg);
1730}
1731void XEmitter::MOVDQU(const OpArg& arg, X64Reg regOp) {
1732 WriteSSEOp(0xF3, sseMOVDQtoRM, regOp, arg);
1733}
1734
1735void XEmitter::MOVSS(X64Reg regOp, const OpArg& arg) {
1736 WriteSSEOp(0xF3, sseMOVUPfromRM, regOp, arg);
1737}
1738void XEmitter::MOVSD(X64Reg regOp, const OpArg& arg) {
1739 WriteSSEOp(0xF2, sseMOVUPfromRM, regOp, arg);
1740}
1741void XEmitter::MOVSS(const OpArg& arg, X64Reg regOp) {
1742 WriteSSEOp(0xF3, sseMOVUPtoRM, regOp, arg);
1743}
1744void XEmitter::MOVSD(const OpArg& arg, X64Reg regOp) {
1745 WriteSSEOp(0xF2, sseMOVUPtoRM, regOp, arg);
1746}
1747
1748void XEmitter::MOVLPS(X64Reg regOp, const OpArg& arg) {
1749 WriteSSEOp(0x00, sseMOVLPfromRM, regOp, arg);
1750}
1751void XEmitter::MOVLPD(X64Reg regOp, const OpArg& arg) {
1752 WriteSSEOp(0x66, sseMOVLPfromRM, regOp, arg);
1753}
1754void XEmitter::MOVLPS(const OpArg& arg, X64Reg regOp) {
1755 WriteSSEOp(0x00, sseMOVLPtoRM, regOp, arg);
1756}
1757void XEmitter::MOVLPD(const OpArg& arg, X64Reg regOp) {
1758 WriteSSEOp(0x66, sseMOVLPtoRM, regOp, arg);
1759}
1760
1761void XEmitter::MOVHPS(X64Reg regOp, const OpArg& arg) {
1762 WriteSSEOp(0x00, sseMOVHPfromRM, regOp, arg);
1763}
1764void XEmitter::MOVHPD(X64Reg regOp, const OpArg& arg) {
1765 WriteSSEOp(0x66, sseMOVHPfromRM, regOp, arg);
1766}
1767void XEmitter::MOVHPS(const OpArg& arg, X64Reg regOp) {
1768 WriteSSEOp(0x00, sseMOVHPtoRM, regOp, arg);
1769}
1770void XEmitter::MOVHPD(const OpArg& arg, X64Reg regOp) {
1771 WriteSSEOp(0x66, sseMOVHPtoRM, regOp, arg);
1772}
1773
1774void XEmitter::MOVHLPS(X64Reg regOp1, X64Reg regOp2) {
1775 WriteSSEOp(0x00, sseMOVHLPS, regOp1, R(regOp2));
1776}
1777void XEmitter::MOVLHPS(X64Reg regOp1, X64Reg regOp2) {
1778 WriteSSEOp(0x00, sseMOVLHPS, regOp1, R(regOp2));
1779}
1780
1781void XEmitter::CVTPS2PD(X64Reg regOp, const OpArg& arg) {
1782 WriteSSEOp(0x00, 0x5A, regOp, arg);
1783}
1784void XEmitter::CVTPD2PS(X64Reg regOp, const OpArg& arg) {
1785 WriteSSEOp(0x66, 0x5A, regOp, arg);
1786}
1787
1788void XEmitter::CVTSD2SS(X64Reg regOp, const OpArg& arg) {
1789 WriteSSEOp(0xF2, 0x5A, regOp, arg);
1790}
1791void XEmitter::CVTSS2SD(X64Reg regOp, const OpArg& arg) {
1792 WriteSSEOp(0xF3, 0x5A, regOp, arg);
1793}
1794void XEmitter::CVTSD2SI(X64Reg regOp, const OpArg& arg) {
1795 WriteSSEOp(0xF2, 0x2D, regOp, arg);
1796}
1797void XEmitter::CVTSS2SI(X64Reg regOp, const OpArg& arg) {
1798 WriteSSEOp(0xF3, 0x2D, regOp, arg);
1799}
1800void XEmitter::CVTSI2SD(X64Reg regOp, const OpArg& arg) {
1801 WriteSSEOp(0xF2, 0x2A, regOp, arg);
1802}
1803void XEmitter::CVTSI2SS(X64Reg regOp, const OpArg& arg) {
1804 WriteSSEOp(0xF3, 0x2A, regOp, arg);
1805}
1806
1807void XEmitter::CVTDQ2PD(X64Reg regOp, const OpArg& arg) {
1808 WriteSSEOp(0xF3, 0xE6, regOp, arg);
1809}
1810void XEmitter::CVTDQ2PS(X64Reg regOp, const OpArg& arg) {
1811 WriteSSEOp(0x00, 0x5B, regOp, arg);
1812}
1813void XEmitter::CVTPD2DQ(X64Reg regOp, const OpArg& arg) {
1814 WriteSSEOp(0xF2, 0xE6, regOp, arg);
1815}
1816void XEmitter::CVTPS2DQ(X64Reg regOp, const OpArg& arg) {
1817 WriteSSEOp(0x66, 0x5B, regOp, arg);
1818}
1819
1820void XEmitter::CVTTSD2SI(X64Reg regOp, const OpArg& arg) {
1821 WriteSSEOp(0xF2, 0x2C, regOp, arg);
1822}
1823void XEmitter::CVTTSS2SI(X64Reg regOp, const OpArg& arg) {
1824 WriteSSEOp(0xF3, 0x2C, regOp, arg);
1825}
1826void XEmitter::CVTTPS2DQ(X64Reg regOp, const OpArg& arg) {
1827 WriteSSEOp(0xF3, 0x5B, regOp, arg);
1828}
1829void XEmitter::CVTTPD2DQ(X64Reg regOp, const OpArg& arg) {
1830 WriteSSEOp(0x66, 0xE6, regOp, arg);
1831}
1832
1833void XEmitter::MASKMOVDQU(X64Reg dest, X64Reg src) {
1834 WriteSSEOp(0x66, sseMASKMOVDQU, dest, R(src));
1835}
1836
1837void XEmitter::MOVMSKPS(X64Reg dest, const OpArg& arg) {
1838 WriteSSEOp(0x00, 0x50, dest, arg);
1839}
1840void XEmitter::MOVMSKPD(X64Reg dest, const OpArg& arg) {
1841 WriteSSEOp(0x66, 0x50, dest, arg);
1842}
1843
1844void XEmitter::LDDQU(X64Reg dest, const OpArg& arg) {
1845 WriteSSEOp(0xF2, sseLDDQU, dest, arg);
1846} // For integer data only
1664 1847
1665// THESE TWO ARE UNTESTED. 1848// THESE TWO ARE UNTESTED.
1666void XEmitter::UNPCKLPS(X64Reg dest, const OpArg& arg) {WriteSSEOp(0x00, 0x14, dest, arg);} 1849void XEmitter::UNPCKLPS(X64Reg dest, const OpArg& arg) {
1667void XEmitter::UNPCKHPS(X64Reg dest, const OpArg& arg) {WriteSSEOp(0x00, 0x15, dest, arg);} 1850 WriteSSEOp(0x00, 0x14, dest, arg);
1851}
1852void XEmitter::UNPCKHPS(X64Reg dest, const OpArg& arg) {
1853 WriteSSEOp(0x00, 0x15, dest, arg);
1854}
1668 1855
1669void XEmitter::UNPCKLPD(X64Reg dest, const OpArg& arg) {WriteSSEOp(0x66, 0x14, dest, arg);} 1856void XEmitter::UNPCKLPD(X64Reg dest, const OpArg& arg) {
1670void XEmitter::UNPCKHPD(X64Reg dest, const OpArg& arg) {WriteSSEOp(0x66, 0x15, dest, arg);} 1857 WriteSSEOp(0x66, 0x14, dest, arg);
1858}
1859void XEmitter::UNPCKHPD(X64Reg dest, const OpArg& arg) {
1860 WriteSSEOp(0x66, 0x15, dest, arg);
1861}
1671 1862
1672void XEmitter::MOVDDUP(X64Reg regOp, const OpArg& arg) 1863void XEmitter::MOVDDUP(X64Reg regOp, const OpArg& arg) {
1673{ 1864 if (Common::GetCPUCaps().sse3) {
1674 if (Common::GetCPUCaps().sse3) 1865 WriteSSEOp(0xF2, 0x12, regOp, arg); // SSE3 movddup
1675 { 1866 } else {
1676 WriteSSEOp(0xF2, 0x12, regOp, arg); //SSE3 movddup
1677 }
1678 else
1679 {
1680 // Simulate this instruction with SSE2 instructions 1867 // Simulate this instruction with SSE2 instructions
1681 if (!arg.IsSimpleReg(regOp)) 1868 if (!arg.IsSimpleReg(regOp))
1682 MOVSD(regOp, arg); 1869 MOVSD(regOp, arg);
@@ -1684,38 +1871,48 @@ void XEmitter::MOVDDUP(X64Reg regOp, const OpArg& arg)
1684 } 1871 }
1685} 1872}
1686 1873
1687//There are a few more left 1874// There are a few more left
1688 1875
1689// Also some integer instructions are missing 1876// Also some integer instructions are missing
1690void XEmitter::PACKSSDW(X64Reg dest, const OpArg& arg) {WriteSSEOp(0x66, 0x6B, dest, arg);} 1877void XEmitter::PACKSSDW(X64Reg dest, const OpArg& arg) {
1691void XEmitter::PACKSSWB(X64Reg dest, const OpArg& arg) {WriteSSEOp(0x66, 0x63, dest, arg);} 1878 WriteSSEOp(0x66, 0x6B, dest, arg);
1692void XEmitter::PACKUSWB(X64Reg dest, const OpArg& arg) {WriteSSEOp(0x66, 0x67, dest, arg);} 1879}
1880void XEmitter::PACKSSWB(X64Reg dest, const OpArg& arg) {
1881 WriteSSEOp(0x66, 0x63, dest, arg);
1882}
1883void XEmitter::PACKUSWB(X64Reg dest, const OpArg& arg) {
1884 WriteSSEOp(0x66, 0x67, dest, arg);
1885}
1693 1886
1694void XEmitter::PUNPCKLBW(X64Reg dest, const OpArg &arg) {WriteSSEOp(0x66, 0x60, dest, arg);} 1887void XEmitter::PUNPCKLBW(X64Reg dest, const OpArg& arg) {
1695void XEmitter::PUNPCKLWD(X64Reg dest, const OpArg &arg) {WriteSSEOp(0x66, 0x61, dest, arg);} 1888 WriteSSEOp(0x66, 0x60, dest, arg);
1696void XEmitter::PUNPCKLDQ(X64Reg dest, const OpArg &arg) {WriteSSEOp(0x66, 0x62, dest, arg);} 1889}
1697void XEmitter::PUNPCKLQDQ(X64Reg dest, const OpArg &arg) {WriteSSEOp(0x66, 0x6C, dest, arg);} 1890void XEmitter::PUNPCKLWD(X64Reg dest, const OpArg& arg) {
1891 WriteSSEOp(0x66, 0x61, dest, arg);
1892}
1893void XEmitter::PUNPCKLDQ(X64Reg dest, const OpArg& arg) {
1894 WriteSSEOp(0x66, 0x62, dest, arg);
1895}
1896void XEmitter::PUNPCKLQDQ(X64Reg dest, const OpArg& arg) {
1897 WriteSSEOp(0x66, 0x6C, dest, arg);
1898}
1698 1899
1699void XEmitter::PSRLW(X64Reg reg, int shift) 1900void XEmitter::PSRLW(X64Reg reg, int shift) {
1700{
1701 WriteSSEOp(0x66, 0x71, (X64Reg)2, R(reg)); 1901 WriteSSEOp(0x66, 0x71, (X64Reg)2, R(reg));
1702 Write8(shift); 1902 Write8(shift);
1703} 1903}
1704 1904
1705void XEmitter::PSRLD(X64Reg reg, int shift) 1905void XEmitter::PSRLD(X64Reg reg, int shift) {
1706{
1707 WriteSSEOp(0x66, 0x72, (X64Reg)2, R(reg)); 1906 WriteSSEOp(0x66, 0x72, (X64Reg)2, R(reg));
1708 Write8(shift); 1907 Write8(shift);
1709} 1908}
1710 1909
1711void XEmitter::PSRLQ(X64Reg reg, int shift) 1910void XEmitter::PSRLQ(X64Reg reg, int shift) {
1712{
1713 WriteSSEOp(0x66, 0x73, (X64Reg)2, R(reg)); 1911 WriteSSEOp(0x66, 0x73, (X64Reg)2, R(reg));
1714 Write8(shift); 1912 Write8(shift);
1715} 1913}
1716 1914
1717void XEmitter::PSRLQ(X64Reg reg, const OpArg& arg) 1915void XEmitter::PSRLQ(X64Reg reg, const OpArg& arg) {
1718{
1719 WriteSSEOp(0x66, 0xd3, reg, arg); 1916 WriteSSEOp(0x66, 0xd3, reg, arg);
1720} 1917}
1721 1918
@@ -1724,20 +1921,17 @@ void XEmitter::PSRLDQ(X64Reg reg, int shift) {
1724 Write8(shift); 1921 Write8(shift);
1725} 1922}
1726 1923
1727void XEmitter::PSLLW(X64Reg reg, int shift) 1924void XEmitter::PSLLW(X64Reg reg, int shift) {
1728{
1729 WriteSSEOp(0x66, 0x71, (X64Reg)6, R(reg)); 1925 WriteSSEOp(0x66, 0x71, (X64Reg)6, R(reg));
1730 Write8(shift); 1926 Write8(shift);
1731} 1927}
1732 1928
1733void XEmitter::PSLLD(X64Reg reg, int shift) 1929void XEmitter::PSLLD(X64Reg reg, int shift) {
1734{
1735 WriteSSEOp(0x66, 0x72, (X64Reg)6, R(reg)); 1930 WriteSSEOp(0x66, 0x72, (X64Reg)6, R(reg));
1736 Write8(shift); 1931 Write8(shift);
1737} 1932}
1738 1933
1739void XEmitter::PSLLQ(X64Reg reg, int shift) 1934void XEmitter::PSLLQ(X64Reg reg, int shift) {
1740{
1741 WriteSSEOp(0x66, 0x73, (X64Reg)6, R(reg)); 1935 WriteSSEOp(0x66, 0x73, (X64Reg)6, R(reg));
1742 Write8(shift); 1936 Write8(shift);
1743} 1937}
@@ -1747,267 +1941,643 @@ void XEmitter::PSLLDQ(X64Reg reg, int shift) {
1747 Write8(shift); 1941 Write8(shift);
1748} 1942}
1749 1943
1750void XEmitter::PSRAW(X64Reg reg, int shift) 1944void XEmitter::PSRAW(X64Reg reg, int shift) {
1751{
1752 WriteSSEOp(0x66, 0x71, (X64Reg)4, R(reg)); 1945 WriteSSEOp(0x66, 0x71, (X64Reg)4, R(reg));
1753 Write8(shift); 1946 Write8(shift);
1754} 1947}
1755 1948
1756void XEmitter::PSRAD(X64Reg reg, int shift) 1949void XEmitter::PSRAD(X64Reg reg, int shift) {
1757{
1758 WriteSSEOp(0x66, 0x72, (X64Reg)4, R(reg)); 1950 WriteSSEOp(0x66, 0x72, (X64Reg)4, R(reg));
1759 Write8(shift); 1951 Write8(shift);
1760} 1952}
1761 1953
1762void XEmitter::WriteSSSE3Op(u8 opPrefix, u16 op, X64Reg regOp, const OpArg& arg, int extrabytes) 1954void XEmitter::WriteSSSE3Op(u8 opPrefix, u16 op, X64Reg regOp, const OpArg& arg, int extrabytes) {
1763{
1764 if (!Common::GetCPUCaps().ssse3) 1955 if (!Common::GetCPUCaps().ssse3)
1765 ASSERT_MSG(0, "Trying to use SSSE3 on a system that doesn't support it. Bad programmer."); 1956 ASSERT_MSG(0, "Trying to use SSSE3 on a system that doesn't support it. Bad programmer.");
1766 WriteSSEOp(opPrefix, op, regOp, arg, extrabytes); 1957 WriteSSEOp(opPrefix, op, regOp, arg, extrabytes);
1767} 1958}
1768 1959
1769void XEmitter::WriteSSE41Op(u8 opPrefix, u16 op, X64Reg regOp, const OpArg& arg, int extrabytes) 1960void XEmitter::WriteSSE41Op(u8 opPrefix, u16 op, X64Reg regOp, const OpArg& arg, int extrabytes) {
1770{
1771 if (!Common::GetCPUCaps().sse4_1) 1961 if (!Common::GetCPUCaps().sse4_1)
1772 ASSERT_MSG(0, "Trying to use SSE4.1 on a system that doesn't support it. Bad programmer."); 1962 ASSERT_MSG(0, "Trying to use SSE4.1 on a system that doesn't support it. Bad programmer.");
1773 WriteSSEOp(opPrefix, op, regOp, arg, extrabytes); 1963 WriteSSEOp(opPrefix, op, regOp, arg, extrabytes);
1774} 1964}
1775 1965
1776void XEmitter::PSHUFB(X64Reg dest, const OpArg& arg) {WriteSSSE3Op(0x66, 0x3800, dest, arg);} 1966void XEmitter::PSHUFB(X64Reg dest, const OpArg& arg) {
1777void XEmitter::PTEST(X64Reg dest, const OpArg& arg) {WriteSSE41Op(0x66, 0x3817, dest, arg);} 1967 WriteSSSE3Op(0x66, 0x3800, dest, arg);
1778void XEmitter::PACKUSDW(X64Reg dest, const OpArg& arg) {WriteSSE41Op(0x66, 0x382b, dest, arg);} 1968}
1779void XEmitter::DPPS(X64Reg dest, const OpArg& arg, u8 mask) {WriteSSE41Op(0x66, 0x3A40, dest, arg, 1); Write8(mask);} 1969void XEmitter::PTEST(X64Reg dest, const OpArg& arg) {
1780 1970 WriteSSE41Op(0x66, 0x3817, dest, arg);
1781void XEmitter::PMINSB(X64Reg dest, const OpArg& arg) {WriteSSE41Op(0x66, 0x3838, dest, arg);} 1971}
1782void XEmitter::PMINSD(X64Reg dest, const OpArg& arg) {WriteSSE41Op(0x66, 0x3839, dest, arg);} 1972void XEmitter::PACKUSDW(X64Reg dest, const OpArg& arg) {
1783void XEmitter::PMINUW(X64Reg dest, const OpArg& arg) {WriteSSE41Op(0x66, 0x383a, dest, arg);} 1973 WriteSSE41Op(0x66, 0x382b, dest, arg);
1784void XEmitter::PMINUD(X64Reg dest, const OpArg& arg) {WriteSSE41Op(0x66, 0x383b, dest, arg);} 1974}
1785void XEmitter::PMAXSB(X64Reg dest, const OpArg& arg) {WriteSSE41Op(0x66, 0x383c, dest, arg);} 1975void XEmitter::DPPS(X64Reg dest, const OpArg& arg, u8 mask) {
1786void XEmitter::PMAXSD(X64Reg dest, const OpArg& arg) {WriteSSE41Op(0x66, 0x383d, dest, arg);} 1976 WriteSSE41Op(0x66, 0x3A40, dest, arg, 1);
1787void XEmitter::PMAXUW(X64Reg dest, const OpArg& arg) {WriteSSE41Op(0x66, 0x383e, dest, arg);} 1977 Write8(mask);
1788void XEmitter::PMAXUD(X64Reg dest, const OpArg& arg) {WriteSSE41Op(0x66, 0x383f, dest, arg);} 1978}
1789 1979
1790void XEmitter::PMOVSXBW(X64Reg dest, const OpArg& arg) {WriteSSE41Op(0x66, 0x3820, dest, arg);} 1980void XEmitter::PMINSB(X64Reg dest, const OpArg& arg) {
1791void XEmitter::PMOVSXBD(X64Reg dest, const OpArg& arg) {WriteSSE41Op(0x66, 0x3821, dest, arg);} 1981 WriteSSE41Op(0x66, 0x3838, dest, arg);
1792void XEmitter::PMOVSXBQ(X64Reg dest, const OpArg& arg) {WriteSSE41Op(0x66, 0x3822, dest, arg);} 1982}
1793void XEmitter::PMOVSXWD(X64Reg dest, const OpArg& arg) {WriteSSE41Op(0x66, 0x3823, dest, arg);} 1983void XEmitter::PMINSD(X64Reg dest, const OpArg& arg) {
1794void XEmitter::PMOVSXWQ(X64Reg dest, const OpArg& arg) {WriteSSE41Op(0x66, 0x3824, dest, arg);} 1984 WriteSSE41Op(0x66, 0x3839, dest, arg);
1795void XEmitter::PMOVSXDQ(X64Reg dest, const OpArg& arg) {WriteSSE41Op(0x66, 0x3825, dest, arg);} 1985}
1796void XEmitter::PMOVZXBW(X64Reg dest, const OpArg& arg) {WriteSSE41Op(0x66, 0x3830, dest, arg);} 1986void XEmitter::PMINUW(X64Reg dest, const OpArg& arg) {
1797void XEmitter::PMOVZXBD(X64Reg dest, const OpArg& arg) {WriteSSE41Op(0x66, 0x3831, dest, arg);} 1987 WriteSSE41Op(0x66, 0x383a, dest, arg);
1798void XEmitter::PMOVZXBQ(X64Reg dest, const OpArg& arg) {WriteSSE41Op(0x66, 0x3832, dest, arg);} 1988}
1799void XEmitter::PMOVZXWD(X64Reg dest, const OpArg& arg) {WriteSSE41Op(0x66, 0x3833, dest, arg);} 1989void XEmitter::PMINUD(X64Reg dest, const OpArg& arg) {
1800void XEmitter::PMOVZXWQ(X64Reg dest, const OpArg& arg) {WriteSSE41Op(0x66, 0x3834, dest, arg);} 1990 WriteSSE41Op(0x66, 0x383b, dest, arg);
1801void XEmitter::PMOVZXDQ(X64Reg dest, const OpArg& arg) {WriteSSE41Op(0x66, 0x3835, dest, arg);} 1991}
1802 1992void XEmitter::PMAXSB(X64Reg dest, const OpArg& arg) {
1803void XEmitter::PBLENDVB(X64Reg dest, const OpArg& arg) {WriteSSE41Op(0x66, 0x3810, dest, arg);} 1993 WriteSSE41Op(0x66, 0x383c, dest, arg);
1804void XEmitter::BLENDVPS(X64Reg dest, const OpArg& arg) {WriteSSE41Op(0x66, 0x3814, dest, arg);} 1994}
1805void XEmitter::BLENDVPD(X64Reg dest, const OpArg& arg) {WriteSSE41Op(0x66, 0x3815, dest, arg);} 1995void XEmitter::PMAXSD(X64Reg dest, const OpArg& arg) {
1806void XEmitter::BLENDPS(X64Reg dest, const OpArg& arg, u8 blend) { WriteSSE41Op(0x66, 0x3A0C, dest, arg, 1); Write8(blend); } 1996 WriteSSE41Op(0x66, 0x383d, dest, arg);
1807void XEmitter::BLENDPD(X64Reg dest, const OpArg& arg, u8 blend) { WriteSSE41Op(0x66, 0x3A0D, dest, arg, 1); Write8(blend); } 1997}
1808 1998void XEmitter::PMAXUW(X64Reg dest, const OpArg& arg) {
1809void XEmitter::ROUNDSS(X64Reg dest, const OpArg& arg, u8 mode) {WriteSSE41Op(0x66, 0x3A0A, dest, arg, 1); Write8(mode);} 1999 WriteSSE41Op(0x66, 0x383e, dest, arg);
1810void XEmitter::ROUNDSD(X64Reg dest, const OpArg& arg, u8 mode) {WriteSSE41Op(0x66, 0x3A0B, dest, arg, 1); Write8(mode);} 2000}
1811void XEmitter::ROUNDPS(X64Reg dest, const OpArg& arg, u8 mode) {WriteSSE41Op(0x66, 0x3A08, dest, arg, 1); Write8(mode);} 2001void XEmitter::PMAXUD(X64Reg dest, const OpArg& arg) {
1812void XEmitter::ROUNDPD(X64Reg dest, const OpArg& arg, u8 mode) {WriteSSE41Op(0x66, 0x3A09, dest, arg, 1); Write8(mode);} 2002 WriteSSE41Op(0x66, 0x383f, dest, arg);
1813 2003}
1814void XEmitter::PAND(X64Reg dest, const OpArg& arg) {WriteSSEOp(0x66, 0xDB, dest, arg);} 2004
1815void XEmitter::PANDN(X64Reg dest, const OpArg& arg) {WriteSSEOp(0x66, 0xDF, dest, arg);} 2005void XEmitter::PMOVSXBW(X64Reg dest, const OpArg& arg) {
1816void XEmitter::PXOR(X64Reg dest, const OpArg& arg) {WriteSSEOp(0x66, 0xEF, dest, arg);} 2006 WriteSSE41Op(0x66, 0x3820, dest, arg);
1817void XEmitter::POR(X64Reg dest, const OpArg& arg) {WriteSSEOp(0x66, 0xEB, dest, arg);} 2007}
1818 2008void XEmitter::PMOVSXBD(X64Reg dest, const OpArg& arg) {
1819void XEmitter::PADDB(X64Reg dest, const OpArg& arg) {WriteSSEOp(0x66, 0xFC, dest, arg);} 2009 WriteSSE41Op(0x66, 0x3821, dest, arg);
1820void XEmitter::PADDW(X64Reg dest, const OpArg& arg) {WriteSSEOp(0x66, 0xFD, dest, arg);} 2010}
1821void XEmitter::PADDD(X64Reg dest, const OpArg& arg) {WriteSSEOp(0x66, 0xFE, dest, arg);} 2011void XEmitter::PMOVSXBQ(X64Reg dest, const OpArg& arg) {
1822void XEmitter::PADDQ(X64Reg dest, const OpArg& arg) {WriteSSEOp(0x66, 0xD4, dest, arg);} 2012 WriteSSE41Op(0x66, 0x3822, dest, arg);
1823 2013}
1824void XEmitter::PADDSB(X64Reg dest, const OpArg& arg) {WriteSSEOp(0x66, 0xEC, dest, arg);} 2014void XEmitter::PMOVSXWD(X64Reg dest, const OpArg& arg) {
1825void XEmitter::PADDSW(X64Reg dest, const OpArg& arg) {WriteSSEOp(0x66, 0xED, dest, arg);} 2015 WriteSSE41Op(0x66, 0x3823, dest, arg);
1826void XEmitter::PADDUSB(X64Reg dest, const OpArg& arg) {WriteSSEOp(0x66, 0xDC, dest, arg);} 2016}
1827void XEmitter::PADDUSW(X64Reg dest, const OpArg& arg) {WriteSSEOp(0x66, 0xDD, dest, arg);} 2017void XEmitter::PMOVSXWQ(X64Reg dest, const OpArg& arg) {
1828 2018 WriteSSE41Op(0x66, 0x3824, dest, arg);
1829void XEmitter::PSUBB(X64Reg dest, const OpArg& arg) {WriteSSEOp(0x66, 0xF8, dest, arg);} 2019}
1830void XEmitter::PSUBW(X64Reg dest, const OpArg& arg) {WriteSSEOp(0x66, 0xF9, dest, arg);} 2020void XEmitter::PMOVSXDQ(X64Reg dest, const OpArg& arg) {
1831void XEmitter::PSUBD(X64Reg dest, const OpArg& arg) {WriteSSEOp(0x66, 0xFA, dest, arg);} 2021 WriteSSE41Op(0x66, 0x3825, dest, arg);
1832void XEmitter::PSUBQ(X64Reg dest, const OpArg& arg) {WriteSSEOp(0x66, 0xFB, dest, arg);} 2022}
1833 2023void XEmitter::PMOVZXBW(X64Reg dest, const OpArg& arg) {
1834void XEmitter::PSUBSB(X64Reg dest, const OpArg& arg) {WriteSSEOp(0x66, 0xE8, dest, arg);} 2024 WriteSSE41Op(0x66, 0x3830, dest, arg);
1835void XEmitter::PSUBSW(X64Reg dest, const OpArg& arg) {WriteSSEOp(0x66, 0xE9, dest, arg);} 2025}
1836void XEmitter::PSUBUSB(X64Reg dest, const OpArg& arg) {WriteSSEOp(0x66, 0xD8, dest, arg);} 2026void XEmitter::PMOVZXBD(X64Reg dest, const OpArg& arg) {
1837void XEmitter::PSUBUSW(X64Reg dest, const OpArg& arg) {WriteSSEOp(0x66, 0xD9, dest, arg);} 2027 WriteSSE41Op(0x66, 0x3831, dest, arg);
1838 2028}
1839void XEmitter::PAVGB(X64Reg dest, const OpArg& arg) {WriteSSEOp(0x66, 0xE0, dest, arg);} 2029void XEmitter::PMOVZXBQ(X64Reg dest, const OpArg& arg) {
1840void XEmitter::PAVGW(X64Reg dest, const OpArg& arg) {WriteSSEOp(0x66, 0xE3, dest, arg);} 2030 WriteSSE41Op(0x66, 0x3832, dest, arg);
1841 2031}
1842void XEmitter::PCMPEQB(X64Reg dest, const OpArg& arg) {WriteSSEOp(0x66, 0x74, dest, arg);} 2032void XEmitter::PMOVZXWD(X64Reg dest, const OpArg& arg) {
1843void XEmitter::PCMPEQW(X64Reg dest, const OpArg& arg) {WriteSSEOp(0x66, 0x75, dest, arg);} 2033 WriteSSE41Op(0x66, 0x3833, dest, arg);
1844void XEmitter::PCMPEQD(X64Reg dest, const OpArg& arg) {WriteSSEOp(0x66, 0x76, dest, arg);} 2034}
1845 2035void XEmitter::PMOVZXWQ(X64Reg dest, const OpArg& arg) {
1846void XEmitter::PCMPGTB(X64Reg dest, const OpArg& arg) {WriteSSEOp(0x66, 0x64, dest, arg);} 2036 WriteSSE41Op(0x66, 0x3834, dest, arg);
1847void XEmitter::PCMPGTW(X64Reg dest, const OpArg& arg) {WriteSSEOp(0x66, 0x65, dest, arg);} 2037}
1848void XEmitter::PCMPGTD(X64Reg dest, const OpArg& arg) {WriteSSEOp(0x66, 0x66, dest, arg);} 2038void XEmitter::PMOVZXDQ(X64Reg dest, const OpArg& arg) {
1849 2039 WriteSSE41Op(0x66, 0x3835, dest, arg);
1850void XEmitter::PEXTRW(X64Reg dest, const OpArg& arg, u8 subreg) {WriteSSEOp(0x66, 0xC5, dest, arg, 1); Write8(subreg);} 2040}
1851void XEmitter::PINSRW(X64Reg dest, const OpArg& arg, u8 subreg) {WriteSSEOp(0x66, 0xC4, dest, arg, 1); Write8(subreg);} 2041
1852 2042void XEmitter::PBLENDVB(X64Reg dest, const OpArg& arg) {
1853void XEmitter::PMADDWD(X64Reg dest, const OpArg& arg) {WriteSSEOp(0x66, 0xF5, dest, arg); } 2043 WriteSSE41Op(0x66, 0x3810, dest, arg);
1854void XEmitter::PSADBW(X64Reg dest, const OpArg& arg) {WriteSSEOp(0x66, 0xF6, dest, arg);} 2044}
1855 2045void XEmitter::BLENDVPS(X64Reg dest, const OpArg& arg) {
1856void XEmitter::PMAXSW(X64Reg dest, const OpArg& arg) {WriteSSEOp(0x66, 0xEE, dest, arg); } 2046 WriteSSE41Op(0x66, 0x3814, dest, arg);
1857void XEmitter::PMAXUB(X64Reg dest, const OpArg& arg) {WriteSSEOp(0x66, 0xDE, dest, arg); } 2047}
1858void XEmitter::PMINSW(X64Reg dest, const OpArg& arg) {WriteSSEOp(0x66, 0xEA, dest, arg); } 2048void XEmitter::BLENDVPD(X64Reg dest, const OpArg& arg) {
1859void XEmitter::PMINUB(X64Reg dest, const OpArg& arg) {WriteSSEOp(0x66, 0xDA, dest, arg); } 2049 WriteSSE41Op(0x66, 0x3815, dest, arg);
1860 2050}
1861void XEmitter::PMOVMSKB(X64Reg dest, const OpArg& arg) {WriteSSEOp(0x66, 0xD7, dest, arg); } 2051void XEmitter::BLENDPS(X64Reg dest, const OpArg& arg, u8 blend) {
1862void XEmitter::PSHUFD(X64Reg regOp, const OpArg& arg, u8 shuffle) {WriteSSEOp(0x66, 0x70, regOp, arg, 1); Write8(shuffle);} 2052 WriteSSE41Op(0x66, 0x3A0C, dest, arg, 1);
1863void XEmitter::PSHUFLW(X64Reg regOp, const OpArg& arg, u8 shuffle) {WriteSSEOp(0xF2, 0x70, regOp, arg, 1); Write8(shuffle);} 2053 Write8(blend);
1864void XEmitter::PSHUFHW(X64Reg regOp, const OpArg& arg, u8 shuffle) {WriteSSEOp(0xF3, 0x70, regOp, arg, 1); Write8(shuffle);} 2054}
2055void XEmitter::BLENDPD(X64Reg dest, const OpArg& arg, u8 blend) {
2056 WriteSSE41Op(0x66, 0x3A0D, dest, arg, 1);
2057 Write8(blend);
2058}
2059
2060void XEmitter::ROUNDSS(X64Reg dest, const OpArg& arg, u8 mode) {
2061 WriteSSE41Op(0x66, 0x3A0A, dest, arg, 1);
2062 Write8(mode);
2063}
2064void XEmitter::ROUNDSD(X64Reg dest, const OpArg& arg, u8 mode) {
2065 WriteSSE41Op(0x66, 0x3A0B, dest, arg, 1);
2066 Write8(mode);
2067}
2068void XEmitter::ROUNDPS(X64Reg dest, const OpArg& arg, u8 mode) {
2069 WriteSSE41Op(0x66, 0x3A08, dest, arg, 1);
2070 Write8(mode);
2071}
2072void XEmitter::ROUNDPD(X64Reg dest, const OpArg& arg, u8 mode) {
2073 WriteSSE41Op(0x66, 0x3A09, dest, arg, 1);
2074 Write8(mode);
2075}
2076
2077void XEmitter::PAND(X64Reg dest, const OpArg& arg) {
2078 WriteSSEOp(0x66, 0xDB, dest, arg);
2079}
2080void XEmitter::PANDN(X64Reg dest, const OpArg& arg) {
2081 WriteSSEOp(0x66, 0xDF, dest, arg);
2082}
2083void XEmitter::PXOR(X64Reg dest, const OpArg& arg) {
2084 WriteSSEOp(0x66, 0xEF, dest, arg);
2085}
2086void XEmitter::POR(X64Reg dest, const OpArg& arg) {
2087 WriteSSEOp(0x66, 0xEB, dest, arg);
2088}
2089
2090void XEmitter::PADDB(X64Reg dest, const OpArg& arg) {
2091 WriteSSEOp(0x66, 0xFC, dest, arg);
2092}
2093void XEmitter::PADDW(X64Reg dest, const OpArg& arg) {
2094 WriteSSEOp(0x66, 0xFD, dest, arg);
2095}
2096void XEmitter::PADDD(X64Reg dest, const OpArg& arg) {
2097 WriteSSEOp(0x66, 0xFE, dest, arg);
2098}
2099void XEmitter::PADDQ(X64Reg dest, const OpArg& arg) {
2100 WriteSSEOp(0x66, 0xD4, dest, arg);
2101}
2102
2103void XEmitter::PADDSB(X64Reg dest, const OpArg& arg) {
2104 WriteSSEOp(0x66, 0xEC, dest, arg);
2105}
2106void XEmitter::PADDSW(X64Reg dest, const OpArg& arg) {
2107 WriteSSEOp(0x66, 0xED, dest, arg);
2108}
2109void XEmitter::PADDUSB(X64Reg dest, const OpArg& arg) {
2110 WriteSSEOp(0x66, 0xDC, dest, arg);
2111}
2112void XEmitter::PADDUSW(X64Reg dest, const OpArg& arg) {
2113 WriteSSEOp(0x66, 0xDD, dest, arg);
2114}
2115
2116void XEmitter::PSUBB(X64Reg dest, const OpArg& arg) {
2117 WriteSSEOp(0x66, 0xF8, dest, arg);
2118}
2119void XEmitter::PSUBW(X64Reg dest, const OpArg& arg) {
2120 WriteSSEOp(0x66, 0xF9, dest, arg);
2121}
2122void XEmitter::PSUBD(X64Reg dest, const OpArg& arg) {
2123 WriteSSEOp(0x66, 0xFA, dest, arg);
2124}
2125void XEmitter::PSUBQ(X64Reg dest, const OpArg& arg) {
2126 WriteSSEOp(0x66, 0xFB, dest, arg);
2127}
2128
2129void XEmitter::PSUBSB(X64Reg dest, const OpArg& arg) {
2130 WriteSSEOp(0x66, 0xE8, dest, arg);
2131}
2132void XEmitter::PSUBSW(X64Reg dest, const OpArg& arg) {
2133 WriteSSEOp(0x66, 0xE9, dest, arg);
2134}
2135void XEmitter::PSUBUSB(X64Reg dest, const OpArg& arg) {
2136 WriteSSEOp(0x66, 0xD8, dest, arg);
2137}
2138void XEmitter::PSUBUSW(X64Reg dest, const OpArg& arg) {
2139 WriteSSEOp(0x66, 0xD9, dest, arg);
2140}
2141
2142void XEmitter::PAVGB(X64Reg dest, const OpArg& arg) {
2143 WriteSSEOp(0x66, 0xE0, dest, arg);
2144}
2145void XEmitter::PAVGW(X64Reg dest, const OpArg& arg) {
2146 WriteSSEOp(0x66, 0xE3, dest, arg);
2147}
2148
2149void XEmitter::PCMPEQB(X64Reg dest, const OpArg& arg) {
2150 WriteSSEOp(0x66, 0x74, dest, arg);
2151}
2152void XEmitter::PCMPEQW(X64Reg dest, const OpArg& arg) {
2153 WriteSSEOp(0x66, 0x75, dest, arg);
2154}
2155void XEmitter::PCMPEQD(X64Reg dest, const OpArg& arg) {
2156 WriteSSEOp(0x66, 0x76, dest, arg);
2157}
2158
2159void XEmitter::PCMPGTB(X64Reg dest, const OpArg& arg) {
2160 WriteSSEOp(0x66, 0x64, dest, arg);
2161}
2162void XEmitter::PCMPGTW(X64Reg dest, const OpArg& arg) {
2163 WriteSSEOp(0x66, 0x65, dest, arg);
2164}
2165void XEmitter::PCMPGTD(X64Reg dest, const OpArg& arg) {
2166 WriteSSEOp(0x66, 0x66, dest, arg);
2167}
2168
2169void XEmitter::PEXTRW(X64Reg dest, const OpArg& arg, u8 subreg) {
2170 WriteSSEOp(0x66, 0xC5, dest, arg, 1);
2171 Write8(subreg);
2172}
2173void XEmitter::PINSRW(X64Reg dest, const OpArg& arg, u8 subreg) {
2174 WriteSSEOp(0x66, 0xC4, dest, arg, 1);
2175 Write8(subreg);
2176}
2177
2178void XEmitter::PMADDWD(X64Reg dest, const OpArg& arg) {
2179 WriteSSEOp(0x66, 0xF5, dest, arg);
2180}
2181void XEmitter::PSADBW(X64Reg dest, const OpArg& arg) {
2182 WriteSSEOp(0x66, 0xF6, dest, arg);
2183}
2184
2185void XEmitter::PMAXSW(X64Reg dest, const OpArg& arg) {
2186 WriteSSEOp(0x66, 0xEE, dest, arg);
2187}
2188void XEmitter::PMAXUB(X64Reg dest, const OpArg& arg) {
2189 WriteSSEOp(0x66, 0xDE, dest, arg);
2190}
2191void XEmitter::PMINSW(X64Reg dest, const OpArg& arg) {
2192 WriteSSEOp(0x66, 0xEA, dest, arg);
2193}
2194void XEmitter::PMINUB(X64Reg dest, const OpArg& arg) {
2195 WriteSSEOp(0x66, 0xDA, dest, arg);
2196}
2197
2198void XEmitter::PMOVMSKB(X64Reg dest, const OpArg& arg) {
2199 WriteSSEOp(0x66, 0xD7, dest, arg);
2200}
2201void XEmitter::PSHUFD(X64Reg regOp, const OpArg& arg, u8 shuffle) {
2202 WriteSSEOp(0x66, 0x70, regOp, arg, 1);
2203 Write8(shuffle);
2204}
2205void XEmitter::PSHUFLW(X64Reg regOp, const OpArg& arg, u8 shuffle) {
2206 WriteSSEOp(0xF2, 0x70, regOp, arg, 1);
2207 Write8(shuffle);
2208}
2209void XEmitter::PSHUFHW(X64Reg regOp, const OpArg& arg, u8 shuffle) {
2210 WriteSSEOp(0xF3, 0x70, regOp, arg, 1);
2211 Write8(shuffle);
2212}
1865 2213
1866// VEX 2214// VEX
1867void XEmitter::VADDSD(X64Reg regOp1, X64Reg regOp2, const OpArg& arg) {WriteAVXOp(0xF2, sseADD, regOp1, regOp2, arg);} 2215void XEmitter::VADDSD(X64Reg regOp1, X64Reg regOp2, const OpArg& arg) {
1868void XEmitter::VSUBSD(X64Reg regOp1, X64Reg regOp2, const OpArg& arg) {WriteAVXOp(0xF2, sseSUB, regOp1, regOp2, arg);} 2216 WriteAVXOp(0xF2, sseADD, regOp1, regOp2, arg);
1869void XEmitter::VMULSD(X64Reg regOp1, X64Reg regOp2, const OpArg& arg) {WriteAVXOp(0xF2, sseMUL, regOp1, regOp2, arg);} 2217}
1870void XEmitter::VDIVSD(X64Reg regOp1, X64Reg regOp2, const OpArg& arg) {WriteAVXOp(0xF2, sseDIV, regOp1, regOp2, arg);} 2218void XEmitter::VSUBSD(X64Reg regOp1, X64Reg regOp2, const OpArg& arg) {
1871void XEmitter::VADDPD(X64Reg regOp1, X64Reg regOp2, const OpArg& arg) {WriteAVXOp(0x66, sseADD, regOp1, regOp2, arg);} 2219 WriteAVXOp(0xF2, sseSUB, regOp1, regOp2, arg);
1872void XEmitter::VSUBPD(X64Reg regOp1, X64Reg regOp2, const OpArg& arg) {WriteAVXOp(0x66, sseSUB, regOp1, regOp2, arg);} 2220}
1873void XEmitter::VMULPD(X64Reg regOp1, X64Reg regOp2, const OpArg& arg) {WriteAVXOp(0x66, sseMUL, regOp1, regOp2, arg);} 2221void XEmitter::VMULSD(X64Reg regOp1, X64Reg regOp2, const OpArg& arg) {
1874void XEmitter::VDIVPD(X64Reg regOp1, X64Reg regOp2, const OpArg& arg) {WriteAVXOp(0x66, sseDIV, regOp1, regOp2, arg);} 2222 WriteAVXOp(0xF2, sseMUL, regOp1, regOp2, arg);
1875void XEmitter::VSQRTSD(X64Reg regOp1, X64Reg regOp2, const OpArg& arg) {WriteAVXOp(0xF2, sseSQRT, regOp1, regOp2, arg);} 2223}
1876void XEmitter::VSHUFPD(X64Reg regOp1, X64Reg regOp2, const OpArg& arg, u8 shuffle) {WriteAVXOp(0x66, sseSHUF, regOp1, regOp2, arg, 1); Write8(shuffle);} 2224void XEmitter::VDIVSD(X64Reg regOp1, X64Reg regOp2, const OpArg& arg) {
1877void XEmitter::VUNPCKLPD(X64Reg regOp1, X64Reg regOp2, const OpArg& arg){WriteAVXOp(0x66, 0x14, regOp1, regOp2, arg);} 2225 WriteAVXOp(0xF2, sseDIV, regOp1, regOp2, arg);
1878void XEmitter::VUNPCKHPD(X64Reg regOp1, X64Reg regOp2, const OpArg& arg){WriteAVXOp(0x66, 0x15, regOp1, regOp2, arg);} 2226}
1879 2227void XEmitter::VADDPD(X64Reg regOp1, X64Reg regOp2, const OpArg& arg) {
1880void XEmitter::VANDPS(X64Reg regOp1, X64Reg regOp2, const OpArg& arg) { WriteAVXOp(0x00, sseAND, regOp1, regOp2, arg); } 2228 WriteAVXOp(0x66, sseADD, regOp1, regOp2, arg);
1881void XEmitter::VANDPD(X64Reg regOp1, X64Reg regOp2, const OpArg& arg) { WriteAVXOp(0x66, sseAND, regOp1, regOp2, arg); } 2229}
1882void XEmitter::VANDNPS(X64Reg regOp1, X64Reg regOp2, const OpArg& arg) { WriteAVXOp(0x00, sseANDN, regOp1, regOp2, arg); } 2230void XEmitter::VSUBPD(X64Reg regOp1, X64Reg regOp2, const OpArg& arg) {
1883void XEmitter::VANDNPD(X64Reg regOp1, X64Reg regOp2, const OpArg& arg) { WriteAVXOp(0x66, sseANDN, regOp1, regOp2, arg); } 2231 WriteAVXOp(0x66, sseSUB, regOp1, regOp2, arg);
1884void XEmitter::VORPS(X64Reg regOp1, X64Reg regOp2, const OpArg& arg) { WriteAVXOp(0x00, sseOR, regOp1, regOp2, arg); } 2232}
1885void XEmitter::VORPD(X64Reg regOp1, X64Reg regOp2, const OpArg& arg) { WriteAVXOp(0x66, sseOR, regOp1, regOp2, arg); } 2233void XEmitter::VMULPD(X64Reg regOp1, X64Reg regOp2, const OpArg& arg) {
1886void XEmitter::VXORPS(X64Reg regOp1, X64Reg regOp2, const OpArg& arg) { WriteAVXOp(0x00, sseXOR, regOp1, regOp2, arg); } 2234 WriteAVXOp(0x66, sseMUL, regOp1, regOp2, arg);
1887void XEmitter::VXORPD(X64Reg regOp1, X64Reg regOp2, const OpArg& arg) { WriteAVXOp(0x66, sseXOR, regOp1, regOp2, arg); } 2235}
1888 2236void XEmitter::VDIVPD(X64Reg regOp1, X64Reg regOp2, const OpArg& arg) {
1889void XEmitter::VPAND(X64Reg regOp1, X64Reg regOp2, const OpArg& arg) { WriteAVXOp(0x66, 0xDB, regOp1, regOp2, arg); } 2237 WriteAVXOp(0x66, sseDIV, regOp1, regOp2, arg);
1890void XEmitter::VPANDN(X64Reg regOp1, X64Reg regOp2, const OpArg& arg) { WriteAVXOp(0x66, 0xDF, regOp1, regOp2, arg); } 2238}
1891void XEmitter::VPOR(X64Reg regOp1, X64Reg regOp2, const OpArg& arg) { WriteAVXOp(0x66, 0xEB, regOp1, regOp2, arg); } 2239void XEmitter::VSQRTSD(X64Reg regOp1, X64Reg regOp2, const OpArg& arg) {
1892void XEmitter::VPXOR(X64Reg regOp1, X64Reg regOp2, const OpArg& arg) { WriteAVXOp(0x66, 0xEF, regOp1, regOp2, arg); } 2240 WriteAVXOp(0xF2, sseSQRT, regOp1, regOp2, arg);
1893 2241}
1894void XEmitter::VFMADD132PS(X64Reg regOp1, X64Reg regOp2, const OpArg& arg) { WriteAVXOp(0x66, 0x3898, regOp1, regOp2, arg); } 2242void XEmitter::VSHUFPD(X64Reg regOp1, X64Reg regOp2, const OpArg& arg, u8 shuffle) {
1895void XEmitter::VFMADD213PS(X64Reg regOp1, X64Reg regOp2, const OpArg& arg) { WriteAVXOp(0x66, 0x38A8, regOp1, regOp2, arg); } 2243 WriteAVXOp(0x66, sseSHUF, regOp1, regOp2, arg, 1);
1896void XEmitter::VFMADD231PS(X64Reg regOp1, X64Reg regOp2, const OpArg& arg) { WriteAVXOp(0x66, 0x38B8, regOp1, regOp2, arg); } 2244 Write8(shuffle);
1897void XEmitter::VFMADD132PD(X64Reg regOp1, X64Reg regOp2, const OpArg& arg) { WriteAVXOp(0x66, 0x3898, regOp1, regOp2, arg, 1); } 2245}
1898void XEmitter::VFMADD213PD(X64Reg regOp1, X64Reg regOp2, const OpArg& arg) { WriteAVXOp(0x66, 0x38A8, regOp1, regOp2, arg, 1); } 2246void XEmitter::VUNPCKLPD(X64Reg regOp1, X64Reg regOp2, const OpArg& arg) {
1899void XEmitter::VFMADD231PD(X64Reg regOp1, X64Reg regOp2, const OpArg& arg) { WriteAVXOp(0x66, 0x38B8, regOp1, regOp2, arg, 1); } 2247 WriteAVXOp(0x66, 0x14, regOp1, regOp2, arg);
1900void XEmitter::VFMADD132SS(X64Reg regOp1, X64Reg regOp2, const OpArg& arg) { WriteAVXOp(0x66, 0x3899, regOp1, regOp2, arg); } 2248}
1901void XEmitter::VFMADD213SS(X64Reg regOp1, X64Reg regOp2, const OpArg& arg) { WriteAVXOp(0x66, 0x38A9, regOp1, regOp2, arg); } 2249void XEmitter::VUNPCKHPD(X64Reg regOp1, X64Reg regOp2, const OpArg& arg) {
1902void XEmitter::VFMADD231SS(X64Reg regOp1, X64Reg regOp2, const OpArg& arg) { WriteAVXOp(0x66, 0x38B9, regOp1, regOp2, arg); } 2250 WriteAVXOp(0x66, 0x15, regOp1, regOp2, arg);
1903void XEmitter::VFMADD132SD(X64Reg regOp1, X64Reg regOp2, const OpArg& arg) { WriteAVXOp(0x66, 0x3899, regOp1, regOp2, arg, 1); } 2251}
1904void XEmitter::VFMADD213SD(X64Reg regOp1, X64Reg regOp2, const OpArg& arg) { WriteAVXOp(0x66, 0x38A9, regOp1, regOp2, arg, 1); } 2252
1905void XEmitter::VFMADD231SD(X64Reg regOp1, X64Reg regOp2, const OpArg& arg) { WriteAVXOp(0x66, 0x38B9, regOp1, regOp2, arg, 1); } 2253void XEmitter::VANDPS(X64Reg regOp1, X64Reg regOp2, const OpArg& arg) {
1906void XEmitter::VFMSUB132PS(X64Reg regOp1, X64Reg regOp2, const OpArg& arg) { WriteAVXOp(0x66, 0x389A, regOp1, regOp2, arg); } 2254 WriteAVXOp(0x00, sseAND, regOp1, regOp2, arg);
1907void XEmitter::VFMSUB213PS(X64Reg regOp1, X64Reg regOp2, const OpArg& arg) { WriteAVXOp(0x66, 0x38AA, regOp1, regOp2, arg); } 2255}
1908void XEmitter::VFMSUB231PS(X64Reg regOp1, X64Reg regOp2, const OpArg& arg) { WriteAVXOp(0x66, 0x38BA, regOp1, regOp2, arg); } 2256void XEmitter::VANDPD(X64Reg regOp1, X64Reg regOp2, const OpArg& arg) {
1909void XEmitter::VFMSUB132PD(X64Reg regOp1, X64Reg regOp2, const OpArg& arg) { WriteAVXOp(0x66, 0x389A, regOp1, regOp2, arg, 1); } 2257 WriteAVXOp(0x66, sseAND, regOp1, regOp2, arg);
1910void XEmitter::VFMSUB213PD(X64Reg regOp1, X64Reg regOp2, const OpArg& arg) { WriteAVXOp(0x66, 0x38AA, regOp1, regOp2, arg, 1); } 2258}
1911void XEmitter::VFMSUB231PD(X64Reg regOp1, X64Reg regOp2, const OpArg& arg) { WriteAVXOp(0x66, 0x38BA, regOp1, regOp2, arg, 1); } 2259void XEmitter::VANDNPS(X64Reg regOp1, X64Reg regOp2, const OpArg& arg) {
1912void XEmitter::VFMSUB132SS(X64Reg regOp1, X64Reg regOp2, const OpArg& arg) { WriteAVXOp(0x66, 0x389B, regOp1, regOp2, arg); } 2260 WriteAVXOp(0x00, sseANDN, regOp1, regOp2, arg);
1913void XEmitter::VFMSUB213SS(X64Reg regOp1, X64Reg regOp2, const OpArg& arg) { WriteAVXOp(0x66, 0x38AB, regOp1, regOp2, arg); } 2261}
1914void XEmitter::VFMSUB231SS(X64Reg regOp1, X64Reg regOp2, const OpArg& arg) { WriteAVXOp(0x66, 0x38BB, regOp1, regOp2, arg); } 2262void XEmitter::VANDNPD(X64Reg regOp1, X64Reg regOp2, const OpArg& arg) {
1915void XEmitter::VFMSUB132SD(X64Reg regOp1, X64Reg regOp2, const OpArg& arg) { WriteAVXOp(0x66, 0x389B, regOp1, regOp2, arg, 1); } 2263 WriteAVXOp(0x66, sseANDN, regOp1, regOp2, arg);
1916void XEmitter::VFMSUB213SD(X64Reg regOp1, X64Reg regOp2, const OpArg& arg) { WriteAVXOp(0x66, 0x38AB, regOp1, regOp2, arg, 1); } 2264}
1917void XEmitter::VFMSUB231SD(X64Reg regOp1, X64Reg regOp2, const OpArg& arg) { WriteAVXOp(0x66, 0x38BB, regOp1, regOp2, arg, 1); } 2265void XEmitter::VORPS(X64Reg regOp1, X64Reg regOp2, const OpArg& arg) {
1918void XEmitter::VFNMADD132PS(X64Reg regOp1, X64Reg regOp2, const OpArg& arg) { WriteAVXOp(0x66, 0x389C, regOp1, regOp2, arg); } 2266 WriteAVXOp(0x00, sseOR, regOp1, regOp2, arg);
1919void XEmitter::VFNMADD213PS(X64Reg regOp1, X64Reg regOp2, const OpArg& arg) { WriteAVXOp(0x66, 0x38AC, regOp1, regOp2, arg); } 2267}
1920void XEmitter::VFNMADD231PS(X64Reg regOp1, X64Reg regOp2, const OpArg& arg) { WriteAVXOp(0x66, 0x38BC, regOp1, regOp2, arg); } 2268void XEmitter::VORPD(X64Reg regOp1, X64Reg regOp2, const OpArg& arg) {
1921void XEmitter::VFNMADD132PD(X64Reg regOp1, X64Reg regOp2, const OpArg& arg) { WriteAVXOp(0x66, 0x389C, regOp1, regOp2, arg, 1); } 2269 WriteAVXOp(0x66, sseOR, regOp1, regOp2, arg);
1922void XEmitter::VFNMADD213PD(X64Reg regOp1, X64Reg regOp2, const OpArg& arg) { WriteAVXOp(0x66, 0x38AC, regOp1, regOp2, arg, 1); } 2270}
1923void XEmitter::VFNMADD231PD(X64Reg regOp1, X64Reg regOp2, const OpArg& arg) { WriteAVXOp(0x66, 0x38BC, regOp1, regOp2, arg, 1); } 2271void XEmitter::VXORPS(X64Reg regOp1, X64Reg regOp2, const OpArg& arg) {
1924void XEmitter::VFNMADD132SS(X64Reg regOp1, X64Reg regOp2, const OpArg& arg) { WriteAVXOp(0x66, 0x389D, regOp1, regOp2, arg); } 2272 WriteAVXOp(0x00, sseXOR, regOp1, regOp2, arg);
1925void XEmitter::VFNMADD213SS(X64Reg regOp1, X64Reg regOp2, const OpArg& arg) { WriteAVXOp(0x66, 0x38AD, regOp1, regOp2, arg); } 2273}
1926void XEmitter::VFNMADD231SS(X64Reg regOp1, X64Reg regOp2, const OpArg& arg) { WriteAVXOp(0x66, 0x38BD, regOp1, regOp2, arg); } 2274void XEmitter::VXORPD(X64Reg regOp1, X64Reg regOp2, const OpArg& arg) {
1927void XEmitter::VFNMADD132SD(X64Reg regOp1, X64Reg regOp2, const OpArg& arg) { WriteAVXOp(0x66, 0x389D, regOp1, regOp2, arg, 1); } 2275 WriteAVXOp(0x66, sseXOR, regOp1, regOp2, arg);
1928void XEmitter::VFNMADD213SD(X64Reg regOp1, X64Reg regOp2, const OpArg& arg) { WriteAVXOp(0x66, 0x38AD, regOp1, regOp2, arg, 1); } 2276}
1929void XEmitter::VFNMADD231SD(X64Reg regOp1, X64Reg regOp2, const OpArg& arg) { WriteAVXOp(0x66, 0x38BD, regOp1, regOp2, arg, 1); } 2277
1930void XEmitter::VFNMSUB132PS(X64Reg regOp1, X64Reg regOp2, const OpArg& arg) { WriteAVXOp(0x66, 0x389E, regOp1, regOp2, arg); } 2278void XEmitter::VPAND(X64Reg regOp1, X64Reg regOp2, const OpArg& arg) {
1931void XEmitter::VFNMSUB213PS(X64Reg regOp1, X64Reg regOp2, const OpArg& arg) { WriteAVXOp(0x66, 0x38AE, regOp1, regOp2, arg); } 2279 WriteAVXOp(0x66, 0xDB, regOp1, regOp2, arg);
1932void XEmitter::VFNMSUB231PS(X64Reg regOp1, X64Reg regOp2, const OpArg& arg) { WriteAVXOp(0x66, 0x38BE, regOp1, regOp2, arg); } 2280}
1933void XEmitter::VFNMSUB132PD(X64Reg regOp1, X64Reg regOp2, const OpArg& arg) { WriteAVXOp(0x66, 0x389E, regOp1, regOp2, arg, 1); } 2281void XEmitter::VPANDN(X64Reg regOp1, X64Reg regOp2, const OpArg& arg) {
1934void XEmitter::VFNMSUB213PD(X64Reg regOp1, X64Reg regOp2, const OpArg& arg) { WriteAVXOp(0x66, 0x38AE, regOp1, regOp2, arg, 1); } 2282 WriteAVXOp(0x66, 0xDF, regOp1, regOp2, arg);
1935void XEmitter::VFNMSUB231PD(X64Reg regOp1, X64Reg regOp2, const OpArg& arg) { WriteAVXOp(0x66, 0x38BE, regOp1, regOp2, arg, 1); } 2283}
1936void XEmitter::VFNMSUB132SS(X64Reg regOp1, X64Reg regOp2, const OpArg& arg) { WriteAVXOp(0x66, 0x389F, regOp1, regOp2, arg); } 2284void XEmitter::VPOR(X64Reg regOp1, X64Reg regOp2, const OpArg& arg) {
1937void XEmitter::VFNMSUB213SS(X64Reg regOp1, X64Reg regOp2, const OpArg& arg) { WriteAVXOp(0x66, 0x38AF, regOp1, regOp2, arg); } 2285 WriteAVXOp(0x66, 0xEB, regOp1, regOp2, arg);
1938void XEmitter::VFNMSUB231SS(X64Reg regOp1, X64Reg regOp2, const OpArg& arg) { WriteAVXOp(0x66, 0x38BF, regOp1, regOp2, arg); } 2286}
1939void XEmitter::VFNMSUB132SD(X64Reg regOp1, X64Reg regOp2, const OpArg& arg) { WriteAVXOp(0x66, 0x389F, regOp1, regOp2, arg, 1); } 2287void XEmitter::VPXOR(X64Reg regOp1, X64Reg regOp2, const OpArg& arg) {
1940void XEmitter::VFNMSUB213SD(X64Reg regOp1, X64Reg regOp2, const OpArg& arg) { WriteAVXOp(0x66, 0x38AF, regOp1, regOp2, arg, 1); } 2288 WriteAVXOp(0x66, 0xEF, regOp1, regOp2, arg);
1941void XEmitter::VFNMSUB231SD(X64Reg regOp1, X64Reg regOp2, const OpArg& arg) { WriteAVXOp(0x66, 0x38BF, regOp1, regOp2, arg, 1); } 2289}
1942void XEmitter::VFMADDSUB132PS(X64Reg regOp1, X64Reg regOp2, const OpArg& arg) { WriteAVXOp(0x66, 0x3896, regOp1, regOp2, arg); } 2290
1943void XEmitter::VFMADDSUB213PS(X64Reg regOp1, X64Reg regOp2, const OpArg& arg) { WriteAVXOp(0x66, 0x38A6, regOp1, regOp2, arg); } 2291void XEmitter::VFMADD132PS(X64Reg regOp1, X64Reg regOp2, const OpArg& arg) {
1944void XEmitter::VFMADDSUB231PS(X64Reg regOp1, X64Reg regOp2, const OpArg& arg) { WriteAVXOp(0x66, 0x38B6, regOp1, regOp2, arg); } 2292 WriteAVXOp(0x66, 0x3898, regOp1, regOp2, arg);
1945void XEmitter::VFMADDSUB132PD(X64Reg regOp1, X64Reg regOp2, const OpArg& arg) { WriteAVXOp(0x66, 0x3896, regOp1, regOp2, arg, 1); } 2293}
1946void XEmitter::VFMADDSUB213PD(X64Reg regOp1, X64Reg regOp2, const OpArg& arg) { WriteAVXOp(0x66, 0x38A6, regOp1, regOp2, arg, 1); } 2294void XEmitter::VFMADD213PS(X64Reg regOp1, X64Reg regOp2, const OpArg& arg) {
1947void XEmitter::VFMADDSUB231PD(X64Reg regOp1, X64Reg regOp2, const OpArg& arg) { WriteAVXOp(0x66, 0x38B6, regOp1, regOp2, arg, 1); } 2295 WriteAVXOp(0x66, 0x38A8, regOp1, regOp2, arg);
1948void XEmitter::VFMSUBADD132PS(X64Reg regOp1, X64Reg regOp2, const OpArg& arg) { WriteAVXOp(0x66, 0x3897, regOp1, regOp2, arg); } 2296}
1949void XEmitter::VFMSUBADD213PS(X64Reg regOp1, X64Reg regOp2, const OpArg& arg) { WriteAVXOp(0x66, 0x38A7, regOp1, regOp2, arg); } 2297void XEmitter::VFMADD231PS(X64Reg regOp1, X64Reg regOp2, const OpArg& arg) {
1950void XEmitter::VFMSUBADD231PS(X64Reg regOp1, X64Reg regOp2, const OpArg& arg) { WriteAVXOp(0x66, 0x38B7, regOp1, regOp2, arg); } 2298 WriteAVXOp(0x66, 0x38B8, regOp1, regOp2, arg);
1951void XEmitter::VFMSUBADD132PD(X64Reg regOp1, X64Reg regOp2, const OpArg& arg) { WriteAVXOp(0x66, 0x3897, regOp1, regOp2, arg, 1); } 2299}
1952void XEmitter::VFMSUBADD213PD(X64Reg regOp1, X64Reg regOp2, const OpArg& arg) { WriteAVXOp(0x66, 0x38A7, regOp1, regOp2, arg, 1); } 2300void XEmitter::VFMADD132PD(X64Reg regOp1, X64Reg regOp2, const OpArg& arg) {
1953void XEmitter::VFMSUBADD231PD(X64Reg regOp1, X64Reg regOp2, const OpArg& arg) { WriteAVXOp(0x66, 0x38B7, regOp1, regOp2, arg, 1); } 2301 WriteAVXOp(0x66, 0x3898, regOp1, regOp2, arg, 1);
1954 2302}
1955void XEmitter::SARX(int bits, X64Reg regOp1, const OpArg& arg, X64Reg regOp2) {WriteBMI2Op(bits, 0xF3, 0x38F7, regOp1, regOp2, arg);} 2303void XEmitter::VFMADD213PD(X64Reg regOp1, X64Reg regOp2, const OpArg& arg) {
1956void XEmitter::SHLX(int bits, X64Reg regOp1, const OpArg& arg, X64Reg regOp2) {WriteBMI2Op(bits, 0x66, 0x38F7, regOp1, regOp2, arg);} 2304 WriteAVXOp(0x66, 0x38A8, regOp1, regOp2, arg, 1);
1957void XEmitter::SHRX(int bits, X64Reg regOp1, const OpArg& arg, X64Reg regOp2) {WriteBMI2Op(bits, 0xF2, 0x38F7, regOp1, regOp2, arg);} 2305}
1958void XEmitter::RORX(int bits, X64Reg regOp, const OpArg& arg, u8 rotate) {WriteBMI2Op(bits, 0xF2, 0x3AF0, regOp, INVALID_REG, arg, 1); Write8(rotate);} 2306void XEmitter::VFMADD231PD(X64Reg regOp1, X64Reg regOp2, const OpArg& arg) {
1959void XEmitter::PEXT(int bits, X64Reg regOp1, X64Reg regOp2, const OpArg& arg) {WriteBMI2Op(bits, 0xF3, 0x38F5, regOp1, regOp2, arg);} 2307 WriteAVXOp(0x66, 0x38B8, regOp1, regOp2, arg, 1);
1960void XEmitter::PDEP(int bits, X64Reg regOp1, X64Reg regOp2, const OpArg& arg) {WriteBMI2Op(bits, 0xF2, 0x38F5, regOp1, regOp2, arg);} 2308}
1961void XEmitter::MULX(int bits, X64Reg regOp1, X64Reg regOp2, const OpArg& arg) {WriteBMI2Op(bits, 0xF2, 0x38F6, regOp2, regOp1, arg);} 2309void XEmitter::VFMADD132SS(X64Reg regOp1, X64Reg regOp2, const OpArg& arg) {
1962void XEmitter::BZHI(int bits, X64Reg regOp1, const OpArg& arg, X64Reg regOp2) {WriteBMI2Op(bits, 0x00, 0x38F5, regOp1, regOp2, arg);} 2310 WriteAVXOp(0x66, 0x3899, regOp1, regOp2, arg);
1963void XEmitter::BLSR(int bits, X64Reg regOp, const OpArg& arg) {WriteBMI1Op(bits, 0x00, 0x38F3, (X64Reg)0x1, regOp, arg);} 2311}
1964void XEmitter::BLSMSK(int bits, X64Reg regOp, const OpArg& arg) {WriteBMI1Op(bits, 0x00, 0x38F3, (X64Reg)0x2, regOp, arg);} 2312void XEmitter::VFMADD213SS(X64Reg regOp1, X64Reg regOp2, const OpArg& arg) {
1965void XEmitter::BLSI(int bits, X64Reg regOp, const OpArg& arg) {WriteBMI1Op(bits, 0x00, 0x38F3, (X64Reg)0x3, regOp, arg);} 2313 WriteAVXOp(0x66, 0x38A9, regOp1, regOp2, arg);
1966void XEmitter::BEXTR(int bits, X64Reg regOp1, const OpArg& arg, X64Reg regOp2){WriteBMI1Op(bits, 0x00, 0x38F7, regOp1, regOp2, arg);} 2314}
1967void XEmitter::ANDN(int bits, X64Reg regOp1, X64Reg regOp2, const OpArg& arg) {WriteBMI1Op(bits, 0x00, 0x38F2, regOp1, regOp2, arg);} 2315void XEmitter::VFMADD231SS(X64Reg regOp1, X64Reg regOp2, const OpArg& arg) {
2316 WriteAVXOp(0x66, 0x38B9, regOp1, regOp2, arg);
2317}
2318void XEmitter::VFMADD132SD(X64Reg regOp1, X64Reg regOp2, const OpArg& arg) {
2319 WriteAVXOp(0x66, 0x3899, regOp1, regOp2, arg, 1);
2320}
2321void XEmitter::VFMADD213SD(X64Reg regOp1, X64Reg regOp2, const OpArg& arg) {
2322 WriteAVXOp(0x66, 0x38A9, regOp1, regOp2, arg, 1);
2323}
2324void XEmitter::VFMADD231SD(X64Reg regOp1, X64Reg regOp2, const OpArg& arg) {
2325 WriteAVXOp(0x66, 0x38B9, regOp1, regOp2, arg, 1);
2326}
2327void XEmitter::VFMSUB132PS(X64Reg regOp1, X64Reg regOp2, const OpArg& arg) {
2328 WriteAVXOp(0x66, 0x389A, regOp1, regOp2, arg);
2329}
2330void XEmitter::VFMSUB213PS(X64Reg regOp1, X64Reg regOp2, const OpArg& arg) {
2331 WriteAVXOp(0x66, 0x38AA, regOp1, regOp2, arg);
2332}
2333void XEmitter::VFMSUB231PS(X64Reg regOp1, X64Reg regOp2, const OpArg& arg) {
2334 WriteAVXOp(0x66, 0x38BA, regOp1, regOp2, arg);
2335}
2336void XEmitter::VFMSUB132PD(X64Reg regOp1, X64Reg regOp2, const OpArg& arg) {
2337 WriteAVXOp(0x66, 0x389A, regOp1, regOp2, arg, 1);
2338}
2339void XEmitter::VFMSUB213PD(X64Reg regOp1, X64Reg regOp2, const OpArg& arg) {
2340 WriteAVXOp(0x66, 0x38AA, regOp1, regOp2, arg, 1);
2341}
2342void XEmitter::VFMSUB231PD(X64Reg regOp1, X64Reg regOp2, const OpArg& arg) {
2343 WriteAVXOp(0x66, 0x38BA, regOp1, regOp2, arg, 1);
2344}
2345void XEmitter::VFMSUB132SS(X64Reg regOp1, X64Reg regOp2, const OpArg& arg) {
2346 WriteAVXOp(0x66, 0x389B, regOp1, regOp2, arg);
2347}
2348void XEmitter::VFMSUB213SS(X64Reg regOp1, X64Reg regOp2, const OpArg& arg) {
2349 WriteAVXOp(0x66, 0x38AB, regOp1, regOp2, arg);
2350}
2351void XEmitter::VFMSUB231SS(X64Reg regOp1, X64Reg regOp2, const OpArg& arg) {
2352 WriteAVXOp(0x66, 0x38BB, regOp1, regOp2, arg);
2353}
2354void XEmitter::VFMSUB132SD(X64Reg regOp1, X64Reg regOp2, const OpArg& arg) {
2355 WriteAVXOp(0x66, 0x389B, regOp1, regOp2, arg, 1);
2356}
2357void XEmitter::VFMSUB213SD(X64Reg regOp1, X64Reg regOp2, const OpArg& arg) {
2358 WriteAVXOp(0x66, 0x38AB, regOp1, regOp2, arg, 1);
2359}
2360void XEmitter::VFMSUB231SD(X64Reg regOp1, X64Reg regOp2, const OpArg& arg) {
2361 WriteAVXOp(0x66, 0x38BB, regOp1, regOp2, arg, 1);
2362}
2363void XEmitter::VFNMADD132PS(X64Reg regOp1, X64Reg regOp2, const OpArg& arg) {
2364 WriteAVXOp(0x66, 0x389C, regOp1, regOp2, arg);
2365}
2366void XEmitter::VFNMADD213PS(X64Reg regOp1, X64Reg regOp2, const OpArg& arg) {
2367 WriteAVXOp(0x66, 0x38AC, regOp1, regOp2, arg);
2368}
2369void XEmitter::VFNMADD231PS(X64Reg regOp1, X64Reg regOp2, const OpArg& arg) {
2370 WriteAVXOp(0x66, 0x38BC, regOp1, regOp2, arg);
2371}
2372void XEmitter::VFNMADD132PD(X64Reg regOp1, X64Reg regOp2, const OpArg& arg) {
2373 WriteAVXOp(0x66, 0x389C, regOp1, regOp2, arg, 1);
2374}
2375void XEmitter::VFNMADD213PD(X64Reg regOp1, X64Reg regOp2, const OpArg& arg) {
2376 WriteAVXOp(0x66, 0x38AC, regOp1, regOp2, arg, 1);
2377}
2378void XEmitter::VFNMADD231PD(X64Reg regOp1, X64Reg regOp2, const OpArg& arg) {
2379 WriteAVXOp(0x66, 0x38BC, regOp1, regOp2, arg, 1);
2380}
2381void XEmitter::VFNMADD132SS(X64Reg regOp1, X64Reg regOp2, const OpArg& arg) {
2382 WriteAVXOp(0x66, 0x389D, regOp1, regOp2, arg);
2383}
2384void XEmitter::VFNMADD213SS(X64Reg regOp1, X64Reg regOp2, const OpArg& arg) {
2385 WriteAVXOp(0x66, 0x38AD, regOp1, regOp2, arg);
2386}
2387void XEmitter::VFNMADD231SS(X64Reg regOp1, X64Reg regOp2, const OpArg& arg) {
2388 WriteAVXOp(0x66, 0x38BD, regOp1, regOp2, arg);
2389}
2390void XEmitter::VFNMADD132SD(X64Reg regOp1, X64Reg regOp2, const OpArg& arg) {
2391 WriteAVXOp(0x66, 0x389D, regOp1, regOp2, arg, 1);
2392}
2393void XEmitter::VFNMADD213SD(X64Reg regOp1, X64Reg regOp2, const OpArg& arg) {
2394 WriteAVXOp(0x66, 0x38AD, regOp1, regOp2, arg, 1);
2395}
2396void XEmitter::VFNMADD231SD(X64Reg regOp1, X64Reg regOp2, const OpArg& arg) {
2397 WriteAVXOp(0x66, 0x38BD, regOp1, regOp2, arg, 1);
2398}
2399void XEmitter::VFNMSUB132PS(X64Reg regOp1, X64Reg regOp2, const OpArg& arg) {
2400 WriteAVXOp(0x66, 0x389E, regOp1, regOp2, arg);
2401}
2402void XEmitter::VFNMSUB213PS(X64Reg regOp1, X64Reg regOp2, const OpArg& arg) {
2403 WriteAVXOp(0x66, 0x38AE, regOp1, regOp2, arg);
2404}
2405void XEmitter::VFNMSUB231PS(X64Reg regOp1, X64Reg regOp2, const OpArg& arg) {
2406 WriteAVXOp(0x66, 0x38BE, regOp1, regOp2, arg);
2407}
2408void XEmitter::VFNMSUB132PD(X64Reg regOp1, X64Reg regOp2, const OpArg& arg) {
2409 WriteAVXOp(0x66, 0x389E, regOp1, regOp2, arg, 1);
2410}
2411void XEmitter::VFNMSUB213PD(X64Reg regOp1, X64Reg regOp2, const OpArg& arg) {
2412 WriteAVXOp(0x66, 0x38AE, regOp1, regOp2, arg, 1);
2413}
2414void XEmitter::VFNMSUB231PD(X64Reg regOp1, X64Reg regOp2, const OpArg& arg) {
2415 WriteAVXOp(0x66, 0x38BE, regOp1, regOp2, arg, 1);
2416}
2417void XEmitter::VFNMSUB132SS(X64Reg regOp1, X64Reg regOp2, const OpArg& arg) {
2418 WriteAVXOp(0x66, 0x389F, regOp1, regOp2, arg);
2419}
2420void XEmitter::VFNMSUB213SS(X64Reg regOp1, X64Reg regOp2, const OpArg& arg) {
2421 WriteAVXOp(0x66, 0x38AF, regOp1, regOp2, arg);
2422}
2423void XEmitter::VFNMSUB231SS(X64Reg regOp1, X64Reg regOp2, const OpArg& arg) {
2424 WriteAVXOp(0x66, 0x38BF, regOp1, regOp2, arg);
2425}
2426void XEmitter::VFNMSUB132SD(X64Reg regOp1, X64Reg regOp2, const OpArg& arg) {
2427 WriteAVXOp(0x66, 0x389F, regOp1, regOp2, arg, 1);
2428}
2429void XEmitter::VFNMSUB213SD(X64Reg regOp1, X64Reg regOp2, const OpArg& arg) {
2430 WriteAVXOp(0x66, 0x38AF, regOp1, regOp2, arg, 1);
2431}
2432void XEmitter::VFNMSUB231SD(X64Reg regOp1, X64Reg regOp2, const OpArg& arg) {
2433 WriteAVXOp(0x66, 0x38BF, regOp1, regOp2, arg, 1);
2434}
2435void XEmitter::VFMADDSUB132PS(X64Reg regOp1, X64Reg regOp2, const OpArg& arg) {
2436 WriteAVXOp(0x66, 0x3896, regOp1, regOp2, arg);
2437}
2438void XEmitter::VFMADDSUB213PS(X64Reg regOp1, X64Reg regOp2, const OpArg& arg) {
2439 WriteAVXOp(0x66, 0x38A6, regOp1, regOp2, arg);
2440}
2441void XEmitter::VFMADDSUB231PS(X64Reg regOp1, X64Reg regOp2, const OpArg& arg) {
2442 WriteAVXOp(0x66, 0x38B6, regOp1, regOp2, arg);
2443}
2444void XEmitter::VFMADDSUB132PD(X64Reg regOp1, X64Reg regOp2, const OpArg& arg) {
2445 WriteAVXOp(0x66, 0x3896, regOp1, regOp2, arg, 1);
2446}
2447void XEmitter::VFMADDSUB213PD(X64Reg regOp1, X64Reg regOp2, const OpArg& arg) {
2448 WriteAVXOp(0x66, 0x38A6, regOp1, regOp2, arg, 1);
2449}
2450void XEmitter::VFMADDSUB231PD(X64Reg regOp1, X64Reg regOp2, const OpArg& arg) {
2451 WriteAVXOp(0x66, 0x38B6, regOp1, regOp2, arg, 1);
2452}
2453void XEmitter::VFMSUBADD132PS(X64Reg regOp1, X64Reg regOp2, const OpArg& arg) {
2454 WriteAVXOp(0x66, 0x3897, regOp1, regOp2, arg);
2455}
2456void XEmitter::VFMSUBADD213PS(X64Reg regOp1, X64Reg regOp2, const OpArg& arg) {
2457 WriteAVXOp(0x66, 0x38A7, regOp1, regOp2, arg);
2458}
2459void XEmitter::VFMSUBADD231PS(X64Reg regOp1, X64Reg regOp2, const OpArg& arg) {
2460 WriteAVXOp(0x66, 0x38B7, regOp1, regOp2, arg);
2461}
2462void XEmitter::VFMSUBADD132PD(X64Reg regOp1, X64Reg regOp2, const OpArg& arg) {
2463 WriteAVXOp(0x66, 0x3897, regOp1, regOp2, arg, 1);
2464}
2465void XEmitter::VFMSUBADD213PD(X64Reg regOp1, X64Reg regOp2, const OpArg& arg) {
2466 WriteAVXOp(0x66, 0x38A7, regOp1, regOp2, arg, 1);
2467}
2468void XEmitter::VFMSUBADD231PD(X64Reg regOp1, X64Reg regOp2, const OpArg& arg) {
2469 WriteAVXOp(0x66, 0x38B7, regOp1, regOp2, arg, 1);
2470}
2471
2472void XEmitter::SARX(int bits, X64Reg regOp1, const OpArg& arg, X64Reg regOp2) {
2473 WriteBMI2Op(bits, 0xF3, 0x38F7, regOp1, regOp2, arg);
2474}
2475void XEmitter::SHLX(int bits, X64Reg regOp1, const OpArg& arg, X64Reg regOp2) {
2476 WriteBMI2Op(bits, 0x66, 0x38F7, regOp1, regOp2, arg);
2477}
2478void XEmitter::SHRX(int bits, X64Reg regOp1, const OpArg& arg, X64Reg regOp2) {
2479 WriteBMI2Op(bits, 0xF2, 0x38F7, regOp1, regOp2, arg);
2480}
2481void XEmitter::RORX(int bits, X64Reg regOp, const OpArg& arg, u8 rotate) {
2482 WriteBMI2Op(bits, 0xF2, 0x3AF0, regOp, INVALID_REG, arg, 1);
2483 Write8(rotate);
2484}
2485void XEmitter::PEXT(int bits, X64Reg regOp1, X64Reg regOp2, const OpArg& arg) {
2486 WriteBMI2Op(bits, 0xF3, 0x38F5, regOp1, regOp2, arg);
2487}
2488void XEmitter::PDEP(int bits, X64Reg regOp1, X64Reg regOp2, const OpArg& arg) {
2489 WriteBMI2Op(bits, 0xF2, 0x38F5, regOp1, regOp2, arg);
2490}
2491void XEmitter::MULX(int bits, X64Reg regOp1, X64Reg regOp2, const OpArg& arg) {
2492 WriteBMI2Op(bits, 0xF2, 0x38F6, regOp2, regOp1, arg);
2493}
2494void XEmitter::BZHI(int bits, X64Reg regOp1, const OpArg& arg, X64Reg regOp2) {
2495 WriteBMI2Op(bits, 0x00, 0x38F5, regOp1, regOp2, arg);
2496}
2497void XEmitter::BLSR(int bits, X64Reg regOp, const OpArg& arg) {
2498 WriteBMI1Op(bits, 0x00, 0x38F3, (X64Reg)0x1, regOp, arg);
2499}
2500void XEmitter::BLSMSK(int bits, X64Reg regOp, const OpArg& arg) {
2501 WriteBMI1Op(bits, 0x00, 0x38F3, (X64Reg)0x2, regOp, arg);
2502}
2503void XEmitter::BLSI(int bits, X64Reg regOp, const OpArg& arg) {
2504 WriteBMI1Op(bits, 0x00, 0x38F3, (X64Reg)0x3, regOp, arg);
2505}
2506void XEmitter::BEXTR(int bits, X64Reg regOp1, const OpArg& arg, X64Reg regOp2) {
2507 WriteBMI1Op(bits, 0x00, 0x38F7, regOp1, regOp2, arg);
2508}
2509void XEmitter::ANDN(int bits, X64Reg regOp1, X64Reg regOp2, const OpArg& arg) {
2510 WriteBMI1Op(bits, 0x00, 0x38F2, regOp1, regOp2, arg);
2511}
1968 2512
1969// Prefixes 2513// Prefixes
1970 2514
1971void XEmitter::LOCK() { Write8(0xF0); } 2515void XEmitter::LOCK() {
1972void XEmitter::REP() { Write8(0xF3); } 2516 Write8(0xF0);
1973void XEmitter::REPNE() { Write8(0xF2); } 2517}
1974void XEmitter::FSOverride() { Write8(0x64); } 2518void XEmitter::REP() {
1975void XEmitter::GSOverride() { Write8(0x65); } 2519 Write8(0xF3);
2520}
2521void XEmitter::REPNE() {
2522 Write8(0xF2);
2523}
2524void XEmitter::FSOverride() {
2525 Write8(0x64);
2526}
2527void XEmitter::GSOverride() {
2528 Write8(0x65);
2529}
1976 2530
1977void XEmitter::FWAIT() 2531void XEmitter::FWAIT() {
1978{
1979 Write8(0x9B); 2532 Write8(0x9B);
1980} 2533}
1981 2534
1982// TODO: make this more generic 2535// TODO: make this more generic
1983void XEmitter::WriteFloatLoadStore(int bits, FloatOp op, FloatOp op_80b, const OpArg& arg) 2536void XEmitter::WriteFloatLoadStore(int bits, FloatOp op, FloatOp op_80b, const OpArg& arg) {
1984{
1985 int mf = 0; 2537 int mf = 0;
1986 ASSERT_MSG(!(bits == 80 && op_80b == floatINVALID), "WriteFloatLoadStore: 80 bits not supported for this instruction"); 2538 ASSERT_MSG(!(bits == 80 && op_80b == floatINVALID),
1987 switch (bits) 2539 "WriteFloatLoadStore: 80 bits not supported for this instruction");
1988 { 2540 switch (bits) {
1989 case 32: mf = 0; break; 2541 case 32:
1990 case 64: mf = 4; break; 2542 mf = 0;
1991 case 80: mf = 2; break; 2543 break;
1992 default: ASSERT_MSG(0, "WriteFloatLoadStore: invalid bits (should be 32/64/80)"); 2544 case 64:
2545 mf = 4;
2546 break;
2547 case 80:
2548 mf = 2;
2549 break;
2550 default:
2551 ASSERT_MSG(0, "WriteFloatLoadStore: invalid bits (should be 32/64/80)");
1993 } 2552 }
1994 Write8(0xd9 | mf); 2553 Write8(0xd9 | mf);
1995 // x87 instructions use the reg field of the ModR/M byte as opcode: 2554 // x87 instructions use the reg field of the ModR/M byte as opcode:
1996 if (bits == 80) 2555 if (bits == 80)
1997 op = op_80b; 2556 op = op_80b;
1998 arg.WriteRest(this, 0, (X64Reg) op); 2557 arg.WriteRest(this, 0, (X64Reg)op);
1999} 2558}
2000 2559
2001void XEmitter::FLD(int bits, const OpArg& src) {WriteFloatLoadStore(bits, floatLD, floatLD80, src);} 2560void XEmitter::FLD(int bits, const OpArg& src) {
2002void XEmitter::FST(int bits, const OpArg& dest) {WriteFloatLoadStore(bits, floatST, floatINVALID, dest);} 2561 WriteFloatLoadStore(bits, floatLD, floatLD80, src);
2003void XEmitter::FSTP(int bits, const OpArg& dest) {WriteFloatLoadStore(bits, floatSTP, floatSTP80, dest);} 2562}
2004void XEmitter::FNSTSW_AX() { Write8(0xDF); Write8(0xE0); } 2563void XEmitter::FST(int bits, const OpArg& dest) {
2564 WriteFloatLoadStore(bits, floatST, floatINVALID, dest);
2565}
2566void XEmitter::FSTP(int bits, const OpArg& dest) {
2567 WriteFloatLoadStore(bits, floatSTP, floatSTP80, dest);
2568}
2569void XEmitter::FNSTSW_AX() {
2570 Write8(0xDF);
2571 Write8(0xE0);
2572}
2005 2573
2006void XEmitter::RDTSC() { Write8(0x0F); Write8(0x31); } 2574void XEmitter::RDTSC() {
2575 Write8(0x0F);
2576 Write8(0x31);
2577}
2007 2578
2008void XCodeBlock::PoisonMemory() { 2579void XCodeBlock::PoisonMemory() {
2009 // x86/64: 0xCC = breakpoint 2580 // x86/64: 0xCC = breakpoint
2010 memset(region, 0xCC, region_size); 2581 memset(region, 0xCC, region_size);
2011} 2582}
2012
2013} 2583}