Line data Source code
1 : /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
2 : * vim: set ts=8 sts=4 et sw=4 tw=99:
3 : *
4 : * ***** BEGIN LICENSE BLOCK *****
5 : * Copyright (C) 2008 Apple Inc. All rights reserved.
6 : *
7 : * Redistribution and use in source and binary forms, with or without
8 : * modification, are permitted provided that the following conditions
9 : * are met:
10 : * 1. Redistributions of source code must retain the above copyright
11 : * notice, this list of conditions and the following disclaimer.
12 : * 2. Redistributions in binary form must reproduce the above copyright
13 : * notice, this list of conditions and the following disclaimer in the
14 : * documentation and/or other materials provided with the distribution.
15 : *
16 : * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
17 : * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18 : * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
19 : * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
20 : * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
21 : * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
22 : * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
23 : * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
24 : * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 : * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
26 : * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 : *
28 : * ***** END LICENSE BLOCK ***** */
29 :
30 : #ifndef jit_x86_shared_BaseAssembler_x86_shared_h
31 : #define jit_x86_shared_BaseAssembler_x86_shared_h
32 :
33 : #include "mozilla/IntegerPrintfMacros.h"
34 :
35 : #include "jit/x86-shared/AssemblerBuffer-x86-shared.h"
36 : #include "jit/x86-shared/Encoding-x86-shared.h"
37 : #include "jit/x86-shared/Patching-x86-shared.h"
38 :
39 : extern volatile uintptr_t* blackbox;
40 :
41 : namespace js {
42 : namespace jit {
43 :
44 : namespace X86Encoding {
45 :
46 : class BaseAssembler;
47 :
48 4503 : class BaseAssembler : public GenericAssembler {
49 : public:
50 4503 : BaseAssembler()
51 4503 : : useVEX_(true)
52 4503 : { }
53 :
54 4503 : void disableVEX() { useVEX_ = false; }
55 :
56 335901 : size_t size() const { return m_formatter.size(); }
57 : const unsigned char* buffer() const { return m_formatter.buffer(); }
58 0 : unsigned char* data() { return m_formatter.data(); }
59 256035 : bool oom() const { return m_formatter.oom(); }
60 :
61 0 : void disableProtection() { m_formatter.disableProtection(); }
62 : void enableProtection() { m_formatter.enableProtection(); }
63 : void setLowerBoundForProtection(size_t size)
64 : {
65 : m_formatter.setLowerBoundForProtection(size);
66 : }
67 : void unprotectRegion(unsigned char* first, size_t size)
68 : {
69 : m_formatter.unprotectRegion(first, size);
70 : }
71 : void reprotectRegion(unsigned char* first, size_t size)
72 : {
73 : m_formatter.reprotectRegion(first, size);
74 : }
75 :
76 64 : void nop()
77 : {
78 64 : spew("nop");
79 64 : m_formatter.oneByteOp(OP_NOP);
80 64 : }
81 :
82 288 : void comment(const char* msg)
83 : {
84 288 : spew("; %s", msg);
85 288 : }
86 :
87 : MOZ_MUST_USE JmpSrc
88 0 : twoByteNop()
89 : {
90 0 : spew("nop (2 byte)");
91 0 : JmpSrc r(m_formatter.size());
92 0 : m_formatter.prefix(PRE_OPERAND_SIZE);
93 0 : m_formatter.oneByteOp(OP_NOP);
94 0 : return r;
95 : }
96 :
97 0 : static void patchTwoByteNopToJump(uint8_t* jump, uint8_t* target)
98 : {
99 : // Note: the offset is relative to the address of the instruction after
100 : // the jump which is two bytes.
101 0 : ptrdiff_t rel8 = target - jump - 2;
102 0 : MOZ_RELEASE_ASSERT(rel8 >= INT8_MIN && rel8 <= INT8_MAX);
103 0 : MOZ_RELEASE_ASSERT(jump[0] == PRE_OPERAND_SIZE);
104 0 : MOZ_RELEASE_ASSERT(jump[1] == OP_NOP);
105 0 : jump[0] = OP_JMP_rel8;
106 0 : jump[1] = rel8;
107 0 : }
108 :
109 0 : static void patchJumpToTwoByteNop(uint8_t* jump)
110 : {
111 : // See twoByteNop.
112 0 : MOZ_RELEASE_ASSERT(jump[0] == OP_JMP_rel8);
113 0 : jump[0] = PRE_OPERAND_SIZE;
114 0 : jump[1] = OP_NOP;
115 0 : }
116 :
117 0 : static void patchFiveByteNopToCall(uint8_t* callsite, uint8_t* target)
118 : {
119 : // Note: the offset is relative to the address of the instruction after
120 : // the call which is five bytes.
121 0 : uint8_t* inst = callsite - sizeof(int32_t) - 1;
122 : // The nop can be already patched as call, overriding the call.
123 : // See also nop_five.
124 0 : MOZ_ASSERT(inst[0] == OP_NOP_0F || inst[0] == OP_CALL_rel32);
125 0 : MOZ_ASSERT_IF(inst[0] == OP_NOP_0F, inst[1] == OP_NOP_1F ||
126 : inst[2] == OP_NOP_44 ||
127 : inst[3] == OP_NOP_00 ||
128 : inst[4] == OP_NOP_00);
129 0 : inst[0] = OP_CALL_rel32;
130 0 : SetRel32(callsite, target);
131 0 : }
132 :
133 0 : static void patchCallToFiveByteNop(uint8_t* callsite)
134 : {
135 : // See also patchFiveByteNopToCall and nop_five.
136 0 : uint8_t* inst = callsite - sizeof(int32_t) - 1;
137 : // The call can be already patched as nop.
138 0 : if (inst[0] == OP_NOP_0F) {
139 0 : MOZ_ASSERT(inst[1] == OP_NOP_1F || inst[2] == OP_NOP_44 ||
140 : inst[3] == OP_NOP_00 || inst[4] == OP_NOP_00);
141 0 : return;
142 : }
143 0 : MOZ_ASSERT(inst[0] == OP_CALL_rel32);
144 0 : inst[0] = OP_NOP_0F;
145 0 : inst[1] = OP_NOP_1F;
146 0 : inst[2] = OP_NOP_44;
147 0 : inst[3] = OP_NOP_00;
148 0 : inst[4] = OP_NOP_00;
149 : }
150 :
151 : /*
152 : * The nop multibytes sequences are directly taken from the Intel's
153 : * architecture software developer manual.
154 : * They are defined for sequences of sizes from 1 to 9 included.
155 : */
156 0 : void nop_one()
157 : {
158 0 : m_formatter.oneByteOp(OP_NOP);
159 0 : }
160 :
161 0 : void nop_two()
162 : {
163 0 : m_formatter.oneByteOp(OP_NOP_66);
164 0 : m_formatter.oneByteOp(OP_NOP);
165 0 : }
166 :
167 0 : void nop_three()
168 : {
169 0 : m_formatter.oneByteOp(OP_NOP_0F);
170 0 : m_formatter.oneByteOp(OP_NOP_1F);
171 0 : m_formatter.oneByteOp(OP_NOP_00);
172 0 : }
173 :
174 0 : void nop_four()
175 : {
176 0 : m_formatter.oneByteOp(OP_NOP_0F);
177 0 : m_formatter.oneByteOp(OP_NOP_1F);
178 0 : m_formatter.oneByteOp(OP_NOP_40);
179 0 : m_formatter.oneByteOp(OP_NOP_00);
180 0 : }
181 :
182 0 : void nop_five()
183 : {
184 0 : m_formatter.oneByteOp(OP_NOP_0F);
185 0 : m_formatter.oneByteOp(OP_NOP_1F);
186 0 : m_formatter.oneByteOp(OP_NOP_44);
187 0 : m_formatter.oneByteOp(OP_NOP_00);
188 0 : m_formatter.oneByteOp(OP_NOP_00);
189 0 : }
190 :
191 0 : void nop_six()
192 : {
193 0 : m_formatter.oneByteOp(OP_NOP_66);
194 0 : nop_five();
195 0 : }
196 :
197 0 : void nop_seven()
198 : {
199 0 : m_formatter.oneByteOp(OP_NOP_0F);
200 0 : m_formatter.oneByteOp(OP_NOP_1F);
201 0 : m_formatter.oneByteOp(OP_NOP_80);
202 0 : for (int i = 0; i < 4; ++i)
203 0 : m_formatter.oneByteOp(OP_NOP_00);
204 0 : }
205 :
206 0 : void nop_eight()
207 : {
208 0 : m_formatter.oneByteOp(OP_NOP_0F);
209 0 : m_formatter.oneByteOp(OP_NOP_1F);
210 0 : m_formatter.oneByteOp(OP_NOP_84);
211 0 : for (int i = 0; i < 5; ++i)
212 0 : m_formatter.oneByteOp(OP_NOP_00);
213 0 : }
214 :
215 0 : void nop_nine()
216 : {
217 0 : m_formatter.oneByteOp(OP_NOP_66);
218 0 : nop_eight();
219 0 : }
220 :
221 0 : void insert_nop(int size)
222 : {
223 0 : switch (size) {
224 : case 1:
225 0 : nop_one();
226 0 : break;
227 : case 2:
228 0 : nop_two();
229 0 : break;
230 : case 3:
231 0 : nop_three();
232 0 : break;
233 : case 4:
234 0 : nop_four();
235 0 : break;
236 : case 5:
237 0 : nop_five();
238 0 : break;
239 : case 6:
240 0 : nop_six();
241 0 : break;
242 : case 7:
243 0 : nop_seven();
244 0 : break;
245 : case 8:
246 0 : nop_eight();
247 0 : break;
248 : case 9:
249 0 : nop_nine();
250 0 : break;
251 : case 10:
252 0 : nop_three();
253 0 : nop_seven();
254 0 : break;
255 : case 11:
256 0 : nop_four();
257 0 : nop_seven();
258 0 : break;
259 : case 12:
260 0 : nop_six();
261 0 : nop_six();
262 0 : break;
263 : case 13:
264 0 : nop_six();
265 0 : nop_seven();
266 0 : break;
267 : case 14:
268 0 : nop_seven();
269 0 : nop_seven();
270 0 : break;
271 : case 15:
272 0 : nop_one();
273 0 : nop_seven();
274 0 : nop_seven();
275 0 : break;
276 : default:
277 0 : MOZ_CRASH("Unhandled alignment");
278 : }
279 0 : }
280 :
281 : // Stack operations:
282 :
283 143086 : void push_r(RegisterID reg)
284 : {
285 143086 : spew("push %s", GPRegName(reg));
286 143087 : m_formatter.oneByteOp(OP_PUSH_EAX, reg);
287 143090 : }
288 :
289 117823 : void pop_r(RegisterID reg)
290 : {
291 117823 : spew("pop %s", GPRegName(reg));
292 117823 : m_formatter.oneByteOp(OP_POP_EAX, reg);
293 117824 : }
294 :
295 6210 : void push_i(int32_t imm)
296 : {
297 6210 : spew("push $%s0x%x", PRETTYHEX(imm));
298 6210 : if (CAN_SIGN_EXTEND_8_32(imm)) {
299 2265 : m_formatter.oneByteOp(OP_PUSH_Ib);
300 2265 : m_formatter.immediate8s(imm);
301 : } else {
302 3945 : m_formatter.oneByteOp(OP_PUSH_Iz);
303 3945 : m_formatter.immediate32(imm);
304 : }
305 6210 : }
306 :
307 : void push_i32(int32_t imm)
308 : {
309 : spew("push $%s0x%04x", PRETTYHEX(imm));
310 : m_formatter.oneByteOp(OP_PUSH_Iz);
311 : m_formatter.immediate32(imm);
312 : }
313 :
314 4054 : void push_m(int32_t offset, RegisterID base)
315 : {
316 4054 : spew("push " MEM_ob, ADDR_ob(offset, base));
317 4054 : m_formatter.oneByteOp(OP_GROUP5_Ev, offset, base, GROUP5_OP_PUSH);
318 4054 : }
319 :
320 665 : void pop_m(int32_t offset, RegisterID base)
321 : {
322 665 : spew("pop " MEM_ob, ADDR_ob(offset, base));
323 665 : m_formatter.oneByteOp(OP_GROUP1A_Ev, offset, base, GROUP1A_OP_POP);
324 665 : }
325 :
326 0 : void push_flags()
327 : {
328 0 : spew("pushf");
329 0 : m_formatter.oneByteOp(OP_PUSHFLAGS);
330 0 : }
331 :
332 0 : void pop_flags()
333 : {
334 0 : spew("popf");
335 0 : m_formatter.oneByteOp(OP_POPFLAGS);
336 0 : }
337 :
338 : // Arithmetic operations:
339 :
340 47 : void addl_rr(RegisterID src, RegisterID dst)
341 : {
342 47 : spew("addl %s, %s", GPReg32Name(src), GPReg32Name(dst));
343 47 : m_formatter.oneByteOp(OP_ADD_GvEv, src, dst);
344 47 : }
345 :
346 0 : void addw_rr(RegisterID src, RegisterID dst)
347 : {
348 0 : spew("addw %s, %s", GPReg16Name(src), GPReg16Name(dst));
349 0 : m_formatter.prefix(PRE_OPERAND_SIZE);
350 0 : m_formatter.oneByteOp(OP_ADD_GvEv, src, dst);
351 0 : }
352 :
353 0 : void addl_mr(int32_t offset, RegisterID base, RegisterID dst)
354 : {
355 0 : spew("addl " MEM_ob ", %s", ADDR_ob(offset, base), GPReg32Name(dst));
356 0 : m_formatter.oneByteOp(OP_ADD_GvEv, offset, base, dst);
357 0 : }
358 :
359 0 : void addl_rm(RegisterID src, int32_t offset, RegisterID base)
360 : {
361 0 : spew("addl %s, " MEM_ob, GPReg32Name(src), ADDR_ob(offset, base));
362 0 : m_formatter.oneByteOp(OP_ADD_EvGv, offset, base, src);
363 0 : }
364 :
365 0 : void addl_rm(RegisterID src, int32_t offset, RegisterID base, RegisterID index, int scale)
366 : {
367 0 : spew("addl %s, " MEM_obs, GPReg32Name(src), ADDR_obs(offset, base, index, scale));
368 0 : m_formatter.oneByteOp(OP_ADD_EvGv, offset, base, index, scale, src);
369 0 : }
370 :
371 1163 : void addl_ir(int32_t imm, RegisterID dst)
372 : {
373 1163 : spew("addl $%d, %s", imm, GPReg32Name(dst));
374 1163 : if (CAN_SIGN_EXTEND_8_32(imm)) {
375 1163 : m_formatter.oneByteOp(OP_GROUP1_EvIb, dst, GROUP1_OP_ADD);
376 1163 : m_formatter.immediate8s(imm);
377 : } else {
378 0 : if (dst == rax)
379 0 : m_formatter.oneByteOp(OP_ADD_EAXIv);
380 : else
381 0 : m_formatter.oneByteOp(OP_GROUP1_EvIz, dst, GROUP1_OP_ADD);
382 0 : m_formatter.immediate32(imm);
383 : }
384 1163 : }
385 :
386 0 : void addw_ir(int32_t imm, RegisterID dst)
387 : {
388 0 : spew("addw $%d, %s", int16_t(imm), GPReg16Name(dst));
389 0 : m_formatter.prefix(PRE_OPERAND_SIZE);
390 0 : m_formatter.oneByteOp(OP_GROUP1_EvIz, dst, GROUP1_OP_ADD);
391 0 : m_formatter.immediate16(imm);
392 0 : }
393 :
394 : void addl_i32r(int32_t imm, RegisterID dst)
395 : {
396 : // 32-bit immediate always, for patching.
397 : spew("addl $0x%04x, %s", imm, GPReg32Name(dst));
398 : if (dst == rax)
399 : m_formatter.oneByteOp(OP_ADD_EAXIv);
400 : else
401 : m_formatter.oneByteOp(OP_GROUP1_EvIz, dst, GROUP1_OP_ADD);
402 : m_formatter.immediate32(imm);
403 : }
404 :
405 8 : void addl_im(int32_t imm, int32_t offset, RegisterID base)
406 : {
407 8 : spew("addl $%d, " MEM_ob, imm, ADDR_ob(offset, base));
408 8 : if (CAN_SIGN_EXTEND_8_32(imm)) {
409 8 : m_formatter.oneByteOp(OP_GROUP1_EvIb, offset, base, GROUP1_OP_ADD);
410 8 : m_formatter.immediate8s(imm);
411 : } else {
412 0 : m_formatter.oneByteOp(OP_GROUP1_EvIz, offset, base, GROUP1_OP_ADD);
413 0 : m_formatter.immediate32(imm);
414 : }
415 8 : }
416 :
417 0 : void addl_im(int32_t imm, int32_t offset, RegisterID base, RegisterID index, int scale)
418 : {
419 0 : spew("addl $%d, " MEM_obs, imm, ADDR_obs(offset, base, index, scale));
420 0 : if (CAN_SIGN_EXTEND_8_32(imm)) {
421 0 : m_formatter.oneByteOp(OP_GROUP1_EvIb, offset, base, index, scale, GROUP1_OP_ADD);
422 0 : m_formatter.immediate8s(imm);
423 : } else {
424 0 : m_formatter.oneByteOp(OP_GROUP1_EvIz, offset, base, index, scale, GROUP1_OP_ADD);
425 0 : m_formatter.immediate32(imm);
426 : }
427 0 : }
428 :
429 0 : void addl_im(int32_t imm, const void* addr)
430 : {
431 0 : spew("addl $%d, %p", imm, addr);
432 0 : if (CAN_SIGN_EXTEND_8_32(imm)) {
433 0 : m_formatter.oneByteOp(OP_GROUP1_EvIb, addr, GROUP1_OP_ADD);
434 0 : m_formatter.immediate8s(imm);
435 : } else {
436 0 : m_formatter.oneByteOp(OP_GROUP1_EvIz, addr, GROUP1_OP_ADD);
437 0 : m_formatter.immediate32(imm);
438 : }
439 0 : }
440 0 : void addw_im(int32_t imm, const void* addr)
441 : {
442 0 : spew("addw $%d, %p", int16_t(imm), addr);
443 0 : m_formatter.prefix(PRE_OPERAND_SIZE);
444 0 : if (CAN_SIGN_EXTEND_8_32(imm)) {
445 0 : m_formatter.oneByteOp(OP_GROUP1_EvIb, addr, GROUP1_OP_ADD);
446 0 : m_formatter.immediate8s(imm);
447 : } else {
448 0 : m_formatter.oneByteOp(OP_GROUP1_EvIz, addr, GROUP1_OP_ADD);
449 0 : m_formatter.immediate16(imm);
450 : }
451 0 : }
452 :
453 0 : void addw_im(int32_t imm, int32_t offset, RegisterID base) {
454 0 : spew("addw $%d, " MEM_ob, int16_t(imm), ADDR_ob(offset, base));
455 0 : m_formatter.prefix(PRE_OPERAND_SIZE);
456 0 : m_formatter.oneByteOp(OP_GROUP1_EvIz, offset, base, GROUP1_OP_ADD);
457 0 : m_formatter.immediate16(imm);
458 0 : }
459 :
460 0 : void addw_im(int32_t imm, int32_t offset, RegisterID base, RegisterID index, int scale)
461 : {
462 0 : spew("addw $%d, " MEM_obs, int16_t(imm), ADDR_obs(offset, base, index, scale));
463 0 : m_formatter.prefix(PRE_OPERAND_SIZE);
464 0 : m_formatter.oneByteOp(OP_GROUP1_EvIz, offset, base, index, scale, GROUP1_OP_ADD);
465 0 : m_formatter.immediate16(imm);
466 0 : }
467 :
468 0 : void addw_rm(RegisterID src, int32_t offset, RegisterID base) {
469 0 : spew("addw %s, " MEM_ob, GPReg16Name(src), ADDR_ob(offset, base));
470 0 : m_formatter.prefix(PRE_OPERAND_SIZE);
471 0 : m_formatter.oneByteOp(OP_ADD_EvGv, offset, base, src);
472 0 : }
473 :
474 0 : void addw_rm(RegisterID src, int32_t offset, RegisterID base, RegisterID index, int scale)
475 : {
476 0 : spew("addw %s, " MEM_obs, GPReg16Name(src), ADDR_obs(offset, base, index, scale));
477 0 : m_formatter.prefix(PRE_OPERAND_SIZE);
478 0 : m_formatter.oneByteOp(OP_ADD_EvGv, offset, base, index, scale, src);
479 0 : }
480 :
481 0 : void addb_im(int32_t imm, int32_t offset, RegisterID base) {
482 0 : spew("addb $%d, " MEM_ob, int8_t(imm), ADDR_ob(offset, base));
483 0 : m_formatter.oneByteOp(OP_GROUP1_EbIb, offset, base, GROUP1_OP_ADD);
484 0 : m_formatter.immediate8(imm);
485 0 : }
486 :
487 0 : void addb_im(int32_t imm, int32_t offset, RegisterID base, RegisterID index, int scale)
488 : {
489 0 : spew("addb $%d, " MEM_obs, int8_t(imm), ADDR_obs(offset, base, index, scale));
490 0 : m_formatter.oneByteOp(OP_GROUP1_EbIb, offset, base, index, scale, GROUP1_OP_ADD);
491 0 : m_formatter.immediate8(imm);
492 0 : }
493 :
494 0 : void addb_rm(RegisterID src, int32_t offset, RegisterID base) {
495 0 : spew("addb %s, " MEM_ob, GPReg8Name(src), ADDR_ob(offset, base));
496 0 : m_formatter.oneByteOp8(OP_ADD_EbGb, offset, base, src);
497 0 : }
498 :
499 0 : void addb_rm(RegisterID src, int32_t offset, RegisterID base, RegisterID index, int scale)
500 : {
501 0 : spew("addb %s, " MEM_obs, GPReg8Name(src), ADDR_obs(offset, base, index, scale));
502 0 : m_formatter.oneByteOp8(OP_ADD_EbGb, offset, base, index, scale, src);
503 0 : }
504 :
505 0 : void subb_im(int32_t imm, int32_t offset, RegisterID base) {
506 0 : spew("subb $%d, " MEM_ob, int8_t(imm), ADDR_ob(offset, base));
507 0 : m_formatter.oneByteOp(OP_GROUP1_EbIb, offset, base, GROUP1_OP_SUB);
508 0 : m_formatter.immediate8(imm);
509 0 : }
510 :
511 0 : void subb_im(int32_t imm, int32_t offset, RegisterID base, RegisterID index, int scale)
512 : {
513 0 : spew("subb $%d, " MEM_obs, int8_t(imm), ADDR_obs(offset, base, index, scale));
514 0 : m_formatter.oneByteOp(OP_GROUP1_EbIb, offset, base, index, scale, GROUP1_OP_SUB);
515 0 : m_formatter.immediate8(imm);
516 0 : }
517 :
518 0 : void subb_rm(RegisterID src, int32_t offset, RegisterID base) {
519 0 : spew("subb %s, " MEM_ob, GPReg8Name(src), ADDR_ob(offset, base));
520 0 : m_formatter.oneByteOp8(OP_SUB_EbGb, offset, base, src);
521 0 : }
522 :
523 0 : void subb_rm(RegisterID src, int32_t offset, RegisterID base, RegisterID index, int scale)
524 : {
525 0 : spew("subb %s, " MEM_obs, GPReg8Name(src), ADDR_obs(offset, base, index, scale));
526 0 : m_formatter.oneByteOp8(OP_SUB_EbGb, offset, base, index, scale, src);
527 0 : }
528 :
529 0 : void andb_im(int32_t imm, int32_t offset, RegisterID base) {
530 0 : spew("andb $%d, " MEM_ob, int8_t(imm), ADDR_ob(offset, base));
531 0 : m_formatter.oneByteOp(OP_GROUP1_EbIb, offset, base, GROUP1_OP_AND);
532 0 : m_formatter.immediate8(imm);
533 0 : }
534 :
535 0 : void andb_im(int32_t imm, int32_t offset, RegisterID base, RegisterID index, int scale)
536 : {
537 0 : spew("andb $%d, " MEM_obs, int8_t(imm), ADDR_obs(offset, base, index, scale));
538 0 : m_formatter.oneByteOp(OP_GROUP1_EbIb, offset, base, index, scale, GROUP1_OP_AND);
539 0 : m_formatter.immediate8(imm);
540 0 : }
541 :
542 0 : void andb_rm(RegisterID src, int32_t offset, RegisterID base) {
543 0 : spew("andb %s, " MEM_ob, GPReg8Name(src), ADDR_ob(offset, base));
544 0 : m_formatter.oneByteOp8(OP_AND_EbGb, offset, base, src);
545 0 : }
546 :
547 0 : void andb_rm(RegisterID src, int32_t offset, RegisterID base, RegisterID index, int scale)
548 : {
549 0 : spew("andb %s, " MEM_obs, GPReg8Name(src), ADDR_obs(offset, base, index, scale));
550 0 : m_formatter.oneByteOp8(OP_AND_EbGb, offset, base, index, scale, src);
551 0 : }
552 :
553 0 : void orb_im(int32_t imm, int32_t offset, RegisterID base) {
554 0 : spew("orb $%d, " MEM_ob, int8_t(imm), ADDR_ob(offset, base));
555 0 : m_formatter.oneByteOp(OP_GROUP1_EbIb, offset, base, GROUP1_OP_OR);
556 0 : m_formatter.immediate8(imm);
557 0 : }
558 :
559 0 : void orb_im(int32_t imm, int32_t offset, RegisterID base, RegisterID index, int scale)
560 : {
561 0 : spew("orb $%d, " MEM_obs, int8_t(imm), ADDR_obs(offset, base, index, scale));
562 0 : m_formatter.oneByteOp(OP_GROUP1_EbIb, offset, base, index, scale, GROUP1_OP_OR);
563 0 : m_formatter.immediate8(imm);
564 0 : }
565 :
566 0 : void orb_rm(RegisterID src, int32_t offset, RegisterID base) {
567 0 : spew("orb %s, " MEM_ob, GPReg8Name(src), ADDR_ob(offset, base));
568 0 : m_formatter.oneByteOp8(OP_OR_EbGb, offset, base, src);
569 0 : }
570 :
571 0 : void orb_rm(RegisterID src, int32_t offset, RegisterID base, RegisterID index, int scale)
572 : {
573 0 : spew("orb %s, " MEM_obs, GPReg8Name(src), ADDR_obs(offset, base, index, scale));
574 0 : m_formatter.oneByteOp8(OP_OR_EbGb, offset, base, index, scale, src);
575 0 : }
576 :
577 0 : void xorb_im(int32_t imm, int32_t offset, RegisterID base) {
578 0 : spew("xorb $%d, " MEM_ob, int8_t(imm), ADDR_ob(offset, base));
579 0 : m_formatter.oneByteOp(OP_GROUP1_EbIb, offset, base, GROUP1_OP_XOR);
580 0 : m_formatter.immediate8(imm);
581 0 : }
582 :
583 0 : void xorb_im(int32_t imm, int32_t offset, RegisterID base, RegisterID index, int scale)
584 : {
585 0 : spew("xorb $%d, " MEM_obs, int8_t(imm), ADDR_obs(offset, base, index, scale));
586 0 : m_formatter.oneByteOp(OP_GROUP1_EbIb, offset, base, index, scale, GROUP1_OP_XOR);
587 0 : m_formatter.immediate8(imm);
588 0 : }
589 :
590 0 : void xorb_rm(RegisterID src, int32_t offset, RegisterID base) {
591 0 : spew("xorb %s, " MEM_ob, GPReg8Name(src), ADDR_ob(offset, base));
592 0 : m_formatter.oneByteOp8(OP_XOR_EbGb, offset, base, src);
593 0 : }
594 :
595 0 : void xorb_rm(RegisterID src, int32_t offset, RegisterID base, RegisterID index, int scale)
596 : {
597 0 : spew("xorb %s, " MEM_obs, GPReg8Name(src), ADDR_obs(offset, base, index, scale));
598 0 : m_formatter.oneByteOp8(OP_XOR_EbGb, offset, base, index, scale, src);
599 0 : }
600 :
601 0 : void lock_xaddb_rm(RegisterID srcdest, int32_t offset, RegisterID base)
602 : {
603 0 : spew("lock xaddb %s, " MEM_ob, GPReg8Name(srcdest), ADDR_ob(offset, base));
604 0 : m_formatter.oneByteOp(PRE_LOCK);
605 0 : m_formatter.twoByteOp8(OP2_XADD_EbGb, offset, base, srcdest);
606 0 : }
607 :
608 0 : void lock_xaddb_rm(RegisterID srcdest, int32_t offset, RegisterID base, RegisterID index, int scale)
609 : {
610 0 : spew("lock xaddb %s, " MEM_obs, GPReg8Name(srcdest), ADDR_obs(offset, base, index, scale));
611 0 : m_formatter.oneByteOp(PRE_LOCK);
612 0 : m_formatter.twoByteOp8(OP2_XADD_EbGb, offset, base, index, scale, srcdest);
613 0 : }
614 :
615 0 : void lock_xaddl_rm(RegisterID srcdest, int32_t offset, RegisterID base)
616 : {
617 0 : spew("lock xaddl %s, " MEM_ob, GPReg32Name(srcdest), ADDR_ob(offset, base));
618 0 : m_formatter.oneByteOp(PRE_LOCK);
619 0 : m_formatter.twoByteOp(OP2_XADD_EvGv, offset, base, srcdest);
620 0 : }
621 :
622 0 : void lock_xaddl_rm(RegisterID srcdest, int32_t offset, RegisterID base, RegisterID index, int scale)
623 : {
624 0 : spew("lock xaddl %s, " MEM_obs, GPReg32Name(srcdest), ADDR_obs(offset, base, index, scale));
625 0 : m_formatter.oneByteOp(PRE_LOCK);
626 0 : m_formatter.twoByteOp(OP2_XADD_EvGv, offset, base, index, scale, srcdest);
627 0 : }
628 :
629 0 : void vpaddb_rr(XMMRegisterID src1, XMMRegisterID src0, XMMRegisterID dst)
630 : {
631 0 : twoByteOpSimd("vpaddb", VEX_PD, OP2_PADDB_VdqWdq, src1, src0, dst);
632 0 : }
633 0 : void vpaddb_mr(int32_t offset, RegisterID base, XMMRegisterID src0, XMMRegisterID dst)
634 : {
635 0 : twoByteOpSimd("vpaddb", VEX_PD, OP2_PADDB_VdqWdq, offset, base, src0, dst);
636 0 : }
637 0 : void vpaddb_mr(const void* address, XMMRegisterID src0, XMMRegisterID dst)
638 : {
639 0 : twoByteOpSimd("vpaddb", VEX_PD, OP2_PADDB_VdqWdq, address, src0, dst);
640 0 : }
641 :
642 0 : void vpaddsb_rr(XMMRegisterID src1, XMMRegisterID src0, XMMRegisterID dst)
643 : {
644 0 : twoByteOpSimd("vpaddsb", VEX_PD, OP2_PADDSB_VdqWdq, src1, src0, dst);
645 0 : }
646 0 : void vpaddsb_mr(int32_t offset, RegisterID base, XMMRegisterID src0, XMMRegisterID dst)
647 : {
648 0 : twoByteOpSimd("vpaddsb", VEX_PD, OP2_PADDSB_VdqWdq, offset, base, src0, dst);
649 0 : }
650 0 : void vpaddsb_mr(const void* address, XMMRegisterID src0, XMMRegisterID dst)
651 : {
652 0 : twoByteOpSimd("vpaddsb", VEX_PD, OP2_PADDSB_VdqWdq, address, src0, dst);
653 0 : }
654 :
655 0 : void vpaddusb_rr(XMMRegisterID src1, XMMRegisterID src0, XMMRegisterID dst)
656 : {
657 0 : twoByteOpSimd("vpaddusb", VEX_PD, OP2_PADDUSB_VdqWdq, src1, src0, dst);
658 0 : }
659 0 : void vpaddusb_mr(int32_t offset, RegisterID base, XMMRegisterID src0, XMMRegisterID dst)
660 : {
661 0 : twoByteOpSimd("vpaddusb", VEX_PD, OP2_PADDUSB_VdqWdq, offset, base, src0, dst);
662 0 : }
663 0 : void vpaddusb_mr(const void* address, XMMRegisterID src0, XMMRegisterID dst)
664 : {
665 0 : twoByteOpSimd("vpaddusb", VEX_PD, OP2_PADDUSB_VdqWdq, address, src0, dst);
666 0 : }
667 :
668 0 : void vpaddw_rr(XMMRegisterID src1, XMMRegisterID src0, XMMRegisterID dst)
669 : {
670 0 : twoByteOpSimd("vpaddw", VEX_PD, OP2_PADDW_VdqWdq, src1, src0, dst);
671 0 : }
672 0 : void vpaddw_mr(int32_t offset, RegisterID base, XMMRegisterID src0, XMMRegisterID dst)
673 : {
674 0 : twoByteOpSimd("vpaddw", VEX_PD, OP2_PADDW_VdqWdq, offset, base, src0, dst);
675 0 : }
676 0 : void vpaddw_mr(const void* address, XMMRegisterID src0, XMMRegisterID dst)
677 : {
678 0 : twoByteOpSimd("vpaddw", VEX_PD, OP2_PADDW_VdqWdq, address, src0, dst);
679 0 : }
680 :
681 0 : void vpaddsw_rr(XMMRegisterID src1, XMMRegisterID src0, XMMRegisterID dst)
682 : {
683 0 : twoByteOpSimd("vpaddsw", VEX_PD, OP2_PADDSW_VdqWdq, src1, src0, dst);
684 0 : }
685 0 : void vpaddsw_mr(int32_t offset, RegisterID base, XMMRegisterID src0, XMMRegisterID dst)
686 : {
687 0 : twoByteOpSimd("vpaddsw", VEX_PD, OP2_PADDSW_VdqWdq, offset, base, src0, dst);
688 0 : }
689 0 : void vpaddsw_mr(const void* address, XMMRegisterID src0, XMMRegisterID dst)
690 : {
691 0 : twoByteOpSimd("vpaddsw", VEX_PD, OP2_PADDSW_VdqWdq, address, src0, dst);
692 0 : }
693 :
694 0 : void vpaddusw_rr(XMMRegisterID src1, XMMRegisterID src0, XMMRegisterID dst)
695 : {
696 0 : twoByteOpSimd("vpaddusw", VEX_PD, OP2_PADDUSW_VdqWdq, src1, src0, dst);
697 0 : }
698 0 : void vpaddusw_mr(int32_t offset, RegisterID base, XMMRegisterID src0, XMMRegisterID dst)
699 : {
700 0 : twoByteOpSimd("vpaddusw", VEX_PD, OP2_PADDUSW_VdqWdq, offset, base, src0, dst);
701 0 : }
702 0 : void vpaddusw_mr(const void* address, XMMRegisterID src0, XMMRegisterID dst)
703 : {
704 0 : twoByteOpSimd("vpaddusw", VEX_PD, OP2_PADDUSW_VdqWdq, address, src0, dst);
705 0 : }
706 :
707 0 : void vpaddd_rr(XMMRegisterID src1, XMMRegisterID src0, XMMRegisterID dst)
708 : {
709 0 : twoByteOpSimd("vpaddd", VEX_PD, OP2_PADDD_VdqWdq, src1, src0, dst);
710 0 : }
711 0 : void vpaddd_mr(int32_t offset, RegisterID base, XMMRegisterID src0, XMMRegisterID dst)
712 : {
713 0 : twoByteOpSimd("vpaddd", VEX_PD, OP2_PADDD_VdqWdq, offset, base, src0, dst);
714 0 : }
715 0 : void vpaddd_mr(const void* address, XMMRegisterID src0, XMMRegisterID dst)
716 : {
717 0 : twoByteOpSimd("vpaddd", VEX_PD, OP2_PADDD_VdqWdq, address, src0, dst);
718 0 : }
719 :
720 0 : void vpsubb_rr(XMMRegisterID src1, XMMRegisterID src0, XMMRegisterID dst)
721 : {
722 0 : twoByteOpSimd("vpsubb", VEX_PD, OP2_PSUBB_VdqWdq, src1, src0, dst);
723 0 : }
724 0 : void vpsubb_mr(int32_t offset, RegisterID base, XMMRegisterID src0, XMMRegisterID dst)
725 : {
726 0 : twoByteOpSimd("vpsubb", VEX_PD, OP2_PSUBB_VdqWdq, offset, base, src0, dst);
727 0 : }
728 0 : void vpsubb_mr(const void* address, XMMRegisterID src0, XMMRegisterID dst)
729 : {
730 0 : twoByteOpSimd("vpsubb", VEX_PD, OP2_PSUBB_VdqWdq, address, src0, dst);
731 0 : }
732 :
733 0 : void vpsubsb_rr(XMMRegisterID src1, XMMRegisterID src0, XMMRegisterID dst)
734 : {
735 0 : twoByteOpSimd("vpsubsb", VEX_PD, OP2_PSUBSB_VdqWdq, src1, src0, dst);
736 0 : }
737 0 : void vpsubsb_mr(int32_t offset, RegisterID base, XMMRegisterID src0, XMMRegisterID dst)
738 : {
739 0 : twoByteOpSimd("vpsubsb", VEX_PD, OP2_PSUBSB_VdqWdq, offset, base, src0, dst);
740 0 : }
741 0 : void vpsubsb_mr(const void* subress, XMMRegisterID src0, XMMRegisterID dst)
742 : {
743 0 : twoByteOpSimd("vpsubsb", VEX_PD, OP2_PSUBSB_VdqWdq, subress, src0, dst);
744 0 : }
745 :
746 0 : void vpsubusb_rr(XMMRegisterID src1, XMMRegisterID src0, XMMRegisterID dst)
747 : {
748 0 : twoByteOpSimd("vpsubusb", VEX_PD, OP2_PSUBUSB_VdqWdq, src1, src0, dst);
749 0 : }
750 0 : void vpsubusb_mr(int32_t offset, RegisterID base, XMMRegisterID src0, XMMRegisterID dst)
751 : {
752 0 : twoByteOpSimd("vpsubusb", VEX_PD, OP2_PSUBUSB_VdqWdq, offset, base, src0, dst);
753 0 : }
754 0 : void vpsubusb_mr(const void* subress, XMMRegisterID src0, XMMRegisterID dst)
755 : {
756 0 : twoByteOpSimd("vpsubusb", VEX_PD, OP2_PSUBUSB_VdqWdq, subress, src0, dst);
757 0 : }
758 :
759 0 : void vpsubw_rr(XMMRegisterID src1, XMMRegisterID src0, XMMRegisterID dst)
760 : {
761 0 : twoByteOpSimd("vpsubw", VEX_PD, OP2_PSUBW_VdqWdq, src1, src0, dst);
762 0 : }
763 0 : void vpsubw_mr(int32_t offset, RegisterID base, XMMRegisterID src0, XMMRegisterID dst)
764 : {
765 0 : twoByteOpSimd("vpsubw", VEX_PD, OP2_PSUBW_VdqWdq, offset, base, src0, dst);
766 0 : }
767 0 : void vpsubw_mr(const void* address, XMMRegisterID src0, XMMRegisterID dst)
768 : {
769 0 : twoByteOpSimd("vpsubw", VEX_PD, OP2_PSUBW_VdqWdq, address, src0, dst);
770 0 : }
771 :
772 0 : void vpsubsw_rr(XMMRegisterID src1, XMMRegisterID src0, XMMRegisterID dst)
773 : {
774 0 : twoByteOpSimd("vpsubsw", VEX_PD, OP2_PSUBSW_VdqWdq, src1, src0, dst);
775 0 : }
776 0 : void vpsubsw_mr(int32_t offset, RegisterID base, XMMRegisterID src0, XMMRegisterID dst)
777 : {
778 0 : twoByteOpSimd("vpsubsw", VEX_PD, OP2_PSUBSW_VdqWdq, offset, base, src0, dst);
779 0 : }
780 0 : void vpsubsw_mr(const void* subress, XMMRegisterID src0, XMMRegisterID dst)
781 : {
782 0 : twoByteOpSimd("vpsubsw", VEX_PD, OP2_PSUBSW_VdqWdq, subress, src0, dst);
783 0 : }
784 :
785 0 : void vpsubusw_rr(XMMRegisterID src1, XMMRegisterID src0, XMMRegisterID dst)
786 : {
787 0 : twoByteOpSimd("vpsubusw", VEX_PD, OP2_PSUBUSW_VdqWdq, src1, src0, dst);
788 0 : }
789 0 : void vpsubusw_mr(int32_t offset, RegisterID base, XMMRegisterID src0, XMMRegisterID dst)
790 : {
791 0 : twoByteOpSimd("vpsubusw", VEX_PD, OP2_PSUBUSW_VdqWdq, offset, base, src0, dst);
792 0 : }
793 0 : void vpsubusw_mr(const void* subress, XMMRegisterID src0, XMMRegisterID dst)
794 : {
795 0 : twoByteOpSimd("vpsubusw", VEX_PD, OP2_PSUBUSW_VdqWdq, subress, src0, dst);
796 0 : }
797 :
798 0 : void vpsubd_rr(XMMRegisterID src1, XMMRegisterID src0, XMMRegisterID dst)
799 : {
800 0 : twoByteOpSimd("vpsubd", VEX_PD, OP2_PSUBD_VdqWdq, src1, src0, dst);
801 0 : }
802 0 : void vpsubd_mr(int32_t offset, RegisterID base, XMMRegisterID src0, XMMRegisterID dst)
803 : {
804 0 : twoByteOpSimd("vpsubd", VEX_PD, OP2_PSUBD_VdqWdq, offset, base, src0, dst);
805 0 : }
806 0 : void vpsubd_mr(const void* address, XMMRegisterID src0, XMMRegisterID dst)
807 : {
808 0 : twoByteOpSimd("vpsubd", VEX_PD, OP2_PSUBD_VdqWdq, address, src0, dst);
809 0 : }
810 :
811 0 : void vpmuludq_rr(XMMRegisterID src1, XMMRegisterID src0, XMMRegisterID dst)
812 : {
813 0 : twoByteOpSimd("vpmuludq", VEX_PD, OP2_PMULUDQ_VdqWdq, src1, src0, dst);
814 0 : }
815 : void vpmuludq_mr(int32_t offset, RegisterID base, XMMRegisterID src0, XMMRegisterID dst)
816 : {
817 : twoByteOpSimd("vpmuludq", VEX_PD, OP2_PMULUDQ_VdqWdq, offset, base, src0, dst);
818 : }
819 :
820 0 : void vpmullw_rr(XMMRegisterID src1, XMMRegisterID src0, XMMRegisterID dst)
821 : {
822 0 : twoByteOpSimd("vpmullw", VEX_PD, OP2_PMULLW_VdqWdq, src1, src0, dst);
823 0 : }
824 0 : void vpmullw_mr(int32_t offset, RegisterID base, XMMRegisterID src0, XMMRegisterID dst)
825 : {
826 0 : twoByteOpSimd("vpmullw", VEX_PD, OP2_PMULLW_VdqWdq, offset, base, src0, dst);
827 0 : }
828 :
829 0 : void vpmulld_rr(XMMRegisterID src1, XMMRegisterID src0, XMMRegisterID dst)
830 : {
831 0 : threeByteOpSimd("vpmulld", VEX_PD, OP3_PMULLD_VdqWdq, ESCAPE_38, src1, src0, dst);
832 0 : }
833 0 : void vpmulld_mr(int32_t offset, RegisterID base, XMMRegisterID src0, XMMRegisterID dst)
834 : {
835 0 : threeByteOpSimd("vpmulld", VEX_PD, OP3_PMULLD_VdqWdq, ESCAPE_38, offset, base, src0, dst);
836 0 : }
837 0 : void vpmulld_mr(const void* address, XMMRegisterID src0, XMMRegisterID dst)
838 : {
839 0 : threeByteOpSimd("vpmulld", VEX_PD, OP3_PMULLD_VdqWdq, ESCAPE_38, address, src0, dst);
840 0 : }
841 :
842 0 : void vaddps_rr(XMMRegisterID src1, XMMRegisterID src0, XMMRegisterID dst)
843 : {
844 0 : twoByteOpSimd("vaddps", VEX_PS, OP2_ADDPS_VpsWps, src1, src0, dst);
845 0 : }
846 0 : void vaddps_mr(int32_t offset, RegisterID base, XMMRegisterID src0, XMMRegisterID dst)
847 : {
848 0 : twoByteOpSimd("vaddps", VEX_PS, OP2_ADDPS_VpsWps, offset, base, src0, dst);
849 0 : }
850 0 : void vaddps_mr(const void* address, XMMRegisterID src0, XMMRegisterID dst)
851 : {
852 0 : twoByteOpSimd("vaddps", VEX_PS, OP2_ADDPS_VpsWps, address, src0, dst);
853 0 : }
854 :
855 0 : void vsubps_rr(XMMRegisterID src1, XMMRegisterID src0, XMMRegisterID dst)
856 : {
857 0 : twoByteOpSimd("vsubps", VEX_PS, OP2_SUBPS_VpsWps, src1, src0, dst);
858 0 : }
859 0 : void vsubps_mr(int32_t offset, RegisterID base, XMMRegisterID src0, XMMRegisterID dst)
860 : {
861 0 : twoByteOpSimd("vsubps", VEX_PS, OP2_SUBPS_VpsWps, offset, base, src0, dst);
862 0 : }
863 0 : void vsubps_mr(const void* address, XMMRegisterID src0, XMMRegisterID dst)
864 : {
865 0 : twoByteOpSimd("vsubps", VEX_PS, OP2_SUBPS_VpsWps, address, src0, dst);
866 0 : }
867 :
868 0 : void vmulps_rr(XMMRegisterID src1, XMMRegisterID src0, XMMRegisterID dst)
869 : {
870 0 : twoByteOpSimd("vmulps", VEX_PS, OP2_MULPS_VpsWps, src1, src0, dst);
871 0 : }
872 0 : void vmulps_mr(int32_t offset, RegisterID base, XMMRegisterID src0, XMMRegisterID dst)
873 : {
874 0 : twoByteOpSimd("vmulps", VEX_PS, OP2_MULPS_VpsWps, offset, base, src0, dst);
875 0 : }
876 0 : void vmulps_mr(const void* address, XMMRegisterID src0, XMMRegisterID dst)
877 : {
878 0 : twoByteOpSimd("vmulps", VEX_PS, OP2_MULPS_VpsWps, address, src0, dst);
879 0 : }
880 :
881 0 : void vdivps_rr(XMMRegisterID src1, XMMRegisterID src0, XMMRegisterID dst)
882 : {
883 0 : twoByteOpSimd("vdivps", VEX_PS, OP2_DIVPS_VpsWps, src1, src0, dst);
884 0 : }
885 0 : void vdivps_mr(int32_t offset, RegisterID base, XMMRegisterID src0, XMMRegisterID dst)
886 : {
887 0 : twoByteOpSimd("vdivps", VEX_PS, OP2_DIVPS_VpsWps, offset, base, src0, dst);
888 0 : }
889 0 : void vdivps_mr(const void* address, XMMRegisterID src0, XMMRegisterID dst)
890 : {
891 0 : twoByteOpSimd("vdivps", VEX_PS, OP2_DIVPS_VpsWps, address, src0, dst);
892 0 : }
893 :
894 0 : void vmaxps_rr(XMMRegisterID src1, XMMRegisterID src0, XMMRegisterID dst)
895 : {
896 0 : twoByteOpSimd("vmaxps", VEX_PS, OP2_MAXPS_VpsWps, src1, src0, dst);
897 0 : }
898 0 : void vmaxps_mr(int32_t offset, RegisterID base, XMMRegisterID src0, XMMRegisterID dst)
899 : {
900 0 : twoByteOpSimd("vmaxps", VEX_PS, OP2_MAXPS_VpsWps, offset, base, src0, dst);
901 0 : }
902 0 : void vmaxps_mr(const void* address, XMMRegisterID src0, XMMRegisterID dst)
903 : {
904 0 : twoByteOpSimd("vmaxps", VEX_PS, OP2_MAXPS_VpsWps, address, src0, dst);
905 0 : }
906 :
907 0 : void vminps_rr(XMMRegisterID src1, XMMRegisterID src0, XMMRegisterID dst)
908 : {
909 0 : twoByteOpSimd("vminps", VEX_PS, OP2_MINPS_VpsWps, src1, src0, dst);
910 0 : }
911 0 : void vminps_mr(int32_t offset, RegisterID base, XMMRegisterID src0, XMMRegisterID dst)
912 : {
913 0 : twoByteOpSimd("vminps", VEX_PS, OP2_MINPS_VpsWps, offset, base, src0, dst);
914 0 : }
915 0 : void vminps_mr(const void* address, XMMRegisterID src0, XMMRegisterID dst)
916 : {
917 0 : twoByteOpSimd("vminps", VEX_PS, OP2_MINPS_VpsWps, address, src0, dst);
918 0 : }
919 :
920 164 : void andl_rr(RegisterID src, RegisterID dst)
921 : {
922 164 : spew("andl %s, %s", GPReg32Name(src), GPReg32Name(dst));
923 164 : m_formatter.oneByteOp(OP_AND_GvEv, src, dst);
924 164 : }
925 :
926 0 : void andw_rr(RegisterID src, RegisterID dst)
927 : {
928 0 : spew("andw %s, %s", GPReg16Name(src), GPReg16Name(dst));
929 0 : m_formatter.prefix(PRE_OPERAND_SIZE);
930 0 : m_formatter.oneByteOp(OP_AND_GvEv, src, dst);
931 0 : }
932 :
933 4 : void andl_mr(int32_t offset, RegisterID base, RegisterID dst)
934 : {
935 4 : spew("andl " MEM_ob ", %s", ADDR_ob(offset, base), GPReg32Name(dst));
936 4 : m_formatter.oneByteOp(OP_AND_GvEv, offset, base, dst);
937 4 : }
938 :
939 0 : void andl_rm(RegisterID src, int32_t offset, RegisterID base)
940 : {
941 0 : spew("andl %s, " MEM_ob, GPReg32Name(src), ADDR_ob(offset, base));
942 0 : m_formatter.oneByteOp(OP_AND_EvGv, offset, base, src);
943 0 : }
944 :
945 0 : void andw_rm(RegisterID src, int32_t offset, RegisterID base)
946 : {
947 0 : spew("andw %s, " MEM_ob, GPReg16Name(src), ADDR_ob(offset, base));
948 0 : m_formatter.prefix(PRE_OPERAND_SIZE);
949 0 : m_formatter.oneByteOp(OP_AND_EvGv, offset, base, src);
950 0 : }
951 :
952 0 : void andl_rm(RegisterID src, int32_t offset, RegisterID base, RegisterID index, int scale)
953 : {
954 0 : spew("andl %s, " MEM_obs, GPReg32Name(src), ADDR_obs(offset, base, index, scale));
955 0 : m_formatter.oneByteOp(OP_AND_EvGv, offset, base, index, scale, src);
956 0 : }
957 :
958 0 : void andw_rm(RegisterID src, int32_t offset, RegisterID base, RegisterID index, int scale)
959 : {
960 0 : spew("andw %s, " MEM_obs, GPReg16Name(src), ADDR_obs(offset, base, index, scale));
961 0 : m_formatter.prefix(PRE_OPERAND_SIZE);
962 0 : m_formatter.oneByteOp(OP_AND_EvGv, offset, base, index, scale, src);
963 0 : }
964 :
965 204 : void andl_ir(int32_t imm, RegisterID dst)
966 : {
967 204 : spew("andl $0x%x, %s", imm, GPReg32Name(dst));
968 204 : if (CAN_SIGN_EXTEND_8_32(imm)) {
969 28 : m_formatter.oneByteOp(OP_GROUP1_EvIb, dst, GROUP1_OP_AND);
970 28 : m_formatter.immediate8s(imm);
971 : } else {
972 176 : if (dst == rax)
973 125 : m_formatter.oneByteOp(OP_AND_EAXIv);
974 : else
975 51 : m_formatter.oneByteOp(OP_GROUP1_EvIz, dst, GROUP1_OP_AND);
976 176 : m_formatter.immediate32(imm);
977 : }
978 204 : }
979 :
980 0 : void andw_ir(int32_t imm, RegisterID dst)
981 : {
982 0 : spew("andw $0x%x, %s", int16_t(imm), GPReg16Name(dst));
983 0 : m_formatter.prefix(PRE_OPERAND_SIZE);
984 0 : if (CAN_SIGN_EXTEND_8_32(imm)) {
985 0 : m_formatter.oneByteOp(OP_GROUP1_EvIb, dst, GROUP1_OP_AND);
986 0 : m_formatter.immediate8s(imm);
987 : } else {
988 0 : if (dst == rax)
989 0 : m_formatter.oneByteOp(OP_AND_EAXIv);
990 : else
991 0 : m_formatter.oneByteOp(OP_GROUP1_EvIz, dst, GROUP1_OP_AND);
992 0 : m_formatter.immediate16(imm);
993 : }
994 0 : }
995 :
996 0 : void andl_im(int32_t imm, int32_t offset, RegisterID base)
997 : {
998 0 : spew("andl $0x%x, " MEM_ob, imm, ADDR_ob(offset, base));
999 0 : if (CAN_SIGN_EXTEND_8_32(imm)) {
1000 0 : m_formatter.oneByteOp(OP_GROUP1_EvIb, offset, base, GROUP1_OP_AND);
1001 0 : m_formatter.immediate8s(imm);
1002 : } else {
1003 0 : m_formatter.oneByteOp(OP_GROUP1_EvIz, offset, base, GROUP1_OP_AND);
1004 0 : m_formatter.immediate32(imm);
1005 : }
1006 0 : }
1007 :
1008 0 : void andw_im(int32_t imm, int32_t offset, RegisterID base)
1009 : {
1010 0 : spew("andw $0x%x, " MEM_ob, int16_t(imm), ADDR_ob(offset, base));
1011 0 : m_formatter.prefix(PRE_OPERAND_SIZE);
1012 0 : if (CAN_SIGN_EXTEND_8_32(imm)) {
1013 0 : m_formatter.oneByteOp(OP_GROUP1_EvIb, offset, base, GROUP1_OP_AND);
1014 0 : m_formatter.immediate8s(imm);
1015 : } else {
1016 0 : m_formatter.oneByteOp(OP_GROUP1_EvIz, offset, base, GROUP1_OP_AND);
1017 0 : m_formatter.immediate16(imm);
1018 : }
1019 0 : }
1020 :
1021 0 : void andl_im(int32_t imm, int32_t offset, RegisterID base, RegisterID index, int scale)
1022 : {
1023 0 : spew("andl $%d, " MEM_obs, imm, ADDR_obs(offset, base, index, scale));
1024 0 : if (CAN_SIGN_EXTEND_8_32(imm)) {
1025 0 : m_formatter.oneByteOp(OP_GROUP1_EvIb, offset, base, index, scale, GROUP1_OP_AND);
1026 0 : m_formatter.immediate8s(imm);
1027 : } else {
1028 0 : m_formatter.oneByteOp(OP_GROUP1_EvIz, offset, base, index, scale, GROUP1_OP_AND);
1029 0 : m_formatter.immediate32(imm);
1030 : }
1031 0 : }
1032 :
1033 0 : void andw_im(int32_t imm, int32_t offset, RegisterID base, RegisterID index, int scale)
1034 : {
1035 0 : spew("andw $%d, " MEM_obs, int16_t(imm), ADDR_obs(offset, base, index, scale));
1036 0 : m_formatter.prefix(PRE_OPERAND_SIZE);
1037 0 : if (CAN_SIGN_EXTEND_8_32(imm)) {
1038 0 : m_formatter.oneByteOp(OP_GROUP1_EvIb, offset, base, index, scale, GROUP1_OP_AND);
1039 0 : m_formatter.immediate8s(imm);
1040 : } else {
1041 0 : m_formatter.oneByteOp(OP_GROUP1_EvIz, offset, base, index, scale, GROUP1_OP_AND);
1042 0 : m_formatter.immediate16(imm);
1043 : }
1044 0 : }
1045 :
1046 : void fld_m(int32_t offset, RegisterID base)
1047 : {
1048 : spew("fld " MEM_ob, ADDR_ob(offset, base));
1049 : m_formatter.oneByteOp(OP_FPU6, offset, base, FPU6_OP_FLD);
1050 : }
1051 : void fld32_m(int32_t offset, RegisterID base)
1052 : {
1053 : spew("fld " MEM_ob, ADDR_ob(offset, base));
1054 : m_formatter.oneByteOp(OP_FPU6_F32, offset, base, FPU6_OP_FLD);
1055 : }
1056 : void faddp()
1057 : {
1058 : spew("addp ");
1059 : m_formatter.oneByteOp(OP_FPU6_ADDP);
1060 : m_formatter.oneByteOp(OP_ADDP_ST0_ST1);
1061 : }
1062 : void fisttp_m(int32_t offset, RegisterID base)
1063 : {
1064 : spew("fisttp " MEM_ob, ADDR_ob(offset, base));
1065 : m_formatter.oneByteOp(OP_FPU6, offset, base, FPU6_OP_FISTTP);
1066 : }
1067 : void fistp_m(int32_t offset, RegisterID base)
1068 : {
1069 : spew("fistp " MEM_ob, ADDR_ob(offset, base));
1070 : m_formatter.oneByteOp(OP_FILD, offset, base, FPU6_OP_FISTP);
1071 : }
1072 : void fstp_m(int32_t offset, RegisterID base)
1073 : {
1074 : spew("fstp " MEM_ob, ADDR_ob(offset, base));
1075 : m_formatter.oneByteOp(OP_FPU6, offset, base, FPU6_OP_FSTP);
1076 : }
1077 : void fstp32_m(int32_t offset, RegisterID base)
1078 : {
1079 : spew("fstp32 " MEM_ob, ADDR_ob(offset, base));
1080 : m_formatter.oneByteOp(OP_FPU6_F32, offset, base, FPU6_OP_FSTP);
1081 : }
1082 : void fnstcw_m(int32_t offset, RegisterID base)
1083 : {
1084 : spew("fnstcw " MEM_ob, ADDR_ob(offset, base));
1085 : m_formatter.oneByteOp(OP_FPU6_F32, offset, base, FPU6_OP_FISTP);
1086 : }
1087 : void fldcw_m(int32_t offset, RegisterID base)
1088 : {
1089 : spew("fldcw " MEM_ob, ADDR_ob(offset, base));
1090 : m_formatter.oneByteOp(OP_FPU6_F32, offset, base, FPU6_OP_FLDCW);
1091 : }
1092 : void fnstsw_m(int32_t offset, RegisterID base)
1093 : {
1094 : spew("fnstsw " MEM_ob, ADDR_ob(offset, base));
1095 : m_formatter.oneByteOp(OP_FPU6, offset, base, FPU6_OP_FISTP);
1096 : }
1097 :
1098 0 : void negl_r(RegisterID dst)
1099 : {
1100 0 : spew("negl %s", GPReg32Name(dst));
1101 0 : m_formatter.oneByteOp(OP_GROUP3_Ev, dst, GROUP3_OP_NEG);
1102 0 : }
1103 :
1104 0 : void negl_m(int32_t offset, RegisterID base)
1105 : {
1106 0 : spew("negl " MEM_ob, ADDR_ob(offset, base));
1107 0 : m_formatter.oneByteOp(OP_GROUP3_Ev, offset, base, GROUP3_OP_NEG);
1108 0 : }
1109 :
1110 1 : void notl_r(RegisterID dst)
1111 : {
1112 1 : spew("notl %s", GPReg32Name(dst));
1113 1 : m_formatter.oneByteOp(OP_GROUP3_Ev, dst, GROUP3_OP_NOT);
1114 1 : }
1115 :
1116 0 : void notl_m(int32_t offset, RegisterID base)
1117 : {
1118 0 : spew("notl " MEM_ob, ADDR_ob(offset, base));
1119 0 : m_formatter.oneByteOp(OP_GROUP3_Ev, offset, base, GROUP3_OP_NOT);
1120 0 : }
1121 :
1122 0 : void orl_rr(RegisterID src, RegisterID dst)
1123 : {
1124 0 : spew("orl %s, %s", GPReg32Name(src), GPReg32Name(dst));
1125 0 : m_formatter.oneByteOp(OP_OR_GvEv, src, dst);
1126 0 : }
1127 :
1128 0 : void orw_rr(RegisterID src, RegisterID dst)
1129 : {
1130 0 : spew("orw %s, %s", GPReg16Name(src), GPReg16Name(dst));
1131 0 : m_formatter.prefix(PRE_OPERAND_SIZE);
1132 0 : m_formatter.oneByteOp(OP_OR_GvEv, src, dst);
1133 0 : }
1134 :
1135 0 : void orl_mr(int32_t offset, RegisterID base, RegisterID dst)
1136 : {
1137 0 : spew("orl " MEM_ob ", %s", ADDR_ob(offset, base), GPReg32Name(dst));
1138 0 : m_formatter.oneByteOp(OP_OR_GvEv, offset, base, dst);
1139 0 : }
1140 :
1141 0 : void orl_rm(RegisterID src, int32_t offset, RegisterID base)
1142 : {
1143 0 : spew("orl %s, " MEM_ob, GPReg32Name(src), ADDR_ob(offset, base));
1144 0 : m_formatter.oneByteOp(OP_OR_EvGv, offset, base, src);
1145 0 : }
1146 :
1147 0 : void orw_rm(RegisterID src, int32_t offset, RegisterID base)
1148 : {
1149 0 : spew("orw %s, " MEM_ob, GPReg16Name(src), ADDR_ob(offset, base));
1150 0 : m_formatter.prefix(PRE_OPERAND_SIZE);
1151 0 : m_formatter.oneByteOp(OP_OR_EvGv, offset, base, src);
1152 0 : }
1153 :
1154 0 : void orl_rm(RegisterID src, int32_t offset, RegisterID base, RegisterID index, int scale)
1155 : {
1156 0 : spew("orl %s, " MEM_obs, GPReg32Name(src), ADDR_obs(offset, base, index, scale));
1157 0 : m_formatter.oneByteOp(OP_OR_EvGv, offset, base, index, scale, src);
1158 0 : }
1159 :
1160 0 : void orw_rm(RegisterID src, int32_t offset, RegisterID base, RegisterID index, int scale)
1161 : {
1162 0 : spew("orw %s, " MEM_obs, GPReg16Name(src), ADDR_obs(offset, base, index, scale));
1163 0 : m_formatter.prefix(PRE_OPERAND_SIZE);
1164 0 : m_formatter.oneByteOp(OP_OR_EvGv, offset, base, index, scale, src);
1165 0 : }
1166 :
1167 0 : void orl_ir(int32_t imm, RegisterID dst)
1168 : {
1169 0 : spew("orl $0x%x, %s", imm, GPReg32Name(dst));
1170 0 : if (CAN_SIGN_EXTEND_8_32(imm)) {
1171 0 : m_formatter.oneByteOp(OP_GROUP1_EvIb, dst, GROUP1_OP_OR);
1172 0 : m_formatter.immediate8s(imm);
1173 : } else {
1174 0 : if (dst == rax)
1175 0 : m_formatter.oneByteOp(OP_OR_EAXIv);
1176 : else
1177 0 : m_formatter.oneByteOp(OP_GROUP1_EvIz, dst, GROUP1_OP_OR);
1178 0 : m_formatter.immediate32(imm);
1179 : }
1180 0 : }
1181 :
1182 0 : void orw_ir(int32_t imm, RegisterID dst)
1183 : {
1184 0 : spew("orw $0x%x, %s", int16_t(imm), GPReg16Name(dst));
1185 0 : m_formatter.prefix(PRE_OPERAND_SIZE);
1186 0 : if (CAN_SIGN_EXTEND_8_32(imm)) {
1187 0 : m_formatter.oneByteOp(OP_GROUP1_EvIb, dst, GROUP1_OP_OR);
1188 0 : m_formatter.immediate8s(imm);
1189 : } else {
1190 0 : if (dst == rax)
1191 0 : m_formatter.oneByteOp(OP_OR_EAXIv);
1192 : else
1193 0 : m_formatter.oneByteOp(OP_GROUP1_EvIz, dst, GROUP1_OP_OR);
1194 0 : m_formatter.immediate16(imm);
1195 : }
1196 0 : }
1197 :
1198 185 : void orl_im(int32_t imm, int32_t offset, RegisterID base)
1199 : {
1200 185 : spew("orl $0x%x, " MEM_ob, imm, ADDR_ob(offset, base));
1201 185 : if (CAN_SIGN_EXTEND_8_32(imm)) {
1202 185 : m_formatter.oneByteOp(OP_GROUP1_EvIb, offset, base, GROUP1_OP_OR);
1203 185 : m_formatter.immediate8s(imm);
1204 : } else {
1205 0 : m_formatter.oneByteOp(OP_GROUP1_EvIz, offset, base, GROUP1_OP_OR);
1206 0 : m_formatter.immediate32(imm);
1207 : }
1208 185 : }
1209 :
1210 0 : void orw_im(int32_t imm, int32_t offset, RegisterID base)
1211 : {
1212 0 : spew("orw $0x%x, " MEM_ob, int16_t(imm), ADDR_ob(offset, base));
1213 0 : m_formatter.prefix(PRE_OPERAND_SIZE);
1214 0 : if (CAN_SIGN_EXTEND_8_32(imm)) {
1215 0 : m_formatter.oneByteOp(OP_GROUP1_EvIb, offset, base, GROUP1_OP_OR);
1216 0 : m_formatter.immediate8s(imm);
1217 : } else {
1218 0 : m_formatter.oneByteOp(OP_GROUP1_EvIz, offset, base, GROUP1_OP_OR);
1219 0 : m_formatter.immediate16(imm);
1220 : }
1221 0 : }
1222 :
1223 0 : void orl_im(int32_t imm, int32_t offset, RegisterID base, RegisterID index, int scale)
1224 : {
1225 0 : spew("orl $%d, " MEM_obs, imm, ADDR_obs(offset, base, index, scale));
1226 0 : if (CAN_SIGN_EXTEND_8_32(imm)) {
1227 0 : m_formatter.oneByteOp(OP_GROUP1_EvIb, offset, base, index, scale, GROUP1_OP_OR);
1228 0 : m_formatter.immediate8s(imm);
1229 : } else {
1230 0 : m_formatter.oneByteOp(OP_GROUP1_EvIz, offset, base, index, scale, GROUP1_OP_OR);
1231 0 : m_formatter.immediate32(imm);
1232 : }
1233 0 : }
1234 :
1235 0 : void orw_im(int32_t imm, int32_t offset, RegisterID base, RegisterID index, int scale)
1236 : {
1237 0 : spew("orw $%d, " MEM_obs, int16_t(imm), ADDR_obs(offset, base, index, scale));
1238 0 : m_formatter.prefix(PRE_OPERAND_SIZE);
1239 0 : if (CAN_SIGN_EXTEND_8_32(imm)) {
1240 0 : m_formatter.oneByteOp(OP_GROUP1_EvIb, offset, base, index, scale, GROUP1_OP_OR);
1241 0 : m_formatter.immediate8s(imm);
1242 : } else {
1243 0 : m_formatter.oneByteOp(OP_GROUP1_EvIz, offset, base, index, scale, GROUP1_OP_OR);
1244 0 : m_formatter.immediate16(imm);
1245 : }
1246 0 : }
1247 :
1248 15 : void subl_rr(RegisterID src, RegisterID dst)
1249 : {
1250 15 : spew("subl %s, %s", GPReg32Name(src), GPReg32Name(dst));
1251 15 : m_formatter.oneByteOp(OP_SUB_GvEv, src, dst);
1252 15 : }
1253 :
1254 0 : void subw_rr(RegisterID src, RegisterID dst)
1255 : {
1256 0 : spew("subw %s, %s", GPReg16Name(src), GPReg16Name(dst));
1257 0 : m_formatter.prefix(PRE_OPERAND_SIZE);
1258 0 : m_formatter.oneByteOp(OP_SUB_GvEv, src, dst);
1259 0 : }
1260 :
1261 0 : void subl_mr(int32_t offset, RegisterID base, RegisterID dst)
1262 : {
1263 0 : spew("subl " MEM_ob ", %s", ADDR_ob(offset, base), GPReg32Name(dst));
1264 0 : m_formatter.oneByteOp(OP_SUB_GvEv, offset, base, dst);
1265 0 : }
1266 :
1267 0 : void subl_rm(RegisterID src, int32_t offset, RegisterID base)
1268 : {
1269 0 : spew("subl %s, " MEM_ob, GPReg32Name(src), ADDR_ob(offset, base));
1270 0 : m_formatter.oneByteOp(OP_SUB_EvGv, offset, base, src);
1271 0 : }
1272 :
1273 0 : void subw_rm(RegisterID src, int32_t offset, RegisterID base)
1274 : {
1275 0 : spew("subw %s, " MEM_ob, GPReg16Name(src), ADDR_ob(offset, base));
1276 0 : m_formatter.prefix(PRE_OPERAND_SIZE);
1277 0 : m_formatter.oneByteOp(OP_SUB_EvGv, offset, base, src);
1278 0 : }
1279 :
1280 0 : void subl_rm(RegisterID src, int32_t offset, RegisterID base, RegisterID index, int scale)
1281 : {
1282 0 : spew("subl %s, " MEM_obs, GPReg32Name(src), ADDR_obs(offset, base, index, scale));
1283 0 : m_formatter.oneByteOp(OP_SUB_EvGv, offset, base, index, scale, src);
1284 0 : }
1285 :
1286 0 : void subw_rm(RegisterID src, int32_t offset, RegisterID base, RegisterID index, int scale)
1287 : {
1288 0 : spew("subw %s, " MEM_obs, GPReg16Name(src), ADDR_obs(offset, base, index, scale));
1289 0 : m_formatter.prefix(PRE_OPERAND_SIZE);
1290 0 : m_formatter.oneByteOp(OP_SUB_EvGv, offset, base, index, scale, src);
1291 0 : }
1292 :
1293 663 : void subl_ir(int32_t imm, RegisterID dst)
1294 : {
1295 663 : spew("subl $%d, %s", imm, GPReg32Name(dst));
1296 663 : if (CAN_SIGN_EXTEND_8_32(imm)) {
1297 663 : m_formatter.oneByteOp(OP_GROUP1_EvIb, dst, GROUP1_OP_SUB);
1298 663 : m_formatter.immediate8s(imm);
1299 : } else {
1300 0 : if (dst == rax)
1301 0 : m_formatter.oneByteOp(OP_SUB_EAXIv);
1302 : else
1303 0 : m_formatter.oneByteOp(OP_GROUP1_EvIz, dst, GROUP1_OP_SUB);
1304 0 : m_formatter.immediate32(imm);
1305 : }
1306 663 : }
1307 :
1308 0 : void subw_ir(int32_t imm, RegisterID dst)
1309 : {
1310 0 : spew("subw $%d, %s", int16_t(imm), GPReg16Name(dst));
1311 0 : m_formatter.prefix(PRE_OPERAND_SIZE);
1312 0 : if (CAN_SIGN_EXTEND_8_32(imm)) {
1313 0 : m_formatter.oneByteOp(OP_GROUP1_EvIb, dst, GROUP1_OP_SUB);
1314 0 : m_formatter.immediate8s(imm);
1315 : } else {
1316 0 : if (dst == rax)
1317 0 : m_formatter.oneByteOp(OP_SUB_EAXIv);
1318 : else
1319 0 : m_formatter.oneByteOp(OP_GROUP1_EvIz, dst, GROUP1_OP_SUB);
1320 0 : m_formatter.immediate16(imm);
1321 : }
1322 0 : }
1323 :
1324 0 : void subl_im(int32_t imm, int32_t offset, RegisterID base)
1325 : {
1326 0 : spew("subl $%d, " MEM_ob, imm, ADDR_ob(offset, base));
1327 0 : if (CAN_SIGN_EXTEND_8_32(imm)) {
1328 0 : m_formatter.oneByteOp(OP_GROUP1_EvIb, offset, base, GROUP1_OP_SUB);
1329 0 : m_formatter.immediate8s(imm);
1330 : } else {
1331 0 : m_formatter.oneByteOp(OP_GROUP1_EvIz, offset, base, GROUP1_OP_SUB);
1332 0 : m_formatter.immediate32(imm);
1333 : }
1334 0 : }
1335 :
1336 0 : void subw_im(int32_t imm, int32_t offset, RegisterID base)
1337 : {
1338 0 : spew("subw $%d, " MEM_ob, int16_t(imm), ADDR_ob(offset, base));
1339 0 : m_formatter.prefix(PRE_OPERAND_SIZE);
1340 0 : if (CAN_SIGN_EXTEND_8_32(imm)) {
1341 0 : m_formatter.oneByteOp(OP_GROUP1_EvIb, offset, base, GROUP1_OP_SUB);
1342 0 : m_formatter.immediate8s(imm);
1343 : } else {
1344 0 : m_formatter.oneByteOp(OP_GROUP1_EvIz, offset, base, GROUP1_OP_SUB);
1345 0 : m_formatter.immediate16(imm);
1346 : }
1347 0 : }
1348 :
1349 0 : void subl_im(int32_t imm, int32_t offset, RegisterID base, RegisterID index, int scale)
1350 : {
1351 0 : spew("subl $%d, " MEM_obs, imm, ADDR_obs(offset, base, index, scale));
1352 0 : if (CAN_SIGN_EXTEND_8_32(imm)) {
1353 0 : m_formatter.oneByteOp(OP_GROUP1_EvIb, offset, base, index, scale, GROUP1_OP_SUB);
1354 0 : m_formatter.immediate8s(imm);
1355 : } else {
1356 0 : m_formatter.oneByteOp(OP_GROUP1_EvIz, offset, base, index, scale, GROUP1_OP_SUB);
1357 0 : m_formatter.immediate32(imm);
1358 : }
1359 0 : }
1360 :
1361 0 : void subw_im(int32_t imm, int32_t offset, RegisterID base, RegisterID index, int scale)
1362 : {
1363 0 : spew("subw $%d, " MEM_obs, int16_t(imm), ADDR_obs(offset, base, index, scale));
1364 0 : m_formatter.prefix(PRE_OPERAND_SIZE);
1365 0 : if (CAN_SIGN_EXTEND_8_32(imm)) {
1366 0 : m_formatter.oneByteOp(OP_GROUP1_EvIb, offset, base, index, scale, GROUP1_OP_SUB);
1367 0 : m_formatter.immediate8s(imm);
1368 : } else {
1369 0 : m_formatter.oneByteOp(OP_GROUP1_EvIz, offset, base, index, scale, GROUP1_OP_SUB);
1370 0 : m_formatter.immediate16(imm);
1371 : }
1372 0 : }
1373 :
1374 1199 : void xorl_rr(RegisterID src, RegisterID dst)
1375 : {
1376 1199 : spew("xorl %s, %s", GPReg32Name(src), GPReg32Name(dst));
1377 1199 : m_formatter.oneByteOp(OP_XOR_GvEv, src, dst);
1378 1199 : }
1379 :
1380 0 : void xorw_rr(RegisterID src, RegisterID dst)
1381 : {
1382 0 : spew("xorw %s, %s", GPReg16Name(src), GPReg16Name(dst));
1383 0 : m_formatter.prefix(PRE_OPERAND_SIZE);
1384 0 : m_formatter.oneByteOp(OP_XOR_GvEv, src, dst);
1385 0 : }
1386 :
1387 0 : void xorl_mr(int32_t offset, RegisterID base, RegisterID dst)
1388 : {
1389 0 : spew("xorl " MEM_ob ", %s", ADDR_ob(offset, base), GPReg32Name(dst));
1390 0 : m_formatter.oneByteOp(OP_XOR_GvEv, offset, base, dst);
1391 0 : }
1392 :
1393 0 : void xorl_rm(RegisterID src, int32_t offset, RegisterID base)
1394 : {
1395 0 : spew("xorl %s, " MEM_ob, GPReg32Name(src), ADDR_ob(offset, base));
1396 0 : m_formatter.oneByteOp(OP_XOR_EvGv, offset, base, src);
1397 0 : }
1398 :
1399 0 : void xorw_rm(RegisterID src, int32_t offset, RegisterID base)
1400 : {
1401 0 : spew("xorw %s, " MEM_ob, GPReg16Name(src), ADDR_ob(offset, base));
1402 0 : m_formatter.prefix(PRE_OPERAND_SIZE);
1403 0 : m_formatter.oneByteOp(OP_XOR_EvGv, offset, base, src);
1404 0 : }
1405 :
1406 0 : void xorl_rm(RegisterID src, int32_t offset, RegisterID base, RegisterID index, int scale)
1407 : {
1408 0 : spew("xorl %s, " MEM_obs, GPReg32Name(src), ADDR_obs(offset, base, index, scale));
1409 0 : m_formatter.oneByteOp(OP_XOR_EvGv, offset, base, index, scale, src);
1410 0 : }
1411 :
1412 0 : void xorw_rm(RegisterID src, int32_t offset, RegisterID base, RegisterID index, int scale)
1413 : {
1414 0 : spew("xorw %s, " MEM_obs, GPReg16Name(src), ADDR_obs(offset, base, index, scale));
1415 0 : m_formatter.prefix(PRE_OPERAND_SIZE);
1416 0 : m_formatter.oneByteOp(OP_XOR_EvGv, offset, base, index, scale, src);
1417 0 : }
1418 :
1419 0 : void xorl_im(int32_t imm, int32_t offset, RegisterID base)
1420 : {
1421 0 : spew("xorl $0x%x, " MEM_ob, imm, ADDR_ob(offset, base));
1422 0 : if (CAN_SIGN_EXTEND_8_32(imm)) {
1423 0 : m_formatter.oneByteOp(OP_GROUP1_EvIb, offset, base, GROUP1_OP_XOR);
1424 0 : m_formatter.immediate8s(imm);
1425 : } else {
1426 0 : m_formatter.oneByteOp(OP_GROUP1_EvIz, offset, base, GROUP1_OP_XOR);
1427 0 : m_formatter.immediate32(imm);
1428 : }
1429 0 : }
1430 :
1431 0 : void xorw_im(int32_t imm, int32_t offset, RegisterID base)
1432 : {
1433 0 : spew("xorw $0x%x, " MEM_ob, int16_t(imm), ADDR_ob(offset, base));
1434 0 : m_formatter.prefix(PRE_OPERAND_SIZE);
1435 0 : if (CAN_SIGN_EXTEND_8_32(imm)) {
1436 0 : m_formatter.oneByteOp(OP_GROUP1_EvIb, offset, base, GROUP1_OP_XOR);
1437 0 : m_formatter.immediate8s(imm);
1438 : } else {
1439 0 : m_formatter.oneByteOp(OP_GROUP1_EvIz, offset, base, GROUP1_OP_XOR);
1440 0 : m_formatter.immediate16(imm);
1441 : }
1442 0 : }
1443 :
1444 0 : void xorl_im(int32_t imm, int32_t offset, RegisterID base, RegisterID index, int scale)
1445 : {
1446 0 : spew("xorl $%d, " MEM_obs, imm, ADDR_obs(offset, base, index, scale));
1447 0 : if (CAN_SIGN_EXTEND_8_32(imm)) {
1448 0 : m_formatter.oneByteOp(OP_GROUP1_EvIb, offset, base, index, scale, GROUP1_OP_XOR);
1449 0 : m_formatter.immediate8s(imm);
1450 : } else {
1451 0 : m_formatter.oneByteOp(OP_GROUP1_EvIz, offset, base, index, scale, GROUP1_OP_XOR);
1452 0 : m_formatter.immediate32(imm);
1453 : }
1454 0 : }
1455 :
1456 0 : void xorw_im(int32_t imm, int32_t offset, RegisterID base, RegisterID index, int scale)
1457 : {
1458 0 : spew("xorw $%d, " MEM_obs, int16_t(imm), ADDR_obs(offset, base, index, scale));
1459 0 : m_formatter.prefix(PRE_OPERAND_SIZE);
1460 0 : if (CAN_SIGN_EXTEND_8_32(imm)) {
1461 0 : m_formatter.oneByteOp(OP_GROUP1_EvIb, offset, base, index, scale, GROUP1_OP_XOR);
1462 0 : m_formatter.immediate8s(imm);
1463 : } else {
1464 0 : m_formatter.oneByteOp(OP_GROUP1_EvIz, offset, base, index, scale, GROUP1_OP_XOR);
1465 0 : m_formatter.immediate16(imm);
1466 : }
1467 0 : }
1468 :
1469 37 : void xorl_ir(int32_t imm, RegisterID dst)
1470 : {
1471 37 : spew("xorl $%d, %s", imm, GPReg32Name(dst));
1472 37 : if (CAN_SIGN_EXTEND_8_32(imm)) {
1473 37 : m_formatter.oneByteOp(OP_GROUP1_EvIb, dst, GROUP1_OP_XOR);
1474 37 : m_formatter.immediate8s(imm);
1475 : } else {
1476 0 : if (dst == rax)
1477 0 : m_formatter.oneByteOp(OP_XOR_EAXIv);
1478 : else
1479 0 : m_formatter.oneByteOp(OP_GROUP1_EvIz, dst, GROUP1_OP_XOR);
1480 0 : m_formatter.immediate32(imm);
1481 : }
1482 37 : }
1483 :
1484 0 : void xorw_ir(int32_t imm, RegisterID dst)
1485 : {
1486 0 : spew("xorw $%d, %s", int16_t(imm), GPReg16Name(dst));
1487 0 : m_formatter.prefix(PRE_OPERAND_SIZE);
1488 0 : if (CAN_SIGN_EXTEND_8_32(imm)) {
1489 0 : m_formatter.oneByteOp(OP_GROUP1_EvIb, dst, GROUP1_OP_XOR);
1490 0 : m_formatter.immediate8s(imm);
1491 : } else {
1492 0 : if (dst == rax)
1493 0 : m_formatter.oneByteOp(OP_XOR_EAXIv);
1494 : else
1495 0 : m_formatter.oneByteOp(OP_GROUP1_EvIz, dst, GROUP1_OP_XOR);
1496 0 : m_formatter.immediate16(imm);
1497 : }
1498 0 : }
1499 :
1500 0 : void sarl_ir(int32_t imm, RegisterID dst)
1501 : {
1502 0 : MOZ_ASSERT(imm < 32);
1503 0 : spew("sarl $%d, %s", imm, GPReg32Name(dst));
1504 0 : if (imm == 1)
1505 0 : m_formatter.oneByteOp(OP_GROUP2_Ev1, dst, GROUP2_OP_SAR);
1506 : else {
1507 0 : m_formatter.oneByteOp(OP_GROUP2_EvIb, dst, GROUP2_OP_SAR);
1508 0 : m_formatter.immediate8u(imm);
1509 : }
1510 0 : }
1511 :
1512 0 : void sarl_CLr(RegisterID dst)
1513 : {
1514 0 : spew("sarl %%cl, %s", GPReg32Name(dst));
1515 0 : m_formatter.oneByteOp(OP_GROUP2_EvCL, dst, GROUP2_OP_SAR);
1516 0 : }
1517 :
1518 2 : void shrl_ir(int32_t imm, RegisterID dst)
1519 : {
1520 2 : MOZ_ASSERT(imm < 32);
1521 2 : spew("shrl $%d, %s", imm, GPReg32Name(dst));
1522 2 : if (imm == 1)
1523 0 : m_formatter.oneByteOp(OP_GROUP2_Ev1, dst, GROUP2_OP_SHR);
1524 : else {
1525 2 : m_formatter.oneByteOp(OP_GROUP2_EvIb, dst, GROUP2_OP_SHR);
1526 2 : m_formatter.immediate8u(imm);
1527 : }
1528 2 : }
1529 :
1530 0 : void shrl_CLr(RegisterID dst)
1531 : {
1532 0 : spew("shrl %%cl, %s", GPReg32Name(dst));
1533 0 : m_formatter.oneByteOp(OP_GROUP2_EvCL, dst, GROUP2_OP_SHR);
1534 0 : }
1535 :
1536 : void shrdl_CLr(RegisterID src, RegisterID dst)
1537 : {
1538 : spew("shrdl %%cl, %s, %s", GPReg32Name(src), GPReg32Name(dst));
1539 : m_formatter.twoByteOp(OP2_SHRD_GvEv, dst, src);
1540 : }
1541 :
1542 : void shldl_CLr(RegisterID src, RegisterID dst)
1543 : {
1544 : spew("shldl %%cl, %s, %s", GPReg32Name(src), GPReg32Name(dst));
1545 : m_formatter.twoByteOp(OP2_SHLD_GvEv, dst, src);
1546 : }
1547 :
1548 12 : void shll_ir(int32_t imm, RegisterID dst)
1549 : {
1550 12 : MOZ_ASSERT(imm < 32);
1551 12 : spew("shll $%d, %s", imm, GPReg32Name(dst));
1552 12 : if (imm == 1)
1553 0 : m_formatter.oneByteOp(OP_GROUP2_Ev1, dst, GROUP2_OP_SHL);
1554 : else {
1555 12 : m_formatter.oneByteOp(OP_GROUP2_EvIb, dst, GROUP2_OP_SHL);
1556 12 : m_formatter.immediate8u(imm);
1557 : }
1558 12 : }
1559 :
1560 0 : void shll_CLr(RegisterID dst)
1561 : {
1562 0 : spew("shll %%cl, %s", GPReg32Name(dst));
1563 0 : m_formatter.oneByteOp(OP_GROUP2_EvCL, dst, GROUP2_OP_SHL);
1564 0 : }
1565 :
1566 0 : void roll_ir(int32_t imm, RegisterID dst)
1567 : {
1568 0 : MOZ_ASSERT(imm < 32);
1569 0 : spew("roll $%d, %s", imm, GPReg32Name(dst));
1570 0 : if (imm == 1)
1571 0 : m_formatter.oneByteOp(OP_GROUP2_Ev1, dst, GROUP2_OP_ROL);
1572 : else {
1573 0 : m_formatter.oneByteOp(OP_GROUP2_EvIb, dst, GROUP2_OP_ROL);
1574 0 : m_formatter.immediate8u(imm);
1575 : }
1576 0 : }
1577 0 : void roll_CLr(RegisterID dst)
1578 : {
1579 0 : spew("roll %%cl, %s", GPReg32Name(dst));
1580 0 : m_formatter.oneByteOp(OP_GROUP2_EvCL, dst, GROUP2_OP_ROL);
1581 0 : }
1582 :
1583 0 : void rorl_ir(int32_t imm, RegisterID dst)
1584 : {
1585 0 : MOZ_ASSERT(imm < 32);
1586 0 : spew("rorl $%d, %s", imm, GPReg32Name(dst));
1587 0 : if (imm == 1)
1588 0 : m_formatter.oneByteOp(OP_GROUP2_Ev1, dst, GROUP2_OP_ROR);
1589 : else {
1590 0 : m_formatter.oneByteOp(OP_GROUP2_EvIb, dst, GROUP2_OP_ROR);
1591 0 : m_formatter.immediate8u(imm);
1592 : }
1593 0 : }
1594 0 : void rorl_CLr(RegisterID dst)
1595 : {
1596 0 : spew("rorl %%cl, %s", GPReg32Name(dst));
1597 0 : m_formatter.oneByteOp(OP_GROUP2_EvCL, dst, GROUP2_OP_ROR);
1598 0 : }
1599 :
1600 0 : void bsrl_rr(RegisterID src, RegisterID dst)
1601 : {
1602 0 : spew("bsrl %s, %s", GPReg32Name(src), GPReg32Name(dst));
1603 0 : m_formatter.twoByteOp(OP2_BSR_GvEv, src, dst);
1604 0 : }
1605 :
1606 0 : void bsfl_rr(RegisterID src, RegisterID dst)
1607 : {
1608 0 : spew("bsfl %s, %s", GPReg32Name(src), GPReg32Name(dst));
1609 0 : m_formatter.twoByteOp(OP2_BSF_GvEv, src, dst);
1610 0 : }
1611 :
1612 0 : void popcntl_rr(RegisterID src, RegisterID dst)
1613 : {
1614 0 : spew("popcntl %s, %s", GPReg32Name(src), GPReg32Name(dst));
1615 0 : m_formatter.legacySSEPrefix(VEX_SS);
1616 0 : m_formatter.twoByteOp(OP2_POPCNT_GvEv, src, dst);
1617 0 : }
1618 :
1619 0 : void imull_rr(RegisterID src, RegisterID dst)
1620 : {
1621 0 : spew("imull %s, %s", GPReg32Name(src), GPReg32Name(dst));
1622 0 : m_formatter.twoByteOp(OP2_IMUL_GvEv, src, dst);
1623 0 : }
1624 :
1625 0 : void imull_r(RegisterID multiplier)
1626 : {
1627 0 : spew("imull %s", GPReg32Name(multiplier));
1628 0 : m_formatter.oneByteOp(OP_GROUP3_Ev, multiplier, GROUP3_OP_IMUL);
1629 0 : }
1630 :
1631 0 : void imull_mr(int32_t offset, RegisterID base, RegisterID dst)
1632 : {
1633 0 : spew("imull " MEM_ob ", %s", ADDR_ob(offset, base), GPReg32Name(dst));
1634 0 : m_formatter.twoByteOp(OP2_IMUL_GvEv, offset, base, dst);
1635 0 : }
1636 :
1637 0 : void imull_ir(int32_t value, RegisterID src, RegisterID dst)
1638 : {
1639 0 : spew("imull $%d, %s, %s", value, GPReg32Name(src), GPReg32Name(dst));
1640 0 : if (CAN_SIGN_EXTEND_8_32(value)) {
1641 0 : m_formatter.oneByteOp(OP_IMUL_GvEvIb, src, dst);
1642 0 : m_formatter.immediate8s(value);
1643 : } else {
1644 0 : m_formatter.oneByteOp(OP_IMUL_GvEvIz, src, dst);
1645 0 : m_formatter.immediate32(value);
1646 : }
1647 0 : }
1648 :
1649 0 : void mull_r(RegisterID multiplier)
1650 : {
1651 0 : spew("mull %s", GPReg32Name(multiplier));
1652 0 : m_formatter.oneByteOp(OP_GROUP3_Ev, multiplier, GROUP3_OP_MUL);
1653 0 : }
1654 :
1655 0 : void idivl_r(RegisterID divisor)
1656 : {
1657 0 : spew("idivl %s", GPReg32Name(divisor));
1658 0 : m_formatter.oneByteOp(OP_GROUP3_Ev, divisor, GROUP3_OP_IDIV);
1659 0 : }
1660 :
1661 0 : void divl_r(RegisterID divisor)
1662 : {
1663 0 : spew("div %s", GPReg32Name(divisor));
1664 0 : m_formatter.oneByteOp(OP_GROUP3_Ev, divisor, GROUP3_OP_DIV);
1665 0 : }
1666 :
1667 0 : void prefix_lock()
1668 : {
1669 0 : spew("lock");
1670 0 : m_formatter.oneByteOp(PRE_LOCK);
1671 0 : }
1672 :
1673 0 : void prefix_16_for_32()
1674 : {
1675 0 : m_formatter.prefix(PRE_OPERAND_SIZE);
1676 0 : }
1677 :
1678 : void incl_m32(int32_t offset, RegisterID base)
1679 : {
1680 : spew("incl " MEM_ob, ADDR_ob(offset, base));
1681 : m_formatter.oneByteOp(OP_GROUP5_Ev, offset, base, GROUP5_OP_INC);
1682 : }
1683 :
1684 : void decl_m32(int32_t offset, RegisterID base)
1685 : {
1686 : spew("decl " MEM_ob, ADDR_ob(offset, base));
1687 : m_formatter.oneByteOp(OP_GROUP5_Ev, offset, base, GROUP5_OP_DEC);
1688 : }
1689 :
1690 : // Note that CMPXCHG performs comparison against REG = %al/%ax/%eax/%rax.
1691 : // If %REG == [%base+offset], then %src -> [%base+offset].
1692 : // Otherwise, [%base+offset] -> %REG.
1693 : // For the 8-bit operations src must also be an 8-bit register.
1694 :
1695 0 : void cmpxchgb(RegisterID src, int32_t offset, RegisterID base)
1696 : {
1697 0 : spew("cmpxchgb %s, " MEM_ob, GPReg8Name(src), ADDR_ob(offset, base));
1698 0 : m_formatter.twoByteOp8(OP2_CMPXCHG_GvEb, offset, base, src);
1699 0 : }
1700 0 : void cmpxchgb(RegisterID src, int32_t offset, RegisterID base, RegisterID index, int scale)
1701 : {
1702 0 : spew("cmpxchgb %s, " MEM_obs, GPReg8Name(src), ADDR_obs(offset, base, index, scale));
1703 0 : m_formatter.twoByteOp8(OP2_CMPXCHG_GvEb, offset, base, index, scale, src);
1704 0 : }
1705 0 : void cmpxchgw(RegisterID src, int32_t offset, RegisterID base)
1706 : {
1707 0 : spew("cmpxchgw %s, " MEM_ob, GPReg16Name(src), ADDR_ob(offset, base));
1708 0 : m_formatter.prefix(PRE_OPERAND_SIZE);
1709 0 : m_formatter.twoByteOp(OP2_CMPXCHG_GvEw, offset, base, src);
1710 0 : }
1711 0 : void cmpxchgw(RegisterID src, int32_t offset, RegisterID base, RegisterID index, int scale)
1712 : {
1713 0 : spew("cmpxchgw %s, " MEM_obs, GPReg16Name(src), ADDR_obs(offset, base, index, scale));
1714 0 : m_formatter.prefix(PRE_OPERAND_SIZE);
1715 0 : m_formatter.twoByteOp(OP2_CMPXCHG_GvEw, offset, base, index, scale, src);
1716 0 : }
1717 0 : void cmpxchgl(RegisterID src, int32_t offset, RegisterID base)
1718 : {
1719 0 : spew("cmpxchgl %s, " MEM_ob, GPReg32Name(src), ADDR_ob(offset, base));
1720 0 : m_formatter.twoByteOp(OP2_CMPXCHG_GvEw, offset, base, src);
1721 0 : }
1722 0 : void cmpxchgl(RegisterID src, int32_t offset, RegisterID base, RegisterID index, int scale)
1723 : {
1724 0 : spew("cmpxchgl %s, " MEM_obs, GPReg32Name(src), ADDR_obs(offset, base, index, scale));
1725 0 : m_formatter.twoByteOp(OP2_CMPXCHG_GvEw, offset, base, index, scale, src);
1726 0 : }
1727 :
1728 :
1729 : // Comparisons:
1730 :
1731 226 : void cmpl_rr(RegisterID rhs, RegisterID lhs)
1732 : {
1733 226 : spew("cmpl %s, %s", GPReg32Name(rhs), GPReg32Name(lhs));
1734 226 : m_formatter.oneByteOp(OP_CMP_GvEv, rhs, lhs);
1735 226 : }
1736 :
1737 101 : void cmpl_rm(RegisterID rhs, int32_t offset, RegisterID base)
1738 : {
1739 101 : spew("cmpl %s, " MEM_ob, GPReg32Name(rhs), ADDR_ob(offset, base));
1740 101 : m_formatter.oneByteOp(OP_CMP_EvGv, offset, base, rhs);
1741 101 : }
1742 :
1743 3 : void cmpl_mr(int32_t offset, RegisterID base, RegisterID lhs)
1744 : {
1745 3 : spew("cmpl " MEM_ob ", %s", ADDR_ob(offset, base), GPReg32Name(lhs));
1746 3 : m_formatter.oneByteOp(OP_CMP_GvEv, offset, base, lhs);
1747 3 : }
1748 :
1749 0 : void cmpl_mr(const void* address, RegisterID lhs)
1750 : {
1751 0 : spew("cmpl %p, %s", address, GPReg32Name(lhs));
1752 0 : m_formatter.oneByteOp(OP_CMP_GvEv, address, lhs);
1753 0 : }
1754 :
1755 7659 : void cmpl_ir(int32_t rhs, RegisterID lhs)
1756 : {
1757 7659 : if (rhs == 0) {
1758 267 : testl_rr(lhs, lhs);
1759 267 : return;
1760 : }
1761 :
1762 7392 : spew("cmpl $0x%x, %s", rhs, GPReg32Name(lhs));
1763 7392 : if (CAN_SIGN_EXTEND_8_32(rhs)) {
1764 711 : m_formatter.oneByteOp(OP_GROUP1_EvIb, lhs, GROUP1_OP_CMP);
1765 711 : m_formatter.immediate8s(rhs);
1766 : } else {
1767 6681 : if (lhs == rax)
1768 264 : m_formatter.oneByteOp(OP_CMP_EAXIv);
1769 : else
1770 6417 : m_formatter.oneByteOp(OP_GROUP1_EvIz, lhs, GROUP1_OP_CMP);
1771 6681 : m_formatter.immediate32(rhs);
1772 : }
1773 : }
1774 :
1775 : void cmpl_i32r(int32_t rhs, RegisterID lhs)
1776 : {
1777 : spew("cmpl $0x%04x, %s", rhs, GPReg32Name(lhs));
1778 : if (lhs == rax)
1779 : m_formatter.oneByteOp(OP_CMP_EAXIv);
1780 : else
1781 : m_formatter.oneByteOp(OP_GROUP1_EvIz, lhs, GROUP1_OP_CMP);
1782 : m_formatter.immediate32(rhs);
1783 : }
1784 :
1785 1658 : void cmpl_im(int32_t rhs, int32_t offset, RegisterID base)
1786 : {
1787 1658 : spew("cmpl $0x%x, " MEM_ob, rhs, ADDR_ob(offset, base));
1788 1658 : if (CAN_SIGN_EXTEND_8_32(rhs)) {
1789 1616 : m_formatter.oneByteOp(OP_GROUP1_EvIb, offset, base, GROUP1_OP_CMP);
1790 1616 : m_formatter.immediate8s(rhs);
1791 : } else {
1792 42 : m_formatter.oneByteOp(OP_GROUP1_EvIz, offset, base, GROUP1_OP_CMP);
1793 42 : m_formatter.immediate32(rhs);
1794 : }
1795 1658 : }
1796 :
1797 : void cmpb_im(int32_t rhs, int32_t offset, RegisterID base)
1798 : {
1799 : spew("cmpb $0x%x, " MEM_ob, rhs, ADDR_ob(offset, base));
1800 : m_formatter.oneByteOp(OP_GROUP1_EbIb, offset, base, GROUP1_OP_CMP);
1801 : m_formatter.immediate8(rhs);
1802 : }
1803 :
1804 : void cmpb_im(int32_t rhs, int32_t offset, RegisterID base, RegisterID index, int scale)
1805 : {
1806 : spew("cmpb $0x%x, " MEM_obs, rhs, ADDR_obs(offset, base, index, scale));
1807 : m_formatter.oneByteOp(OP_GROUP1_EbIb, offset, base, index, scale, GROUP1_OP_CMP);
1808 : m_formatter.immediate8(rhs);
1809 : }
1810 :
1811 0 : void cmpl_im(int32_t rhs, int32_t offset, RegisterID base, RegisterID index, int scale)
1812 : {
1813 0 : spew("cmpl $0x%x, " MEM_o32b, rhs, ADDR_o32b(offset, base));
1814 0 : if (CAN_SIGN_EXTEND_8_32(rhs)) {
1815 0 : m_formatter.oneByteOp(OP_GROUP1_EvIb, offset, base, index, scale, GROUP1_OP_CMP);
1816 0 : m_formatter.immediate8s(rhs);
1817 : } else {
1818 0 : m_formatter.oneByteOp(OP_GROUP1_EvIz, offset, base, index, scale, GROUP1_OP_CMP);
1819 0 : m_formatter.immediate32(rhs);
1820 : }
1821 0 : }
1822 :
1823 : MOZ_MUST_USE JmpSrc
1824 : cmpl_im_disp32(int32_t rhs, int32_t offset, RegisterID base)
1825 : {
1826 : spew("cmpl $0x%x, " MEM_o32b, rhs, ADDR_o32b(offset, base));
1827 : JmpSrc r;
1828 : if (CAN_SIGN_EXTEND_8_32(rhs)) {
1829 : m_formatter.oneByteOp_disp32(OP_GROUP1_EvIb, offset, base, GROUP1_OP_CMP);
1830 : r = JmpSrc(m_formatter.size());
1831 : m_formatter.immediate8s(rhs);
1832 : } else {
1833 : m_formatter.oneByteOp_disp32(OP_GROUP1_EvIz, offset, base, GROUP1_OP_CMP);
1834 : r = JmpSrc(m_formatter.size());
1835 : m_formatter.immediate32(rhs);
1836 : }
1837 : return r;
1838 : }
1839 :
1840 : MOZ_MUST_USE JmpSrc
1841 : cmpl_im_disp32(int32_t rhs, const void* addr)
1842 : {
1843 : spew("cmpl $0x%x, %p", rhs, addr);
1844 : JmpSrc r;
1845 : if (CAN_SIGN_EXTEND_8_32(rhs)) {
1846 : m_formatter.oneByteOp_disp32(OP_GROUP1_EvIb, addr, GROUP1_OP_CMP);
1847 : r = JmpSrc(m_formatter.size());
1848 : m_formatter.immediate8s(rhs);
1849 : } else {
1850 : m_formatter.oneByteOp_disp32(OP_GROUP1_EvIz, addr, GROUP1_OP_CMP);
1851 : r = JmpSrc(m_formatter.size());
1852 : m_formatter.immediate32(rhs);
1853 : }
1854 : return r;
1855 : }
1856 :
1857 : void cmpl_i32m(int32_t rhs, int32_t offset, RegisterID base)
1858 : {
1859 : spew("cmpl $0x%04x, " MEM_ob, rhs, ADDR_ob(offset, base));
1860 : m_formatter.oneByteOp(OP_GROUP1_EvIz, offset, base, GROUP1_OP_CMP);
1861 : m_formatter.immediate32(rhs);
1862 : }
1863 :
1864 : void cmpl_i32m(int32_t rhs, const void* addr)
1865 : {
1866 : spew("cmpl $0x%04x, %p", rhs, addr);
1867 : m_formatter.oneByteOp(OP_GROUP1_EvIz, addr, GROUP1_OP_CMP);
1868 : m_formatter.immediate32(rhs);
1869 : }
1870 :
1871 0 : void cmpl_rm(RegisterID rhs, const void* addr)
1872 : {
1873 0 : spew("cmpl %s, %p", GPReg32Name(rhs), addr);
1874 0 : m_formatter.oneByteOp(OP_CMP_EvGv, addr, rhs);
1875 0 : }
1876 :
1877 : void cmpl_rm_disp32(RegisterID rhs, const void* addr)
1878 : {
1879 : spew("cmpl %s, %p", GPReg32Name(rhs), addr);
1880 : m_formatter.oneByteOp_disp32(OP_CMP_EvGv, addr, rhs);
1881 : }
1882 :
1883 0 : void cmpl_im(int32_t rhs, const void* addr)
1884 : {
1885 0 : spew("cmpl $0x%x, %p", rhs, addr);
1886 0 : if (CAN_SIGN_EXTEND_8_32(rhs)) {
1887 0 : m_formatter.oneByteOp(OP_GROUP1_EvIb, addr, GROUP1_OP_CMP);
1888 0 : m_formatter.immediate8s(rhs);
1889 : } else {
1890 0 : m_formatter.oneByteOp(OP_GROUP1_EvIz, addr, GROUP1_OP_CMP);
1891 0 : m_formatter.immediate32(rhs);
1892 : }
1893 0 : }
1894 :
1895 : void cmpw_rr(RegisterID rhs, RegisterID lhs)
1896 : {
1897 : spew("cmpw %s, %s", GPReg16Name(rhs), GPReg16Name(lhs));
1898 : m_formatter.prefix(PRE_OPERAND_SIZE);
1899 : m_formatter.oneByteOp(OP_CMP_GvEv, rhs, lhs);
1900 : }
1901 :
1902 : void cmpw_rm(RegisterID rhs, int32_t offset, RegisterID base, RegisterID index, int scale)
1903 : {
1904 : spew("cmpw %s, " MEM_obs, GPReg16Name(rhs), ADDR_obs(offset, base, index, scale));
1905 : m_formatter.prefix(PRE_OPERAND_SIZE);
1906 : m_formatter.oneByteOp(OP_CMP_EvGv, offset, base, index, scale, rhs);
1907 : }
1908 :
1909 : void cmpw_im(int32_t imm, int32_t offset, RegisterID base, RegisterID index, int scale)
1910 : {
1911 : spew("cmpw $%d, " MEM_obs, imm, ADDR_obs(offset, base, index, scale));
1912 : if (CAN_SIGN_EXTEND_8_32(imm)) {
1913 : m_formatter.prefix(PRE_OPERAND_SIZE);
1914 : m_formatter.oneByteOp(OP_GROUP1_EvIb, offset, base, index, scale, GROUP1_OP_CMP);
1915 : m_formatter.immediate8s(imm);
1916 : } else {
1917 : m_formatter.prefix(PRE_OPERAND_SIZE);
1918 : m_formatter.oneByteOp(OP_GROUP1_EvIz, offset, base, index, scale, GROUP1_OP_CMP);
1919 : m_formatter.immediate16(imm);
1920 : }
1921 : }
1922 :
1923 3515 : void testl_rr(RegisterID rhs, RegisterID lhs)
1924 : {
1925 3515 : spew("testl %s, %s", GPReg32Name(rhs), GPReg32Name(lhs));
1926 3515 : m_formatter.oneByteOp(OP_TEST_EvGv, lhs, rhs);
1927 3515 : }
1928 :
1929 796 : void testb_rr(RegisterID rhs, RegisterID lhs)
1930 : {
1931 796 : spew("testb %s, %s", GPReg8Name(rhs), GPReg8Name(lhs));
1932 796 : m_formatter.oneByteOp(OP_TEST_EbGb, lhs, rhs);
1933 796 : }
1934 :
1935 13589 : void testl_ir(int32_t rhs, RegisterID lhs)
1936 : {
1937 : // If the mask fits in an 8-bit immediate, we can use testb with an
1938 : // 8-bit subreg.
1939 13589 : if (CAN_ZERO_EXTEND_8_32(rhs) && HasSubregL(lhs)) {
1940 13577 : testb_ir(rhs, lhs);
1941 13577 : return;
1942 : }
1943 : // If the mask is a subset of 0xff00, we can use testb with an h reg, if
1944 : // one happens to be available.
1945 12 : if (CAN_ZERO_EXTEND_8H_32(rhs) && HasSubregH(lhs)) {
1946 0 : testb_ir_norex(rhs >> 8, GetSubregH(lhs));
1947 0 : return;
1948 : }
1949 12 : spew("testl $0x%x, %s", rhs, GPReg32Name(lhs));
1950 12 : if (lhs == rax)
1951 0 : m_formatter.oneByteOp(OP_TEST_EAXIv);
1952 : else
1953 12 : m_formatter.oneByteOp(OP_GROUP3_EvIz, lhs, GROUP3_OP_TEST);
1954 12 : m_formatter.immediate32(rhs);
1955 : }
1956 :
1957 7960 : void testl_i32m(int32_t rhs, int32_t offset, RegisterID base)
1958 : {
1959 7960 : spew("testl $0x%x, " MEM_ob, rhs, ADDR_ob(offset, base));
1960 7960 : m_formatter.oneByteOp(OP_GROUP3_EvIz, offset, base, GROUP3_OP_TEST);
1961 7960 : m_formatter.immediate32(rhs);
1962 7960 : }
1963 :
1964 0 : void testl_i32m(int32_t rhs, const void* addr)
1965 : {
1966 0 : spew("testl $0x%x, %p", rhs, addr);
1967 0 : m_formatter.oneByteOp(OP_GROUP3_EvIz, addr, GROUP3_OP_TEST);
1968 0 : m_formatter.immediate32(rhs);
1969 0 : }
1970 :
1971 : void testb_im(int32_t rhs, int32_t offset, RegisterID base)
1972 : {
1973 : spew("testb $0x%x, " MEM_ob, rhs, ADDR_ob(offset, base));
1974 : m_formatter.oneByteOp(OP_GROUP3_EbIb, offset, base, GROUP3_OP_TEST);
1975 : m_formatter.immediate8(rhs);
1976 : }
1977 :
1978 : void testb_im(int32_t rhs, int32_t offset, RegisterID base, RegisterID index, int scale)
1979 : {
1980 : spew("testb $0x%x, " MEM_obs, rhs, ADDR_obs(offset, base, index, scale));
1981 : m_formatter.oneByteOp(OP_GROUP3_EbIb, offset, base, index, scale, GROUP3_OP_TEST);
1982 : m_formatter.immediate8(rhs);
1983 : }
1984 :
1985 : void testl_i32m(int32_t rhs, int32_t offset, RegisterID base, RegisterID index, int scale)
1986 : {
1987 : spew("testl $0x%4x, " MEM_obs, rhs, ADDR_obs(offset, base, index, scale));
1988 : m_formatter.oneByteOp(OP_GROUP3_EvIz, offset, base, index, scale, GROUP3_OP_TEST);
1989 : m_formatter.immediate32(rhs);
1990 : }
1991 :
1992 : void testw_rr(RegisterID rhs, RegisterID lhs)
1993 : {
1994 : spew("testw %s, %s", GPReg16Name(rhs), GPReg16Name(lhs));
1995 : m_formatter.prefix(PRE_OPERAND_SIZE);
1996 : m_formatter.oneByteOp(OP_TEST_EvGv, lhs, rhs);
1997 : }
1998 :
1999 13577 : void testb_ir(int32_t rhs, RegisterID lhs)
2000 : {
2001 13577 : spew("testb $0x%x, %s", rhs, GPReg8Name(lhs));
2002 13577 : if (lhs == rax)
2003 135 : m_formatter.oneByteOp8(OP_TEST_EAXIb);
2004 : else
2005 13442 : m_formatter.oneByteOp8(OP_GROUP3_EbIb, lhs, GROUP3_OP_TEST);
2006 13577 : m_formatter.immediate8(rhs);
2007 13577 : }
2008 :
2009 : // Like testb_ir, but never emits a REX prefix. This may be used to
2010 : // reference ah..bh.
2011 0 : void testb_ir_norex(int32_t rhs, HRegisterID lhs)
2012 : {
2013 0 : spew("testb $0x%x, %s", rhs, HRegName8(lhs));
2014 0 : m_formatter.oneByteOp8_norex(OP_GROUP3_EbIb, lhs, GROUP3_OP_TEST);
2015 0 : m_formatter.immediate8(rhs);
2016 0 : }
2017 :
2018 186 : void setCC_r(Condition cond, RegisterID lhs)
2019 : {
2020 186 : spew("set%s %s", CCName(cond), GPReg8Name(lhs));
2021 186 : m_formatter.twoByteOp8(setccOpcode(cond), lhs, (GroupOpcodeID)0);
2022 186 : }
2023 :
2024 : void sete_r(RegisterID dst)
2025 : {
2026 : setCC_r(ConditionE, dst);
2027 : }
2028 :
2029 : void setz_r(RegisterID dst)
2030 : {
2031 : sete_r(dst);
2032 : }
2033 :
2034 : void setne_r(RegisterID dst)
2035 : {
2036 : setCC_r(ConditionNE, dst);
2037 : }
2038 :
2039 : void setnz_r(RegisterID dst)
2040 : {
2041 : setne_r(dst);
2042 : }
2043 :
2044 : // Various move ops:
2045 :
2046 0 : void cdq()
2047 : {
2048 0 : spew("cdq ");
2049 0 : m_formatter.oneByteOp(OP_CDQ);
2050 0 : }
2051 :
2052 0 : void xchgb_rm(RegisterID src, int32_t offset, RegisterID base)
2053 : {
2054 0 : spew("xchgb %s, " MEM_ob, GPReg8Name(src), ADDR_ob(offset, base));
2055 0 : m_formatter.oneByteOp8(OP_XCHG_GbEb, offset, base, src);
2056 0 : }
2057 0 : void xchgb_rm(RegisterID src, int32_t offset, RegisterID base, RegisterID index, int scale)
2058 : {
2059 0 : spew("xchgb %s, " MEM_obs, GPReg8Name(src), ADDR_obs(offset, base, index, scale));
2060 0 : m_formatter.oneByteOp8(OP_XCHG_GbEb, offset, base, index, scale, src);
2061 0 : }
2062 :
2063 0 : void xchgw_rm(RegisterID src, int32_t offset, RegisterID base)
2064 : {
2065 0 : spew("xchgw %s, " MEM_ob, GPReg16Name(src), ADDR_ob(offset, base));
2066 0 : m_formatter.prefix(PRE_OPERAND_SIZE);
2067 0 : m_formatter.oneByteOp(OP_XCHG_GvEv, offset, base, src);
2068 0 : }
2069 0 : void xchgw_rm(RegisterID src, int32_t offset, RegisterID base, RegisterID index, int scale)
2070 : {
2071 0 : spew("xchgw %s, " MEM_obs, GPReg16Name(src), ADDR_obs(offset, base, index, scale));
2072 0 : m_formatter.prefix(PRE_OPERAND_SIZE);
2073 0 : m_formatter.oneByteOp(OP_XCHG_GvEv, offset, base, index, scale, src);
2074 0 : }
2075 :
2076 : void xchgl_rr(RegisterID src, RegisterID dst)
2077 : {
2078 : spew("xchgl %s, %s", GPReg32Name(src), GPReg32Name(dst));
2079 : m_formatter.oneByteOp(OP_XCHG_GvEv, src, dst);
2080 : }
2081 0 : void xchgl_rm(RegisterID src, int32_t offset, RegisterID base)
2082 : {
2083 0 : spew("xchgl %s, " MEM_ob, GPReg32Name(src), ADDR_ob(offset, base));
2084 0 : m_formatter.oneByteOp(OP_XCHG_GvEv, offset, base, src);
2085 0 : }
2086 0 : void xchgl_rm(RegisterID src, int32_t offset, RegisterID base, RegisterID index, int scale)
2087 : {
2088 0 : spew("xchgl %s, " MEM_obs, GPReg32Name(src), ADDR_obs(offset, base, index, scale));
2089 0 : m_formatter.oneByteOp(OP_XCHG_GvEv, offset, base, index, scale, src);
2090 0 : }
2091 :
2092 0 : void cmovz_rr(RegisterID src, RegisterID dst)
2093 : {
2094 0 : spew("cmovz %s, %s", GPReg16Name(src), GPReg32Name(dst));
2095 0 : m_formatter.twoByteOp(OP2_CMOVZ_GvEv, src, dst);
2096 0 : }
2097 0 : void cmovz_mr(int32_t offset, RegisterID base, RegisterID dst)
2098 : {
2099 0 : spew("cmovz " MEM_ob ", %s", ADDR_ob(offset, base), GPReg32Name(dst));
2100 0 : m_formatter.twoByteOp(OP2_CMOVZ_GvEv, offset, base, dst);
2101 0 : }
2102 0 : void cmovz_mr(int32_t offset, RegisterID base, RegisterID index, int scale, RegisterID dst)
2103 : {
2104 0 : spew("cmovz " MEM_obs ", %s", ADDR_obs(offset, base, index, scale), GPReg32Name(dst));
2105 0 : m_formatter.twoByteOp(OP2_CMOVZ_GvEv, offset, base, index, scale, dst);
2106 0 : }
2107 :
2108 420 : void movl_rr(RegisterID src, RegisterID dst)
2109 : {
2110 420 : spew("movl %s, %s", GPReg32Name(src), GPReg32Name(dst));
2111 420 : m_formatter.oneByteOp(OP_MOV_GvEv, src, dst);
2112 420 : }
2113 :
2114 36 : void movw_rm(RegisterID src, int32_t offset, RegisterID base)
2115 : {
2116 36 : spew("movw %s, " MEM_ob, GPReg16Name(src), ADDR_ob(offset, base));
2117 36 : m_formatter.prefix(PRE_OPERAND_SIZE);
2118 36 : m_formatter.oneByteOp(OP_MOV_EvGv, offset, base, src);
2119 36 : }
2120 :
2121 : void movw_rm_disp32(RegisterID src, int32_t offset, RegisterID base)
2122 : {
2123 : spew("movw %s, " MEM_o32b, GPReg16Name(src), ADDR_o32b(offset, base));
2124 : m_formatter.prefix(PRE_OPERAND_SIZE);
2125 : m_formatter.oneByteOp_disp32(OP_MOV_EvGv, offset, base, src);
2126 : }
2127 :
2128 0 : void movw_rm(RegisterID src, int32_t offset, RegisterID base, RegisterID index, int scale)
2129 : {
2130 0 : spew("movw %s, " MEM_obs, GPReg16Name(src), ADDR_obs(offset, base, index, scale));
2131 0 : m_formatter.prefix(PRE_OPERAND_SIZE);
2132 0 : m_formatter.oneByteOp(OP_MOV_EvGv, offset, base, index, scale, src);
2133 0 : }
2134 :
2135 : void movw_rm(RegisterID src, const void* addr)
2136 : {
2137 : spew("movw %s, %p", GPReg16Name(src), addr);
2138 : m_formatter.prefix(PRE_OPERAND_SIZE);
2139 : m_formatter.oneByteOp_disp32(OP_MOV_EvGv, addr, src);
2140 : }
2141 :
2142 2598 : void movl_rm(RegisterID src, int32_t offset, RegisterID base)
2143 : {
2144 2598 : spew("movl %s, " MEM_ob, GPReg32Name(src), ADDR_ob(offset, base));
2145 2598 : m_formatter.oneByteOp(OP_MOV_EvGv, offset, base, src);
2146 2598 : }
2147 :
2148 : void movl_rm_disp32(RegisterID src, int32_t offset, RegisterID base)
2149 : {
2150 : spew("movl %s, " MEM_o32b, GPReg32Name(src), ADDR_o32b(offset, base));
2151 : m_formatter.oneByteOp_disp32(OP_MOV_EvGv, offset, base, src);
2152 : }
2153 :
2154 0 : void movl_rm(RegisterID src, int32_t offset, RegisterID base, RegisterID index, int scale)
2155 : {
2156 0 : spew("movl %s, " MEM_obs, GPReg32Name(src), ADDR_obs(offset, base, index, scale));
2157 0 : m_formatter.oneByteOp(OP_MOV_EvGv, offset, base, index, scale, src);
2158 0 : }
2159 :
2160 0 : void movl_mEAX(const void* addr)
2161 : {
2162 : #ifdef JS_CODEGEN_X64
2163 0 : if (IsAddressImmediate(addr)) {
2164 0 : movl_mr(addr, rax);
2165 0 : return;
2166 : }
2167 : #endif
2168 :
2169 : #ifdef JS_CODEGEN_X64
2170 0 : spew("movabs %p, %%eax", addr);
2171 : #else
2172 : spew("movl %p, %%eax", addr);
2173 : #endif
2174 0 : m_formatter.oneByteOp(OP_MOV_EAXOv);
2175 : #ifdef JS_CODEGEN_X64
2176 0 : m_formatter.immediate64(reinterpret_cast<int64_t>(addr));
2177 : #else
2178 : m_formatter.immediate32(reinterpret_cast<int32_t>(addr));
2179 : #endif
2180 : }
2181 :
2182 1670 : void movl_mr(int32_t offset, RegisterID base, RegisterID dst)
2183 : {
2184 1670 : spew("movl " MEM_ob ", %s", ADDR_ob(offset, base), GPReg32Name(dst));
2185 1670 : m_formatter.oneByteOp(OP_MOV_GvEv, offset, base, dst);
2186 1670 : }
2187 :
2188 : void movl_mr_disp32(int32_t offset, RegisterID base, RegisterID dst)
2189 : {
2190 : spew("movl " MEM_o32b ", %s", ADDR_o32b(offset, base), GPReg32Name(dst));
2191 : m_formatter.oneByteOp_disp32(OP_MOV_GvEv, offset, base, dst);
2192 : }
2193 :
2194 : void movl_mr(const void* base, RegisterID index, int scale, RegisterID dst)
2195 : {
2196 : int32_t disp = AddressImmediate(base);
2197 :
2198 : spew("movl " MEM_os ", %s", ADDR_os(disp, index, scale), GPReg32Name(dst));
2199 : m_formatter.oneByteOp_disp32(OP_MOV_GvEv, disp, index, scale, dst);
2200 : }
2201 :
2202 51 : void movl_mr(int32_t offset, RegisterID base, RegisterID index, int scale, RegisterID dst)
2203 : {
2204 51 : spew("movl " MEM_obs ", %s", ADDR_obs(offset, base, index, scale), GPReg32Name(dst));
2205 51 : m_formatter.oneByteOp(OP_MOV_GvEv, offset, base, index, scale, dst);
2206 51 : }
2207 :
2208 0 : void movl_mr(const void* addr, RegisterID dst)
2209 : {
2210 0 : if (dst == rax
2211 : #ifdef JS_CODEGEN_X64
2212 0 : && !IsAddressImmediate(addr)
2213 : #endif
2214 : )
2215 : {
2216 0 : movl_mEAX(addr);
2217 0 : return;
2218 : }
2219 :
2220 0 : spew("movl %p, %s", addr, GPReg32Name(dst));
2221 0 : m_formatter.oneByteOp(OP_MOV_GvEv, addr, dst);
2222 : }
2223 :
2224 5777 : void movl_i32r(int32_t imm, RegisterID dst)
2225 : {
2226 5777 : spew("movl $0x%x, %s", imm, GPReg32Name(dst));
2227 5777 : m_formatter.oneByteOp(OP_MOV_EAXIv, dst);
2228 5777 : m_formatter.immediate32(imm);
2229 5777 : }
2230 :
2231 0 : void movb_ir(int32_t imm, RegisterID reg)
2232 : {
2233 0 : spew("movb $0x%x, %s", imm, GPReg8Name(reg));
2234 0 : m_formatter.oneByteOp8(OP_MOV_EbIb, reg);
2235 0 : m_formatter.immediate8(imm);
2236 0 : }
2237 :
2238 4 : void movb_im(int32_t imm, int32_t offset, RegisterID base)
2239 : {
2240 4 : spew("movb $0x%x, " MEM_ob, imm, ADDR_ob(offset, base));
2241 4 : m_formatter.oneByteOp(OP_GROUP11_EvIb, offset, base, GROUP11_MOV);
2242 4 : m_formatter.immediate8(imm);
2243 4 : }
2244 :
2245 0 : void movb_im(int32_t imm, int32_t offset, RegisterID base, RegisterID index, int scale)
2246 : {
2247 0 : spew("movb $0x%x, " MEM_obs, imm, ADDR_obs(offset, base, index, scale));
2248 0 : m_formatter.oneByteOp(OP_GROUP11_EvIb, offset, base, index, scale, GROUP11_MOV);
2249 0 : m_formatter.immediate8(imm);
2250 0 : }
2251 :
2252 : void movb_im(int32_t imm, const void* addr)
2253 : {
2254 : spew("movb $%d, %p", imm, addr);
2255 : m_formatter.oneByteOp_disp32(OP_GROUP11_EvIb, addr, GROUP11_MOV);
2256 : m_formatter.immediate8(imm);
2257 : }
2258 :
2259 4 : void movw_im(int32_t imm, int32_t offset, RegisterID base)
2260 : {
2261 4 : spew("movw $0x%x, " MEM_ob, imm, ADDR_ob(offset, base));
2262 4 : m_formatter.prefix(PRE_OPERAND_SIZE);
2263 4 : m_formatter.oneByteOp(OP_GROUP11_EvIz, offset, base, GROUP11_MOV);
2264 4 : m_formatter.immediate16(imm);
2265 4 : }
2266 :
2267 : void movw_im(int32_t imm, const void* addr)
2268 : {
2269 : spew("movw $%d, %p", imm, addr);
2270 : m_formatter.prefix(PRE_OPERAND_SIZE);
2271 : m_formatter.oneByteOp_disp32(OP_GROUP11_EvIz, addr, GROUP11_MOV);
2272 : m_formatter.immediate16(imm);
2273 : }
2274 :
2275 4123 : void movl_i32m(int32_t imm, int32_t offset, RegisterID base)
2276 : {
2277 4123 : spew("movl $0x%x, " MEM_ob, imm, ADDR_ob(offset, base));
2278 4123 : m_formatter.oneByteOp(OP_GROUP11_EvIz, offset, base, GROUP11_MOV);
2279 4123 : m_formatter.immediate32(imm);
2280 4123 : }
2281 :
2282 0 : void movw_im(int32_t imm, int32_t offset, RegisterID base, RegisterID index, int scale)
2283 : {
2284 0 : spew("movw $0x%x, " MEM_obs, imm, ADDR_obs(offset, base, index, scale));
2285 0 : m_formatter.prefix(PRE_OPERAND_SIZE);
2286 0 : m_formatter.oneByteOp(OP_GROUP11_EvIz, offset, base, index, scale, GROUP11_MOV);
2287 0 : m_formatter.immediate16(imm);
2288 0 : }
2289 :
2290 0 : void movl_i32m(int32_t imm, int32_t offset, RegisterID base, RegisterID index, int scale)
2291 : {
2292 0 : spew("movl $0x%x, " MEM_obs, imm, ADDR_obs(offset, base, index, scale));
2293 0 : m_formatter.oneByteOp(OP_GROUP11_EvIz, offset, base, index, scale, GROUP11_MOV);
2294 0 : m_formatter.immediate32(imm);
2295 0 : }
2296 :
2297 0 : void movl_EAXm(const void* addr)
2298 : {
2299 : #ifdef JS_CODEGEN_X64
2300 0 : if (IsAddressImmediate(addr)) {
2301 0 : movl_rm(rax, addr);
2302 0 : return;
2303 : }
2304 : #endif
2305 :
2306 0 : spew("movl %%eax, %p", addr);
2307 0 : m_formatter.oneByteOp(OP_MOV_OvEAX);
2308 : #ifdef JS_CODEGEN_X64
2309 0 : m_formatter.immediate64(reinterpret_cast<int64_t>(addr));
2310 : #else
2311 : m_formatter.immediate32(reinterpret_cast<int32_t>(addr));
2312 : #endif
2313 : }
2314 :
2315 0 : void vmovq_rm(XMMRegisterID src, int32_t offset, RegisterID base)
2316 : {
2317 : // vmovq_rm can be encoded either as a true vmovq or as a vmovd with a
2318 : // REX prefix modifying it to be 64-bit. We choose the vmovq encoding
2319 : // because it's smaller (when it doesn't need a REX prefix for other
2320 : // reasons) and because it works on 32-bit x86 too.
2321 0 : twoByteOpSimd("vmovq", VEX_PD, OP2_MOVQ_WdVd, offset, base, invalid_xmm, src);
2322 0 : }
2323 :
2324 : void vmovq_rm_disp32(XMMRegisterID src, int32_t offset, RegisterID base)
2325 : {
2326 : twoByteOpSimd_disp32("vmovq", VEX_PD, OP2_MOVQ_WdVd, offset, base, invalid_xmm, src);
2327 : }
2328 :
2329 0 : void vmovq_rm(XMMRegisterID src, int32_t offset, RegisterID base, RegisterID index, int scale)
2330 : {
2331 0 : twoByteOpSimd("vmovq", VEX_PD, OP2_MOVQ_WdVd, offset, base, index, scale, invalid_xmm, src);
2332 0 : }
2333 :
2334 0 : void vmovq_rm(XMMRegisterID src, const void* addr)
2335 : {
2336 0 : twoByteOpSimd("vmovq", VEX_PD, OP2_MOVQ_WdVd, addr, invalid_xmm, src);
2337 0 : }
2338 :
2339 0 : void vmovq_mr(int32_t offset, RegisterID base, XMMRegisterID dst)
2340 : {
2341 : // vmovq_mr can be encoded either as a true vmovq or as a vmovd with a
2342 : // REX prefix modifying it to be 64-bit. We choose the vmovq encoding
2343 : // because it's smaller (when it doesn't need a REX prefix for other
2344 : // reasons) and because it works on 32-bit x86 too.
2345 0 : twoByteOpSimd("vmovq", VEX_SS, OP2_MOVQ_VdWd, offset, base, invalid_xmm, dst);
2346 0 : }
2347 :
2348 : void vmovq_mr_disp32(int32_t offset, RegisterID base, XMMRegisterID dst)
2349 : {
2350 : twoByteOpSimd_disp32("vmovq", VEX_SS, OP2_MOVQ_VdWd, offset, base, invalid_xmm, dst);
2351 : }
2352 :
2353 0 : void vmovq_mr(int32_t offset, RegisterID base, RegisterID index, int32_t scale, XMMRegisterID dst)
2354 : {
2355 0 : twoByteOpSimd("vmovq", VEX_SS, OP2_MOVQ_VdWd, offset, base, index, scale, invalid_xmm, dst);
2356 0 : }
2357 :
2358 0 : void vmovq_mr(const void* addr, XMMRegisterID dst)
2359 : {
2360 0 : twoByteOpSimd("vmovq", VEX_SS, OP2_MOVQ_VdWd, addr, invalid_xmm, dst);
2361 0 : }
2362 :
2363 0 : void movl_rm(RegisterID src, const void* addr)
2364 : {
2365 0 : if (src == rax
2366 : #ifdef JS_CODEGEN_X64
2367 0 : && !IsAddressImmediate(addr)
2368 : #endif
2369 : ) {
2370 0 : movl_EAXm(addr);
2371 0 : return;
2372 : }
2373 :
2374 0 : spew("movl %s, %p", GPReg32Name(src), addr);
2375 0 : m_formatter.oneByteOp(OP_MOV_EvGv, addr, src);
2376 : }
2377 :
2378 0 : void movl_i32m(int32_t imm, const void* addr)
2379 : {
2380 0 : spew("movl $%d, %p", imm, addr);
2381 0 : m_formatter.oneByteOp(OP_GROUP11_EvIz, addr, GROUP11_MOV);
2382 0 : m_formatter.immediate32(imm);
2383 0 : }
2384 :
2385 8 : void movb_rm(RegisterID src, int32_t offset, RegisterID base)
2386 : {
2387 8 : spew("movb %s, " MEM_ob, GPReg8Name(src), ADDR_ob(offset, base));
2388 8 : m_formatter.oneByteOp8(OP_MOV_EbGv, offset, base, src);
2389 8 : }
2390 :
2391 : void movb_rm_disp32(RegisterID src, int32_t offset, RegisterID base)
2392 : {
2393 : spew("movb %s, " MEM_o32b, GPReg8Name(src), ADDR_o32b(offset, base));
2394 : m_formatter.oneByteOp8_disp32(OP_MOV_EbGv, offset, base, src);
2395 : }
2396 :
2397 3 : void movb_rm(RegisterID src, int32_t offset, RegisterID base, RegisterID index, int scale)
2398 : {
2399 3 : spew("movb %s, " MEM_obs, GPReg8Name(src), ADDR_obs(offset, base, index, scale));
2400 3 : m_formatter.oneByteOp8(OP_MOV_EbGv, offset, base, index, scale, src);
2401 3 : }
2402 :
2403 : void movb_rm(RegisterID src, const void* addr)
2404 : {
2405 : spew("movb %s, %p", GPReg8Name(src), addr);
2406 : m_formatter.oneByteOp8(OP_MOV_EbGv, addr, src);
2407 : }
2408 :
2409 0 : void movb_mr(int32_t offset, RegisterID base, RegisterID dst)
2410 : {
2411 0 : spew("movb " MEM_ob ", %s", ADDR_ob(offset, base), GPReg8Name(dst));
2412 0 : m_formatter.oneByteOp(OP_MOV_GvEb, offset, base, dst);
2413 0 : }
2414 :
2415 0 : void movb_mr(int32_t offset, RegisterID base, RegisterID index, int scale, RegisterID dst)
2416 : {
2417 0 : spew("movb " MEM_obs ", %s", ADDR_obs(offset, base, index, scale), GPReg8Name(dst));
2418 0 : m_formatter.oneByteOp(OP_MOV_GvEb, offset, base, index, scale, dst);
2419 0 : }
2420 :
2421 124 : void movzbl_mr(int32_t offset, RegisterID base, RegisterID dst)
2422 : {
2423 124 : spew("movzbl " MEM_ob ", %s", ADDR_ob(offset, base), GPReg32Name(dst));
2424 124 : m_formatter.twoByteOp(OP2_MOVZX_GvEb, offset, base, dst);
2425 124 : }
2426 :
2427 : void movzbl_mr_disp32(int32_t offset, RegisterID base, RegisterID dst)
2428 : {
2429 : spew("movzbl " MEM_o32b ", %s", ADDR_o32b(offset, base), GPReg32Name(dst));
2430 : m_formatter.twoByteOp_disp32(OP2_MOVZX_GvEb, offset, base, dst);
2431 : }
2432 :
2433 532 : void movzbl_mr(int32_t offset, RegisterID base, RegisterID index, int scale, RegisterID dst)
2434 : {
2435 532 : spew("movzbl " MEM_obs ", %s", ADDR_obs(offset, base, index, scale), GPReg32Name(dst));
2436 532 : m_formatter.twoByteOp(OP2_MOVZX_GvEb, offset, base, index, scale, dst);
2437 532 : }
2438 :
2439 : void movzbl_mr(const void* addr, RegisterID dst)
2440 : {
2441 : spew("movzbl %p, %s", addr, GPReg32Name(dst));
2442 : m_formatter.twoByteOp(OP2_MOVZX_GvEb, addr, dst);
2443 : }
2444 :
2445 0 : void movsbl_rr(RegisterID src, RegisterID dst)
2446 : {
2447 0 : spew("movsbl %s, %s", GPReg8Name(src), GPReg32Name(dst));
2448 0 : m_formatter.twoByteOp8_movx(OP2_MOVSX_GvEb, src, dst);
2449 0 : }
2450 :
2451 0 : void movsbl_mr(int32_t offset, RegisterID base, RegisterID dst)
2452 : {
2453 0 : spew("movsbl " MEM_ob ", %s", ADDR_ob(offset, base), GPReg32Name(dst));
2454 0 : m_formatter.twoByteOp(OP2_MOVSX_GvEb, offset, base, dst);
2455 0 : }
2456 :
2457 : void movsbl_mr_disp32(int32_t offset, RegisterID base, RegisterID dst)
2458 : {
2459 : spew("movsbl " MEM_o32b ", %s", ADDR_o32b(offset, base), GPReg32Name(dst));
2460 : m_formatter.twoByteOp_disp32(OP2_MOVSX_GvEb, offset, base, dst);
2461 : }
2462 :
2463 0 : void movsbl_mr(int32_t offset, RegisterID base, RegisterID index, int scale, RegisterID dst)
2464 : {
2465 0 : spew("movsbl " MEM_obs ", %s", ADDR_obs(offset, base, index, scale), GPReg32Name(dst));
2466 0 : m_formatter.twoByteOp(OP2_MOVSX_GvEb, offset, base, index, scale, dst);
2467 0 : }
2468 :
2469 : void movsbl_mr(const void* addr, RegisterID dst)
2470 : {
2471 : spew("movsbl %p, %s", addr, GPReg32Name(dst));
2472 : m_formatter.twoByteOp(OP2_MOVSX_GvEb, addr, dst);
2473 : }
2474 :
2475 0 : void movzwl_rr(RegisterID src, RegisterID dst)
2476 : {
2477 0 : spew("movzwl %s, %s", GPReg16Name(src), GPReg32Name(dst));
2478 0 : m_formatter.twoByteOp(OP2_MOVZX_GvEw, src, dst);
2479 0 : }
2480 :
2481 130 : void movzwl_mr(int32_t offset, RegisterID base, RegisterID dst)
2482 : {
2483 130 : spew("movzwl " MEM_ob ", %s", ADDR_ob(offset, base), GPReg32Name(dst));
2484 130 : m_formatter.twoByteOp(OP2_MOVZX_GvEw, offset, base, dst);
2485 130 : }
2486 :
2487 : void movzwl_mr_disp32(int32_t offset, RegisterID base, RegisterID dst)
2488 : {
2489 : spew("movzwl " MEM_o32b ", %s", ADDR_o32b(offset, base), GPReg32Name(dst));
2490 : m_formatter.twoByteOp_disp32(OP2_MOVZX_GvEw, offset, base, dst);
2491 : }
2492 :
2493 73 : void movzwl_mr(int32_t offset, RegisterID base, RegisterID index, int scale, RegisterID dst)
2494 : {
2495 73 : spew("movzwl " MEM_obs ", %s", ADDR_obs(offset, base, index, scale), GPReg32Name(dst));
2496 73 : m_formatter.twoByteOp(OP2_MOVZX_GvEw, offset, base, index, scale, dst);
2497 73 : }
2498 :
2499 : void movzwl_mr(const void* addr, RegisterID dst)
2500 : {
2501 : spew("movzwl %p, %s", addr, GPReg32Name(dst));
2502 : m_formatter.twoByteOp(OP2_MOVZX_GvEw, addr, dst);
2503 : }
2504 :
2505 0 : void movswl_rr(RegisterID src, RegisterID dst)
2506 : {
2507 0 : spew("movswl %s, %s", GPReg16Name(src), GPReg32Name(dst));
2508 0 : m_formatter.twoByteOp(OP2_MOVSX_GvEw, src, dst);
2509 0 : }
2510 :
2511 0 : void movswl_mr(int32_t offset, RegisterID base, RegisterID dst)
2512 : {
2513 0 : spew("movswl " MEM_ob ", %s", ADDR_ob(offset, base), GPReg32Name(dst));
2514 0 : m_formatter.twoByteOp(OP2_MOVSX_GvEw, offset, base, dst);
2515 0 : }
2516 :
2517 : void movswl_mr_disp32(int32_t offset, RegisterID base, RegisterID dst)
2518 : {
2519 : spew("movswl " MEM_o32b ", %s", ADDR_o32b(offset, base), GPReg32Name(dst));
2520 : m_formatter.twoByteOp_disp32(OP2_MOVSX_GvEw, offset, base, dst);
2521 : }
2522 :
2523 0 : void movswl_mr(int32_t offset, RegisterID base, RegisterID index, int scale, RegisterID dst)
2524 : {
2525 0 : spew("movswl " MEM_obs ", %s", ADDR_obs(offset, base, index, scale), GPReg32Name(dst));
2526 0 : m_formatter.twoByteOp(OP2_MOVSX_GvEw, offset, base, index, scale, dst);
2527 0 : }
2528 :
2529 : void movswl_mr(const void* addr, RegisterID dst)
2530 : {
2531 : spew("movswl %p, %s", addr, GPReg32Name(dst));
2532 : m_formatter.twoByteOp(OP2_MOVSX_GvEw, addr, dst);
2533 : }
2534 :
2535 61 : void movzbl_rr(RegisterID src, RegisterID dst)
2536 : {
2537 61 : spew("movzbl %s, %s", GPReg8Name(src), GPReg32Name(dst));
2538 61 : m_formatter.twoByteOp8_movx(OP2_MOVZX_GvEb, src, dst);
2539 61 : }
2540 :
2541 0 : void leal_mr(int32_t offset, RegisterID base, RegisterID index, int scale, RegisterID dst)
2542 : {
2543 0 : spew("leal " MEM_obs ", %s", ADDR_obs(offset, base, index, scale), GPReg32Name(dst));
2544 0 : m_formatter.oneByteOp(OP_LEA, offset, base, index, scale, dst);
2545 0 : }
2546 :
2547 0 : void leal_mr(int32_t offset, RegisterID base, RegisterID dst)
2548 : {
2549 0 : spew("leal " MEM_ob ", %s", ADDR_ob(offset, base), GPReg32Name(dst));
2550 0 : m_formatter.oneByteOp(OP_LEA, offset, base, dst);
2551 0 : }
2552 :
2553 : // Flow control:
2554 :
2555 : MOZ_MUST_USE JmpSrc
2556 17388 : call()
2557 : {
2558 17388 : m_formatter.oneByteOp(OP_CALL_rel32);
2559 17388 : JmpSrc r = m_formatter.immediateRel32();
2560 17387 : spew("call .Lfrom%d", r.offset());
2561 17387 : return r;
2562 : }
2563 :
2564 94 : void call_r(RegisterID dst)
2565 : {
2566 94 : m_formatter.oneByteOp(OP_GROUP5_Ev, dst, GROUP5_OP_CALLN);
2567 94 : spew("call *%s", GPRegName(dst));
2568 94 : }
2569 :
2570 19474 : void call_m(int32_t offset, RegisterID base)
2571 : {
2572 19474 : spew("call *" MEM_ob, ADDR_ob(offset, base));
2573 19474 : m_formatter.oneByteOp(OP_GROUP5_Ev, offset, base, GROUP5_OP_CALLN);
2574 19474 : }
2575 :
2576 : // Comparison of EAX against a 32-bit immediate. The immediate is patched
2577 : // in as if it were a jump target. The intention is to toggle the first
2578 : // byte of the instruction between a CMP and a JMP to produce a pseudo-NOP.
2579 : MOZ_MUST_USE JmpSrc
2580 0 : cmp_eax()
2581 : {
2582 0 : m_formatter.oneByteOp(OP_CMP_EAXIv);
2583 0 : JmpSrc r = m_formatter.immediateRel32();
2584 0 : spew("cmpl %%eax, .Lfrom%d", r.offset());
2585 0 : return r;
2586 : }
2587 :
2588 695 : void jmp_i(JmpDst dst)
2589 : {
2590 695 : int32_t diff = dst.offset() - m_formatter.size();
2591 695 : spew("jmp .Llabel%d", dst.offset());
2592 :
2593 : // The jump immediate is an offset from the end of the jump instruction.
2594 : // A jump instruction is either 1 byte opcode and 1 byte offset, or 1
2595 : // byte opcode and 4 bytes offset.
2596 695 : if (CAN_SIGN_EXTEND_8_32(diff - 2)) {
2597 365 : m_formatter.oneByteOp(OP_JMP_rel8);
2598 365 : m_formatter.immediate8s(diff - 2);
2599 : } else {
2600 330 : m_formatter.oneByteOp(OP_JMP_rel32);
2601 330 : m_formatter.immediate32(diff - 5);
2602 : }
2603 695 : }
2604 : MOZ_MUST_USE JmpSrc
2605 9220 : jmp()
2606 : {
2607 9220 : m_formatter.oneByteOp(OP_JMP_rel32);
2608 9220 : JmpSrc r = m_formatter.immediateRel32();
2609 9220 : spew("jmp .Lfrom%d", r.offset());
2610 9220 : return r;
2611 : }
2612 :
2613 199 : void jmp_r(RegisterID dst)
2614 : {
2615 199 : spew("jmp *%s", GPRegName(dst));
2616 199 : m_formatter.oneByteOp(OP_GROUP5_Ev, dst, GROUP5_OP_JMPN);
2617 199 : }
2618 :
2619 2384 : void jmp_m(int32_t offset, RegisterID base)
2620 : {
2621 2384 : spew("jmp *" MEM_ob, ADDR_ob(offset, base));
2622 2384 : m_formatter.oneByteOp(OP_GROUP5_Ev, offset, base, GROUP5_OP_JMPN);
2623 2384 : }
2624 :
2625 0 : void jmp_m(int32_t offset, RegisterID base, RegisterID index, int scale) {
2626 0 : spew("jmp *" MEM_obs, ADDR_obs(offset, base, index, scale));
2627 0 : m_formatter.oneByteOp(OP_GROUP5_Ev, offset, base, index, scale, GROUP5_OP_JMPN);
2628 0 : }
2629 :
2630 535 : void jCC_i(Condition cond, JmpDst dst)
2631 : {
2632 535 : int32_t diff = dst.offset() - m_formatter.size();
2633 535 : spew("j%s .Llabel%d", CCName(cond), dst.offset());
2634 :
2635 : // The jump immediate is an offset from the end of the jump instruction.
2636 : // A conditional jump instruction is either 1 byte opcode and 1 byte
2637 : // offset, or 2 bytes opcode and 4 bytes offset.
2638 535 : if (CAN_SIGN_EXTEND_8_32(diff - 2)) {
2639 245 : m_formatter.oneByteOp(jccRel8(cond));
2640 245 : m_formatter.immediate8s(diff - 2);
2641 : } else {
2642 290 : m_formatter.twoByteOp(jccRel32(cond));
2643 290 : m_formatter.immediate32(diff - 6);
2644 : }
2645 535 : }
2646 :
2647 : MOZ_MUST_USE JmpSrc
2648 40369 : jCC(Condition cond)
2649 : {
2650 40369 : m_formatter.twoByteOp(jccRel32(cond));
2651 40369 : JmpSrc r = m_formatter.immediateRel32();
2652 40368 : spew("j%s .Lfrom%d", CCName(cond), r.offset());
2653 40368 : return r;
2654 : }
2655 :
2656 : // SSE operations:
2657 :
2658 0 : void vpcmpeqb_rr(XMMRegisterID src1, XMMRegisterID src0, XMMRegisterID dst)
2659 : {
2660 0 : twoByteOpSimd("vpcmpeqb", VEX_PD, OP2_PCMPEQB_VdqWdq, src1, src0, dst);
2661 0 : }
2662 0 : void vpcmpeqb_mr(int32_t offset, RegisterID base, XMMRegisterID src0, XMMRegisterID dst)
2663 : {
2664 0 : twoByteOpSimd("vpcmpeqb", VEX_PD, OP2_PCMPEQB_VdqWdq, offset, base, src0, dst);
2665 0 : }
2666 0 : void vpcmpeqb_mr(const void* address, XMMRegisterID src0, XMMRegisterID dst)
2667 : {
2668 0 : twoByteOpSimd("vpcmpeqb", VEX_PD, OP2_PCMPEQB_VdqWdq, address, src0, dst);
2669 0 : }
2670 :
2671 0 : void vpcmpgtb_rr(XMMRegisterID src1, XMMRegisterID src0, XMMRegisterID dst)
2672 : {
2673 0 : twoByteOpSimd("vpcmpgtb", VEX_PD, OP2_PCMPGTB_VdqWdq, src1, src0, dst);
2674 0 : }
2675 0 : void vpcmpgtb_mr(int32_t offset, RegisterID base, XMMRegisterID src0, XMMRegisterID dst)
2676 : {
2677 0 : twoByteOpSimd("vpcmpgtb", VEX_PD, OP2_PCMPGTB_VdqWdq, offset, base, src0, dst);
2678 0 : }
2679 0 : void vpcmpgtb_mr(const void* address, XMMRegisterID src0, XMMRegisterID dst)
2680 : {
2681 0 : twoByteOpSimd("vpcmpgtb", VEX_PD, OP2_PCMPGTB_VdqWdq, address, src0, dst);
2682 0 : }
2683 :
2684 0 : void vpcmpeqw_rr(XMMRegisterID src1, XMMRegisterID src0, XMMRegisterID dst)
2685 : {
2686 0 : twoByteOpSimd("vpcmpeqw", VEX_PD, OP2_PCMPEQW_VdqWdq, src1, src0, dst);
2687 0 : }
2688 0 : void vpcmpeqw_mr(int32_t offset, RegisterID base, XMMRegisterID src0, XMMRegisterID dst)
2689 : {
2690 0 : twoByteOpSimd("vpcmpeqw", VEX_PD, OP2_PCMPEQW_VdqWdq, offset, base, src0, dst);
2691 0 : }
2692 0 : void vpcmpeqw_mr(const void* address, XMMRegisterID src0, XMMRegisterID dst)
2693 : {
2694 0 : twoByteOpSimd("vpcmpeqw", VEX_PD, OP2_PCMPEQW_VdqWdq, address, src0, dst);
2695 0 : }
2696 :
2697 0 : void vpcmpgtw_rr(XMMRegisterID src1, XMMRegisterID src0, XMMRegisterID dst)
2698 : {
2699 0 : twoByteOpSimd("vpcmpgtw", VEX_PD, OP2_PCMPGTW_VdqWdq, src1, src0, dst);
2700 0 : }
2701 0 : void vpcmpgtw_mr(int32_t offset, RegisterID base, XMMRegisterID src0, XMMRegisterID dst)
2702 : {
2703 0 : twoByteOpSimd("vpcmpgtw", VEX_PD, OP2_PCMPGTW_VdqWdq, offset, base, src0, dst);
2704 0 : }
2705 0 : void vpcmpgtw_mr(const void* address, XMMRegisterID src0, XMMRegisterID dst)
2706 : {
2707 0 : twoByteOpSimd("vpcmpgtw", VEX_PD, OP2_PCMPGTW_VdqWdq, address, src0, dst);
2708 0 : }
2709 :
2710 0 : void vpcmpeqd_rr(XMMRegisterID src1, XMMRegisterID src0, XMMRegisterID dst)
2711 : {
2712 0 : twoByteOpSimd("vpcmpeqd", VEX_PD, OP2_PCMPEQD_VdqWdq, src1, src0, dst);
2713 0 : }
2714 0 : void vpcmpeqd_mr(int32_t offset, RegisterID base, XMMRegisterID src0, XMMRegisterID dst)
2715 : {
2716 0 : twoByteOpSimd("vpcmpeqd", VEX_PD, OP2_PCMPEQD_VdqWdq, offset, base, src0, dst);
2717 0 : }
2718 0 : void vpcmpeqd_mr(const void* address, XMMRegisterID src0, XMMRegisterID dst)
2719 : {
2720 0 : twoByteOpSimd("vpcmpeqd", VEX_PD, OP2_PCMPEQD_VdqWdq, address, src0, dst);
2721 0 : }
2722 :
2723 0 : void vpcmpgtd_rr(XMMRegisterID src1, XMMRegisterID src0, XMMRegisterID dst)
2724 : {
2725 0 : twoByteOpSimd("vpcmpgtd", VEX_PD, OP2_PCMPGTD_VdqWdq, src1, src0, dst);
2726 0 : }
2727 0 : void vpcmpgtd_mr(int32_t offset, RegisterID base, XMMRegisterID src0, XMMRegisterID dst)
2728 : {
2729 0 : twoByteOpSimd("vpcmpgtd", VEX_PD, OP2_PCMPGTD_VdqWdq, offset, base, src0, dst);
2730 0 : }
2731 0 : void vpcmpgtd_mr(const void* address, XMMRegisterID src0, XMMRegisterID dst)
2732 : {
2733 0 : twoByteOpSimd("vpcmpgtd", VEX_PD, OP2_PCMPGTD_VdqWdq, address, src0, dst);
2734 0 : }
2735 :
2736 0 : void vcmpps_rr(uint8_t order, XMMRegisterID src1, XMMRegisterID src0, XMMRegisterID dst)
2737 : {
2738 0 : twoByteOpImmSimd("vcmpps", VEX_PS, OP2_CMPPS_VpsWps, order, src1, src0, dst);
2739 0 : }
2740 0 : void vcmpps_mr(uint8_t order, int32_t offset, RegisterID base, XMMRegisterID src0, XMMRegisterID dst)
2741 : {
2742 0 : twoByteOpImmSimd("vcmpps", VEX_PS, OP2_CMPPS_VpsWps, order, offset, base, src0, dst);
2743 0 : }
2744 0 : void vcmpps_mr(uint8_t order, const void* address, XMMRegisterID src0, XMMRegisterID dst)
2745 : {
2746 0 : twoByteOpImmSimd("vcmpps", VEX_PS, OP2_CMPPS_VpsWps, order, address, src0, dst);
2747 0 : }
2748 :
2749 0 : void vrcpps_rr(XMMRegisterID src, XMMRegisterID dst) {
2750 0 : twoByteOpSimd("vrcpps", VEX_PS, OP2_RCPPS_VpsWps, src, invalid_xmm, dst);
2751 0 : }
2752 0 : void vrcpps_mr(int32_t offset, RegisterID base, XMMRegisterID dst) {
2753 0 : twoByteOpSimd("vrcpps", VEX_PS, OP2_RCPPS_VpsWps, offset, base, invalid_xmm, dst);
2754 0 : }
2755 0 : void vrcpps_mr(const void* address, XMMRegisterID dst) {
2756 0 : twoByteOpSimd("vrcpps", VEX_PS, OP2_RCPPS_VpsWps, address, invalid_xmm, dst);
2757 0 : }
2758 :
2759 0 : void vrsqrtps_rr(XMMRegisterID src, XMMRegisterID dst) {
2760 0 : twoByteOpSimd("vrsqrtps", VEX_PS, OP2_RSQRTPS_VpsWps, src, invalid_xmm, dst);
2761 0 : }
2762 0 : void vrsqrtps_mr(int32_t offset, RegisterID base, XMMRegisterID dst) {
2763 0 : twoByteOpSimd("vrsqrtps", VEX_PS, OP2_RSQRTPS_VpsWps, offset, base, invalid_xmm, dst);
2764 0 : }
2765 0 : void vrsqrtps_mr(const void* address, XMMRegisterID dst) {
2766 0 : twoByteOpSimd("vrsqrtps", VEX_PS, OP2_RSQRTPS_VpsWps, address, invalid_xmm, dst);
2767 0 : }
2768 :
2769 0 : void vsqrtps_rr(XMMRegisterID src, XMMRegisterID dst) {
2770 0 : twoByteOpSimd("vsqrtps", VEX_PS, OP2_SQRTPS_VpsWps, src, invalid_xmm, dst);
2771 0 : }
2772 0 : void vsqrtps_mr(int32_t offset, RegisterID base, XMMRegisterID dst) {
2773 0 : twoByteOpSimd("vsqrtps", VEX_PS, OP2_SQRTPS_VpsWps, offset, base, invalid_xmm, dst);
2774 0 : }
2775 0 : void vsqrtps_mr(const void* address, XMMRegisterID dst) {
2776 0 : twoByteOpSimd("vsqrtps", VEX_PS, OP2_SQRTPS_VpsWps, address, invalid_xmm, dst);
2777 0 : }
2778 :
2779 0 : void vaddsd_rr(XMMRegisterID src1, XMMRegisterID src0, XMMRegisterID dst)
2780 : {
2781 0 : twoByteOpSimd("vaddsd", VEX_SD, OP2_ADDSD_VsdWsd, src1, src0, dst);
2782 0 : }
2783 :
2784 0 : void vaddss_rr(XMMRegisterID src1, XMMRegisterID src0, XMMRegisterID dst)
2785 : {
2786 0 : twoByteOpSimd("vaddss", VEX_SS, OP2_ADDSD_VsdWsd, src1, src0, dst);
2787 0 : }
2788 :
2789 0 : void vaddsd_mr(int32_t offset, RegisterID base, XMMRegisterID src0, XMMRegisterID dst)
2790 : {
2791 0 : twoByteOpSimd("vaddsd", VEX_SD, OP2_ADDSD_VsdWsd, offset, base, src0, dst);
2792 0 : }
2793 :
2794 0 : void vaddss_mr(int32_t offset, RegisterID base, XMMRegisterID src0, XMMRegisterID dst)
2795 : {
2796 0 : twoByteOpSimd("vaddss", VEX_SS, OP2_ADDSD_VsdWsd, offset, base, src0, dst);
2797 0 : }
2798 :
2799 0 : void vaddsd_mr(const void* address, XMMRegisterID src0, XMMRegisterID dst)
2800 : {
2801 0 : twoByteOpSimd("vaddsd", VEX_SD, OP2_ADDSD_VsdWsd, address, src0, dst);
2802 0 : }
2803 0 : void vaddss_mr(const void* address, XMMRegisterID src0, XMMRegisterID dst)
2804 : {
2805 0 : twoByteOpSimd("vaddss", VEX_SS, OP2_ADDSD_VsdWsd, address, src0, dst);
2806 0 : }
2807 :
2808 0 : void vcvtss2sd_rr(XMMRegisterID src1, XMMRegisterID src0, XMMRegisterID dst)
2809 : {
2810 0 : twoByteOpSimd("vcvtss2sd", VEX_SS, OP2_CVTSS2SD_VsdEd, src1, src0, dst);
2811 0 : }
2812 :
2813 0 : void vcvtsd2ss_rr(XMMRegisterID src1, XMMRegisterID src0, XMMRegisterID dst)
2814 : {
2815 0 : twoByteOpSimd("vcvtsd2ss", VEX_SD, OP2_CVTSD2SS_VsdEd, src1, src0, dst);
2816 0 : }
2817 :
2818 0 : void vcvtsi2ss_rr(RegisterID src1, XMMRegisterID src0, XMMRegisterID dst)
2819 : {
2820 0 : twoByteOpInt32Simd("vcvtsi2ss", VEX_SS, OP2_CVTSI2SD_VsdEd, src1, src0, dst);
2821 0 : }
2822 :
2823 58 : void vcvtsi2sd_rr(RegisterID src1, XMMRegisterID src0, XMMRegisterID dst)
2824 : {
2825 58 : twoByteOpInt32Simd("vcvtsi2sd", VEX_SD, OP2_CVTSI2SD_VsdEd, src1, src0, dst);
2826 58 : }
2827 :
2828 0 : void vcvttps2dq_rr(XMMRegisterID src, XMMRegisterID dst)
2829 : {
2830 0 : twoByteOpSimd("vcvttps2dq", VEX_SS, OP2_CVTTPS2DQ_VdqWps, src, invalid_xmm, dst);
2831 0 : }
2832 :
2833 0 : void vcvtdq2ps_rr(XMMRegisterID src, XMMRegisterID dst)
2834 : {
2835 0 : twoByteOpSimd("vcvtdq2ps", VEX_PS, OP2_CVTDQ2PS_VpsWdq, src, invalid_xmm, dst);
2836 0 : }
2837 :
2838 0 : void vcvtsi2sd_mr(int32_t offset, RegisterID base, XMMRegisterID src0, XMMRegisterID dst)
2839 : {
2840 0 : twoByteOpSimd("vcvtsi2sd", VEX_SD, OP2_CVTSI2SD_VsdEd, offset, base, src0, dst);
2841 0 : }
2842 :
2843 0 : void vcvtsi2sd_mr(int32_t offset, RegisterID base, RegisterID index, int scale, XMMRegisterID src0, XMMRegisterID dst)
2844 : {
2845 0 : twoByteOpSimd("vcvtsi2sd", VEX_SD, OP2_CVTSI2SD_VsdEd, offset, base, index, scale, src0, dst);
2846 0 : }
2847 :
2848 : void vcvtsi2ss_mr(int32_t offset, RegisterID base, XMMRegisterID src0, XMMRegisterID dst)
2849 : {
2850 : twoByteOpSimd("vcvtsi2ss", VEX_SS, OP2_CVTSI2SD_VsdEd, offset, base, src0, dst);
2851 : }
2852 :
2853 : void vcvtsi2ss_mr(int32_t offset, RegisterID base, RegisterID index, int scale, XMMRegisterID src0, XMMRegisterID dst)
2854 : {
2855 : twoByteOpSimd("vcvtsi2ss", VEX_SS, OP2_CVTSI2SD_VsdEd, offset, base, index, scale, src0, dst);
2856 : }
2857 :
2858 26 : void vcvttsd2si_rr(XMMRegisterID src, RegisterID dst)
2859 : {
2860 26 : twoByteOpSimdInt32("vcvttsd2si", VEX_SD, OP2_CVTTSD2SI_GdWsd, src, dst);
2861 26 : }
2862 :
2863 0 : void vcvttss2si_rr(XMMRegisterID src, RegisterID dst)
2864 : {
2865 0 : twoByteOpSimdInt32("vcvttss2si", VEX_SS, OP2_CVTTSD2SI_GdWsd, src, dst);
2866 0 : }
2867 :
2868 0 : void vunpcklps_rr(XMMRegisterID src1, XMMRegisterID src0, XMMRegisterID dst)
2869 : {
2870 0 : twoByteOpSimd("vunpcklps", VEX_PS, OP2_UNPCKLPS_VsdWsd, src1, src0, dst);
2871 0 : }
2872 0 : void vunpcklps_mr(int32_t offset, RegisterID base, XMMRegisterID src0, XMMRegisterID dst)
2873 : {
2874 0 : twoByteOpSimd("vunpcklps", VEX_PS, OP2_UNPCKLPS_VsdWsd, offset, base, src0, dst);
2875 0 : }
2876 0 : void vunpcklps_mr(const void* addr, XMMRegisterID src0, XMMRegisterID dst)
2877 : {
2878 0 : twoByteOpSimd("vunpcklps", VEX_PS, OP2_UNPCKLPS_VsdWsd, addr, src0, dst);
2879 0 : }
2880 :
2881 0 : void vunpckhps_rr(XMMRegisterID src1, XMMRegisterID src0, XMMRegisterID dst)
2882 : {
2883 0 : twoByteOpSimd("vunpckhps", VEX_PS, OP2_UNPCKHPS_VsdWsd, src1, src0, dst);
2884 0 : }
2885 0 : void vunpckhps_mr(int32_t offset, RegisterID base, XMMRegisterID src0, XMMRegisterID dst)
2886 : {
2887 0 : twoByteOpSimd("vunpckhps", VEX_PS, OP2_UNPCKHPS_VsdWsd, offset, base, src0, dst);
2888 0 : }
2889 0 : void vunpckhps_mr(const void* addr, XMMRegisterID src0, XMMRegisterID dst)
2890 : {
2891 0 : twoByteOpSimd("vunpckhps", VEX_PS, OP2_UNPCKHPS_VsdWsd, addr, src0, dst);
2892 0 : }
2893 :
2894 0 : void vpand_rr(XMMRegisterID src1, XMMRegisterID src0, XMMRegisterID dst)
2895 : {
2896 0 : twoByteOpSimd("vpand", VEX_PD, OP2_PANDDQ_VdqWdq, src1, src0, dst);
2897 0 : }
2898 0 : void vpand_mr(int32_t offset, RegisterID base, XMMRegisterID src0, XMMRegisterID dst)
2899 : {
2900 0 : twoByteOpSimd("vpand", VEX_PD, OP2_PANDDQ_VdqWdq, offset, base, src0, dst);
2901 0 : }
2902 0 : void vpand_mr(const void* address, XMMRegisterID src0, XMMRegisterID dst)
2903 : {
2904 0 : twoByteOpSimd("vpand", VEX_PD, OP2_PANDDQ_VdqWdq, address, src0, dst);
2905 0 : }
2906 0 : void vpor_rr(XMMRegisterID src1, XMMRegisterID src0, XMMRegisterID dst)
2907 : {
2908 0 : twoByteOpSimd("vpor", VEX_PD, OP2_PORDQ_VdqWdq, src1, src0, dst);
2909 0 : }
2910 0 : void vpor_mr(int32_t offset, RegisterID base, XMMRegisterID src0, XMMRegisterID dst)
2911 : {
2912 0 : twoByteOpSimd("vpor", VEX_PD, OP2_PORDQ_VdqWdq, offset, base, src0, dst);
2913 0 : }
2914 0 : void vpor_mr(const void* address, XMMRegisterID src0, XMMRegisterID dst)
2915 : {
2916 0 : twoByteOpSimd("vpor", VEX_PD, OP2_PORDQ_VdqWdq, address, src0, dst);
2917 0 : }
2918 0 : void vpxor_rr(XMMRegisterID src1, XMMRegisterID src0, XMMRegisterID dst)
2919 : {
2920 0 : twoByteOpSimd("vpxor", VEX_PD, OP2_PXORDQ_VdqWdq, src1, src0, dst);
2921 0 : }
2922 0 : void vpxor_mr(int32_t offset, RegisterID base, XMMRegisterID src0, XMMRegisterID dst)
2923 : {
2924 0 : twoByteOpSimd("vpxor", VEX_PD, OP2_PXORDQ_VdqWdq, offset, base, src0, dst);
2925 0 : }
2926 0 : void vpxor_mr(const void* address, XMMRegisterID src0, XMMRegisterID dst)
2927 : {
2928 0 : twoByteOpSimd("vpxor", VEX_PD, OP2_PXORDQ_VdqWdq, address, src0, dst);
2929 0 : }
2930 : void vpandn_rr(XMMRegisterID src1, XMMRegisterID src0, XMMRegisterID dst)
2931 : {
2932 : twoByteOpSimd("vpandn", VEX_PD, OP2_PANDNDQ_VdqWdq, src1, src0, dst);
2933 : }
2934 : void vpandn_mr(int32_t offset, RegisterID base, XMMRegisterID src0, XMMRegisterID dst)
2935 : {
2936 : twoByteOpSimd("vpandn", VEX_PD, OP2_PANDNDQ_VdqWdq, offset, base, src0, dst);
2937 : }
2938 : void vpandn_mr(const void* address, XMMRegisterID src0, XMMRegisterID dst)
2939 : {
2940 : twoByteOpSimd("vpandn", VEX_PD, OP2_PANDNDQ_VdqWdq, address, src0, dst);
2941 : }
2942 :
2943 0 : void vpshufd_irr(uint32_t mask, XMMRegisterID src, XMMRegisterID dst)
2944 : {
2945 0 : twoByteOpImmSimd("vpshufd", VEX_PD, OP2_PSHUFD_VdqWdqIb, mask, src, invalid_xmm, dst);
2946 0 : }
2947 0 : void vpshufd_imr(uint32_t mask, int32_t offset, RegisterID base, XMMRegisterID dst)
2948 : {
2949 0 : twoByteOpImmSimd("vpshufd", VEX_PD, OP2_PSHUFD_VdqWdqIb, mask, offset, base, invalid_xmm, dst);
2950 0 : }
2951 0 : void vpshufd_imr(uint32_t mask, const void* address, XMMRegisterID dst)
2952 : {
2953 0 : twoByteOpImmSimd("vpshufd", VEX_PD, OP2_PSHUFD_VdqWdqIb, mask, address, invalid_xmm, dst);
2954 0 : }
2955 :
2956 0 : void vpshuflw_irr(uint32_t mask, XMMRegisterID src, XMMRegisterID dst)
2957 : {
2958 0 : twoByteOpImmSimd("vpshuflw", VEX_SD, OP2_PSHUFLW_VdqWdqIb, mask, src, invalid_xmm, dst);
2959 0 : }
2960 :
2961 : void vpshufhw_irr(uint32_t mask, XMMRegisterID src, XMMRegisterID dst)
2962 : {
2963 : twoByteOpImmSimd("vpshufhw", VEX_SS, OP2_PSHUFHW_VdqWdqIb, mask, src, invalid_xmm, dst);
2964 : }
2965 :
2966 0 : void vpshufb_rr(XMMRegisterID src1, XMMRegisterID src0, XMMRegisterID dst)
2967 : {
2968 0 : threeByteOpSimd("vpshufb", VEX_PD, OP3_PSHUFB_VdqWdq, ESCAPE_38, src1, src0, dst);
2969 0 : }
2970 :
2971 0 : void vshufps_irr(uint32_t mask, XMMRegisterID src1, XMMRegisterID src0, XMMRegisterID dst)
2972 : {
2973 0 : twoByteOpImmSimd("vshufps", VEX_PS, OP2_SHUFPS_VpsWpsIb, mask, src1, src0, dst);
2974 0 : }
2975 0 : void vshufps_imr(uint32_t mask, int32_t offset, RegisterID base, XMMRegisterID src0, XMMRegisterID dst)
2976 : {
2977 0 : twoByteOpImmSimd("vshufps", VEX_PS, OP2_SHUFPS_VpsWpsIb, mask, offset, base, src0, dst);
2978 0 : }
2979 0 : void vshufps_imr(uint32_t mask, const void* address, XMMRegisterID src0, XMMRegisterID dst)
2980 : {
2981 0 : twoByteOpImmSimd("vshufps", VEX_PS, OP2_SHUFPS_VpsWpsIb, mask, address, src0, dst);
2982 0 : }
2983 :
2984 0 : void vmovddup_rr(XMMRegisterID src, XMMRegisterID dst)
2985 : {
2986 0 : twoByteOpSimd("vmovddup", VEX_SD, OP2_MOVDDUP_VqWq, src, invalid_xmm, dst);
2987 0 : }
2988 :
2989 0 : void vmovhlps_rr(XMMRegisterID src1, XMMRegisterID src0, XMMRegisterID dst)
2990 : {
2991 0 : twoByteOpSimd("vmovhlps", VEX_PS, OP2_MOVHLPS_VqUq, src1, src0, dst);
2992 0 : }
2993 :
2994 0 : void vmovlhps_rr(XMMRegisterID src1, XMMRegisterID src0, XMMRegisterID dst)
2995 : {
2996 0 : twoByteOpSimd("vmovlhps", VEX_PS, OP2_MOVLHPS_VqUq, src1, src0, dst);
2997 0 : }
2998 :
2999 : void vpsrldq_ir(uint32_t count, XMMRegisterID src, XMMRegisterID dst)
3000 : {
3001 : MOZ_ASSERT(count < 16);
3002 : shiftOpImmSimd("vpsrldq", OP2_PSRLDQ_Vd, ShiftID::vpsrldq, count, src, dst);
3003 : }
3004 :
3005 0 : void vpsllq_ir(uint32_t count, XMMRegisterID src, XMMRegisterID dst)
3006 : {
3007 0 : MOZ_ASSERT(count < 64);
3008 0 : shiftOpImmSimd("vpsllq", OP2_PSRLDQ_Vd, ShiftID::vpsllx, count, src, dst);
3009 0 : }
3010 :
3011 : void vpsrlq_ir(uint32_t count, XMMRegisterID src, XMMRegisterID dst)
3012 : {
3013 : MOZ_ASSERT(count < 64);
3014 : shiftOpImmSimd("vpsrlq", OP2_PSRLDQ_Vd, ShiftID::vpsrlx, count, src, dst);
3015 : }
3016 :
3017 0 : void vpslld_rr(XMMRegisterID src1, XMMRegisterID src0, XMMRegisterID dst)
3018 : {
3019 0 : twoByteOpSimd("vpslld", VEX_PD, OP2_PSLLD_VdqWdq, src1, src0, dst);
3020 0 : }
3021 :
3022 0 : void vpslld_ir(uint32_t count, XMMRegisterID src, XMMRegisterID dst)
3023 : {
3024 0 : MOZ_ASSERT(count < 32);
3025 0 : shiftOpImmSimd("vpslld", OP2_PSLLD_UdqIb, ShiftID::vpsllx, count, src, dst);
3026 0 : }
3027 :
3028 0 : void vpsrad_rr(XMMRegisterID src1, XMMRegisterID src0, XMMRegisterID dst)
3029 : {
3030 0 : twoByteOpSimd("vpsrad", VEX_PD, OP2_PSRAD_VdqWdq, src1, src0, dst);
3031 0 : }
3032 :
3033 0 : void vpsrad_ir(int32_t count, XMMRegisterID src, XMMRegisterID dst)
3034 : {
3035 0 : MOZ_ASSERT(count < 32);
3036 0 : shiftOpImmSimd("vpsrad", OP2_PSRAD_UdqIb, ShiftID::vpsrad, count, src, dst);
3037 0 : }
3038 :
3039 0 : void vpsrld_rr(XMMRegisterID src1, XMMRegisterID src0, XMMRegisterID dst)
3040 : {
3041 0 : twoByteOpSimd("vpsrld", VEX_PD, OP2_PSRLD_VdqWdq, src1, src0, dst);
3042 0 : }
3043 :
3044 0 : void vpsrld_ir(uint32_t count, XMMRegisterID src, XMMRegisterID dst)
3045 : {
3046 0 : MOZ_ASSERT(count < 32);
3047 0 : shiftOpImmSimd("vpsrld", OP2_PSRLD_UdqIb, ShiftID::vpsrlx, count, src, dst);
3048 0 : }
3049 :
3050 0 : void vpsllw_rr(XMMRegisterID src1, XMMRegisterID src0, XMMRegisterID dst)
3051 : {
3052 0 : twoByteOpSimd("vpsllw", VEX_PD, OP2_PSLLW_VdqWdq, src1, src0, dst);
3053 0 : }
3054 :
3055 0 : void vpsllw_ir(uint32_t count, XMMRegisterID src, XMMRegisterID dst)
3056 : {
3057 0 : MOZ_ASSERT(count < 16);
3058 0 : shiftOpImmSimd("vpsllw", OP2_PSLLW_UdqIb, ShiftID::vpsllx, count, src, dst);
3059 0 : }
3060 :
3061 0 : void vpsraw_rr(XMMRegisterID src1, XMMRegisterID src0, XMMRegisterID dst)
3062 : {
3063 0 : twoByteOpSimd("vpsraw", VEX_PD, OP2_PSRAW_VdqWdq, src1, src0, dst);
3064 0 : }
3065 :
3066 0 : void vpsraw_ir(int32_t count, XMMRegisterID src, XMMRegisterID dst)
3067 : {
3068 0 : MOZ_ASSERT(count < 16);
3069 0 : shiftOpImmSimd("vpsraw", OP2_PSRAW_UdqIb, ShiftID::vpsrad, count, src, dst);
3070 0 : }
3071 :
3072 0 : void vpsrlw_rr(XMMRegisterID src1, XMMRegisterID src0, XMMRegisterID dst)
3073 : {
3074 0 : twoByteOpSimd("vpsrlw", VEX_PD, OP2_PSRLW_VdqWdq, src1, src0, dst);
3075 0 : }
3076 :
3077 0 : void vpsrlw_ir(uint32_t count, XMMRegisterID src, XMMRegisterID dst)
3078 : {
3079 0 : MOZ_ASSERT(count < 16);
3080 0 : shiftOpImmSimd("vpsrlw", OP2_PSRLW_UdqIb, ShiftID::vpsrlx, count, src, dst);
3081 0 : }
3082 :
3083 0 : void vmovmskpd_rr(XMMRegisterID src, RegisterID dst)
3084 : {
3085 0 : twoByteOpSimdInt32("vmovmskpd", VEX_PD, OP2_MOVMSKPD_EdVd, src, dst);
3086 0 : }
3087 :
3088 0 : void vmovmskps_rr(XMMRegisterID src, RegisterID dst)
3089 : {
3090 0 : twoByteOpSimdInt32("vmovmskps", VEX_PS, OP2_MOVMSKPD_EdVd, src, dst);
3091 0 : }
3092 :
3093 0 : void vpmovmskb_rr(XMMRegisterID src, RegisterID dst)
3094 : {
3095 0 : twoByteOpSimdInt32("vpmovmskb", VEX_PD, OP2_PMOVMSKB_EdVd, src, dst);
3096 0 : }
3097 :
3098 : void vptest_rr(XMMRegisterID rhs, XMMRegisterID lhs) {
3099 : threeByteOpSimd("vptest", VEX_PD, OP3_PTEST_VdVd, ESCAPE_38, rhs, invalid_xmm, lhs);
3100 : }
3101 :
3102 0 : void vmovd_rr(XMMRegisterID src, RegisterID dst)
3103 : {
3104 0 : twoByteOpSimdInt32("vmovd", VEX_PD, OP2_MOVD_EdVd, (XMMRegisterID)dst, (RegisterID)src);
3105 0 : }
3106 :
3107 0 : void vmovd_rr(RegisterID src, XMMRegisterID dst)
3108 : {
3109 0 : twoByteOpInt32Simd("vmovd", VEX_PD, OP2_MOVD_VdEd, src, invalid_xmm, dst);
3110 0 : }
3111 :
3112 0 : void vmovd_mr(int32_t offset, RegisterID base, XMMRegisterID dst)
3113 : {
3114 0 : twoByteOpSimd("vmovd", VEX_PD, OP2_MOVD_VdEd, offset, base, invalid_xmm, dst);
3115 0 : }
3116 :
3117 0 : void vmovd_mr(int32_t offset, RegisterID base, RegisterID index, int32_t scale, XMMRegisterID dst)
3118 : {
3119 0 : twoByteOpSimd("vmovd", VEX_PD, OP2_MOVD_VdEd, offset, base, index, scale, invalid_xmm, dst);
3120 0 : }
3121 :
3122 : void vmovd_mr_disp32(int32_t offset, RegisterID base, XMMRegisterID dst)
3123 : {
3124 : twoByteOpSimd_disp32("vmovd", VEX_PD, OP2_MOVD_VdEd, offset, base, invalid_xmm, dst);
3125 : }
3126 :
3127 : void vmovd_mr(const void* address, XMMRegisterID dst)
3128 : {
3129 : twoByteOpSimd("vmovd", VEX_PD, OP2_MOVD_VdEd, address, invalid_xmm, dst);
3130 : }
3131 :
3132 0 : void vmovd_rm(XMMRegisterID src, int32_t offset, RegisterID base)
3133 : {
3134 0 : twoByteOpSimd("vmovd", VEX_PD, OP2_MOVD_EdVd, offset, base, invalid_xmm, src);
3135 0 : }
3136 :
3137 0 : void vmovd_rm(XMMRegisterID src, int32_t offset, RegisterID base, RegisterID index, int scale)
3138 : {
3139 0 : twoByteOpSimd("vmovd", VEX_PD, OP2_MOVD_EdVd, offset, base, index, scale, invalid_xmm, src);
3140 0 : }
3141 :
3142 : void vmovd_rm_disp32(XMMRegisterID src, int32_t offset, RegisterID base)
3143 : {
3144 : twoByteOpSimd_disp32("vmovd", VEX_PD, OP2_MOVD_EdVd, offset, base, invalid_xmm, src);
3145 : }
3146 :
3147 : void vmovd_rm(XMMRegisterID src, const void* address)
3148 : {
3149 : twoByteOpSimd("vmovd", VEX_PD, OP2_MOVD_EdVd, address, invalid_xmm, src);
3150 : }
3151 :
3152 7 : void vmovsd_rm(XMMRegisterID src, int32_t offset, RegisterID base)
3153 : {
3154 7 : twoByteOpSimd("vmovsd", VEX_SD, OP2_MOVSD_WsdVsd, offset, base, invalid_xmm, src);
3155 7 : }
3156 :
3157 : void vmovsd_rm_disp32(XMMRegisterID src, int32_t offset, RegisterID base)
3158 : {
3159 : twoByteOpSimd_disp32("vmovsd", VEX_SD, OP2_MOVSD_WsdVsd, offset, base, invalid_xmm, src);
3160 : }
3161 :
3162 0 : void vmovss_rm(XMMRegisterID src, int32_t offset, RegisterID base)
3163 : {
3164 0 : twoByteOpSimd("vmovss", VEX_SS, OP2_MOVSD_WsdVsd, offset, base, invalid_xmm, src);
3165 0 : }
3166 :
3167 : void vmovss_rm_disp32(XMMRegisterID src, int32_t offset, RegisterID base)
3168 : {
3169 : twoByteOpSimd_disp32("vmovss", VEX_SS, OP2_MOVSD_WsdVsd, offset, base, invalid_xmm, src);
3170 : }
3171 :
3172 0 : void vmovss_mr(int32_t offset, RegisterID base, XMMRegisterID dst)
3173 : {
3174 0 : twoByteOpSimd("vmovss", VEX_SS, OP2_MOVSD_VsdWsd, offset, base, invalid_xmm, dst);
3175 0 : }
3176 :
3177 : void vmovss_mr_disp32(int32_t offset, RegisterID base, XMMRegisterID dst)
3178 : {
3179 : twoByteOpSimd_disp32("vmovss", VEX_SS, OP2_MOVSD_VsdWsd, offset, base, invalid_xmm, dst);
3180 : }
3181 :
3182 0 : void vmovsd_rm(XMMRegisterID src, int32_t offset, RegisterID base, RegisterID index, int scale)
3183 : {
3184 0 : twoByteOpSimd("vmovsd", VEX_SD, OP2_MOVSD_WsdVsd, offset, base, index, scale, invalid_xmm, src);
3185 0 : }
3186 :
3187 0 : void vmovss_rm(XMMRegisterID src, int32_t offset, RegisterID base, RegisterID index, int scale)
3188 : {
3189 0 : twoByteOpSimd("vmovss", VEX_SS, OP2_MOVSD_WsdVsd, offset, base, index, scale, invalid_xmm, src);
3190 0 : }
3191 :
3192 0 : void vmovss_mr(int32_t offset, RegisterID base, RegisterID index, int scale, XMMRegisterID dst)
3193 : {
3194 0 : twoByteOpSimd("vmovss", VEX_SS, OP2_MOVSD_VsdWsd, offset, base, index, scale, invalid_xmm, dst);
3195 0 : }
3196 :
3197 16 : void vmovsd_mr(int32_t offset, RegisterID base, XMMRegisterID dst)
3198 : {
3199 16 : twoByteOpSimd("vmovsd", VEX_SD, OP2_MOVSD_VsdWsd, offset, base, invalid_xmm, dst);
3200 16 : }
3201 :
3202 : void vmovsd_mr_disp32(int32_t offset, RegisterID base, XMMRegisterID dst)
3203 : {
3204 : twoByteOpSimd_disp32("vmovsd", VEX_SD, OP2_MOVSD_VsdWsd, offset, base, invalid_xmm, dst);
3205 : }
3206 :
3207 0 : void vmovsd_mr(int32_t offset, RegisterID base, RegisterID index, int scale, XMMRegisterID dst)
3208 : {
3209 0 : twoByteOpSimd("vmovsd", VEX_SD, OP2_MOVSD_VsdWsd, offset, base, index, scale, invalid_xmm, dst);
3210 0 : }
3211 :
3212 : // Note that the register-to-register form of vmovsd does not write to the
3213 : // entire output register. For general-purpose register-to-register moves,
3214 : // use vmovapd instead.
3215 : void vmovsd_rr(XMMRegisterID src1, XMMRegisterID src0, XMMRegisterID dst)
3216 : {
3217 : twoByteOpSimd("vmovsd", VEX_SD, OP2_MOVSD_VsdWsd, src1, src0, dst);
3218 : }
3219 :
3220 : // The register-to-register form of vmovss has the same problem as vmovsd
3221 : // above. Prefer vmovaps for register-to-register moves.
3222 0 : void vmovss_rr(XMMRegisterID src1, XMMRegisterID src0, XMMRegisterID dst)
3223 : {
3224 0 : twoByteOpSimd("vmovss", VEX_SS, OP2_MOVSD_VsdWsd, src1, src0, dst);
3225 0 : }
3226 :
3227 : void vmovsd_mr(const void* address, XMMRegisterID dst)
3228 : {
3229 : twoByteOpSimd("vmovsd", VEX_SD, OP2_MOVSD_VsdWsd, address, invalid_xmm, dst);
3230 : }
3231 :
3232 : void vmovss_mr(const void* address, XMMRegisterID dst)
3233 : {
3234 : twoByteOpSimd("vmovss", VEX_SS, OP2_MOVSD_VsdWsd, address, invalid_xmm, dst);
3235 : }
3236 :
3237 : void vmovups_mr(const void* address, XMMRegisterID dst)
3238 : {
3239 : twoByteOpSimd("vmovups", VEX_PS, OP2_MOVPS_VpsWps, address, invalid_xmm, dst);
3240 : }
3241 :
3242 : void vmovdqu_mr(const void* address, XMMRegisterID dst)
3243 : {
3244 : twoByteOpSimd("vmovdqu", VEX_SS, OP2_MOVDQ_VdqWdq, address, invalid_xmm, dst);
3245 : }
3246 :
3247 : void vmovsd_rm(XMMRegisterID src, const void* address)
3248 : {
3249 : twoByteOpSimd("vmovsd", VEX_SD, OP2_MOVSD_WsdVsd, address, invalid_xmm, src);
3250 : }
3251 :
3252 : void vmovss_rm(XMMRegisterID src, const void* address)
3253 : {
3254 : twoByteOpSimd("vmovss", VEX_SS, OP2_MOVSD_WsdVsd, address, invalid_xmm, src);
3255 : }
3256 :
3257 : void vmovdqa_rm(XMMRegisterID src, const void* address)
3258 : {
3259 : twoByteOpSimd("vmovdqa", VEX_PD, OP2_MOVDQ_WdqVdq, address, invalid_xmm, src);
3260 : }
3261 :
3262 : void vmovaps_rm(XMMRegisterID src, const void* address)
3263 : {
3264 : twoByteOpSimd("vmovaps", VEX_PS, OP2_MOVAPS_WsdVsd, address, invalid_xmm, src);
3265 : }
3266 :
3267 : void vmovdqu_rm(XMMRegisterID src, const void* address)
3268 : {
3269 : twoByteOpSimd("vmovdqu", VEX_SS, OP2_MOVDQ_WdqVdq, address, invalid_xmm, src);
3270 : }
3271 :
3272 : void vmovups_rm(XMMRegisterID src, const void* address)
3273 : {
3274 : twoByteOpSimd("vmovups", VEX_PS, OP2_MOVPS_WpsVps, address, invalid_xmm, src);
3275 : }
3276 :
3277 0 : void vmovaps_rr(XMMRegisterID src, XMMRegisterID dst)
3278 : {
3279 : #ifdef JS_CODEGEN_X64
3280 : // There are two opcodes that can encode this instruction. If we have
3281 : // one register in [xmm8,xmm15] and one in [xmm0,xmm7], use the
3282 : // opcode which swaps the operands, as that way we can get a two-byte
3283 : // VEX in that case.
3284 0 : if (src >= xmm8 && dst < xmm8) {
3285 0 : twoByteOpSimd("vmovaps", VEX_PS, OP2_MOVAPS_WsdVsd, dst, invalid_xmm, src);
3286 0 : return;
3287 : }
3288 : #endif
3289 0 : twoByteOpSimd("vmovaps", VEX_PS, OP2_MOVAPS_VsdWsd, src, invalid_xmm, dst);
3290 : }
3291 0 : void vmovaps_rm(XMMRegisterID src, int32_t offset, RegisterID base)
3292 : {
3293 0 : twoByteOpSimd("vmovaps", VEX_PS, OP2_MOVAPS_WsdVsd, offset, base, invalid_xmm, src);
3294 0 : }
3295 0 : void vmovaps_rm(XMMRegisterID src, int32_t offset, RegisterID base, RegisterID index, int scale)
3296 : {
3297 0 : twoByteOpSimd("vmovaps", VEX_PS, OP2_MOVAPS_WsdVsd, offset, base, index, scale, invalid_xmm, src);
3298 0 : }
3299 0 : void vmovaps_mr(int32_t offset, RegisterID base, XMMRegisterID dst)
3300 : {
3301 0 : twoByteOpSimd("vmovaps", VEX_PS, OP2_MOVAPS_VsdWsd, offset, base, invalid_xmm, dst);
3302 0 : }
3303 0 : void vmovaps_mr(int32_t offset, RegisterID base, RegisterID index, int scale, XMMRegisterID dst)
3304 : {
3305 0 : twoByteOpSimd("vmovaps", VEX_PS, OP2_MOVAPS_VsdWsd, offset, base, index, scale, invalid_xmm, dst);
3306 0 : }
3307 :
3308 165673 : void vmovups_rm(XMMRegisterID src, int32_t offset, RegisterID base)
3309 : {
3310 165673 : twoByteOpSimd("vmovups", VEX_PS, OP2_MOVPS_WpsVps, offset, base, invalid_xmm, src);
3311 165663 : }
3312 : void vmovups_rm_disp32(XMMRegisterID src, int32_t offset, RegisterID base)
3313 : {
3314 : twoByteOpSimd_disp32("vmovups", VEX_PS, OP2_MOVPS_WpsVps, offset, base, invalid_xmm, src);
3315 : }
3316 0 : void vmovups_rm(XMMRegisterID src, int32_t offset, RegisterID base, RegisterID index, int scale)
3317 : {
3318 0 : twoByteOpSimd("vmovups", VEX_PS, OP2_MOVPS_WpsVps, offset, base, index, scale, invalid_xmm, src);
3319 0 : }
3320 165542 : void vmovups_mr(int32_t offset, RegisterID base, XMMRegisterID dst)
3321 : {
3322 165542 : twoByteOpSimd("vmovups", VEX_PS, OP2_MOVPS_VpsWps, offset, base, invalid_xmm, dst);
3323 165522 : }
3324 : void vmovups_mr_disp32(int32_t offset, RegisterID base, XMMRegisterID dst)
3325 : {
3326 : twoByteOpSimd_disp32("vmovups", VEX_PS, OP2_MOVPS_VpsWps, offset, base, invalid_xmm, dst);
3327 : }
3328 0 : void vmovups_mr(int32_t offset, RegisterID base, RegisterID index, int scale, XMMRegisterID dst)
3329 : {
3330 0 : twoByteOpSimd("vmovups", VEX_PS, OP2_MOVPS_VpsWps, offset, base, index, scale, invalid_xmm, dst);
3331 0 : }
3332 :
3333 0 : void vmovapd_rr(XMMRegisterID src, XMMRegisterID dst)
3334 : {
3335 : #ifdef JS_CODEGEN_X64
3336 : // There are two opcodes that can encode this instruction. If we have
3337 : // one register in [xmm8,xmm15] and one in [xmm0,xmm7], use the
3338 : // opcode which swaps the operands, as that way we can get a two-byte
3339 : // VEX in that case.
3340 0 : if (src >= xmm8 && dst < xmm8) {
3341 0 : twoByteOpSimd("vmovapd", VEX_PD, OP2_MOVAPS_WsdVsd, dst, invalid_xmm, src);
3342 0 : return;
3343 : }
3344 : #endif
3345 0 : twoByteOpSimd("vmovapd", VEX_PD, OP2_MOVAPD_VsdWsd, src, invalid_xmm, dst);
3346 : }
3347 :
3348 0 : void vmovdqu_rm(XMMRegisterID src, int32_t offset, RegisterID base)
3349 : {
3350 0 : twoByteOpSimd("vmovdqu", VEX_SS, OP2_MOVDQ_WdqVdq, offset, base, invalid_xmm, src);
3351 0 : }
3352 :
3353 : void vmovdqu_rm_disp32(XMMRegisterID src, int32_t offset, RegisterID base)
3354 : {
3355 : twoByteOpSimd_disp32("vmovdqu", VEX_SS, OP2_MOVDQ_WdqVdq, offset, base, invalid_xmm, src);
3356 : }
3357 :
3358 0 : void vmovdqu_rm(XMMRegisterID src, int32_t offset, RegisterID base, RegisterID index, int scale)
3359 : {
3360 0 : twoByteOpSimd("vmovdqu", VEX_SS, OP2_MOVDQ_WdqVdq, offset, base, index, scale, invalid_xmm, src);
3361 0 : }
3362 :
3363 0 : void vmovdqu_mr(int32_t offset, RegisterID base, XMMRegisterID dst)
3364 : {
3365 0 : twoByteOpSimd("vmovdqu", VEX_SS, OP2_MOVDQ_VdqWdq, offset, base, invalid_xmm, dst);
3366 0 : }
3367 :
3368 : void vmovdqu_mr_disp32(int32_t offset, RegisterID base, XMMRegisterID dst)
3369 : {
3370 : twoByteOpSimd_disp32("vmovdqu", VEX_SS, OP2_MOVDQ_VdqWdq, offset, base, invalid_xmm, dst);
3371 : }
3372 :
3373 0 : void vmovdqu_mr(int32_t offset, RegisterID base, RegisterID index, int scale, XMMRegisterID dst)
3374 : {
3375 0 : twoByteOpSimd("vmovdqu", VEX_SS, OP2_MOVDQ_VdqWdq, offset, base, index, scale, invalid_xmm, dst);
3376 0 : }
3377 :
3378 0 : void vmovdqa_rr(XMMRegisterID src, XMMRegisterID dst)
3379 : {
3380 : #ifdef JS_CODEGEN_X64
3381 : // There are two opcodes that can encode this instruction. If we have
3382 : // one register in [xmm8,xmm15] and one in [xmm0,xmm7], use the
3383 : // opcode which swaps the operands, as that way we can get a two-byte
3384 : // VEX in that case.
3385 0 : if (src >= xmm8 && dst < xmm8) {
3386 0 : twoByteOpSimd("vmovdqa", VEX_PD, OP2_MOVDQ_WdqVdq, dst, invalid_xmm, src);
3387 0 : return;
3388 : }
3389 : #endif
3390 0 : twoByteOpSimd("vmovdqa", VEX_PD, OP2_MOVDQ_VdqWdq, src, invalid_xmm, dst);
3391 : }
3392 :
3393 0 : void vmovdqa_rm(XMMRegisterID src, int32_t offset, RegisterID base)
3394 : {
3395 0 : twoByteOpSimd("vmovdqa", VEX_PD, OP2_MOVDQ_WdqVdq, offset, base, invalid_xmm, src);
3396 0 : }
3397 :
3398 0 : void vmovdqa_rm(XMMRegisterID src, int32_t offset, RegisterID base, RegisterID index, int scale)
3399 : {
3400 0 : twoByteOpSimd("vmovdqa", VEX_PD, OP2_MOVDQ_WdqVdq, offset, base, index, scale, invalid_xmm, src);
3401 0 : }
3402 :
3403 0 : void vmovdqa_mr(int32_t offset, RegisterID base, XMMRegisterID dst)
3404 : {
3405 :
3406 0 : twoByteOpSimd("vmovdqa", VEX_PD, OP2_MOVDQ_VdqWdq, offset, base, invalid_xmm, dst);
3407 0 : }
3408 :
3409 0 : void vmovdqa_mr(int32_t offset, RegisterID base, RegisterID index, int scale, XMMRegisterID dst)
3410 : {
3411 0 : twoByteOpSimd("vmovdqa", VEX_PD, OP2_MOVDQ_VdqWdq, offset, base, index, scale, invalid_xmm, dst);
3412 0 : }
3413 :
3414 0 : void vmulsd_rr(XMMRegisterID src1, XMMRegisterID src0, XMMRegisterID dst)
3415 : {
3416 0 : twoByteOpSimd("vmulsd", VEX_SD, OP2_MULSD_VsdWsd, src1, src0, dst);
3417 0 : }
3418 :
3419 0 : void vmulss_rr(XMMRegisterID src1, XMMRegisterID src0, XMMRegisterID dst)
3420 : {
3421 0 : twoByteOpSimd("vmulss", VEX_SS, OP2_MULSD_VsdWsd, src1, src0, dst);
3422 0 : }
3423 :
3424 0 : void vmulsd_mr(int32_t offset, RegisterID base, XMMRegisterID src0, XMMRegisterID dst)
3425 : {
3426 0 : twoByteOpSimd("vmulsd", VEX_SD, OP2_MULSD_VsdWsd, offset, base, src0, dst);
3427 0 : }
3428 :
3429 0 : void vmulss_mr(int32_t offset, RegisterID base, XMMRegisterID src0, XMMRegisterID dst)
3430 : {
3431 0 : twoByteOpSimd("vmulss", VEX_SS, OP2_MULSD_VsdWsd, offset, base, src0, dst);
3432 0 : }
3433 :
3434 0 : void vpinsrw_irr(uint32_t whichWord, RegisterID src1, XMMRegisterID src0, XMMRegisterID dst)
3435 : {
3436 0 : MOZ_ASSERT(whichWord < 8);
3437 0 : twoByteOpImmInt32Simd("vpinsrw", VEX_PD, OP2_PINSRW, whichWord, src1, src0, dst);
3438 0 : }
3439 :
3440 0 : void vpextrw_irr(uint32_t whichWord, XMMRegisterID src, RegisterID dst)
3441 : {
3442 0 : MOZ_ASSERT(whichWord < 8);
3443 0 : twoByteOpImmSimdInt32("vpextrw", VEX_PD, OP2_PEXTRW_GdUdIb, whichWord, src, dst);
3444 0 : }
3445 :
3446 0 : void vsubsd_rr(XMMRegisterID src1, XMMRegisterID src0, XMMRegisterID dst)
3447 : {
3448 0 : twoByteOpSimd("vsubsd", VEX_SD, OP2_SUBSD_VsdWsd, src1, src0, dst);
3449 0 : }
3450 :
3451 0 : void vsubss_rr(XMMRegisterID src1, XMMRegisterID src0, XMMRegisterID dst)
3452 : {
3453 0 : twoByteOpSimd("vsubss", VEX_SS, OP2_SUBSD_VsdWsd, src1, src0, dst);
3454 0 : }
3455 :
3456 0 : void vsubsd_mr(int32_t offset, RegisterID base, XMMRegisterID src0, XMMRegisterID dst)
3457 : {
3458 0 : twoByteOpSimd("vsubsd", VEX_SD, OP2_SUBSD_VsdWsd, offset, base, src0, dst);
3459 0 : }
3460 :
3461 0 : void vsubss_mr(int32_t offset, RegisterID base, XMMRegisterID src0, XMMRegisterID dst)
3462 : {
3463 0 : twoByteOpSimd("vsubss", VEX_SS, OP2_SUBSD_VsdWsd, offset, base, src0, dst);
3464 0 : }
3465 :
3466 0 : void vucomiss_rr(XMMRegisterID rhs, XMMRegisterID lhs)
3467 : {
3468 0 : twoByteOpSimdFlags("vucomiss", VEX_PS, OP2_UCOMISD_VsdWsd, rhs, lhs);
3469 0 : }
3470 :
3471 38 : void vucomisd_rr(XMMRegisterID rhs, XMMRegisterID lhs)
3472 : {
3473 38 : twoByteOpSimdFlags("vucomisd", VEX_PD, OP2_UCOMISD_VsdWsd, rhs, lhs);
3474 38 : }
3475 :
3476 : void vucomisd_mr(int32_t offset, RegisterID base, XMMRegisterID lhs)
3477 : {
3478 : twoByteOpSimdFlags("vucomisd", VEX_PD, OP2_UCOMISD_VsdWsd, offset, base, lhs);
3479 : }
3480 :
3481 1 : void vdivsd_rr(XMMRegisterID src1, XMMRegisterID src0, XMMRegisterID dst)
3482 : {
3483 1 : twoByteOpSimd("vdivsd", VEX_SD, OP2_DIVSD_VsdWsd, src1, src0, dst);
3484 1 : }
3485 :
3486 0 : void vdivss_rr(XMMRegisterID src1, XMMRegisterID src0, XMMRegisterID dst)
3487 : {
3488 0 : twoByteOpSimd("vdivss", VEX_SS, OP2_DIVSD_VsdWsd, src1, src0, dst);
3489 0 : }
3490 :
3491 0 : void vdivsd_mr(int32_t offset, RegisterID base, XMMRegisterID src0, XMMRegisterID dst)
3492 : {
3493 0 : twoByteOpSimd("vdivsd", VEX_SD, OP2_DIVSD_VsdWsd, offset, base, src0, dst);
3494 0 : }
3495 :
3496 0 : void vdivss_mr(int32_t offset, RegisterID base, XMMRegisterID src0, XMMRegisterID dst)
3497 : {
3498 0 : twoByteOpSimd("vdivss", VEX_SS, OP2_DIVSD_VsdWsd, offset, base, src0, dst);
3499 0 : }
3500 :
3501 59 : void vxorpd_rr(XMMRegisterID src1, XMMRegisterID src0, XMMRegisterID dst)
3502 : {
3503 59 : twoByteOpSimd("vxorpd", VEX_PD, OP2_XORPD_VpdWpd, src1, src0, dst);
3504 59 : }
3505 :
3506 0 : void vorpd_rr(XMMRegisterID src1, XMMRegisterID src0, XMMRegisterID dst)
3507 : {
3508 0 : twoByteOpSimd("vorpd", VEX_PD, OP2_ORPD_VpdWpd, src1, src0, dst);
3509 0 : }
3510 :
3511 0 : void vandpd_rr(XMMRegisterID src1, XMMRegisterID src0, XMMRegisterID dst)
3512 : {
3513 0 : twoByteOpSimd("vandpd", VEX_PD, OP2_ANDPD_VpdWpd, src1, src0, dst);
3514 0 : }
3515 :
3516 0 : void vandps_rr(XMMRegisterID src1, XMMRegisterID src0, XMMRegisterID dst)
3517 : {
3518 0 : twoByteOpSimd("vandps", VEX_PS, OP2_ANDPS_VpsWps, src1, src0, dst);
3519 0 : }
3520 :
3521 0 : void vandps_mr(int32_t offset, RegisterID base, XMMRegisterID src0, XMMRegisterID dst)
3522 : {
3523 0 : twoByteOpSimd("vandps", VEX_PS, OP2_ANDPS_VpsWps, offset, base, src0, dst);
3524 0 : }
3525 :
3526 0 : void vandps_mr(const void* address, XMMRegisterID src0, XMMRegisterID dst)
3527 : {
3528 0 : twoByteOpSimd("vandps", VEX_PS, OP2_ANDPS_VpsWps, address, src0, dst);
3529 0 : }
3530 :
3531 0 : void vandnps_rr(XMMRegisterID src1, XMMRegisterID src0, XMMRegisterID dst)
3532 : {
3533 0 : twoByteOpSimd("vandnps", VEX_PS, OP2_ANDNPS_VpsWps, src1, src0, dst);
3534 0 : }
3535 :
3536 0 : void vandnps_mr(int32_t offset, RegisterID base, XMMRegisterID src0, XMMRegisterID dst)
3537 : {
3538 0 : twoByteOpSimd("vandnps", VEX_PS, OP2_ANDNPS_VpsWps, offset, base, src0, dst);
3539 0 : }
3540 :
3541 0 : void vandnps_mr(const void* address, XMMRegisterID src0, XMMRegisterID dst)
3542 : {
3543 0 : twoByteOpSimd("vandnps", VEX_PS, OP2_ANDNPS_VpsWps, address, src0, dst);
3544 0 : }
3545 :
3546 0 : void vorps_rr(XMMRegisterID src1, XMMRegisterID src0, XMMRegisterID dst)
3547 : {
3548 0 : twoByteOpSimd("vorps", VEX_PS, OP2_ORPS_VpsWps, src1, src0, dst);
3549 0 : }
3550 :
3551 0 : void vorps_mr(int32_t offset, RegisterID base, XMMRegisterID src0, XMMRegisterID dst)
3552 : {
3553 0 : twoByteOpSimd("vorps", VEX_PS, OP2_ORPS_VpsWps, offset, base, src0, dst);
3554 0 : }
3555 :
3556 0 : void vorps_mr(const void* address, XMMRegisterID src0, XMMRegisterID dst)
3557 : {
3558 0 : twoByteOpSimd("vorps", VEX_PS, OP2_ORPS_VpsWps, address, src0, dst);
3559 0 : }
3560 :
3561 0 : void vxorps_rr(XMMRegisterID src1, XMMRegisterID src0, XMMRegisterID dst)
3562 : {
3563 0 : twoByteOpSimd("vxorps", VEX_PS, OP2_XORPS_VpsWps, src1, src0, dst);
3564 0 : }
3565 :
3566 0 : void vxorps_mr(int32_t offset, RegisterID base, XMMRegisterID src0, XMMRegisterID dst)
3567 : {
3568 0 : twoByteOpSimd("vxorps", VEX_PS, OP2_XORPS_VpsWps, offset, base, src0, dst);
3569 0 : }
3570 :
3571 0 : void vxorps_mr(const void* address, XMMRegisterID src0, XMMRegisterID dst)
3572 : {
3573 0 : twoByteOpSimd("vxorps", VEX_PS, OP2_XORPS_VpsWps, address, src0, dst);
3574 0 : }
3575 :
3576 0 : void vsqrtsd_rr(XMMRegisterID src1, XMMRegisterID src0, XMMRegisterID dst)
3577 : {
3578 0 : twoByteOpSimd("vsqrtsd", VEX_SD, OP2_SQRTSD_VsdWsd, src1, src0, dst);
3579 0 : }
3580 :
3581 0 : void vsqrtss_rr(XMMRegisterID src1, XMMRegisterID src0, XMMRegisterID dst)
3582 : {
3583 0 : twoByteOpSimd("vsqrtss", VEX_SS, OP2_SQRTSS_VssWss, src1, src0, dst);
3584 0 : }
3585 :
3586 0 : void vroundsd_irr(RoundingMode mode, XMMRegisterID src1, XMMRegisterID src0, XMMRegisterID dst)
3587 : {
3588 0 : threeByteOpImmSimd("vroundsd", VEX_PD, OP3_ROUNDSD_VsdWsd, ESCAPE_3A, mode, src1, src0, dst);
3589 0 : }
3590 :
3591 0 : void vroundss_irr(RoundingMode mode, XMMRegisterID src1, XMMRegisterID src0, XMMRegisterID dst)
3592 : {
3593 0 : threeByteOpImmSimd("vroundss", VEX_PD, OP3_ROUNDSS_VsdWsd, ESCAPE_3A, mode, src1, src0, dst);
3594 0 : }
3595 :
3596 0 : void vinsertps_irr(uint32_t mask, XMMRegisterID src1, XMMRegisterID src0, XMMRegisterID dst)
3597 : {
3598 0 : threeByteOpImmSimd("vinsertps", VEX_PD, OP3_INSERTPS_VpsUps, ESCAPE_3A, mask, src1, src0, dst);
3599 0 : }
3600 0 : void vinsertps_imr(uint32_t mask, int32_t offset, RegisterID base, XMMRegisterID src0, XMMRegisterID dst)
3601 : {
3602 0 : threeByteOpImmSimd("vinsertps", VEX_PD, OP3_INSERTPS_VpsUps, ESCAPE_3A, mask, offset, base, src0, dst);
3603 0 : }
3604 :
3605 0 : void vpinsrb_irr(unsigned lane, RegisterID src1, XMMRegisterID src0, XMMRegisterID dst)
3606 : {
3607 0 : MOZ_ASSERT(lane < 16);
3608 0 : threeByteOpImmInt32Simd("vpinsrb", VEX_PD, OP3_PINSRB_VdqEdIb, ESCAPE_3A, lane, src1, src0, dst);
3609 0 : }
3610 :
3611 0 : void vpinsrd_irr(unsigned lane, RegisterID src1, XMMRegisterID src0, XMMRegisterID dst)
3612 : {
3613 0 : MOZ_ASSERT(lane < 4);
3614 0 : threeByteOpImmInt32Simd("vpinsrd", VEX_PD, OP3_PINSRD_VdqEdIb, ESCAPE_3A, lane, src1, src0, dst);
3615 0 : }
3616 :
3617 0 : void vpextrb_irr(unsigned lane, XMMRegisterID src, RegisterID dst)
3618 : {
3619 0 : MOZ_ASSERT(lane < 16);
3620 0 : threeByteOpImmSimdInt32("vpextrb", VEX_PD, OP3_PEXTRB_EdVdqIb, ESCAPE_3A, lane, (XMMRegisterID)dst, (RegisterID)src);
3621 0 : }
3622 :
3623 0 : void vpextrd_irr(unsigned lane, XMMRegisterID src, RegisterID dst)
3624 : {
3625 0 : MOZ_ASSERT(lane < 4);
3626 0 : threeByteOpImmSimdInt32("vpextrd", VEX_PD, OP3_PEXTRD_EdVdqIb, ESCAPE_3A, lane, (XMMRegisterID)dst, (RegisterID)src);
3627 0 : }
3628 :
3629 0 : void vblendps_irr(unsigned imm, XMMRegisterID src1, XMMRegisterID src0, XMMRegisterID dst)
3630 : {
3631 0 : MOZ_ASSERT(imm < 16);
3632 : // Despite being a "ps" instruction, vblendps is encoded with the "pd" prefix.
3633 0 : threeByteOpImmSimd("vblendps", VEX_PD, OP3_BLENDPS_VpsWpsIb, ESCAPE_3A, imm, src1, src0, dst);
3634 0 : }
3635 :
3636 0 : void vblendps_imr(unsigned imm, int32_t offset, RegisterID base, XMMRegisterID src0, XMMRegisterID dst)
3637 : {
3638 0 : MOZ_ASSERT(imm < 16);
3639 : // Despite being a "ps" instruction, vblendps is encoded with the "pd" prefix.
3640 0 : threeByteOpImmSimd("vblendps", VEX_PD, OP3_BLENDPS_VpsWpsIb, ESCAPE_3A, imm, offset, base, src0, dst);
3641 0 : }
3642 :
3643 0 : void vblendvps_rr(XMMRegisterID mask, XMMRegisterID src1, XMMRegisterID src0, XMMRegisterID dst) {
3644 0 : vblendvOpSimd(mask, src1, src0, dst);
3645 0 : }
3646 : void vblendvps_mr(XMMRegisterID mask, int32_t offset, RegisterID base, XMMRegisterID src0, XMMRegisterID dst) {
3647 : vblendvOpSimd(mask, offset, base, src0, dst);
3648 : }
3649 :
3650 0 : void vmovsldup_rr(XMMRegisterID src, XMMRegisterID dst)
3651 : {
3652 0 : twoByteOpSimd("vmovsldup", VEX_SS, OP2_MOVSLDUP_VpsWps, src, invalid_xmm, dst);
3653 0 : }
3654 : void vmovsldup_mr(int32_t offset, RegisterID base, XMMRegisterID dst)
3655 : {
3656 : twoByteOpSimd("vmovsldup", VEX_SS, OP2_MOVSLDUP_VpsWps, offset, base, invalid_xmm, dst);
3657 : }
3658 :
3659 0 : void vmovshdup_rr(XMMRegisterID src, XMMRegisterID dst)
3660 : {
3661 0 : twoByteOpSimd("vmovshdup", VEX_SS, OP2_MOVSHDUP_VpsWps, src, invalid_xmm, dst);
3662 0 : }
3663 : void vmovshdup_mr(int32_t offset, RegisterID base, XMMRegisterID dst)
3664 : {
3665 : twoByteOpSimd("vmovshdup", VEX_SS, OP2_MOVSHDUP_VpsWps, offset, base, invalid_xmm, dst);
3666 : }
3667 :
3668 0 : void vminsd_rr(XMMRegisterID src1, XMMRegisterID src0, XMMRegisterID dst)
3669 : {
3670 0 : twoByteOpSimd("vminsd", VEX_SD, OP2_MINSD_VsdWsd, src1, src0, dst);
3671 0 : }
3672 : void vminsd_mr(int32_t offset, RegisterID base, XMMRegisterID src0, XMMRegisterID dst)
3673 : {
3674 : twoByteOpSimd("vminsd", VEX_SD, OP2_MINSD_VsdWsd, offset, base, src0, dst);
3675 : }
3676 :
3677 0 : void vminss_rr(XMMRegisterID src1, XMMRegisterID src0, XMMRegisterID dst)
3678 : {
3679 0 : twoByteOpSimd("vminss", VEX_SS, OP2_MINSS_VssWss, src1, src0, dst);
3680 0 : }
3681 :
3682 0 : void vmaxsd_rr(XMMRegisterID src1, XMMRegisterID src0, XMMRegisterID dst)
3683 : {
3684 0 : twoByteOpSimd("vmaxsd", VEX_SD, OP2_MAXSD_VsdWsd, src1, src0, dst);
3685 0 : }
3686 : void vmaxsd_mr(int32_t offset, RegisterID base, XMMRegisterID src0, XMMRegisterID dst)
3687 : {
3688 : twoByteOpSimd("vmaxsd", VEX_SD, OP2_MAXSD_VsdWsd, offset, base, src0, dst);
3689 : }
3690 :
3691 0 : void vmaxss_rr(XMMRegisterID src1, XMMRegisterID src0, XMMRegisterID dst)
3692 : {
3693 0 : twoByteOpSimd("vmaxss", VEX_SS, OP2_MAXSS_VssWss, src1, src0, dst);
3694 0 : }
3695 :
3696 : // Misc instructions:
3697 :
3698 21541 : void int3()
3699 : {
3700 21541 : spew("int3");
3701 21541 : m_formatter.oneByteOp(OP_INT3);
3702 21541 : }
3703 :
3704 19127 : void ud2()
3705 : {
3706 19127 : spew("ud2");
3707 19127 : m_formatter.twoByteOp(OP2_UD2);
3708 19127 : }
3709 :
3710 3552 : void ret()
3711 : {
3712 3552 : spew("ret");
3713 3552 : m_formatter.oneByteOp(OP_RET);
3714 3552 : }
3715 :
3716 1036 : void ret_i(int32_t imm)
3717 : {
3718 1036 : spew("ret $%d", imm);
3719 1036 : m_formatter.oneByteOp(OP_RET_Iz);
3720 1036 : m_formatter.immediate16u(imm);
3721 1036 : }
3722 :
3723 0 : void mfence() {
3724 0 : spew("mfence");
3725 0 : m_formatter.twoByteOp(OP_FENCE, (RegisterID)0, 6);
3726 0 : }
3727 :
3728 : // Assembler admin methods:
3729 :
3730 200888 : JmpDst label()
3731 : {
3732 200888 : JmpDst r = JmpDst(m_formatter.size());
3733 200896 : spew(".set .Llabel%d, .", r.offset());
3734 200896 : return r;
3735 : }
3736 :
3737 31963 : size_t currentOffset() const {
3738 31963 : return m_formatter.size();
3739 : }
3740 :
3741 : static JmpDst labelFor(JmpSrc jump, intptr_t offset = 0)
3742 : {
3743 : return JmpDst(jump.offset() + offset);
3744 : }
3745 :
3746 3142 : void haltingAlign(int alignment)
3747 : {
3748 3142 : spew(".balign %d, 0x%x # hlt", alignment, OP_HLT);
3749 48674 : while (!m_formatter.isAligned(alignment))
3750 22766 : m_formatter.oneByteOp(OP_HLT);
3751 3142 : }
3752 :
3753 0 : void nopAlign(int alignment)
3754 : {
3755 0 : spew(".balign %d", alignment);
3756 :
3757 0 : int remainder = m_formatter.size() % alignment;
3758 0 : if (remainder > 0)
3759 0 : insert_nop(alignment - remainder);
3760 0 : }
3761 :
3762 0 : void jumpTablePointer(uintptr_t ptr)
3763 : {
3764 : #ifdef JS_CODEGEN_X64
3765 0 : spew(".quad 0x%" PRIxPTR, ptr);
3766 : #else
3767 : spew(".int 0x%" PRIxPTR, ptr);
3768 : #endif
3769 0 : m_formatter.jumpTablePointer(ptr);
3770 0 : }
3771 :
3772 0 : void doubleConstant(double d)
3773 : {
3774 0 : spew(".double %.16g", d);
3775 0 : m_formatter.doubleConstant(d);
3776 0 : }
3777 0 : void floatConstant(float f)
3778 : {
3779 0 : spew(".float %.16g", f);
3780 0 : m_formatter.floatConstant(f);
3781 0 : }
3782 :
3783 0 : void simd128Constant(const void* data)
3784 : {
3785 0 : const uint32_t* dw = reinterpret_cast<const uint32_t*>(data);
3786 0 : spew(".int 0x%08x,0x%08x,0x%08x,0x%08x", dw[0], dw[1], dw[2], dw[3]);
3787 0 : MOZ_ASSERT(m_formatter.isAligned(16));
3788 0 : m_formatter.simd128Constant(data);
3789 0 : }
3790 :
3791 : void int32Constant(int32_t i)
3792 : {
3793 : spew(".int %d", i);
3794 : m_formatter.int32Constant(i);
3795 : }
3796 : void int64Constant(int64_t i)
3797 : {
3798 : spew(".quad %lld", (long long)i);
3799 : m_formatter.int64Constant(i);
3800 : }
3801 :
3802 : // Linking & patching:
3803 :
3804 142599 : void assertValidJmpSrc(JmpSrc src)
3805 : {
3806 : // The target offset is stored at offset - 4.
3807 142599 : MOZ_RELEASE_ASSERT(src.offset() > int32_t(sizeof(int32_t)));
3808 142599 : MOZ_RELEASE_ASSERT(size_t(src.offset()) <= size());
3809 142597 : }
3810 :
3811 47628 : bool nextJump(const JmpSrc& from, JmpSrc* next)
3812 : {
3813 : // Sanity check - if the assembler has OOM'd, it will start overwriting
3814 : // its internal buffer and thus our links could be garbage.
3815 47628 : if (oom())
3816 0 : return false;
3817 :
3818 47628 : assertValidJmpSrc(from);
3819 :
3820 47628 : const unsigned char* code = m_formatter.data();
3821 47628 : int32_t offset = GetInt32(code + from.offset());
3822 47628 : if (offset == -1)
3823 40622 : return false;
3824 :
3825 7006 : if (MOZ_UNLIKELY(size_t(offset) >= size())) {
3826 : #ifdef NIGHTLY_BUILD
3827 : // Stash some data on the stack so we can retrieve it from minidumps,
3828 : // see bug 1124397.
3829 0 : int32_t startOffset = from.offset() - 1;
3830 0 : while (startOffset >= 0 && code[startOffset] == 0xe5)
3831 0 : startOffset--;
3832 0 : int32_t endOffset = from.offset() - 1;
3833 0 : while (endOffset < int32_t(size()) && code[endOffset] == 0xe5)
3834 0 : endOffset++;
3835 : volatile uintptr_t dump[10];
3836 0 : blackbox = dump;
3837 0 : blackbox[0] = uintptr_t(0xABCD1234);
3838 0 : blackbox[1] = uintptr_t(offset);
3839 0 : blackbox[2] = uintptr_t(size());
3840 0 : blackbox[3] = uintptr_t(from.offset());
3841 0 : blackbox[4] = uintptr_t(code[from.offset() - 5]);
3842 0 : blackbox[5] = uintptr_t(code[from.offset() - 4]);
3843 0 : blackbox[6] = uintptr_t(code[from.offset() - 3]);
3844 0 : blackbox[7] = uintptr_t(startOffset);
3845 0 : blackbox[8] = uintptr_t(endOffset);
3846 0 : blackbox[9] = uintptr_t(0xFFFF7777);
3847 : #endif
3848 0 : MOZ_CRASH("nextJump bogus offset");
3849 : }
3850 :
3851 7006 : *next = JmpSrc(offset);
3852 7006 : return true;
3853 : }
3854 47631 : void setNextJump(const JmpSrc& from, const JmpSrc& to)
3855 : {
3856 : // Sanity check - if the assembler has OOM'd, it will start overwriting
3857 : // its internal buffer and thus our links could be garbage.
3858 47631 : if (oom())
3859 0 : return;
3860 :
3861 47631 : assertValidJmpSrc(from);
3862 47631 : MOZ_RELEASE_ASSERT(to.offset() == -1 || size_t(to.offset()) <= size());
3863 :
3864 47630 : unsigned char* code = m_formatter.data();
3865 47630 : SetInt32(code + from.offset(), to.offset());
3866 : }
3867 :
3868 47344 : void linkJump(JmpSrc from, JmpDst to)
3869 : {
3870 47344 : MOZ_ASSERT(from.offset() != -1);
3871 47344 : MOZ_ASSERT(to.offset() != -1);
3872 :
3873 : // Sanity check - if the assembler has OOM'd, it will start overwriting
3874 : // its internal buffer and thus our links could be garbage.
3875 47344 : if (oom())
3876 0 : return;
3877 :
3878 47344 : assertValidJmpSrc(from);
3879 47344 : MOZ_RELEASE_ASSERT(size_t(to.offset()) <= size());
3880 :
3881 47344 : spew(".set .Lfrom%d, .Llabel%d", from.offset(), to.offset());
3882 47345 : unsigned char* code = m_formatter.data();
3883 47345 : SetRel32(code + from.offset(), code + to.offset());
3884 : }
3885 :
3886 4499 : void executableCopy(void* dst)
3887 : {
3888 4499 : const unsigned char* src = m_formatter.buffer();
3889 4499 : memcpy(dst, src, size());
3890 4499 : }
3891 0 : MOZ_MUST_USE bool appendBuffer(const BaseAssembler& other)
3892 : {
3893 0 : const unsigned char* buf = other.m_formatter.buffer();
3894 0 : bool ret = m_formatter.append(buf, other.size());
3895 0 : return ret;
3896 : }
3897 :
3898 : protected:
3899 556000 : static bool CAN_SIGN_EXTEND_8_32(int32_t value) { return value == (int32_t)(int8_t)value; }
3900 : static bool CAN_SIGN_EXTEND_16_32(int32_t value) { return value == (int32_t)(int16_t)value; }
3901 21077 : static bool CAN_ZERO_EXTEND_8_32(int32_t value) { return value == (int32_t)(uint8_t)value; }
3902 12 : static bool CAN_ZERO_EXTEND_8H_32(int32_t value) { return value == (value & 0xff00); }
3903 1036 : static bool CAN_ZERO_EXTEND_16_32(int32_t value) { return value == (int32_t)(uint16_t)value; }
3904 13390 : static bool CAN_ZERO_EXTEND_32_64(int32_t value) { return value >= 0; }
3905 :
3906 : // Methods for encoding SIMD instructions via either legacy SSE encoding or
3907 : // VEX encoding.
3908 :
3909 331360 : bool useLegacySSEEncoding(XMMRegisterID src0, XMMRegisterID dst)
3910 : {
3911 : // If we don't have AVX or it's disabled, use the legacy SSE encoding.
3912 331360 : if (!useVEX_) {
3913 331360 : MOZ_ASSERT(src0 == invalid_xmm || src0 == dst,
3914 : "Legacy SSE (pre-AVX) encoding requires the output register to be "
3915 : "the same as the src0 input register");
3916 331360 : return true;
3917 : }
3918 :
3919 : // If src0 is the same as the output register, we might as well use
3920 : // the legacy SSE encoding, since it is smaller. However, this is only
3921 : // beneficial as long as we're not using ymm registers anywhere.
3922 0 : return src0 == dst;
3923 : }
3924 :
3925 0 : bool useLegacySSEEncodingForVblendv(XMMRegisterID mask, XMMRegisterID src0, XMMRegisterID dst)
3926 : {
3927 : // Similar to useLegacySSEEncoding, but for vblendv the Legacy SSE
3928 : // encoding also requires the mask to be in xmm0.
3929 :
3930 0 : if (!useVEX_) {
3931 0 : MOZ_ASSERT(src0 == dst,
3932 : "Legacy SSE (pre-AVX) encoding requires the output register to be "
3933 : "the same as the src0 input register");
3934 0 : MOZ_ASSERT(mask == xmm0,
3935 : "Legacy SSE (pre-AVX) encoding for blendv requires the mask to be "
3936 : "in xmm0");
3937 0 : return true;
3938 : }
3939 :
3940 0 : return src0 == dst && mask == xmm0;
3941 : }
3942 :
3943 73 : bool useLegacySSEEncodingForOtherOutput()
3944 : {
3945 73 : return !useVEX_;
3946 : }
3947 :
3948 331429 : const char* legacySSEOpName(const char* name)
3949 : {
3950 331429 : MOZ_ASSERT(name[0] == 'v');
3951 331429 : return name + 1;
3952 : }
3953 :
3954 60 : void twoByteOpSimd(const char* name, VexOperandType ty, TwoByteOpcodeID opcode,
3955 : XMMRegisterID rm, XMMRegisterID src0, XMMRegisterID dst)
3956 : {
3957 60 : if (useLegacySSEEncoding(src0, dst)) {
3958 60 : if (IsXMMReversedOperands(opcode))
3959 0 : spew("%-11s%s, %s", legacySSEOpName(name), XMMRegName(dst), XMMRegName(rm));
3960 : else
3961 60 : spew("%-11s%s, %s", legacySSEOpName(name), XMMRegName(rm), XMMRegName(dst));
3962 60 : m_formatter.legacySSEPrefix(ty);
3963 60 : m_formatter.twoByteOp(opcode, (RegisterID)rm, dst);
3964 60 : return;
3965 : }
3966 :
3967 0 : if (src0 == invalid_xmm) {
3968 0 : if (IsXMMReversedOperands(opcode))
3969 0 : spew("%-11s%s, %s", name, XMMRegName(dst), XMMRegName(rm));
3970 : else
3971 0 : spew("%-11s%s, %s", name, XMMRegName(rm), XMMRegName(dst));
3972 : } else {
3973 0 : spew("%-11s%s, %s, %s", name, XMMRegName(rm), XMMRegName(src0), XMMRegName(dst));
3974 : }
3975 0 : m_formatter.twoByteOpVex(ty, opcode, (RegisterID)rm, src0, dst);
3976 : }
3977 :
3978 0 : void twoByteOpImmSimd(const char* name, VexOperandType ty, TwoByteOpcodeID opcode,
3979 : uint32_t imm, XMMRegisterID rm, XMMRegisterID src0, XMMRegisterID dst)
3980 : {
3981 0 : if (useLegacySSEEncoding(src0, dst)) {
3982 0 : spew("%-11s$0x%x, %s, %s", legacySSEOpName(name), imm, XMMRegName(rm), XMMRegName(dst));
3983 0 : m_formatter.legacySSEPrefix(ty);
3984 0 : m_formatter.twoByteOp(opcode, (RegisterID)rm, dst);
3985 0 : m_formatter.immediate8u(imm);
3986 0 : return;
3987 : }
3988 :
3989 0 : if (src0 == invalid_xmm)
3990 0 : spew("%-11s$0x%x, %s, %s", name, imm, XMMRegName(rm), XMMRegName(dst));
3991 : else
3992 0 : spew("%-11s$0x%x, %s, %s, %s", name, imm, XMMRegName(rm), XMMRegName(src0), XMMRegName(dst));
3993 0 : m_formatter.twoByteOpVex(ty, opcode, (RegisterID)rm, src0, dst);
3994 0 : m_formatter.immediate8u(imm);
3995 : }
3996 :
3997 331189 : void twoByteOpSimd(const char* name, VexOperandType ty, TwoByteOpcodeID opcode,
3998 : int32_t offset, RegisterID base, XMMRegisterID src0, XMMRegisterID dst)
3999 : {
4000 331189 : if (useLegacySSEEncoding(src0, dst)) {
4001 331190 : if (IsXMMReversedOperands(opcode)) {
4002 165680 : spew("%-11s%s, " MEM_ob, legacySSEOpName(name),
4003 165680 : XMMRegName(dst), ADDR_ob(offset, base));
4004 : } else {
4005 165558 : spew("%-11s" MEM_ob ", %s", legacySSEOpName(name),
4006 165558 : ADDR_ob(offset, base), XMMRegName(dst));
4007 : }
4008 331238 : m_formatter.legacySSEPrefix(ty);
4009 331186 : m_formatter.twoByteOp(opcode, offset, base, dst);
4010 331174 : return;
4011 : }
4012 :
4013 0 : if (src0 == invalid_xmm) {
4014 0 : if (IsXMMReversedOperands(opcode))
4015 0 : spew("%-11s%s, " MEM_ob, name, XMMRegName(dst), ADDR_ob(offset, base));
4016 : else
4017 0 : spew("%-11s" MEM_ob ", %s", name, ADDR_ob(offset, base), XMMRegName(dst));
4018 : } else {
4019 0 : spew("%-11s" MEM_ob ", %s, %s", name,
4020 0 : ADDR_ob(offset, base), XMMRegName(src0), XMMRegName(dst));
4021 : }
4022 0 : m_formatter.twoByteOpVex(ty, opcode, offset, base, src0, dst);
4023 : }
4024 :
4025 : void twoByteOpSimd_disp32(const char* name, VexOperandType ty, TwoByteOpcodeID opcode,
4026 : int32_t offset, RegisterID base, XMMRegisterID src0, XMMRegisterID dst)
4027 : {
4028 : if (useLegacySSEEncoding(src0, dst)) {
4029 : if (IsXMMReversedOperands(opcode))
4030 : spew("%-11s%s, " MEM_o32b, legacySSEOpName(name), XMMRegName(dst), ADDR_o32b(offset, base));
4031 : else
4032 : spew("%-11s" MEM_o32b ", %s", legacySSEOpName(name), ADDR_o32b(offset, base), XMMRegName(dst));
4033 : m_formatter.legacySSEPrefix(ty);
4034 : m_formatter.twoByteOp_disp32(opcode, offset, base, dst);
4035 : return;
4036 : }
4037 :
4038 : if (src0 == invalid_xmm) {
4039 : if (IsXMMReversedOperands(opcode))
4040 : spew("%-11s%s, " MEM_o32b, name, XMMRegName(dst), ADDR_o32b(offset, base));
4041 : else
4042 : spew("%-11s" MEM_o32b ", %s", name, ADDR_o32b(offset, base), XMMRegName(dst));
4043 : } else {
4044 : spew("%-11s" MEM_o32b ", %s, %s", name,
4045 : ADDR_o32b(offset, base), XMMRegName(src0), XMMRegName(dst));
4046 : }
4047 : m_formatter.twoByteOpVex_disp32(ty, opcode, offset, base, src0, dst);
4048 : }
4049 :
4050 0 : void twoByteOpImmSimd(const char* name, VexOperandType ty, TwoByteOpcodeID opcode,
4051 : uint32_t imm, int32_t offset, RegisterID base, XMMRegisterID src0, XMMRegisterID dst)
4052 : {
4053 0 : if (useLegacySSEEncoding(src0, dst)) {
4054 0 : spew("%-11s$0x%x, " MEM_ob ", %s", legacySSEOpName(name), imm,
4055 0 : ADDR_ob(offset, base), XMMRegName(dst));
4056 0 : m_formatter.legacySSEPrefix(ty);
4057 0 : m_formatter.twoByteOp(opcode, offset, base, dst);
4058 0 : m_formatter.immediate8u(imm);
4059 0 : return;
4060 : }
4061 :
4062 0 : spew("%-11s$0x%x, " MEM_ob ", %s, %s", name, imm, ADDR_ob(offset, base),
4063 0 : XMMRegName(src0), XMMRegName(dst));
4064 0 : m_formatter.twoByteOpVex(ty, opcode, offset, base, src0, dst);
4065 0 : m_formatter.immediate8u(imm);
4066 : }
4067 :
4068 0 : void twoByteOpSimd(const char* name, VexOperandType ty, TwoByteOpcodeID opcode,
4069 : int32_t offset, RegisterID base, RegisterID index, int scale,
4070 : XMMRegisterID src0, XMMRegisterID dst)
4071 : {
4072 0 : if (useLegacySSEEncoding(src0, dst)) {
4073 0 : if (IsXMMReversedOperands(opcode)) {
4074 0 : spew("%-11s%s, " MEM_obs, legacySSEOpName(name),
4075 0 : XMMRegName(dst), ADDR_obs(offset, base, index, scale));
4076 : } else {
4077 0 : spew("%-11s" MEM_obs ", %s", legacySSEOpName(name),
4078 0 : ADDR_obs(offset, base, index, scale), XMMRegName(dst));
4079 : }
4080 0 : m_formatter.legacySSEPrefix(ty);
4081 0 : m_formatter.twoByteOp(opcode, offset, base, index, scale, dst);
4082 0 : return;
4083 : }
4084 :
4085 0 : if (src0 == invalid_xmm) {
4086 0 : if (IsXMMReversedOperands(opcode)) {
4087 0 : spew("%-11s%s, " MEM_obs, name, XMMRegName(dst),
4088 0 : ADDR_obs(offset, base, index, scale));
4089 : } else {
4090 0 : spew("%-11s" MEM_obs ", %s", name, ADDR_obs(offset, base, index, scale),
4091 0 : XMMRegName(dst));
4092 : }
4093 : } else {
4094 0 : spew("%-11s" MEM_obs ", %s, %s", name, ADDR_obs(offset, base, index, scale),
4095 0 : XMMRegName(src0), XMMRegName(dst));
4096 : }
4097 0 : m_formatter.twoByteOpVex(ty, opcode, offset, base, index, scale, src0, dst);
4098 : }
4099 :
4100 0 : void twoByteOpSimd(const char* name, VexOperandType ty, TwoByteOpcodeID opcode,
4101 : const void* address, XMMRegisterID src0, XMMRegisterID dst)
4102 : {
4103 0 : if (useLegacySSEEncoding(src0, dst)) {
4104 0 : if (IsXMMReversedOperands(opcode))
4105 0 : spew("%-11s%s, %p", legacySSEOpName(name), XMMRegName(dst), address);
4106 : else
4107 0 : spew("%-11s%p, %s", legacySSEOpName(name), address, XMMRegName(dst));
4108 0 : m_formatter.legacySSEPrefix(ty);
4109 0 : m_formatter.twoByteOp(opcode, address, dst);
4110 0 : return;
4111 : }
4112 :
4113 0 : if (src0 == invalid_xmm) {
4114 0 : if (IsXMMReversedOperands(opcode))
4115 0 : spew("%-11s%s, %p", name, XMMRegName(dst), address);
4116 : else
4117 0 : spew("%-11s%p, %s", name, address, XMMRegName(dst));
4118 : } else {
4119 0 : spew("%-11s%p, %s, %s", name, address, XMMRegName(src0), XMMRegName(dst));
4120 : }
4121 0 : m_formatter.twoByteOpVex(ty, opcode, address, src0, dst);
4122 : }
4123 :
4124 0 : void twoByteOpImmSimd(const char* name, VexOperandType ty, TwoByteOpcodeID opcode,
4125 : uint32_t imm, const void* address, XMMRegisterID src0, XMMRegisterID dst)
4126 : {
4127 0 : if (useLegacySSEEncoding(src0, dst)) {
4128 0 : spew("%-11s$0x%x, %p, %s", legacySSEOpName(name), imm, address, XMMRegName(dst));
4129 0 : m_formatter.legacySSEPrefix(ty);
4130 0 : m_formatter.twoByteOp(opcode, address, dst);
4131 0 : m_formatter.immediate8u(imm);
4132 0 : return;
4133 : }
4134 :
4135 0 : spew("%-11s$0x%x, %p, %s, %s", name, imm, address, XMMRegName(src0), XMMRegName(dst));
4136 0 : m_formatter.twoByteOpVex(ty, opcode, address, src0, dst);
4137 0 : m_formatter.immediate8u(imm);
4138 : }
4139 :
4140 58 : void twoByteOpInt32Simd(const char* name, VexOperandType ty, TwoByteOpcodeID opcode,
4141 : RegisterID rm, XMMRegisterID src0, XMMRegisterID dst)
4142 : {
4143 58 : if (useLegacySSEEncoding(src0, dst)) {
4144 58 : if (IsXMMReversedOperands(opcode))
4145 0 : spew("%-11s%s, %s", legacySSEOpName(name), XMMRegName(dst), GPReg32Name(rm));
4146 : else
4147 58 : spew("%-11s%s, %s", legacySSEOpName(name), GPReg32Name(rm), XMMRegName(dst));
4148 58 : m_formatter.legacySSEPrefix(ty);
4149 58 : m_formatter.twoByteOp(opcode, rm, dst);
4150 58 : return;
4151 : }
4152 :
4153 0 : if (src0 == invalid_xmm) {
4154 0 : if (IsXMMReversedOperands(opcode))
4155 0 : spew("%-11s%s, %s", name, XMMRegName(dst), GPReg32Name(rm));
4156 : else
4157 0 : spew("%-11s%s, %s", name, GPReg32Name(rm), XMMRegName(dst));
4158 : } else {
4159 0 : spew("%-11s%s, %s, %s", name, GPReg32Name(rm), XMMRegName(src0), XMMRegName(dst));
4160 : }
4161 0 : m_formatter.twoByteOpVex(ty, opcode, rm, src0, dst);
4162 : }
4163 :
4164 26 : void twoByteOpSimdInt32(const char* name, VexOperandType ty, TwoByteOpcodeID opcode,
4165 : XMMRegisterID rm, RegisterID dst)
4166 : {
4167 26 : if (useLegacySSEEncodingForOtherOutput()) {
4168 26 : if (IsXMMReversedOperands(opcode))
4169 0 : spew("%-11s%s, %s", legacySSEOpName(name), GPReg32Name(dst), XMMRegName(rm));
4170 26 : else if (opcode == OP2_MOVD_EdVd)
4171 0 : spew("%-11s%s, %s", legacySSEOpName(name), XMMRegName((XMMRegisterID)dst), GPReg32Name((RegisterID)rm));
4172 : else
4173 26 : spew("%-11s%s, %s", legacySSEOpName(name), XMMRegName(rm), GPReg32Name(dst));
4174 26 : m_formatter.legacySSEPrefix(ty);
4175 26 : m_formatter.twoByteOp(opcode, (RegisterID)rm, dst);
4176 26 : return;
4177 : }
4178 :
4179 0 : if (IsXMMReversedOperands(opcode))
4180 0 : spew("%-11s%s, %s", name, GPReg32Name(dst), XMMRegName(rm));
4181 0 : else if (opcode == OP2_MOVD_EdVd)
4182 0 : spew("%-11s%s, %s", name, XMMRegName((XMMRegisterID)dst), GPReg32Name((RegisterID)rm));
4183 : else
4184 0 : spew("%-11s%s, %s", name, XMMRegName(rm), GPReg32Name(dst));
4185 0 : m_formatter.twoByteOpVex(ty, opcode, (RegisterID)rm, invalid_xmm, dst);
4186 : }
4187 :
4188 0 : void twoByteOpImmSimdInt32(const char* name, VexOperandType ty, TwoByteOpcodeID opcode,
4189 : uint32_t imm, XMMRegisterID rm, RegisterID dst)
4190 : {
4191 0 : if (useLegacySSEEncodingForOtherOutput()) {
4192 0 : spew("%-11s$0x%x, %s, %s", legacySSEOpName(name), imm, XMMRegName(rm), GPReg32Name(dst));
4193 0 : m_formatter.legacySSEPrefix(ty);
4194 0 : m_formatter.twoByteOp(opcode, (RegisterID)rm, dst);
4195 0 : m_formatter.immediate8u(imm);
4196 0 : return;
4197 : }
4198 :
4199 0 : spew("%-11s$0x%x, %s, %s", name, imm, XMMRegName(rm), GPReg32Name(dst));
4200 0 : m_formatter.twoByteOpVex(ty, opcode, (RegisterID)rm, invalid_xmm, dst);
4201 0 : m_formatter.immediate8u(imm);
4202 : }
4203 :
4204 0 : void twoByteOpImmInt32Simd(const char* name, VexOperandType ty, TwoByteOpcodeID opcode,
4205 : uint32_t imm, RegisterID rm, XMMRegisterID src0, XMMRegisterID dst)
4206 : {
4207 0 : if (useLegacySSEEncodingForOtherOutput()) {
4208 0 : spew("%-11s$0x%x, %s, %s", legacySSEOpName(name), imm, GPReg32Name(rm), XMMRegName(dst));
4209 0 : m_formatter.legacySSEPrefix(ty);
4210 0 : m_formatter.twoByteOp(opcode, rm, dst);
4211 0 : m_formatter.immediate8u(imm);
4212 0 : return;
4213 : }
4214 :
4215 0 : spew("%-11s$0x%x, %s, %s", name, imm, GPReg32Name(rm), XMMRegName(dst));
4216 0 : m_formatter.twoByteOpVex(ty, opcode, rm, src0, dst);
4217 0 : m_formatter.immediate8u(imm);
4218 : }
4219 :
4220 38 : void twoByteOpSimdFlags(const char* name, VexOperandType ty, TwoByteOpcodeID opcode,
4221 : XMMRegisterID rm, XMMRegisterID reg)
4222 : {
4223 38 : if (useLegacySSEEncodingForOtherOutput()) {
4224 38 : spew("%-11s%s, %s", legacySSEOpName(name), XMMRegName(rm), XMMRegName(reg));
4225 38 : m_formatter.legacySSEPrefix(ty);
4226 38 : m_formatter.twoByteOp(opcode, (RegisterID)rm, reg);
4227 38 : return;
4228 : }
4229 :
4230 0 : spew("%-11s%s, %s", name, XMMRegName(rm), XMMRegName(reg));
4231 0 : m_formatter.twoByteOpVex(ty, opcode, (RegisterID)rm, invalid_xmm, (XMMRegisterID)reg);
4232 : }
4233 :
4234 : void twoByteOpSimdFlags(const char* name, VexOperandType ty, TwoByteOpcodeID opcode,
4235 : int32_t offset, RegisterID base, XMMRegisterID reg)
4236 : {
4237 : if (useLegacySSEEncodingForOtherOutput()) {
4238 : spew("%-11s" MEM_ob ", %s", legacySSEOpName(name),
4239 : ADDR_ob(offset, base), XMMRegName(reg));
4240 : m_formatter.legacySSEPrefix(ty);
4241 : m_formatter.twoByteOp(opcode, offset, base, reg);
4242 : return;
4243 : }
4244 :
4245 : spew("%-11s" MEM_ob ", %s", name,
4246 : ADDR_ob(offset, base), XMMRegName(reg));
4247 : m_formatter.twoByteOpVex(ty, opcode, offset, base, invalid_xmm, (XMMRegisterID)reg);
4248 : }
4249 :
4250 0 : void threeByteOpSimd(const char* name, VexOperandType ty, ThreeByteOpcodeID opcode,
4251 : ThreeByteEscape escape,
4252 : XMMRegisterID rm, XMMRegisterID src0, XMMRegisterID dst)
4253 : {
4254 0 : if (useLegacySSEEncoding(src0, dst)) {
4255 0 : spew("%-11s%s, %s", legacySSEOpName(name), XMMRegName(rm), XMMRegName(dst));
4256 0 : m_formatter.legacySSEPrefix(ty);
4257 0 : m_formatter.threeByteOp(opcode, escape, (RegisterID)rm, dst);
4258 0 : return;
4259 : }
4260 :
4261 0 : spew("%-11s%s, %s, %s", name, XMMRegName(rm), XMMRegName(src0), XMMRegName(dst));
4262 0 : m_formatter.threeByteOpVex(ty, opcode, escape, (RegisterID)rm, src0, dst);
4263 : }
4264 :
4265 0 : void threeByteOpImmSimd(const char* name, VexOperandType ty, ThreeByteOpcodeID opcode,
4266 : ThreeByteEscape escape,
4267 : uint32_t imm, XMMRegisterID rm, XMMRegisterID src0, XMMRegisterID dst)
4268 : {
4269 0 : if (useLegacySSEEncoding(src0, dst)) {
4270 0 : spew("%-11s$0x%x, %s, %s", legacySSEOpName(name), imm, XMMRegName(rm), XMMRegName(dst));
4271 0 : m_formatter.legacySSEPrefix(ty);
4272 0 : m_formatter.threeByteOp(opcode, escape, (RegisterID)rm, dst);
4273 0 : m_formatter.immediate8u(imm);
4274 0 : return;
4275 : }
4276 :
4277 0 : spew("%-11s$0x%x, %s, %s, %s", name, imm, XMMRegName(rm), XMMRegName(src0), XMMRegName(dst));
4278 0 : m_formatter.threeByteOpVex(ty, opcode, escape, (RegisterID)rm, src0, dst);
4279 0 : m_formatter.immediate8u(imm);
4280 : }
4281 :
4282 0 : void threeByteOpSimd(const char* name, VexOperandType ty, ThreeByteOpcodeID opcode,
4283 : ThreeByteEscape escape,
4284 : int32_t offset, RegisterID base, XMMRegisterID src0, XMMRegisterID dst)
4285 : {
4286 0 : if (useLegacySSEEncoding(src0, dst)) {
4287 0 : spew("%-11s" MEM_ob ", %s", legacySSEOpName(name),
4288 0 : ADDR_ob(offset, base), XMMRegName(dst));
4289 0 : m_formatter.legacySSEPrefix(ty);
4290 0 : m_formatter.threeByteOp(opcode, escape, offset, base, dst);
4291 0 : return;
4292 : }
4293 :
4294 0 : spew("%-11s" MEM_ob ", %s, %s", name,
4295 0 : ADDR_ob(offset, base), XMMRegName(src0), XMMRegName(dst));
4296 0 : m_formatter.threeByteOpVex(ty, opcode, escape, offset, base, src0, dst);
4297 : }
4298 :
4299 0 : void threeByteOpImmSimd(const char* name, VexOperandType ty, ThreeByteOpcodeID opcode,
4300 : ThreeByteEscape escape,
4301 : uint32_t imm, int32_t offset, RegisterID base, XMMRegisterID src0, XMMRegisterID dst)
4302 : {
4303 0 : if (useLegacySSEEncoding(src0, dst)) {
4304 0 : spew("%-11s$0x%x, " MEM_ob ", %s", legacySSEOpName(name), imm,
4305 0 : ADDR_ob(offset, base), XMMRegName(dst));
4306 0 : m_formatter.legacySSEPrefix(ty);
4307 0 : m_formatter.threeByteOp(opcode, escape, offset, base, dst);
4308 0 : m_formatter.immediate8u(imm);
4309 0 : return;
4310 : }
4311 :
4312 0 : spew("%-11s$0x%x, " MEM_ob ", %s, %s", name, imm, ADDR_ob(offset, base),
4313 0 : XMMRegName(src0), XMMRegName(dst));
4314 0 : m_formatter.threeByteOpVex(ty, opcode, escape, offset, base, src0, dst);
4315 0 : m_formatter.immediate8u(imm);
4316 : }
4317 :
4318 0 : void threeByteOpSimd(const char* name, VexOperandType ty, ThreeByteOpcodeID opcode,
4319 : ThreeByteEscape escape,
4320 : const void* address, XMMRegisterID src0, XMMRegisterID dst)
4321 : {
4322 0 : if (useLegacySSEEncoding(src0, dst)) {
4323 0 : spew("%-11s%p, %s", legacySSEOpName(name), address, XMMRegName(dst));
4324 0 : m_formatter.legacySSEPrefix(ty);
4325 0 : m_formatter.threeByteOp(opcode, escape, address, dst);
4326 0 : return;
4327 : }
4328 :
4329 0 : spew("%-11s%p, %s, %s", name, address, XMMRegName(src0), XMMRegName(dst));
4330 0 : m_formatter.threeByteOpVex(ty, opcode, escape, address, src0, dst);
4331 : }
4332 :
4333 0 : void threeByteOpImmInt32Simd(const char* name, VexOperandType ty, ThreeByteOpcodeID opcode,
4334 : ThreeByteEscape escape, uint32_t imm,
4335 : RegisterID src1, XMMRegisterID src0, XMMRegisterID dst)
4336 : {
4337 0 : if (useLegacySSEEncoding(src0, dst)) {
4338 0 : spew("%-11s$0x%x, %s, %s", legacySSEOpName(name), imm, GPReg32Name(src1), XMMRegName(dst));
4339 0 : m_formatter.legacySSEPrefix(ty);
4340 0 : m_formatter.threeByteOp(opcode, escape, src1, dst);
4341 0 : m_formatter.immediate8u(imm);
4342 0 : return;
4343 : }
4344 :
4345 0 : spew("%-11s$0x%x, %s, %s, %s", name, imm, GPReg32Name(src1), XMMRegName(src0), XMMRegName(dst));
4346 0 : m_formatter.threeByteOpVex(ty, opcode, escape, src1, src0, dst);
4347 0 : m_formatter.immediate8u(imm);
4348 : }
4349 :
4350 : void threeByteOpImmInt32Simd(const char* name, VexOperandType ty, ThreeByteOpcodeID opcode,
4351 : ThreeByteEscape escape, uint32_t imm,
4352 : int32_t offset, RegisterID base, XMMRegisterID src0, XMMRegisterID dst)
4353 : {
4354 : if (useLegacySSEEncoding(src0, dst)) {
4355 : spew("%-11s$0x%x, " MEM_ob ", %s", legacySSEOpName(name), imm, ADDR_ob(offset, base), XMMRegName(dst));
4356 : m_formatter.legacySSEPrefix(ty);
4357 : m_formatter.threeByteOp(opcode, escape, offset, base, dst);
4358 : m_formatter.immediate8u(imm);
4359 : return;
4360 : }
4361 :
4362 : spew("%-11s$0x%x, " MEM_ob ", %s, %s", name, imm, ADDR_ob(offset, base), XMMRegName(src0), XMMRegName(dst));
4363 : m_formatter.threeByteOpVex(ty, opcode, escape, offset, base, src0, dst);
4364 : m_formatter.immediate8u(imm);
4365 : }
4366 :
4367 0 : void threeByteOpImmSimdInt32(const char* name, VexOperandType ty, ThreeByteOpcodeID opcode,
4368 : ThreeByteEscape escape, uint32_t imm,
4369 : XMMRegisterID src, RegisterID dst)
4370 : {
4371 0 : if (useLegacySSEEncodingForOtherOutput()) {
4372 0 : spew("%-11s$0x%x, %s, %s", legacySSEOpName(name), imm, XMMRegName(src), GPReg32Name(dst));
4373 0 : m_formatter.legacySSEPrefix(ty);
4374 0 : m_formatter.threeByteOp(opcode, escape, (RegisterID)src, dst);
4375 0 : m_formatter.immediate8u(imm);
4376 0 : return;
4377 : }
4378 :
4379 0 : if (opcode == OP3_PEXTRD_EdVdqIb)
4380 0 : spew("%-11s$0x%x, %s, %s", name, imm, XMMRegName((XMMRegisterID)dst), GPReg32Name((RegisterID)src));
4381 : else
4382 0 : spew("%-11s$0x%x, %s, %s", name, imm, XMMRegName(src), GPReg32Name(dst));
4383 0 : m_formatter.threeByteOpVex(ty, opcode, escape, (RegisterID)src, invalid_xmm, dst);
4384 0 : m_formatter.immediate8u(imm);
4385 : }
4386 :
4387 : void threeByteOpImmSimdInt32(const char* name, VexOperandType ty, ThreeByteOpcodeID opcode,
4388 : ThreeByteEscape escape, uint32_t imm,
4389 : int32_t offset, RegisterID base, RegisterID dst)
4390 : {
4391 : if (useLegacySSEEncodingForOtherOutput()) {
4392 : spew("%-11s$0x%x, " MEM_ob ", %s", legacySSEOpName(name), imm, ADDR_ob(offset, base), GPReg32Name(dst));
4393 : m_formatter.legacySSEPrefix(ty);
4394 : m_formatter.threeByteOp(opcode, escape, offset, base, dst);
4395 : m_formatter.immediate8u(imm);
4396 : return;
4397 : }
4398 :
4399 : spew("%-11s$0x%x, " MEM_ob ", %s", name, imm, ADDR_ob(offset, base), GPReg32Name(dst));
4400 : m_formatter.threeByteOpVex(ty, opcode, escape, offset, base, invalid_xmm, dst);
4401 : m_formatter.immediate8u(imm);
4402 : }
4403 :
4404 : // Blendv is a three-byte op, but the VEX encoding has a different opcode
4405 : // than the SSE encoding, so we handle it specially.
4406 0 : void vblendvOpSimd(XMMRegisterID mask, XMMRegisterID rm, XMMRegisterID src0, XMMRegisterID dst)
4407 : {
4408 0 : if (useLegacySSEEncodingForVblendv(mask, src0, dst)) {
4409 0 : spew("blendvps %s, %s", XMMRegName(rm), XMMRegName(dst));
4410 : // Even though a "ps" instruction, vblendv is encoded with the "pd" prefix.
4411 0 : m_formatter.legacySSEPrefix(VEX_PD);
4412 0 : m_formatter.threeByteOp(OP3_BLENDVPS_VdqWdq, ESCAPE_3A, (RegisterID)rm, dst);
4413 0 : return;
4414 : }
4415 :
4416 0 : spew("vblendvps %s, %s, %s, %s",
4417 0 : XMMRegName(mask), XMMRegName(rm), XMMRegName(src0), XMMRegName(dst));
4418 : // Even though a "ps" instruction, vblendv is encoded with the "pd" prefix.
4419 0 : m_formatter.vblendvOpVex(VEX_PD, OP3_VBLENDVPS_VdqWdq, ESCAPE_3A,
4420 0 : mask, (RegisterID)rm, src0, dst);
4421 : }
4422 :
4423 : void vblendvOpSimd(XMMRegisterID mask, int32_t offset, RegisterID base, XMMRegisterID src0, XMMRegisterID dst)
4424 : {
4425 : if (useLegacySSEEncodingForVblendv(mask, src0, dst)) {
4426 : spew("blendvps " MEM_ob ", %s", ADDR_ob(offset, base), XMMRegName(dst));
4427 : // Even though a "ps" instruction, vblendv is encoded with the "pd" prefix.
4428 : m_formatter.legacySSEPrefix(VEX_PD);
4429 : m_formatter.threeByteOp(OP3_BLENDVPS_VdqWdq, ESCAPE_3A, offset, base, dst);
4430 : return;
4431 : }
4432 :
4433 : spew("vblendvps %s, " MEM_ob ", %s, %s",
4434 : XMMRegName(mask), ADDR_ob(offset, base), XMMRegName(src0), XMMRegName(dst));
4435 : // Even though a "ps" instruction, vblendv is encoded with the "pd" prefix.
4436 : m_formatter.vblendvOpVex(VEX_PD, OP3_VBLENDVPS_VdqWdq, ESCAPE_3A,
4437 : mask, offset, base, src0, dst);
4438 : }
4439 :
4440 0 : void shiftOpImmSimd(const char* name, TwoByteOpcodeID opcode, ShiftID shiftKind,
4441 : uint32_t imm, XMMRegisterID src, XMMRegisterID dst)
4442 : {
4443 0 : if (useLegacySSEEncoding(src, dst)) {
4444 0 : spew("%-11s$%d, %s", legacySSEOpName(name), imm, XMMRegName(dst));
4445 0 : m_formatter.legacySSEPrefix(VEX_PD);
4446 0 : m_formatter.twoByteOp(opcode, (RegisterID)dst, (int)shiftKind);
4447 0 : m_formatter.immediate8u(imm);
4448 0 : return;
4449 : }
4450 :
4451 0 : spew("%-11s$%d, %s, %s", name, imm, XMMRegName(src), XMMRegName(dst));
4452 0 : m_formatter.twoByteOpVex(VEX_PD, opcode, (RegisterID)dst, src, (int)shiftKind);
4453 0 : m_formatter.immediate8u(imm);
4454 : }
4455 :
4456 9006 : class X86InstructionFormatter {
4457 :
4458 : public:
4459 : // Legacy prefix bytes:
4460 : //
4461 : // These are emmitted prior to the instruction.
4462 :
4463 306 : void prefix(OneByteOpcodeID pre)
4464 : {
4465 306 : m_buffer.putByte(pre);
4466 306 : }
4467 :
4468 331428 : void legacySSEPrefix(VexOperandType ty)
4469 : {
4470 331428 : switch (ty) {
4471 331162 : case VEX_PS: break;
4472 158 : case VEX_PD: prefix(PRE_SSE_66); break;
4473 0 : case VEX_SS: prefix(PRE_SSE_F3); break;
4474 108 : case VEX_SD: prefix(PRE_SSE_F2); break;
4475 : }
4476 331428 : }
4477 :
4478 : // Word-sized operands / no operand instruction formatters.
4479 : //
4480 : // In addition to the opcode, the following operand permutations are supported:
4481 : // * None - instruction takes no operands.
4482 : // * One register - the low three bits of the RegisterID are added into the opcode.
4483 : // * Two registers - encode a register form ModRm (for all ModRm formats, the reg field is passed first, and a GroupOpcodeID may be passed in its place).
4484 : // * Three argument ModRM - a register, and a register and an offset describing a memory operand.
4485 : // * Five argument ModRM - a register, and a base register, an index, scale, and offset describing a memory operand.
4486 : //
4487 : // For 32-bit x86 targets, the address operand may also be provided as a
4488 : // void*. On 64-bit targets REX prefixes will be planted as necessary,
4489 : // where high numbered registers are used.
4490 : //
4491 : // The twoByteOp methods plant two-byte Intel instructions sequences
4492 : // (first opcode byte 0x0F).
4493 :
4494 83106 : void oneByteOp(OneByteOpcodeID opcode)
4495 : {
4496 83106 : m_buffer.ensureSpace(MaxInstructionSize);
4497 83106 : m_buffer.putByteUnchecked(opcode);
4498 83106 : }
4499 :
4500 266679 : void oneByteOp(OneByteOpcodeID opcode, RegisterID reg)
4501 : {
4502 266679 : m_buffer.ensureSpace(MaxInstructionSize);
4503 266683 : emitRexIfNeeded(0, 0, reg);
4504 266680 : m_buffer.putByteUnchecked(opcode + (reg & 7));
4505 266682 : }
4506 :
4507 15772 : void oneByteOp(OneByteOpcodeID opcode, RegisterID rm, int reg)
4508 : {
4509 15772 : m_buffer.ensureSpace(MaxInstructionSize);
4510 15772 : emitRexIfNeeded(reg, 0, rm);
4511 15772 : m_buffer.putByteUnchecked(opcode);
4512 15772 : registerModRM(rm, reg);
4513 15772 : }
4514 :
4515 44931 : void oneByteOp(OneByteOpcodeID opcode, int32_t offset, RegisterID base, int reg)
4516 : {
4517 44931 : m_buffer.ensureSpace(MaxInstructionSize);
4518 44931 : emitRexIfNeeded(reg, 0, base);
4519 44931 : m_buffer.putByteUnchecked(opcode);
4520 44931 : memoryModRM(offset, base, reg);
4521 44931 : }
4522 :
4523 : void oneByteOp_disp32(OneByteOpcodeID opcode, int32_t offset, RegisterID base, int reg)
4524 : {
4525 : m_buffer.ensureSpace(MaxInstructionSize);
4526 : emitRexIfNeeded(reg, 0, base);
4527 : m_buffer.putByteUnchecked(opcode);
4528 : memoryModRM_disp32(offset, base, reg);
4529 : }
4530 :
4531 51 : void oneByteOp(OneByteOpcodeID opcode, int32_t offset, RegisterID base, RegisterID index, int scale, int reg)
4532 : {
4533 51 : m_buffer.ensureSpace(MaxInstructionSize);
4534 51 : emitRexIfNeeded(reg, index, base);
4535 51 : m_buffer.putByteUnchecked(opcode);
4536 51 : memoryModRM(offset, base, index, scale, reg);
4537 51 : }
4538 :
4539 : void oneByteOp_disp32(OneByteOpcodeID opcode, int32_t offset, RegisterID index, int scale, int reg)
4540 : {
4541 : m_buffer.ensureSpace(MaxInstructionSize);
4542 : emitRexIfNeeded(reg, index, 0);
4543 : m_buffer.putByteUnchecked(opcode);
4544 : memoryModRM_disp32(offset, index, scale, reg);
4545 : }
4546 :
4547 0 : void oneByteOp(OneByteOpcodeID opcode, const void* address, int reg)
4548 : {
4549 0 : m_buffer.ensureSpace(MaxInstructionSize);
4550 0 : emitRexIfNeeded(reg, 0, 0);
4551 0 : m_buffer.putByteUnchecked(opcode);
4552 0 : memoryModRM_disp32(address, reg);
4553 0 : }
4554 :
4555 : void oneByteOp_disp32(OneByteOpcodeID opcode, const void* address, int reg)
4556 : {
4557 : m_buffer.ensureSpace(MaxInstructionSize);
4558 : emitRexIfNeeded(reg, 0, 0);
4559 : m_buffer.putByteUnchecked(opcode);
4560 : memoryModRM_disp32(address, reg);
4561 : }
4562 : #ifdef JS_CODEGEN_X64
4563 19127 : void oneByteRipOp(OneByteOpcodeID opcode, int ripOffset, int reg)
4564 : {
4565 19127 : m_buffer.ensureSpace(MaxInstructionSize);
4566 19127 : emitRexIfNeeded(reg, 0, 0);
4567 19127 : m_buffer.putByteUnchecked(opcode);
4568 19127 : putModRm(ModRmMemoryNoDisp, noBase, reg);
4569 19127 : m_buffer.putIntUnchecked(ripOffset);
4570 19127 : }
4571 :
4572 : void oneByteRipOp64(OneByteOpcodeID opcode, int ripOffset, int reg)
4573 : {
4574 : m_buffer.ensureSpace(MaxInstructionSize);
4575 : emitRexW(reg, 0, 0);
4576 : m_buffer.putByteUnchecked(opcode);
4577 : putModRm(ModRmMemoryNoDisp, noBase, reg);
4578 : m_buffer.putIntUnchecked(ripOffset);
4579 : }
4580 :
4581 0 : void twoByteRipOp(TwoByteOpcodeID opcode, int ripOffset, int reg)
4582 : {
4583 0 : m_buffer.ensureSpace(MaxInstructionSize);
4584 0 : emitRexIfNeeded(reg, 0, 0);
4585 0 : m_buffer.putByteUnchecked(OP_2BYTE_ESCAPE);
4586 0 : m_buffer.putByteUnchecked(opcode);
4587 0 : putModRm(ModRmMemoryNoDisp, noBase, reg);
4588 0 : m_buffer.putIntUnchecked(ripOffset);
4589 0 : }
4590 :
4591 0 : void twoByteRipOpVex(VexOperandType ty, TwoByteOpcodeID opcode, int ripOffset,
4592 : XMMRegisterID src0, XMMRegisterID reg)
4593 : {
4594 0 : int r = (reg >> 3), x = 0, b = 0;
4595 0 : int m = 1; // 0x0F
4596 0 : int w = 0, v = src0, l = 0;
4597 0 : threeOpVex(ty, r, x, b, m, w, v, l, opcode);
4598 0 : putModRm(ModRmMemoryNoDisp, noBase, reg);
4599 0 : m_buffer.putIntUnchecked(ripOffset);
4600 0 : }
4601 : #endif
4602 :
4603 59786 : void twoByteOp(TwoByteOpcodeID opcode)
4604 : {
4605 59786 : m_buffer.ensureSpace(MaxInstructionSize);
4606 59785 : m_buffer.putByteUnchecked(OP_2BYTE_ESCAPE);
4607 59785 : m_buffer.putByteUnchecked(opcode);
4608 59785 : }
4609 :
4610 182 : void twoByteOp(TwoByteOpcodeID opcode, RegisterID rm, int reg)
4611 : {
4612 182 : m_buffer.ensureSpace(MaxInstructionSize);
4613 182 : emitRexIfNeeded(reg, 0, rm);
4614 182 : m_buffer.putByteUnchecked(OP_2BYTE_ESCAPE);
4615 182 : m_buffer.putByteUnchecked(opcode);
4616 182 : registerModRM(rm, reg);
4617 182 : }
4618 :
4619 0 : void twoByteOpVex(VexOperandType ty, TwoByteOpcodeID opcode,
4620 : RegisterID rm, XMMRegisterID src0, int reg)
4621 : {
4622 0 : int r = (reg >> 3), x = 0, b = (rm >> 3);
4623 0 : int m = 1; // 0x0F
4624 0 : int w = 0, v = src0, l = 0;
4625 0 : threeOpVex(ty, r, x, b, m, w, v, l, opcode);
4626 0 : registerModRM(rm, reg);
4627 0 : }
4628 :
4629 331440 : void twoByteOp(TwoByteOpcodeID opcode, int32_t offset, RegisterID base, int reg)
4630 : {
4631 331440 : m_buffer.ensureSpace(MaxInstructionSize);
4632 331452 : emitRexIfNeeded(reg, 0, base);
4633 331453 : m_buffer.putByteUnchecked(OP_2BYTE_ESCAPE);
4634 331470 : m_buffer.putByteUnchecked(opcode);
4635 331465 : memoryModRM(offset, base, reg);
4636 331428 : }
4637 :
4638 0 : void twoByteOpVex(VexOperandType ty, TwoByteOpcodeID opcode,
4639 : int32_t offset, RegisterID base, XMMRegisterID src0, int reg)
4640 : {
4641 0 : int r = (reg >> 3), x = 0, b = (base >> 3);
4642 0 : int m = 1; // 0x0F
4643 0 : int w = 0, v = src0, l = 0;
4644 0 : threeOpVex(ty, r, x, b, m, w, v, l, opcode);
4645 0 : memoryModRM(offset, base, reg);
4646 0 : }
4647 :
4648 : void twoByteOp_disp32(TwoByteOpcodeID opcode, int32_t offset, RegisterID base, int reg)
4649 : {
4650 : m_buffer.ensureSpace(MaxInstructionSize);
4651 : emitRexIfNeeded(reg, 0, base);
4652 : m_buffer.putByteUnchecked(OP_2BYTE_ESCAPE);
4653 : m_buffer.putByteUnchecked(opcode);
4654 : memoryModRM_disp32(offset, base, reg);
4655 : }
4656 :
4657 : void twoByteOpVex_disp32(VexOperandType ty, TwoByteOpcodeID opcode,
4658 : int32_t offset, RegisterID base, XMMRegisterID src0, int reg)
4659 : {
4660 : int r = (reg >> 3), x = 0, b = (base >> 3);
4661 : int m = 1; // 0x0F
4662 : int w = 0, v = src0, l = 0;
4663 : threeOpVex(ty, r, x, b, m, w, v, l, opcode);
4664 : memoryModRM_disp32(offset, base, reg);
4665 : }
4666 :
4667 605 : void twoByteOp(TwoByteOpcodeID opcode, int32_t offset, RegisterID base, RegisterID index, int scale, int reg)
4668 : {
4669 605 : m_buffer.ensureSpace(MaxInstructionSize);
4670 605 : emitRexIfNeeded(reg, index, base);
4671 605 : m_buffer.putByteUnchecked(OP_2BYTE_ESCAPE);
4672 605 : m_buffer.putByteUnchecked(opcode);
4673 605 : memoryModRM(offset, base, index, scale, reg);
4674 605 : }
4675 :
4676 0 : void twoByteOpVex(VexOperandType ty, TwoByteOpcodeID opcode,
4677 : int32_t offset, RegisterID base, RegisterID index, int scale,
4678 : XMMRegisterID src0, int reg)
4679 : {
4680 0 : int r = (reg >> 3), x = (index >> 3), b = (base >> 3);
4681 0 : int m = 1; // 0x0F
4682 0 : int w = 0, v = src0, l = 0;
4683 0 : threeOpVex(ty, r, x, b, m, w, v, l, opcode);
4684 0 : memoryModRM(offset, base, index, scale, reg);
4685 0 : }
4686 :
4687 0 : void twoByteOp(TwoByteOpcodeID opcode, const void* address, int reg)
4688 : {
4689 0 : m_buffer.ensureSpace(MaxInstructionSize);
4690 0 : emitRexIfNeeded(reg, 0, 0);
4691 0 : m_buffer.putByteUnchecked(OP_2BYTE_ESCAPE);
4692 0 : m_buffer.putByteUnchecked(opcode);
4693 0 : memoryModRM(address, reg);
4694 0 : }
4695 :
4696 0 : void twoByteOpVex(VexOperandType ty, TwoByteOpcodeID opcode,
4697 : const void* address, XMMRegisterID src0, int reg)
4698 : {
4699 0 : int r = (reg >> 3), x = 0, b = 0;
4700 0 : int m = 1; // 0x0F
4701 0 : int w = 0, v = src0, l = 0;
4702 0 : threeOpVex(ty, r, x, b, m, w, v, l, opcode);
4703 0 : memoryModRM(address, reg);
4704 0 : }
4705 :
4706 0 : void threeByteOp(ThreeByteOpcodeID opcode, ThreeByteEscape escape, RegisterID rm, int reg)
4707 : {
4708 0 : m_buffer.ensureSpace(MaxInstructionSize);
4709 0 : emitRexIfNeeded(reg, 0, rm);
4710 0 : m_buffer.putByteUnchecked(OP_2BYTE_ESCAPE);
4711 0 : m_buffer.putByteUnchecked(escape);
4712 0 : m_buffer.putByteUnchecked(opcode);
4713 0 : registerModRM(rm, reg);
4714 0 : }
4715 :
4716 0 : void threeByteOpVex(VexOperandType ty, ThreeByteOpcodeID opcode, ThreeByteEscape escape,
4717 : RegisterID rm, XMMRegisterID src0, int reg)
4718 : {
4719 0 : int r = (reg >> 3), x = 0, b = (rm >> 3);
4720 0 : int m = 0, w = 0, v = src0, l = 0;
4721 0 : switch (escape) {
4722 0 : case ESCAPE_38: m = 2; break;
4723 0 : case ESCAPE_3A: m = 3; break;
4724 0 : default: MOZ_CRASH("unexpected escape");
4725 : }
4726 0 : threeOpVex(ty, r, x, b, m, w, v, l, opcode);
4727 0 : registerModRM(rm, reg);
4728 0 : }
4729 :
4730 0 : void threeByteOp(ThreeByteOpcodeID opcode, ThreeByteEscape escape, int32_t offset, RegisterID base, int reg)
4731 : {
4732 0 : m_buffer.ensureSpace(MaxInstructionSize);
4733 0 : emitRexIfNeeded(reg, 0, base);
4734 0 : m_buffer.putByteUnchecked(OP_2BYTE_ESCAPE);
4735 0 : m_buffer.putByteUnchecked(escape);
4736 0 : m_buffer.putByteUnchecked(opcode);
4737 0 : memoryModRM(offset, base, reg);
4738 0 : }
4739 :
4740 0 : void threeByteOpVex(VexOperandType ty, ThreeByteOpcodeID opcode, ThreeByteEscape escape,
4741 : int32_t offset, RegisterID base, XMMRegisterID src0, int reg)
4742 : {
4743 0 : int r = (reg >> 3), x = 0, b = (base >> 3);
4744 0 : int m = 0, w = 0, v = src0, l = 0;
4745 0 : switch (escape) {
4746 0 : case ESCAPE_38: m = 2; break;
4747 0 : case ESCAPE_3A: m = 3; break;
4748 0 : default: MOZ_CRASH("unexpected escape");
4749 : }
4750 0 : threeOpVex(ty, r, x, b, m, w, v, l, opcode);
4751 0 : memoryModRM(offset, base, reg);
4752 0 : }
4753 :
4754 0 : void threeByteOp(ThreeByteOpcodeID opcode, ThreeByteEscape escape, const void* address, int reg)
4755 : {
4756 0 : m_buffer.ensureSpace(MaxInstructionSize);
4757 0 : emitRexIfNeeded(reg, 0, 0);
4758 0 : m_buffer.putByteUnchecked(OP_2BYTE_ESCAPE);
4759 0 : m_buffer.putByteUnchecked(escape);
4760 0 : m_buffer.putByteUnchecked(opcode);
4761 0 : memoryModRM(address, reg);
4762 0 : }
4763 :
4764 0 : void threeByteOpVex(VexOperandType ty, ThreeByteOpcodeID opcode, ThreeByteEscape escape,
4765 : const void* address, XMMRegisterID src0, int reg)
4766 : {
4767 0 : int r = (reg >> 3), x = 0, b = 0;
4768 0 : int m = 0, w = 0, v = src0, l = 0;
4769 0 : switch (escape) {
4770 0 : case ESCAPE_38: m = 2; break;
4771 0 : case ESCAPE_3A: m = 3; break;
4772 0 : default: MOZ_CRASH("unexpected escape");
4773 : }
4774 0 : threeOpVex(ty, r, x, b, m, w, v, l, opcode);
4775 0 : memoryModRM(address, reg);
4776 0 : }
4777 :
4778 0 : void vblendvOpVex(VexOperandType ty, ThreeByteOpcodeID opcode, ThreeByteEscape escape,
4779 : XMMRegisterID mask, RegisterID rm, XMMRegisterID src0, int reg)
4780 : {
4781 0 : int r = (reg >> 3), x = 0, b = (rm >> 3);
4782 0 : int m = 0, w = 0, v = src0, l = 0;
4783 0 : switch (escape) {
4784 0 : case ESCAPE_38: m = 2; break;
4785 0 : case ESCAPE_3A: m = 3; break;
4786 0 : default: MOZ_CRASH("unexpected escape");
4787 : }
4788 0 : threeOpVex(ty, r, x, b, m, w, v, l, opcode);
4789 0 : registerModRM(rm, reg);
4790 0 : immediate8u(mask << 4);
4791 0 : }
4792 :
4793 : void vblendvOpVex(VexOperandType ty, ThreeByteOpcodeID opcode, ThreeByteEscape escape,
4794 : XMMRegisterID mask, int32_t offset, RegisterID base, XMMRegisterID src0, int reg)
4795 : {
4796 : int r = (reg >> 3), x = 0, b = (base >> 3);
4797 : int m = 0, w = 0, v = src0, l = 0;
4798 : switch (escape) {
4799 : case ESCAPE_38: m = 2; break;
4800 : case ESCAPE_3A: m = 3; break;
4801 : default: MOZ_CRASH("unexpected escape");
4802 : }
4803 : threeOpVex(ty, r, x, b, m, w, v, l, opcode);
4804 : memoryModRM(offset, base, reg);
4805 : immediate8u(mask << 4);
4806 : }
4807 :
4808 : #ifdef JS_CODEGEN_X64
4809 : // Quad-word-sized operands:
4810 : //
4811 : // Used to format 64-bit operantions, planting a REX.w prefix. When
4812 : // planting d64 or f64 instructions, not requiring a REX.w prefix, the
4813 : // normal (non-'64'-postfixed) formatters should be used.
4814 :
4815 0 : void oneByteOp64(OneByteOpcodeID opcode)
4816 : {
4817 0 : m_buffer.ensureSpace(MaxInstructionSize);
4818 0 : emitRexW(0, 0, 0);
4819 0 : m_buffer.putByteUnchecked(opcode);
4820 0 : }
4821 :
4822 62253 : void oneByteOp64(OneByteOpcodeID opcode, RegisterID reg)
4823 : {
4824 62253 : m_buffer.ensureSpace(MaxInstructionSize);
4825 62253 : emitRexW(0, 0, reg);
4826 62254 : m_buffer.putByteUnchecked(opcode + (reg & 7));
4827 62251 : }
4828 :
4829 146031 : void oneByteOp64(OneByteOpcodeID opcode, RegisterID rm, int reg)
4830 : {
4831 146031 : m_buffer.ensureSpace(MaxInstructionSize);
4832 146031 : emitRexW(reg, 0, rm);
4833 146034 : m_buffer.putByteUnchecked(opcode);
4834 146035 : registerModRM(rm, reg);
4835 146034 : }
4836 :
4837 75843 : void oneByteOp64(OneByteOpcodeID opcode, int32_t offset, RegisterID base, int reg)
4838 : {
4839 75843 : m_buffer.ensureSpace(MaxInstructionSize);
4840 75843 : emitRexW(reg, 0, base);
4841 75845 : m_buffer.putByteUnchecked(opcode);
4842 75845 : memoryModRM(offset, base, reg);
4843 75845 : }
4844 :
4845 : void oneByteOp64_disp32(OneByteOpcodeID opcode, int32_t offset, RegisterID base, int reg)
4846 : {
4847 : m_buffer.ensureSpace(MaxInstructionSize);
4848 : emitRexW(reg, 0, base);
4849 : m_buffer.putByteUnchecked(opcode);
4850 : memoryModRM_disp32(offset, base, reg);
4851 : }
4852 :
4853 535 : void oneByteOp64(OneByteOpcodeID opcode, int32_t offset, RegisterID base, RegisterID index, int scale, int reg)
4854 : {
4855 535 : m_buffer.ensureSpace(MaxInstructionSize);
4856 535 : emitRexW(reg, index, base);
4857 535 : m_buffer.putByteUnchecked(opcode);
4858 535 : memoryModRM(offset, base, index, scale, reg);
4859 535 : }
4860 :
4861 0 : void oneByteOp64(OneByteOpcodeID opcode, const void* address, int reg)
4862 : {
4863 0 : m_buffer.ensureSpace(MaxInstructionSize);
4864 0 : emitRexW(reg, 0, 0);
4865 0 : m_buffer.putByteUnchecked(opcode);
4866 0 : memoryModRM(address, reg);
4867 0 : }
4868 :
4869 61 : void twoByteOp64(TwoByteOpcodeID opcode, RegisterID rm, int reg)
4870 : {
4871 61 : m_buffer.ensureSpace(MaxInstructionSize);
4872 61 : emitRexW(reg, 0, rm);
4873 61 : m_buffer.putByteUnchecked(OP_2BYTE_ESCAPE);
4874 61 : m_buffer.putByteUnchecked(opcode);
4875 61 : registerModRM(rm, reg);
4876 61 : }
4877 :
4878 0 : void twoByteOp64(TwoByteOpcodeID opcode, int offset, RegisterID base, int reg)
4879 : {
4880 0 : m_buffer.ensureSpace(MaxInstructionSize);
4881 0 : emitRexW(reg, 0, base);
4882 0 : m_buffer.putByteUnchecked(OP_2BYTE_ESCAPE);
4883 0 : m_buffer.putByteUnchecked(opcode);
4884 0 : memoryModRM(offset, base, reg);
4885 0 : }
4886 :
4887 0 : void twoByteOp64(TwoByteOpcodeID opcode, int offset, RegisterID base, RegisterID index, int scale, int reg)
4888 : {
4889 0 : m_buffer.ensureSpace(MaxInstructionSize);
4890 0 : emitRexW(reg, index, base);
4891 0 : m_buffer.putByteUnchecked(OP_2BYTE_ESCAPE);
4892 0 : m_buffer.putByteUnchecked(opcode);
4893 0 : memoryModRM(offset, base, index, scale, reg);
4894 0 : }
4895 :
4896 : void twoByteOp64(TwoByteOpcodeID opcode, const void* address, int reg)
4897 : {
4898 : m_buffer.ensureSpace(MaxInstructionSize);
4899 : emitRexW(reg, 0, 0);
4900 : m_buffer.putByteUnchecked(OP_2BYTE_ESCAPE);
4901 : m_buffer.putByteUnchecked(opcode);
4902 : memoryModRM(address, reg);
4903 : }
4904 :
4905 0 : void twoByteOpVex64(VexOperandType ty, TwoByteOpcodeID opcode,
4906 : RegisterID rm, XMMRegisterID src0, XMMRegisterID reg)
4907 : {
4908 0 : int r = (reg >> 3), x = 0, b = (rm >> 3);
4909 0 : int m = 1; // 0x0F
4910 0 : int w = 1, v = src0, l = 0;
4911 0 : threeOpVex(ty, r, x, b, m, w, v, l, opcode);
4912 0 : registerModRM(rm, reg);
4913 0 : }
4914 : #endif
4915 :
4916 : // Byte-operands:
4917 : //
4918 : // These methods format byte operations. Byte operations differ from
4919 : // the normal formatters in the circumstances under which they will
4920 : // decide to emit REX prefixes. These should be used where any register
4921 : // operand signifies a byte register.
4922 : //
4923 : // The disctinction is due to the handling of register numbers in the
4924 : // range 4..7 on x86-64. These register numbers may either represent
4925 : // the second byte of the first four registers (ah..bh) or the first
4926 : // byte of the second four registers (spl..dil).
4927 : //
4928 : // Address operands should still be checked using regRequiresRex(),
4929 : // while byteRegRequiresRex() is provided to check byte register
4930 : // operands.
4931 :
4932 135 : void oneByteOp8(OneByteOpcodeID opcode)
4933 : {
4934 135 : m_buffer.ensureSpace(MaxInstructionSize);
4935 135 : m_buffer.putByteUnchecked(opcode);
4936 135 : }
4937 :
4938 0 : void oneByteOp8(OneByteOpcodeID opcode, RegisterID r)
4939 : {
4940 0 : m_buffer.ensureSpace(MaxInstructionSize);
4941 0 : emitRexIf(byteRegRequiresRex(r), 0, 0, r);
4942 0 : m_buffer.putByteUnchecked(opcode + (r & 7));
4943 0 : }
4944 :
4945 13442 : void oneByteOp8(OneByteOpcodeID opcode, RegisterID rm, GroupOpcodeID groupOp)
4946 : {
4947 13442 : m_buffer.ensureSpace(MaxInstructionSize);
4948 13442 : emitRexIf(byteRegRequiresRex(rm), 0, 0, rm);
4949 13442 : m_buffer.putByteUnchecked(opcode);
4950 13442 : registerModRM(rm, groupOp);
4951 13442 : }
4952 :
4953 : // Like oneByteOp8, but never emits a REX prefix.
4954 0 : void oneByteOp8_norex(OneByteOpcodeID opcode, HRegisterID rm, GroupOpcodeID groupOp)
4955 : {
4956 0 : MOZ_ASSERT(!regRequiresRex(RegisterID(rm)));
4957 0 : m_buffer.ensureSpace(MaxInstructionSize);
4958 0 : m_buffer.putByteUnchecked(opcode);
4959 0 : registerModRM(RegisterID(rm), groupOp);
4960 0 : }
4961 :
4962 8 : void oneByteOp8(OneByteOpcodeID opcode, int32_t offset, RegisterID base, RegisterID reg)
4963 : {
4964 8 : m_buffer.ensureSpace(MaxInstructionSize);
4965 8 : emitRexIf(byteRegRequiresRex(reg), reg, 0, base);
4966 8 : m_buffer.putByteUnchecked(opcode);
4967 8 : memoryModRM(offset, base, reg);
4968 8 : }
4969 :
4970 : void oneByteOp8_disp32(OneByteOpcodeID opcode, int32_t offset, RegisterID base,
4971 : RegisterID reg)
4972 : {
4973 : m_buffer.ensureSpace(MaxInstructionSize);
4974 : emitRexIf(byteRegRequiresRex(reg), reg, 0, base);
4975 : m_buffer.putByteUnchecked(opcode);
4976 : memoryModRM_disp32(offset, base, reg);
4977 : }
4978 :
4979 3 : void oneByteOp8(OneByteOpcodeID opcode, int32_t offset, RegisterID base,
4980 : RegisterID index, int scale, RegisterID reg)
4981 : {
4982 3 : m_buffer.ensureSpace(MaxInstructionSize);
4983 3 : emitRexIf(byteRegRequiresRex(reg), reg, index, base);
4984 3 : m_buffer.putByteUnchecked(opcode);
4985 3 : memoryModRM(offset, base, index, scale, reg);
4986 3 : }
4987 :
4988 : void oneByteOp8(OneByteOpcodeID opcode, const void* address, RegisterID reg)
4989 : {
4990 : m_buffer.ensureSpace(MaxInstructionSize);
4991 : emitRexIf(byteRegRequiresRex(reg), reg, 0, 0);
4992 : m_buffer.putByteUnchecked(opcode);
4993 : memoryModRM_disp32(address, reg);
4994 : }
4995 :
4996 : void twoByteOp8(TwoByteOpcodeID opcode, RegisterID rm, RegisterID reg)
4997 : {
4998 : m_buffer.ensureSpace(MaxInstructionSize);
4999 : emitRexIf(byteRegRequiresRex(reg)|byteRegRequiresRex(rm), reg, 0, rm);
5000 : m_buffer.putByteUnchecked(OP_2BYTE_ESCAPE);
5001 : m_buffer.putByteUnchecked(opcode);
5002 : registerModRM(rm, reg);
5003 : }
5004 :
5005 0 : void twoByteOp8(TwoByteOpcodeID opcode, int32_t offset, RegisterID base, RegisterID reg)
5006 : {
5007 0 : m_buffer.ensureSpace(MaxInstructionSize);
5008 0 : emitRexIf(byteRegRequiresRex(reg)|regRequiresRex(base), reg, 0, base);
5009 0 : m_buffer.putByteUnchecked(OP_2BYTE_ESCAPE);
5010 0 : m_buffer.putByteUnchecked(opcode);
5011 0 : memoryModRM(offset, base, reg);
5012 0 : }
5013 :
5014 0 : void twoByteOp8(TwoByteOpcodeID opcode, int32_t offset, RegisterID base, RegisterID index,
5015 : int scale, RegisterID reg)
5016 : {
5017 0 : m_buffer.ensureSpace(MaxInstructionSize);
5018 0 : emitRexIf(byteRegRequiresRex(reg)|regRequiresRex(base)|regRequiresRex(index),
5019 0 : reg, index, base);
5020 0 : m_buffer.putByteUnchecked(OP_2BYTE_ESCAPE);
5021 0 : m_buffer.putByteUnchecked(opcode);
5022 0 : memoryModRM(offset, base, index, scale, reg);
5023 0 : }
5024 :
5025 : // Like twoByteOp8 but doesn't add a REX prefix if the destination reg
5026 : // is in esp..edi. This may be used when the destination is not an 8-bit
5027 : // register (as in a movzbl instruction), so it doesn't need a REX
5028 : // prefix to disambiguate it from ah..bh.
5029 61 : void twoByteOp8_movx(TwoByteOpcodeID opcode, RegisterID rm, RegisterID reg)
5030 : {
5031 61 : m_buffer.ensureSpace(MaxInstructionSize);
5032 61 : emitRexIf(regRequiresRex(reg)|byteRegRequiresRex(rm), reg, 0, rm);
5033 61 : m_buffer.putByteUnchecked(OP_2BYTE_ESCAPE);
5034 61 : m_buffer.putByteUnchecked(opcode);
5035 61 : registerModRM(rm, reg);
5036 61 : }
5037 :
5038 186 : void twoByteOp8(TwoByteOpcodeID opcode, RegisterID rm, GroupOpcodeID groupOp)
5039 : {
5040 186 : m_buffer.ensureSpace(MaxInstructionSize);
5041 186 : emitRexIf(byteRegRequiresRex(rm), 0, 0, rm);
5042 186 : m_buffer.putByteUnchecked(OP_2BYTE_ESCAPE);
5043 186 : m_buffer.putByteUnchecked(opcode);
5044 186 : registerModRM(rm, groupOp);
5045 186 : }
5046 :
5047 : // Immediates:
5048 : //
5049 : // An immedaite should be appended where appropriate after an op has
5050 : // been emitted. The writes are unchecked since the opcode formatters
5051 : // above will have ensured space.
5052 :
5053 : // A signed 8-bit immediate.
5054 75134 : MOZ_ALWAYS_INLINE void immediate8s(int32_t imm)
5055 : {
5056 75134 : MOZ_ASSERT(CAN_SIGN_EXTEND_8_32(imm));
5057 75134 : m_buffer.putByteUnchecked(imm);
5058 75134 : }
5059 :
5060 : // An unsigned 8-bit immediate.
5061 7488 : MOZ_ALWAYS_INLINE void immediate8u(uint32_t imm)
5062 : {
5063 7488 : MOZ_ASSERT(CAN_ZERO_EXTEND_8_32(imm));
5064 7488 : m_buffer.putByteUnchecked(int32_t(imm));
5065 7488 : }
5066 :
5067 : // An 8-bit immediate with is either signed or unsigned, for use in
5068 : // instructions which actually only operate on 8 bits.
5069 13581 : MOZ_ALWAYS_INLINE void immediate8(int32_t imm)
5070 : {
5071 13581 : m_buffer.putByteUnchecked(imm);
5072 13581 : }
5073 :
5074 : // A signed 16-bit immediate.
5075 : MOZ_ALWAYS_INLINE void immediate16s(int32_t imm)
5076 : {
5077 : MOZ_ASSERT(CAN_SIGN_EXTEND_16_32(imm));
5078 : m_buffer.putShortUnchecked(imm);
5079 : }
5080 :
5081 : // An unsigned 16-bit immediate.
5082 1036 : MOZ_ALWAYS_INLINE void immediate16u(int32_t imm)
5083 : {
5084 1036 : MOZ_ASSERT(CAN_ZERO_EXTEND_16_32(imm));
5085 1036 : m_buffer.putShortUnchecked(imm);
5086 1036 : }
5087 :
5088 : // A 16-bit immediate with is either signed or unsigned, for use in
5089 : // instructions which actually only operate on 16 bits.
5090 4 : MOZ_ALWAYS_INLINE void immediate16(int32_t imm)
5091 : {
5092 4 : m_buffer.putShortUnchecked(imm);
5093 4 : }
5094 :
5095 53309 : MOZ_ALWAYS_INLINE void immediate32(int32_t imm)
5096 : {
5097 53309 : m_buffer.putIntUnchecked(imm);
5098 53308 : }
5099 :
5100 81378 : MOZ_ALWAYS_INLINE void immediate64(int64_t imm)
5101 : {
5102 81378 : m_buffer.putInt64Unchecked(imm);
5103 81374 : }
5104 :
5105 : MOZ_ALWAYS_INLINE MOZ_MUST_USE JmpSrc
5106 66977 : immediateRel32()
5107 : {
5108 66977 : m_buffer.putIntUnchecked(0);
5109 66975 : return JmpSrc(m_buffer.size());
5110 : }
5111 :
5112 : // Data:
5113 :
5114 0 : void jumpTablePointer(uintptr_t ptr)
5115 : {
5116 0 : m_buffer.ensureSpace(sizeof(uintptr_t));
5117 : #ifdef JS_CODEGEN_X64
5118 0 : m_buffer.putInt64Unchecked(ptr);
5119 : #else
5120 : m_buffer.putIntUnchecked(ptr);
5121 : #endif
5122 0 : }
5123 :
5124 0 : void doubleConstant(double d)
5125 : {
5126 0 : m_buffer.ensureSpace(sizeof(double));
5127 0 : m_buffer.putInt64Unchecked(mozilla::BitwiseCast<uint64_t>(d));
5128 0 : }
5129 :
5130 0 : void floatConstant(float f)
5131 : {
5132 0 : m_buffer.ensureSpace(sizeof(float));
5133 0 : m_buffer.putIntUnchecked(mozilla::BitwiseCast<uint32_t>(f));
5134 0 : }
5135 :
5136 0 : void simd128Constant(const void* data)
5137 : {
5138 0 : const uint8_t* bytes = reinterpret_cast<const uint8_t*>(data);
5139 0 : m_buffer.ensureSpace(16);
5140 0 : for (size_t i = 0; i < 16; ++i)
5141 0 : m_buffer.putByteUnchecked(bytes[i]);
5142 0 : }
5143 :
5144 : void int64Constant(int64_t i)
5145 : {
5146 : m_buffer.ensureSpace(sizeof(int64_t));
5147 : m_buffer.putInt64Unchecked(i);
5148 : }
5149 :
5150 : void int32Constant(int32_t i)
5151 : {
5152 : m_buffer.ensureSpace(sizeof(int32_t));
5153 : m_buffer.putIntUnchecked(i);
5154 : }
5155 :
5156 : // Administrative methods:
5157 :
5158 569941 : size_t size() const { return m_buffer.size(); }
5159 4499 : const unsigned char* buffer() const { return m_buffer.buffer(); }
5160 142599 : unsigned char* data() { return m_buffer.data(); }
5161 256035 : bool oom() const { return m_buffer.oom(); }
5162 25908 : bool isAligned(int alignment) const { return m_buffer.isAligned(alignment); }
5163 :
5164 0 : void disableProtection() { m_buffer.disableProtection(); }
5165 : void enableProtection() { m_buffer.enableProtection(); }
5166 : void setLowerBoundForProtection(size_t size)
5167 : {
5168 : m_buffer.setLowerBoundForProtection(size);
5169 : }
5170 : void unprotectRegion(unsigned char* first, size_t size)
5171 : {
5172 : m_buffer.unprotectRegion(first, size);
5173 : }
5174 : void reprotectRegion(unsigned char* first, size_t size)
5175 : {
5176 : m_buffer.reprotectRegion(first, size);
5177 : }
5178 :
5179 0 : MOZ_MUST_USE bool append(const unsigned char* values, size_t size)
5180 : {
5181 0 : return m_buffer.append(values, size);
5182 : }
5183 :
5184 : private:
5185 :
5186 : // Internals; ModRm and REX formatters.
5187 :
5188 : // Byte operand register spl & above requir a REX prefix, which precludes
5189 : // use of the h registers in the same instruction.
5190 13700 : static bool byteRegRequiresRex(RegisterID reg)
5191 : {
5192 : #ifdef JS_CODEGEN_X64
5193 13700 : return reg >= rsp;
5194 : #else
5195 : return false;
5196 : #endif
5197 : }
5198 :
5199 : // For non-byte sizes, registers r8 & above always require a REX prefix.
5200 1726036 : static bool regRequiresRex(RegisterID reg)
5201 : {
5202 : #ifdef JS_CODEGEN_X64
5203 1726036 : return reg >= r8;
5204 : #else
5205 : return false;
5206 : #endif
5207 : }
5208 :
5209 : #ifdef JS_CODEGEN_X64
5210 : // Format a REX prefix byte.
5211 537224 : void emitRex(bool w, int r, int x, int b)
5212 : {
5213 537224 : m_buffer.putByteUnchecked(PRE_REX | ((int)w << 3) | ((r>>3)<<2) | ((x>>3)<<1) | (b>>3));
5214 537267 : }
5215 :
5216 : // Used to plant a REX byte with REX.w set (for 64-bit operations).
5217 284709 : void emitRexW(int r, int x, int b)
5218 : {
5219 284709 : emitRex(true, r, x, b);
5220 284724 : }
5221 :
5222 : // Used for operations with byte operands - use byteRegRequiresRex() to
5223 : // check register operands, regRequiresRex() to check other registers
5224 : // (i.e. address base & index).
5225 : //
5226 : // NB: WebKit's use of emitRexIf() is limited such that the
5227 : // reqRequiresRex() checks are not needed. SpiderMonkey extends
5228 : // oneByteOp8 and twoByteOp8 functionality such that r, x, and b
5229 : // can all be used.
5230 692485 : void emitRexIf(bool condition, int r, int x, int b)
5231 : {
5232 1371447 : if (condition ||
5233 1202512 : regRequiresRex(RegisterID(r)) ||
5234 1739610 : regRequiresRex(RegisterID(x)) ||
5235 523559 : regRequiresRex(RegisterID(b)))
5236 : {
5237 252550 : emitRex(false, r, x, b);
5238 : }
5239 692506 : }
5240 :
5241 : // Used for word sized operations, will plant a REX prefix if necessary
5242 : // (if any register is r8 or above).
5243 678742 : void emitRexIfNeeded(int r, int x, int b)
5244 : {
5245 678742 : emitRexIf(false, r, x, b);
5246 678711 : }
5247 : #else
5248 : // No REX prefix bytes on 32-bit x86.
5249 : void emitRexIf(bool condition, int, int, int)
5250 : {
5251 : MOZ_ASSERT(!condition, "32-bit x86 should never use a REX prefix");
5252 : }
5253 : void emitRexIfNeeded(int, int, int) {}
5254 : #endif
5255 :
5256 648253 : void putModRm(ModRmMode mode, RegisterID rm, int reg)
5257 : {
5258 648253 : m_buffer.putByteUnchecked((mode << 6) | ((reg & 7) << 3) | (rm & 7));
5259 648269 : }
5260 :
5261 338420 : void putModRmSib(ModRmMode mode, RegisterID base, RegisterID index, int scale, int reg)
5262 : {
5263 338420 : MOZ_ASSERT(mode != ModRmRegister);
5264 :
5265 338420 : putModRm(mode, hasSib, reg);
5266 338429 : m_buffer.putByteUnchecked((scale << 6) | ((index & 7) << 3) | (base & 7));
5267 338439 : }
5268 :
5269 175739 : void registerModRM(RegisterID rm, int reg)
5270 : {
5271 175739 : putModRm(ModRmRegister, rm, reg);
5272 175737 : }
5273 :
5274 452251 : void memoryModRM(int32_t offset, RegisterID base, int reg)
5275 : {
5276 : // A base of esp or r12 would be interpreted as a sib, so force a
5277 : // sib with no index & put the base in there.
5278 : #ifdef JS_CODEGEN_X64
5279 452251 : if ((base == hasSib) || (base == hasSib2))
5280 : #else
5281 : if (base == hasSib)
5282 : #endif
5283 : {
5284 674425 : if (!offset) // No need to check if the base is noBase, since we know it is hasSib!
5285 23624 : putModRmSib(ModRmMemoryNoDisp, base, noIndex, 0, reg);
5286 313608 : else if (CAN_SIGN_EXTEND_8_32(offset)) {
5287 158689 : putModRmSib(ModRmMemoryDisp8, base, noIndex, 0, reg);
5288 158696 : m_buffer.putByteUnchecked(offset);
5289 : } else {
5290 154923 : putModRmSib(ModRmMemoryDisp32, base, noIndex, 0, reg);
5291 154927 : m_buffer.putIntUnchecked(offset);
5292 : }
5293 : } else {
5294 : #ifdef JS_CODEGEN_X64
5295 115019 : if (!offset && (base != noBase) && (base != noBase2))
5296 : #else
5297 : if (!offset && (base != noBase))
5298 : #endif
5299 57564 : putModRm(ModRmMemoryNoDisp, base, reg);
5300 57455 : else if (CAN_SIGN_EXTEND_8_32(offset)) {
5301 48466 : putModRm(ModRmMemoryDisp8, base, reg);
5302 48466 : m_buffer.putByteUnchecked(offset);
5303 : } else {
5304 8989 : putModRm(ModRmMemoryDisp32, base, reg);
5305 8989 : m_buffer.putIntUnchecked(offset);
5306 : }
5307 : }
5308 452212 : }
5309 :
5310 : void memoryModRM_disp32(int32_t offset, RegisterID base, int reg)
5311 : {
5312 : // A base of esp or r12 would be interpreted as a sib, so force a
5313 : // sib with no index & put the base in there.
5314 : #ifdef JS_CODEGEN_X64
5315 : if ((base == hasSib) || (base == hasSib2))
5316 : #else
5317 : if (base == hasSib)
5318 : #endif
5319 : {
5320 : putModRmSib(ModRmMemoryDisp32, base, noIndex, 0, reg);
5321 : m_buffer.putIntUnchecked(offset);
5322 : } else {
5323 : putModRm(ModRmMemoryDisp32, base, reg);
5324 : m_buffer.putIntUnchecked(offset);
5325 : }
5326 : }
5327 :
5328 1194 : void memoryModRM(int32_t offset, RegisterID base, RegisterID index, int scale, int reg)
5329 : {
5330 1194 : MOZ_ASSERT(index != noIndex);
5331 :
5332 : #ifdef JS_CODEGEN_X64
5333 1194 : if (!offset && (base != noBase) && (base != noBase2))
5334 : #else
5335 : if (!offset && (base != noBase))
5336 : #endif
5337 461 : putModRmSib(ModRmMemoryNoDisp, base, index, scale, reg);
5338 733 : else if (CAN_SIGN_EXTEND_8_32(offset)) {
5339 729 : putModRmSib(ModRmMemoryDisp8, base, index, scale, reg);
5340 729 : m_buffer.putByteUnchecked(offset);
5341 : } else {
5342 4 : putModRmSib(ModRmMemoryDisp32, base, index, scale, reg);
5343 4 : m_buffer.putIntUnchecked(offset);
5344 : }
5345 1194 : }
5346 :
5347 : void memoryModRM_disp32(int32_t offset, RegisterID index, int scale, int reg)
5348 : {
5349 : MOZ_ASSERT(index != noIndex);
5350 :
5351 : // NB: the base-less memoryModRM overloads generate different code
5352 : // then the base-full memoryModRM overloads in the base == noBase
5353 : // case. The base-less overloads assume that the desired effective
5354 : // address is:
5355 : //
5356 : // reg := [scaled index] + disp32
5357 : //
5358 : // which means the mod needs to be ModRmMemoryNoDisp. The base-full
5359 : // overloads pass ModRmMemoryDisp32 in all cases and thus, when
5360 : // base == noBase (== ebp), the effective address is:
5361 : //
5362 : // reg := [scaled index] + disp32 + [ebp]
5363 : //
5364 : // See Intel developer manual, Vol 2, 2.1.5, Table 2-3.
5365 : putModRmSib(ModRmMemoryNoDisp, noBase, index, scale, reg);
5366 : m_buffer.putIntUnchecked(offset);
5367 : }
5368 :
5369 0 : void memoryModRM_disp32(const void* address, int reg)
5370 : {
5371 0 : int32_t disp = AddressImmediate(address);
5372 :
5373 : #ifdef JS_CODEGEN_X64
5374 : // On x64-64, non-RIP-relative absolute mode requires a SIB.
5375 0 : putModRmSib(ModRmMemoryNoDisp, noBase, noIndex, 0, reg);
5376 : #else
5377 : // noBase + ModRmMemoryNoDisp means noBase + ModRmMemoryDisp32!
5378 : putModRm(ModRmMemoryNoDisp, noBase, reg);
5379 : #endif
5380 0 : m_buffer.putIntUnchecked(disp);
5381 0 : }
5382 :
5383 0 : void memoryModRM(const void* address, int reg)
5384 : {
5385 0 : memoryModRM_disp32(address, reg);
5386 0 : }
5387 :
5388 0 : void threeOpVex(VexOperandType p, int r, int x, int b, int m, int w, int v, int l,
5389 : int opcode)
5390 : {
5391 0 : m_buffer.ensureSpace(MaxInstructionSize);
5392 :
5393 0 : if (v == invalid_xmm)
5394 0 : v = XMMRegisterID(0);
5395 :
5396 0 : if (x == 0 && b == 0 && m == 1 && w == 0) {
5397 : // Two byte VEX.
5398 0 : m_buffer.putByteUnchecked(PRE_VEX_C5);
5399 0 : m_buffer.putByteUnchecked(((r << 7) | (v << 3) | (l << 2) | p) ^ 0xf8);
5400 : } else {
5401 : // Three byte VEX.
5402 0 : m_buffer.putByteUnchecked(PRE_VEX_C4);
5403 0 : m_buffer.putByteUnchecked(((r << 7) | (x << 6) | (b << 5) | m) ^ 0xe0);
5404 0 : m_buffer.putByteUnchecked(((w << 7) | (v << 3) | (l << 2) | p) ^ 0x78);
5405 : }
5406 :
5407 0 : m_buffer.putByteUnchecked(opcode);
5408 0 : }
5409 :
5410 : AssemblerBuffer m_buffer;
5411 : } m_formatter;
5412 :
5413 : bool useVEX_;
5414 : };
5415 :
5416 : } // namespace X86Encoding
5417 :
5418 : } // namespace jit
5419 : } // namespace js
5420 :
5421 : #endif /* jit_x86_shared_BaseAssembler_x86_shared_h */
|