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