1 /*
2 * Copyright (C) 2008 Apple Inc. All rights reserved.
3 *
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions
6 * are met:
7 * 1. Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * 2. Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 *
13 * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
14 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
15 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
17 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
18 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
19 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
20 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
21 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
23 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
24 */
25
26 #ifndef X86Assembler_h
27 #define X86Assembler_h
28
29 #include <wtf/Platform.h>
30
31 #if ENABLE(ASSEMBLER) && (PLATFORM(X86) || PLATFORM(X86_64))
32
33 #include "AssemblerBuffer.h"
34 #include <stdint.h>
35 #include <wtf/Assertions.h>
36 #include <wtf/Vector.h>
37
38 namespace JSC {
39
CAN_SIGN_EXTEND_8_32(int32_t value)40 inline bool CAN_SIGN_EXTEND_8_32(int32_t value) { return value == (int32_t)(signed char)value; }
41 #if PLATFORM(X86_64)
CAN_SIGN_EXTEND_32_64(intptr_t value)42 inline bool CAN_SIGN_EXTEND_32_64(intptr_t value) { return value == (intptr_t)(int32_t)value; }
CAN_SIGN_EXTEND_U32_64(intptr_t value)43 inline bool CAN_SIGN_EXTEND_U32_64(intptr_t value) { return value == (intptr_t)(uint32_t)value; }
44 #endif
45
46 namespace X86 {
47 typedef enum {
48 eax,
49 ecx,
50 edx,
51 ebx,
52 esp,
53 ebp,
54 esi,
55 edi,
56
57 #if PLATFORM(X86_64)
58 r8,
59 r9,
60 r10,
61 r11,
62 r12,
63 r13,
64 r14,
65 r15,
66 #endif
67 } RegisterID;
68
69 typedef enum {
70 xmm0,
71 xmm1,
72 xmm2,
73 xmm3,
74 xmm4,
75 xmm5,
76 xmm6,
77 xmm7,
78 } XMMRegisterID;
79 }
80
81 class X86Assembler {
82 public:
83 typedef X86::RegisterID RegisterID;
84 typedef X86::XMMRegisterID XMMRegisterID;
85
86 typedef enum {
87 OP_ADD_EvGv = 0x01,
88 OP_ADD_GvEv = 0x03,
89 OP_OR_EvGv = 0x09,
90 OP_OR_GvEv = 0x0B,
91 OP_2BYTE_ESCAPE = 0x0F,
92 OP_AND_EvGv = 0x21,
93 OP_SUB_EvGv = 0x29,
94 OP_SUB_GvEv = 0x2B,
95 PRE_PREDICT_BRANCH_NOT_TAKEN = 0x2E,
96 OP_XOR_EvGv = 0x31,
97 OP_CMP_EvGv = 0x39,
98 OP_CMP_GvEv = 0x3B,
99 #if PLATFORM(X86_64)
100 PRE_REX = 0x40,
101 #endif
102 OP_PUSH_EAX = 0x50,
103 OP_POP_EAX = 0x58,
104 #if PLATFORM(X86_64)
105 OP_MOVSXD_GvEv = 0x63,
106 #endif
107 PRE_OPERAND_SIZE = 0x66,
108 PRE_SSE_66 = 0x66,
109 OP_PUSH_Iz = 0x68,
110 OP_IMUL_GvEvIz = 0x69,
111 OP_GROUP1_EvIz = 0x81,
112 OP_GROUP1_EvIb = 0x83,
113 OP_TEST_EvGv = 0x85,
114 OP_XCHG_EvGv = 0x87,
115 OP_MOV_EvGv = 0x89,
116 OP_MOV_GvEv = 0x8B,
117 OP_LEA = 0x8D,
118 OP_GROUP1A_Ev = 0x8F,
119 OP_CDQ = 0x99,
120 OP_MOV_EAXOv = 0xA1,
121 OP_MOV_OvEAX = 0xA3,
122 OP_MOV_EAXIv = 0xB8,
123 OP_GROUP2_EvIb = 0xC1,
124 OP_RET = 0xC3,
125 OP_GROUP11_EvIz = 0xC7,
126 OP_INT3 = 0xCC,
127 OP_GROUP2_Ev1 = 0xD1,
128 OP_GROUP2_EvCL = 0xD3,
129 OP_CALL_rel32 = 0xE8,
130 OP_JMP_rel32 = 0xE9,
131 PRE_SSE_F2 = 0xF2,
132 OP_HLT = 0xF4,
133 OP_GROUP3_EbIb = 0xF6,
134 OP_GROUP3_Ev = 0xF7,
135 OP_GROUP3_EvIz = 0xF7, // OP_GROUP3_Ev has an immediate, when instruction is a test.
136 OP_GROUP5_Ev = 0xFF,
137 } OneByteOpcodeID;
138
139 typedef enum {
140 OP2_MOVSD_VsdWsd = 0x10,
141 OP2_MOVSD_WsdVsd = 0x11,
142 OP2_CVTSI2SD_VsdEd = 0x2A,
143 OP2_CVTTSD2SI_GdWsd = 0x2C,
144 OP2_UCOMISD_VsdWsd = 0x2E,
145 OP2_ADDSD_VsdWsd = 0x58,
146 OP2_MULSD_VsdWsd = 0x59,
147 OP2_SUBSD_VsdWsd = 0x5C,
148 OP2_MOVD_VdEd = 0x6E,
149 OP2_MOVD_EdVd = 0x7E,
150 OP2_JO_rel32 = 0x80,
151 OP2_JB_rel32 = 0x82,
152 OP2_JAE_rel32 = 0x83,
153 OP2_JE_rel32 = 0x84,
154 OP2_JNE_rel32 = 0x85,
155 OP2_JBE_rel32 = 0x86,
156 OP2_JA_rel32 = 0x87,
157 OP2_JS_rel32 = 0x88,
158 OP2_JP_rel32 = 0x8A,
159 OP2_JL_rel32 = 0x8C,
160 OP2_JGE_rel32 = 0x8D,
161 OP2_JLE_rel32 = 0x8E,
162 OP2_JG_rel32 = 0x8F,
163 OP_SETE = 0x94,
164 OP_SETNE = 0x95,
165 OP2_IMUL_GvEv = 0xAF,
166 OP2_MOVZX_GvEb = 0xB6,
167 OP2_MOVZX_GvEw = 0xB7,
168 OP2_PEXTRW_GdUdIb = 0xC5,
169 } TwoByteOpcodeID;
170
171 typedef enum {
172 GROUP1_OP_ADD = 0,
173 GROUP1_OP_OR = 1,
174 GROUP1_OP_AND = 4,
175 GROUP1_OP_SUB = 5,
176 GROUP1_OP_XOR = 6,
177 GROUP1_OP_CMP = 7,
178
179 GROUP1A_OP_POP = 0,
180
181 GROUP2_OP_SHL = 4,
182 GROUP2_OP_SAR = 7,
183
184 GROUP3_OP_TEST = 0,
185 GROUP3_OP_NOT = 2,
186 GROUP3_OP_IDIV = 7,
187
188 GROUP5_OP_CALLN = 2,
189 GROUP5_OP_JMPN = 4,
190 GROUP5_OP_PUSH = 6,
191
192 GROUP11_MOV = 0,
193 } GroupOpcodeID;
194
195 // Opaque label types
196
197 private:
198 class X86InstructionFormatter;
199 public:
200
201 class JmpSrc {
202 friend class X86Assembler;
203 friend class X86InstructionFormatter;
204 public:
JmpSrc()205 JmpSrc()
206 : m_offset(-1)
207 {
208 }
209
210 private:
JmpSrc(int offset)211 JmpSrc(int offset)
212 : m_offset(offset)
213 {
214 }
215
216 int m_offset;
217 };
218
219 class JmpDst {
220 friend class X86Assembler;
221 friend class X86InstructionFormatter;
222 public:
JmpDst()223 JmpDst()
224 : m_offset(-1)
225 {
226 }
227
228 private:
JmpDst(int offset)229 JmpDst(int offset)
230 : m_offset(offset)
231 {
232 }
233
234 int m_offset;
235 };
236
X86Assembler()237 X86Assembler()
238 {
239 }
240
size()241 size_t size() const { return m_formatter.size(); }
242
243 // Stack operations:
244
push_r(RegisterID reg)245 void push_r(RegisterID reg)
246 {
247 m_formatter.oneByteOp(OP_PUSH_EAX, reg);
248 }
249
pop_r(RegisterID reg)250 void pop_r(RegisterID reg)
251 {
252 m_formatter.oneByteOp(OP_POP_EAX, reg);
253 }
254
push_i32(int imm)255 void push_i32(int imm)
256 {
257 m_formatter.oneByteOp(OP_PUSH_Iz);
258 m_formatter.immediate32(imm);
259 }
260
push_m(int offset,RegisterID base)261 void push_m(int offset, RegisterID base)
262 {
263 m_formatter.oneByteOp(OP_GROUP5_Ev, GROUP5_OP_PUSH, base, offset);
264 }
265
pop_m(int offset,RegisterID base)266 void pop_m(int offset, RegisterID base)
267 {
268 m_formatter.oneByteOp(OP_GROUP1A_Ev, GROUP1A_OP_POP, base, offset);
269 }
270
271 // Arithmetic operations:
272
addl_rr(RegisterID src,RegisterID dst)273 void addl_rr(RegisterID src, RegisterID dst)
274 {
275 m_formatter.oneByteOp(OP_ADD_EvGv, src, dst);
276 }
277
addl_mr(int offset,RegisterID base,RegisterID dst)278 void addl_mr(int offset, RegisterID base, RegisterID dst)
279 {
280 m_formatter.oneByteOp(OP_ADD_GvEv, dst, base, offset);
281 }
282
addl_ir(int imm,RegisterID dst)283 void addl_ir(int imm, RegisterID dst)
284 {
285 if (CAN_SIGN_EXTEND_8_32(imm)) {
286 m_formatter.oneByteOp(OP_GROUP1_EvIb, GROUP1_OP_ADD, dst);
287 m_formatter.immediate8(imm);
288 } else {
289 m_formatter.oneByteOp(OP_GROUP1_EvIz, GROUP1_OP_ADD, dst);
290 m_formatter.immediate32(imm);
291 }
292 }
293
addl_im(int imm,int offset,RegisterID base)294 void addl_im(int imm, int offset, RegisterID base)
295 {
296 if (CAN_SIGN_EXTEND_8_32(imm)) {
297 m_formatter.oneByteOp(OP_GROUP1_EvIb, GROUP1_OP_ADD, base, offset);
298 m_formatter.immediate8(imm);
299 } else {
300 m_formatter.oneByteOp(OP_GROUP1_EvIz, GROUP1_OP_ADD, base, offset);
301 m_formatter.immediate32(imm);
302 }
303 }
304
305 #if PLATFORM(X86_64)
addq_rr(RegisterID src,RegisterID dst)306 void addq_rr(RegisterID src, RegisterID dst)
307 {
308 m_formatter.oneByteOp64(OP_ADD_EvGv, src, dst);
309 }
310
addq_ir(int imm,RegisterID dst)311 void addq_ir(int imm, RegisterID dst)
312 {
313 if (CAN_SIGN_EXTEND_8_32(imm)) {
314 m_formatter.oneByteOp64(OP_GROUP1_EvIb, GROUP1_OP_ADD, dst);
315 m_formatter.immediate8(imm);
316 } else {
317 m_formatter.oneByteOp64(OP_GROUP1_EvIz, GROUP1_OP_ADD, dst);
318 m_formatter.immediate32(imm);
319 }
320 }
321 #else
addl_im(int imm,void * addr)322 void addl_im(int imm, void* addr)
323 {
324 if (CAN_SIGN_EXTEND_8_32(imm)) {
325 m_formatter.oneByteOp(OP_GROUP1_EvIb, GROUP1_OP_ADD, addr);
326 m_formatter.immediate8(imm);
327 } else {
328 m_formatter.oneByteOp(OP_GROUP1_EvIz, GROUP1_OP_ADD, addr);
329 m_formatter.immediate32(imm);
330 }
331 }
332 #endif
333
andl_rr(RegisterID src,RegisterID dst)334 void andl_rr(RegisterID src, RegisterID dst)
335 {
336 m_formatter.oneByteOp(OP_AND_EvGv, src, dst);
337 }
338
andl_ir(int imm,RegisterID dst)339 void andl_ir(int imm, RegisterID dst)
340 {
341 if (CAN_SIGN_EXTEND_8_32(imm)) {
342 m_formatter.oneByteOp(OP_GROUP1_EvIb, GROUP1_OP_AND, dst);
343 m_formatter.immediate8(imm);
344 } else {
345 m_formatter.oneByteOp(OP_GROUP1_EvIz, GROUP1_OP_AND, dst);
346 m_formatter.immediate32(imm);
347 }
348 }
349
350 #if PLATFORM(X86_64)
andq_rr(RegisterID src,RegisterID dst)351 void andq_rr(RegisterID src, RegisterID dst)
352 {
353 m_formatter.oneByteOp64(OP_AND_EvGv, src, dst);
354 }
355
andq_ir(int imm,RegisterID dst)356 void andq_ir(int imm, RegisterID dst)
357 {
358 if (CAN_SIGN_EXTEND_8_32(imm)) {
359 m_formatter.oneByteOp64(OP_GROUP1_EvIb, GROUP1_OP_AND, dst);
360 m_formatter.immediate8(imm);
361 } else {
362 m_formatter.oneByteOp64(OP_GROUP1_EvIz, GROUP1_OP_AND, dst);
363 m_formatter.immediate32(imm);
364 }
365 }
366 #endif
367
notl_r(RegisterID dst)368 void notl_r(RegisterID dst)
369 {
370 m_formatter.oneByteOp(OP_GROUP3_Ev, GROUP3_OP_NOT, dst);
371 }
372
orl_rr(RegisterID src,RegisterID dst)373 void orl_rr(RegisterID src, RegisterID dst)
374 {
375 m_formatter.oneByteOp(OP_OR_EvGv, src, dst);
376 }
377
orl_mr(int offset,RegisterID base,RegisterID dst)378 void orl_mr(int offset, RegisterID base, RegisterID dst)
379 {
380 m_formatter.oneByteOp(OP_OR_GvEv, dst, base, offset);
381 }
382
orl_ir(int imm,RegisterID dst)383 void orl_ir(int imm, RegisterID dst)
384 {
385 if (CAN_SIGN_EXTEND_8_32(imm)) {
386 m_formatter.oneByteOp(OP_GROUP1_EvIb, GROUP1_OP_OR, dst);
387 m_formatter.immediate8(imm);
388 } else {
389 m_formatter.oneByteOp(OP_GROUP1_EvIz, GROUP1_OP_OR, dst);
390 m_formatter.immediate32(imm);
391 }
392 }
393
394 #if PLATFORM(X86_64)
orq_rr(RegisterID src,RegisterID dst)395 void orq_rr(RegisterID src, RegisterID dst)
396 {
397 m_formatter.oneByteOp64(OP_OR_EvGv, src, dst);
398 }
399
orq_ir(int imm,RegisterID dst)400 void orq_ir(int imm, RegisterID dst)
401 {
402 if (CAN_SIGN_EXTEND_8_32(imm)) {
403 m_formatter.oneByteOp64(OP_GROUP1_EvIb, GROUP1_OP_OR, dst);
404 m_formatter.immediate8(imm);
405 } else {
406 m_formatter.oneByteOp64(OP_GROUP1_EvIz, GROUP1_OP_OR, dst);
407 m_formatter.immediate32(imm);
408 }
409 }
410 #endif
411
subl_rr(RegisterID src,RegisterID dst)412 void subl_rr(RegisterID src, RegisterID dst)
413 {
414 m_formatter.oneByteOp(OP_SUB_EvGv, src, dst);
415 }
416
subl_mr(int offset,RegisterID base,RegisterID dst)417 void subl_mr(int offset, RegisterID base, RegisterID dst)
418 {
419 m_formatter.oneByteOp(OP_SUB_GvEv, dst, base, offset);
420 }
421
subl_ir(int imm,RegisterID dst)422 void subl_ir(int imm, RegisterID dst)
423 {
424 if (CAN_SIGN_EXTEND_8_32(imm)) {
425 m_formatter.oneByteOp(OP_GROUP1_EvIb, GROUP1_OP_SUB, dst);
426 m_formatter.immediate8(imm);
427 } else {
428 m_formatter.oneByteOp(OP_GROUP1_EvIz, GROUP1_OP_SUB, dst);
429 m_formatter.immediate32(imm);
430 }
431 }
432
subl_im(int imm,int offset,RegisterID base)433 void subl_im(int imm, int offset, RegisterID base)
434 {
435 if (CAN_SIGN_EXTEND_8_32(imm)) {
436 m_formatter.oneByteOp(OP_GROUP1_EvIb, GROUP1_OP_SUB, base, offset);
437 m_formatter.immediate8(imm);
438 } else {
439 m_formatter.oneByteOp(OP_GROUP1_EvIz, GROUP1_OP_SUB, base, offset);
440 m_formatter.immediate32(imm);
441 }
442 }
443
444 #if PLATFORM(X86_64)
subq_rr(RegisterID src,RegisterID dst)445 void subq_rr(RegisterID src, RegisterID dst)
446 {
447 m_formatter.oneByteOp64(OP_SUB_EvGv, src, dst);
448 }
449
subq_ir(int imm,RegisterID dst)450 void subq_ir(int imm, RegisterID dst)
451 {
452 if (CAN_SIGN_EXTEND_8_32(imm)) {
453 m_formatter.oneByteOp64(OP_GROUP1_EvIb, GROUP1_OP_SUB, dst);
454 m_formatter.immediate8(imm);
455 } else {
456 m_formatter.oneByteOp64(OP_GROUP1_EvIz, GROUP1_OP_SUB, dst);
457 m_formatter.immediate32(imm);
458 }
459 }
460 #else
subl_im(int imm,void * addr)461 void subl_im(int imm, void* addr)
462 {
463 if (CAN_SIGN_EXTEND_8_32(imm)) {
464 m_formatter.oneByteOp(OP_GROUP1_EvIb, GROUP1_OP_SUB, addr);
465 m_formatter.immediate8(imm);
466 } else {
467 m_formatter.oneByteOp(OP_GROUP1_EvIz, GROUP1_OP_SUB, addr);
468 m_formatter.immediate32(imm);
469 }
470 }
471 #endif
472
xorl_rr(RegisterID src,RegisterID dst)473 void xorl_rr(RegisterID src, RegisterID dst)
474 {
475 m_formatter.oneByteOp(OP_XOR_EvGv, src, dst);
476 }
477
xorl_ir(int imm,RegisterID dst)478 void xorl_ir(int imm, RegisterID dst)
479 {
480 if (CAN_SIGN_EXTEND_8_32(imm)) {
481 m_formatter.oneByteOp(OP_GROUP1_EvIb, GROUP1_OP_XOR, dst);
482 m_formatter.immediate8(imm);
483 } else {
484 m_formatter.oneByteOp(OP_GROUP1_EvIz, GROUP1_OP_XOR, dst);
485 m_formatter.immediate32(imm);
486 }
487 }
488
489 #if PLATFORM(X86_64)
xorq_rr(RegisterID src,RegisterID dst)490 void xorq_rr(RegisterID src, RegisterID dst)
491 {
492 m_formatter.oneByteOp64(OP_XOR_EvGv, src, dst);
493 }
494
xorq_ir(int imm,RegisterID dst)495 void xorq_ir(int imm, RegisterID dst)
496 {
497 if (CAN_SIGN_EXTEND_8_32(imm)) {
498 m_formatter.oneByteOp64(OP_GROUP1_EvIb, GROUP1_OP_XOR, dst);
499 m_formatter.immediate8(imm);
500 } else {
501 m_formatter.oneByteOp64(OP_GROUP1_EvIz, GROUP1_OP_XOR, dst);
502 m_formatter.immediate32(imm);
503 }
504 }
505 #endif
506
sarl_i8r(int imm,RegisterID dst)507 void sarl_i8r(int imm, RegisterID dst)
508 {
509 if (imm == 1)
510 m_formatter.oneByteOp(OP_GROUP2_Ev1, GROUP2_OP_SAR, dst);
511 else {
512 m_formatter.oneByteOp(OP_GROUP2_EvIb, GROUP2_OP_SAR, dst);
513 m_formatter.immediate8(imm);
514 }
515 }
516
sarl_CLr(RegisterID dst)517 void sarl_CLr(RegisterID dst)
518 {
519 m_formatter.oneByteOp(OP_GROUP2_EvCL, GROUP2_OP_SAR, dst);
520 }
521
shll_i8r(int imm,RegisterID dst)522 void shll_i8r(int imm, RegisterID dst)
523 {
524 if (imm == 1)
525 m_formatter.oneByteOp(OP_GROUP2_Ev1, GROUP2_OP_SHL, dst);
526 else {
527 m_formatter.oneByteOp(OP_GROUP2_EvIb, GROUP2_OP_SHL, dst);
528 m_formatter.immediate8(imm);
529 }
530 }
531
shll_CLr(RegisterID dst)532 void shll_CLr(RegisterID dst)
533 {
534 m_formatter.oneByteOp(OP_GROUP2_EvCL, GROUP2_OP_SHL, dst);
535 }
536
537 #if PLATFORM(X86_64)
sarq_CLr(RegisterID dst)538 void sarq_CLr(RegisterID dst)
539 {
540 m_formatter.oneByteOp64(OP_GROUP2_EvCL, GROUP2_OP_SAR, dst);
541 }
542
sarq_i8r(int imm,RegisterID dst)543 void sarq_i8r(int imm, RegisterID dst)
544 {
545 if (imm == 1)
546 m_formatter.oneByteOp64(OP_GROUP2_Ev1, GROUP2_OP_SAR, dst);
547 else {
548 m_formatter.oneByteOp64(OP_GROUP2_EvIb, GROUP2_OP_SAR, dst);
549 m_formatter.immediate8(imm);
550 }
551 }
552 #endif
553
imull_rr(RegisterID src,RegisterID dst)554 void imull_rr(RegisterID src, RegisterID dst)
555 {
556 m_formatter.twoByteOp(OP2_IMUL_GvEv, dst, src);
557 }
558
imull_i32r(RegisterID src,int32_t value,RegisterID dst)559 void imull_i32r(RegisterID src, int32_t value, RegisterID dst)
560 {
561 m_formatter.oneByteOp(OP_IMUL_GvEvIz, dst, src);
562 m_formatter.immediate32(value);
563 }
564
idivl_r(RegisterID dst)565 void idivl_r(RegisterID dst)
566 {
567 m_formatter.oneByteOp(OP_GROUP3_Ev, GROUP3_OP_IDIV, dst);
568 }
569
570 // Comparisons:
571
cmpl_rr(RegisterID src,RegisterID dst)572 void cmpl_rr(RegisterID src, RegisterID dst)
573 {
574 m_formatter.oneByteOp(OP_CMP_EvGv, src, dst);
575 }
576
cmpl_rm(RegisterID src,int offset,RegisterID base)577 void cmpl_rm(RegisterID src, int offset, RegisterID base)
578 {
579 m_formatter.oneByteOp(OP_CMP_EvGv, src, base, offset);
580 }
581
cmpl_mr(int offset,RegisterID base,RegisterID src)582 void cmpl_mr(int offset, RegisterID base, RegisterID src)
583 {
584 m_formatter.oneByteOp(OP_CMP_GvEv, src, base, offset);
585 }
586
cmpl_ir(int imm,RegisterID dst)587 void cmpl_ir(int imm, RegisterID dst)
588 {
589 if (CAN_SIGN_EXTEND_8_32(imm)) {
590 m_formatter.oneByteOp(OP_GROUP1_EvIb, GROUP1_OP_CMP, dst);
591 m_formatter.immediate8(imm);
592 } else {
593 m_formatter.oneByteOp(OP_GROUP1_EvIz, GROUP1_OP_CMP, dst);
594 m_formatter.immediate32(imm);
595 }
596 }
597
cmpl_ir_force32(int imm,RegisterID dst)598 void cmpl_ir_force32(int imm, RegisterID dst)
599 {
600 m_formatter.oneByteOp(OP_GROUP1_EvIz, GROUP1_OP_CMP, dst);
601 m_formatter.immediate32(imm);
602 }
603
cmpl_im(int imm,int offset,RegisterID base)604 void cmpl_im(int imm, int offset, RegisterID base)
605 {
606 if (CAN_SIGN_EXTEND_8_32(imm)) {
607 m_formatter.oneByteOp(OP_GROUP1_EvIb, GROUP1_OP_CMP, base, offset);
608 m_formatter.immediate8(imm);
609 } else {
610 m_formatter.oneByteOp(OP_GROUP1_EvIz, GROUP1_OP_CMP, base, offset);
611 m_formatter.immediate32(imm);
612 }
613 }
614
cmpl_im(int imm,int offset,RegisterID base,RegisterID index,int scale)615 void cmpl_im(int imm, int offset, RegisterID base, RegisterID index, int scale)
616 {
617 if (CAN_SIGN_EXTEND_8_32(imm)) {
618 m_formatter.oneByteOp(OP_GROUP1_EvIb, GROUP1_OP_CMP, base, index, scale, offset);
619 m_formatter.immediate8(imm);
620 } else {
621 m_formatter.oneByteOp(OP_GROUP1_EvIz, GROUP1_OP_CMP, base, index, scale, offset);
622 m_formatter.immediate32(imm);
623 }
624 }
625
cmpl_im_force32(int imm,int offset,RegisterID base)626 void cmpl_im_force32(int imm, int offset, RegisterID base)
627 {
628 m_formatter.oneByteOp(OP_GROUP1_EvIz, GROUP1_OP_CMP, base, offset);
629 m_formatter.immediate32(imm);
630 }
631
632 #if PLATFORM(X86_64)
cmpq_rr(RegisterID src,RegisterID dst)633 void cmpq_rr(RegisterID src, RegisterID dst)
634 {
635 m_formatter.oneByteOp64(OP_CMP_EvGv, src, dst);
636 }
637
cmpq_rm(RegisterID src,int offset,RegisterID base)638 void cmpq_rm(RegisterID src, int offset, RegisterID base)
639 {
640 m_formatter.oneByteOp64(OP_CMP_EvGv, src, base, offset);
641 }
642
cmpq_ir(int imm,RegisterID dst)643 void cmpq_ir(int imm, RegisterID dst)
644 {
645 if (CAN_SIGN_EXTEND_8_32(imm)) {
646 m_formatter.oneByteOp64(OP_GROUP1_EvIb, GROUP1_OP_CMP, dst);
647 m_formatter.immediate8(imm);
648 } else {
649 m_formatter.oneByteOp64(OP_GROUP1_EvIz, GROUP1_OP_CMP, dst);
650 m_formatter.immediate32(imm);
651 }
652 }
653
cmpq_im(int imm,int offset,RegisterID base)654 void cmpq_im(int imm, int offset, RegisterID base)
655 {
656 if (CAN_SIGN_EXTEND_8_32(imm)) {
657 m_formatter.oneByteOp64(OP_GROUP1_EvIb, GROUP1_OP_CMP, base, offset);
658 m_formatter.immediate8(imm);
659 } else {
660 m_formatter.oneByteOp64(OP_GROUP1_EvIz, GROUP1_OP_CMP, base, offset);
661 m_formatter.immediate32(imm);
662 }
663 }
664
cmpq_im(int imm,int offset,RegisterID base,RegisterID index,int scale)665 void cmpq_im(int imm, int offset, RegisterID base, RegisterID index, int scale)
666 {
667 if (CAN_SIGN_EXTEND_8_32(imm)) {
668 m_formatter.oneByteOp64(OP_GROUP1_EvIb, GROUP1_OP_CMP, base, index, scale, offset);
669 m_formatter.immediate8(imm);
670 } else {
671 m_formatter.oneByteOp64(OP_GROUP1_EvIz, GROUP1_OP_CMP, base, index, scale, offset);
672 m_formatter.immediate32(imm);
673 }
674 }
675 #else
cmpl_rm(RegisterID reg,void * addr)676 void cmpl_rm(RegisterID reg, void* addr)
677 {
678 m_formatter.oneByteOp(OP_CMP_EvGv, reg, addr);
679 }
680
cmpl_im(int imm,void * addr)681 void cmpl_im(int imm, void* addr)
682 {
683 if (CAN_SIGN_EXTEND_8_32(imm)) {
684 m_formatter.oneByteOp(OP_GROUP1_EvIb, GROUP1_OP_CMP, addr);
685 m_formatter.immediate8(imm);
686 } else {
687 m_formatter.oneByteOp(OP_GROUP1_EvIz, GROUP1_OP_CMP, addr);
688 m_formatter.immediate32(imm);
689 }
690 }
691 #endif
692
cmpw_rm(RegisterID src,int offset,RegisterID base,RegisterID index,int scale)693 void cmpw_rm(RegisterID src, int offset, RegisterID base, RegisterID index, int scale)
694 {
695 m_formatter.prefix(PRE_OPERAND_SIZE);
696 m_formatter.oneByteOp(OP_CMP_EvGv, src, base, index, scale, offset);
697 }
698
testl_rr(RegisterID src,RegisterID dst)699 void testl_rr(RegisterID src, RegisterID dst)
700 {
701 m_formatter.oneByteOp(OP_TEST_EvGv, src, dst);
702 }
703
testl_i32r(int imm,RegisterID dst)704 void testl_i32r(int imm, RegisterID dst)
705 {
706 m_formatter.oneByteOp(OP_GROUP3_EvIz, GROUP3_OP_TEST, dst);
707 m_formatter.immediate32(imm);
708 }
709
testl_i32m(int imm,int offset,RegisterID base)710 void testl_i32m(int imm, int offset, RegisterID base)
711 {
712 m_formatter.oneByteOp(OP_GROUP3_EvIz, GROUP3_OP_TEST, base, offset);
713 m_formatter.immediate32(imm);
714 }
715
testl_i32m(int imm,int offset,RegisterID base,RegisterID index,int scale)716 void testl_i32m(int imm, int offset, RegisterID base, RegisterID index, int scale)
717 {
718 m_formatter.oneByteOp(OP_GROUP3_EvIz, GROUP3_OP_TEST, base, index, scale, offset);
719 m_formatter.immediate32(imm);
720 }
721
722 #if PLATFORM(X86_64)
testq_rr(RegisterID src,RegisterID dst)723 void testq_rr(RegisterID src, RegisterID dst)
724 {
725 m_formatter.oneByteOp64(OP_TEST_EvGv, src, dst);
726 }
727
testq_i32r(int imm,RegisterID dst)728 void testq_i32r(int imm, RegisterID dst)
729 {
730 m_formatter.oneByteOp64(OP_GROUP3_EvIz, GROUP3_OP_TEST, dst);
731 m_formatter.immediate32(imm);
732 }
733
testq_i32m(int imm,int offset,RegisterID base)734 void testq_i32m(int imm, int offset, RegisterID base)
735 {
736 m_formatter.oneByteOp64(OP_GROUP3_EvIz, GROUP3_OP_TEST, base, offset);
737 m_formatter.immediate32(imm);
738 }
739
testq_i32m(int imm,int offset,RegisterID base,RegisterID index,int scale)740 void testq_i32m(int imm, int offset, RegisterID base, RegisterID index, int scale)
741 {
742 m_formatter.oneByteOp64(OP_GROUP3_EvIz, GROUP3_OP_TEST, base, index, scale, offset);
743 m_formatter.immediate32(imm);
744 }
745 #endif
746
testb_i8r(int imm,RegisterID dst)747 void testb_i8r(int imm, RegisterID dst)
748 {
749 m_formatter.oneByteOp8(OP_GROUP3_EbIb, GROUP3_OP_TEST, dst);
750 m_formatter.immediate8(imm);
751 }
752
sete_r(RegisterID dst)753 void sete_r(RegisterID dst)
754 {
755 m_formatter.twoByteOp8(OP_SETE, (GroupOpcodeID)0, dst);
756 }
757
setz_r(RegisterID dst)758 void setz_r(RegisterID dst)
759 {
760 sete_r(dst);
761 }
762
setne_r(RegisterID dst)763 void setne_r(RegisterID dst)
764 {
765 m_formatter.twoByteOp8(OP_SETNE, (GroupOpcodeID)0, dst);
766 }
767
setnz_r(RegisterID dst)768 void setnz_r(RegisterID dst)
769 {
770 setne_r(dst);
771 }
772
773 // Various move ops:
774
cdq()775 void cdq()
776 {
777 m_formatter.oneByteOp(OP_CDQ);
778 }
779
xchgl_rr(RegisterID src,RegisterID dst)780 void xchgl_rr(RegisterID src, RegisterID dst)
781 {
782 m_formatter.oneByteOp(OP_XCHG_EvGv, src, dst);
783 }
784
785 #if PLATFORM(X86_64)
xchgq_rr(RegisterID src,RegisterID dst)786 void xchgq_rr(RegisterID src, RegisterID dst)
787 {
788 m_formatter.oneByteOp64(OP_XCHG_EvGv, src, dst);
789 }
790 #endif
791
movl_rr(RegisterID src,RegisterID dst)792 void movl_rr(RegisterID src, RegisterID dst)
793 {
794 m_formatter.oneByteOp(OP_MOV_EvGv, src, dst);
795 }
796
movl_rm(RegisterID src,int offset,RegisterID base)797 void movl_rm(RegisterID src, int offset, RegisterID base)
798 {
799 m_formatter.oneByteOp(OP_MOV_EvGv, src, base, offset);
800 }
801
movl_rm_disp32(RegisterID src,int offset,RegisterID base)802 void movl_rm_disp32(RegisterID src, int offset, RegisterID base)
803 {
804 m_formatter.oneByteOp_disp32(OP_MOV_EvGv, src, base, offset);
805 }
806
movl_rm(RegisterID src,int offset,RegisterID base,RegisterID index,int scale)807 void movl_rm(RegisterID src, int offset, RegisterID base, RegisterID index, int scale)
808 {
809 m_formatter.oneByteOp(OP_MOV_EvGv, src, base, index, scale, offset);
810 }
811
movl_mEAX(void * addr)812 void movl_mEAX(void* addr)
813 {
814 m_formatter.oneByteOp(OP_MOV_EAXOv);
815 #if PLATFORM(X86_64)
816 m_formatter.immediate64(reinterpret_cast<int64_t>(addr));
817 #else
818 m_formatter.immediate32(reinterpret_cast<int>(addr));
819 #endif
820 }
821
movl_mr(int offset,RegisterID base,RegisterID dst)822 void movl_mr(int offset, RegisterID base, RegisterID dst)
823 {
824 m_formatter.oneByteOp(OP_MOV_GvEv, dst, base, offset);
825 }
826
movl_mr_disp32(int offset,RegisterID base,RegisterID dst)827 void movl_mr_disp32(int offset, RegisterID base, RegisterID dst)
828 {
829 m_formatter.oneByteOp_disp32(OP_MOV_GvEv, dst, base, offset);
830 }
831
movl_mr(int offset,RegisterID base,RegisterID index,int scale,RegisterID dst)832 void movl_mr(int offset, RegisterID base, RegisterID index, int scale, RegisterID dst)
833 {
834 m_formatter.oneByteOp(OP_MOV_GvEv, dst, base, index, scale, offset);
835 }
836
movl_i32r(int imm,RegisterID dst)837 void movl_i32r(int imm, RegisterID dst)
838 {
839 m_formatter.oneByteOp(OP_MOV_EAXIv, dst);
840 m_formatter.immediate32(imm);
841 }
842
movl_i32m(int imm,int offset,RegisterID base)843 void movl_i32m(int imm, int offset, RegisterID base)
844 {
845 m_formatter.oneByteOp(OP_GROUP11_EvIz, GROUP11_MOV, base, offset);
846 m_formatter.immediate32(imm);
847 }
848
movl_EAXm(void * addr)849 void movl_EAXm(void* addr)
850 {
851 m_formatter.oneByteOp(OP_MOV_OvEAX);
852 #if PLATFORM(X86_64)
853 m_formatter.immediate64(reinterpret_cast<int64_t>(addr));
854 #else
855 m_formatter.immediate32(reinterpret_cast<int>(addr));
856 #endif
857 }
858
859 #if PLATFORM(X86_64)
movq_rr(RegisterID src,RegisterID dst)860 void movq_rr(RegisterID src, RegisterID dst)
861 {
862 m_formatter.oneByteOp64(OP_MOV_EvGv, src, dst);
863 }
864
movq_rm(RegisterID src,int offset,RegisterID base)865 void movq_rm(RegisterID src, int offset, RegisterID base)
866 {
867 m_formatter.oneByteOp64(OP_MOV_EvGv, src, base, offset);
868 }
869
movq_rm_disp32(RegisterID src,int offset,RegisterID base)870 void movq_rm_disp32(RegisterID src, int offset, RegisterID base)
871 {
872 m_formatter.oneByteOp64_disp32(OP_MOV_EvGv, src, base, offset);
873 }
874
movq_rm(RegisterID src,int offset,RegisterID base,RegisterID index,int scale)875 void movq_rm(RegisterID src, int offset, RegisterID base, RegisterID index, int scale)
876 {
877 m_formatter.oneByteOp64(OP_MOV_EvGv, src, base, index, scale, offset);
878 }
879
movq_mEAX(void * addr)880 void movq_mEAX(void* addr)
881 {
882 m_formatter.oneByteOp64(OP_MOV_EAXOv);
883 m_formatter.immediate64(reinterpret_cast<int64_t>(addr));
884 }
885
movq_mr(int offset,RegisterID base,RegisterID dst)886 void movq_mr(int offset, RegisterID base, RegisterID dst)
887 {
888 m_formatter.oneByteOp64(OP_MOV_GvEv, dst, base, offset);
889 }
890
movq_mr_disp32(int offset,RegisterID base,RegisterID dst)891 void movq_mr_disp32(int offset, RegisterID base, RegisterID dst)
892 {
893 m_formatter.oneByteOp64_disp32(OP_MOV_GvEv, dst, base, offset);
894 }
895
movq_mr(int offset,RegisterID base,RegisterID index,int scale,RegisterID dst)896 void movq_mr(int offset, RegisterID base, RegisterID index, int scale, RegisterID dst)
897 {
898 m_formatter.oneByteOp64(OP_MOV_GvEv, dst, base, index, scale, offset);
899 }
900
movq_i64r(int64_t imm,RegisterID dst)901 void movq_i64r(int64_t imm, RegisterID dst)
902 {
903 m_formatter.oneByteOp64(OP_MOV_EAXIv, dst);
904 m_formatter.immediate64(imm);
905 }
906
movsxd_rr(RegisterID src,RegisterID dst)907 void movsxd_rr(RegisterID src, RegisterID dst)
908 {
909 m_formatter.oneByteOp64(OP_MOVSXD_GvEv, dst, src);
910 }
911
912
913 #else
movl_mr(void * addr,RegisterID dst)914 void movl_mr(void* addr, RegisterID dst)
915 {
916 if (dst == X86::eax)
917 movl_mEAX(addr);
918 else
919 m_formatter.oneByteOp(OP_MOV_GvEv, dst, addr);
920 }
921
movl_i32m(int imm,void * addr)922 void movl_i32m(int imm, void* addr)
923 {
924 m_formatter.oneByteOp(OP_GROUP11_EvIz, GROUP11_MOV, addr);
925 m_formatter.immediate32(imm);
926 }
927 #endif
928
movzwl_mr(int offset,RegisterID base,RegisterID dst)929 void movzwl_mr(int offset, RegisterID base, RegisterID dst)
930 {
931 m_formatter.twoByteOp(OP2_MOVZX_GvEw, dst, base, offset);
932 }
933
movzwl_mr(int offset,RegisterID base,RegisterID index,int scale,RegisterID dst)934 void movzwl_mr(int offset, RegisterID base, RegisterID index, int scale, RegisterID dst)
935 {
936 m_formatter.twoByteOp(OP2_MOVZX_GvEw, dst, base, index, scale, offset);
937 }
938
movzbl_rr(RegisterID src,RegisterID dst)939 void movzbl_rr(RegisterID src, RegisterID dst)
940 {
941 // In 64-bit, this may cause an unnecessary REX to be planted (if the dst register
942 // is in the range ESP-EDI, and the src would not have required a REX). Unneeded
943 // REX prefixes are defined to be silently ignored by the processor.
944 m_formatter.twoByteOp8(OP2_MOVZX_GvEb, dst, src);
945 }
946
leal_mr(int offset,RegisterID base,RegisterID dst)947 void leal_mr(int offset, RegisterID base, RegisterID dst)
948 {
949 m_formatter.oneByteOp(OP_LEA, dst, base, offset);
950 }
951
952 // Flow control:
953
call()954 JmpSrc call()
955 {
956 m_formatter.oneByteOp(OP_CALL_rel32);
957 return m_formatter.immediateRel32();
958 }
959
call(RegisterID dst)960 JmpSrc call(RegisterID dst)
961 {
962 m_formatter.oneByteOp(OP_GROUP5_Ev, GROUP5_OP_CALLN, dst);
963 return JmpSrc(m_formatter.size());
964 }
965
jmp()966 JmpSrc jmp()
967 {
968 m_formatter.oneByteOp(OP_JMP_rel32);
969 return m_formatter.immediateRel32();
970 }
971
jmp_r(RegisterID dst)972 void jmp_r(RegisterID dst)
973 {
974 m_formatter.oneByteOp(OP_GROUP5_Ev, GROUP5_OP_JMPN, dst);
975 }
976
jmp_m(int offset,RegisterID base)977 void jmp_m(int offset, RegisterID base)
978 {
979 m_formatter.oneByteOp(OP_GROUP5_Ev, GROUP5_OP_JMPN, base, offset);
980 }
981
jne()982 JmpSrc jne()
983 {
984 m_formatter.twoByteOp(OP2_JNE_rel32);
985 return m_formatter.immediateRel32();
986 }
987
jnz()988 JmpSrc jnz()
989 {
990 return jne();
991 }
992
je()993 JmpSrc je()
994 {
995 m_formatter.twoByteOp(OP2_JE_rel32);
996 return m_formatter.immediateRel32();
997 }
998
jl()999 JmpSrc jl()
1000 {
1001 m_formatter.twoByteOp(OP2_JL_rel32);
1002 return m_formatter.immediateRel32();
1003 }
1004
jb()1005 JmpSrc jb()
1006 {
1007 m_formatter.twoByteOp(OP2_JB_rel32);
1008 return m_formatter.immediateRel32();
1009 }
1010
jle()1011 JmpSrc jle()
1012 {
1013 m_formatter.twoByteOp(OP2_JLE_rel32);
1014 return m_formatter.immediateRel32();
1015 }
1016
jbe()1017 JmpSrc jbe()
1018 {
1019 m_formatter.twoByteOp(OP2_JBE_rel32);
1020 return m_formatter.immediateRel32();
1021 }
1022
jge()1023 JmpSrc jge()
1024 {
1025 m_formatter.twoByteOp(OP2_JGE_rel32);
1026 return m_formatter.immediateRel32();
1027 }
1028
jg()1029 JmpSrc jg()
1030 {
1031 m_formatter.twoByteOp(OP2_JG_rel32);
1032 return m_formatter.immediateRel32();
1033 }
1034
ja()1035 JmpSrc ja()
1036 {
1037 m_formatter.twoByteOp(OP2_JA_rel32);
1038 return m_formatter.immediateRel32();
1039 }
1040
jae()1041 JmpSrc jae()
1042 {
1043 m_formatter.twoByteOp(OP2_JAE_rel32);
1044 return m_formatter.immediateRel32();
1045 }
1046
jo()1047 JmpSrc jo()
1048 {
1049 m_formatter.twoByteOp(OP2_JO_rel32);
1050 return m_formatter.immediateRel32();
1051 }
1052
jp()1053 JmpSrc jp()
1054 {
1055 m_formatter.twoByteOp(OP2_JP_rel32);
1056 return m_formatter.immediateRel32();
1057 }
1058
js()1059 JmpSrc js()
1060 {
1061 m_formatter.twoByteOp(OP2_JS_rel32);
1062 return m_formatter.immediateRel32();
1063 }
1064
1065 // SSE operations:
1066
addsd_rr(XMMRegisterID src,XMMRegisterID dst)1067 void addsd_rr(XMMRegisterID src, XMMRegisterID dst)
1068 {
1069 m_formatter.prefix(PRE_SSE_F2);
1070 m_formatter.twoByteOp(OP2_ADDSD_VsdWsd, (RegisterID)dst, (RegisterID)src);
1071 }
1072
addsd_mr(int offset,RegisterID base,XMMRegisterID dst)1073 void addsd_mr(int offset, RegisterID base, XMMRegisterID dst)
1074 {
1075 m_formatter.prefix(PRE_SSE_F2);
1076 m_formatter.twoByteOp(OP2_ADDSD_VsdWsd, (RegisterID)dst, base, offset);
1077 }
1078
cvtsi2sd_rr(RegisterID src,XMMRegisterID dst)1079 void cvtsi2sd_rr(RegisterID src, XMMRegisterID dst)
1080 {
1081 m_formatter.prefix(PRE_SSE_F2);
1082 m_formatter.twoByteOp(OP2_CVTSI2SD_VsdEd, (RegisterID)dst, src);
1083 }
1084
cvttsd2si_rr(XMMRegisterID src,RegisterID dst)1085 void cvttsd2si_rr(XMMRegisterID src, RegisterID dst)
1086 {
1087 m_formatter.prefix(PRE_SSE_F2);
1088 m_formatter.twoByteOp(OP2_CVTTSD2SI_GdWsd, dst, (RegisterID)src);
1089 }
1090
movd_rr(XMMRegisterID src,RegisterID dst)1091 void movd_rr(XMMRegisterID src, RegisterID dst)
1092 {
1093 m_formatter.prefix(PRE_SSE_66);
1094 m_formatter.twoByteOp(OP2_MOVD_EdVd, (RegisterID)src, dst);
1095 }
1096
1097 #if PLATFORM(X86_64)
movq_rr(XMMRegisterID src,RegisterID dst)1098 void movq_rr(XMMRegisterID src, RegisterID dst)
1099 {
1100 m_formatter.prefix(PRE_SSE_66);
1101 m_formatter.twoByteOp64(OP2_MOVD_EdVd, (RegisterID)src, dst);
1102 }
1103
movq_rr(RegisterID src,XMMRegisterID dst)1104 void movq_rr(RegisterID src, XMMRegisterID dst)
1105 {
1106 m_formatter.prefix(PRE_SSE_66);
1107 m_formatter.twoByteOp64(OP2_MOVD_VdEd, (RegisterID)dst, src);
1108 }
1109 #endif
1110
movsd_rm(XMMRegisterID src,int offset,RegisterID base)1111 void movsd_rm(XMMRegisterID src, int offset, RegisterID base)
1112 {
1113 m_formatter.prefix(PRE_SSE_F2);
1114 m_formatter.twoByteOp(OP2_MOVSD_WsdVsd, (RegisterID)src, base, offset);
1115 }
1116
movsd_mr(int offset,RegisterID base,XMMRegisterID dst)1117 void movsd_mr(int offset, RegisterID base, XMMRegisterID dst)
1118 {
1119 m_formatter.prefix(PRE_SSE_F2);
1120 m_formatter.twoByteOp(OP2_MOVSD_VsdWsd, (RegisterID)dst, base, offset);
1121 }
1122
mulsd_rr(XMMRegisterID src,XMMRegisterID dst)1123 void mulsd_rr(XMMRegisterID src, XMMRegisterID dst)
1124 {
1125 m_formatter.prefix(PRE_SSE_F2);
1126 m_formatter.twoByteOp(OP2_MULSD_VsdWsd, (RegisterID)dst, (RegisterID)src);
1127 }
1128
mulsd_mr(int offset,RegisterID base,XMMRegisterID dst)1129 void mulsd_mr(int offset, RegisterID base, XMMRegisterID dst)
1130 {
1131 m_formatter.prefix(PRE_SSE_F2);
1132 m_formatter.twoByteOp(OP2_MULSD_VsdWsd, (RegisterID)dst, base, offset);
1133 }
1134
pextrw_irr(int whichWord,XMMRegisterID src,RegisterID dst)1135 void pextrw_irr(int whichWord, XMMRegisterID src, RegisterID dst)
1136 {
1137 m_formatter.prefix(PRE_SSE_66);
1138 m_formatter.twoByteOp(OP2_PEXTRW_GdUdIb, (RegisterID)dst, (RegisterID)src);
1139 m_formatter.immediate8(whichWord);
1140 }
1141
subsd_rr(XMMRegisterID src,XMMRegisterID dst)1142 void subsd_rr(XMMRegisterID src, XMMRegisterID dst)
1143 {
1144 m_formatter.prefix(PRE_SSE_F2);
1145 m_formatter.twoByteOp(OP2_SUBSD_VsdWsd, (RegisterID)dst, (RegisterID)src);
1146 }
1147
subsd_mr(int offset,RegisterID base,XMMRegisterID dst)1148 void subsd_mr(int offset, RegisterID base, XMMRegisterID dst)
1149 {
1150 m_formatter.prefix(PRE_SSE_F2);
1151 m_formatter.twoByteOp(OP2_SUBSD_VsdWsd, (RegisterID)dst, base, offset);
1152 }
1153
ucomisd_rr(XMMRegisterID src,XMMRegisterID dst)1154 void ucomisd_rr(XMMRegisterID src, XMMRegisterID dst)
1155 {
1156 m_formatter.prefix(PRE_SSE_66);
1157 m_formatter.twoByteOp(OP2_UCOMISD_VsdWsd, (RegisterID)dst, (RegisterID)src);
1158 }
1159
1160 // Misc instructions:
1161
int3()1162 void int3()
1163 {
1164 m_formatter.oneByteOp(OP_INT3);
1165 }
1166
ret()1167 void ret()
1168 {
1169 m_formatter.oneByteOp(OP_RET);
1170 }
1171
predictNotTaken()1172 void predictNotTaken()
1173 {
1174 m_formatter.prefix(PRE_PREDICT_BRANCH_NOT_TAKEN);
1175 }
1176
1177 // Assembler admin methods:
1178
label()1179 JmpDst label()
1180 {
1181 return JmpDst(m_formatter.size());
1182 }
1183
align(int alignment)1184 JmpDst align(int alignment)
1185 {
1186 while (!m_formatter.isAligned(alignment))
1187 m_formatter.oneByteOp(OP_HLT);
1188
1189 return label();
1190 }
1191
1192 // Linking & patching:
1193
link(JmpSrc from,JmpDst to)1194 void link(JmpSrc from, JmpDst to)
1195 {
1196 ASSERT(to.m_offset != -1);
1197 ASSERT(from.m_offset != -1);
1198
1199 reinterpret_cast<int*>(reinterpret_cast<ptrdiff_t>(m_formatter.data()) + from.m_offset)[-1] = to.m_offset - from.m_offset;
1200 }
1201
patchAddress(void * code,JmpDst position,void * value)1202 static void patchAddress(void* code, JmpDst position, void* value)
1203 {
1204 ASSERT(position.m_offset != -1);
1205
1206 reinterpret_cast<void**>(reinterpret_cast<ptrdiff_t>(code) + position.m_offset)[-1] = value;
1207 }
1208
link(void * code,JmpSrc from,void * to)1209 static void link(void* code, JmpSrc from, void* to)
1210 {
1211 ASSERT(from.m_offset != -1);
1212
1213 reinterpret_cast<int*>(reinterpret_cast<ptrdiff_t>(code) + from.m_offset)[-1] = reinterpret_cast<ptrdiff_t>(to) - (reinterpret_cast<ptrdiff_t>(code) + from.m_offset);
1214 }
1215
getRelocatedAddress(void * code,JmpSrc jump)1216 static void* getRelocatedAddress(void* code, JmpSrc jump)
1217 {
1218 return reinterpret_cast<void*>(reinterpret_cast<ptrdiff_t>(code) + jump.m_offset);
1219 }
1220
getRelocatedAddress(void * code,JmpDst destination)1221 static void* getRelocatedAddress(void* code, JmpDst destination)
1222 {
1223 ASSERT(destination.m_offset != -1);
1224
1225 return reinterpret_cast<void*>(reinterpret_cast<ptrdiff_t>(code) + destination.m_offset);
1226 }
1227
getDifferenceBetweenLabels(JmpDst src,JmpDst dst)1228 static int getDifferenceBetweenLabels(JmpDst src, JmpDst dst)
1229 {
1230 return dst.m_offset - src.m_offset;
1231 }
1232
getDifferenceBetweenLabels(JmpDst src,JmpSrc dst)1233 static int getDifferenceBetweenLabels(JmpDst src, JmpSrc dst)
1234 {
1235 return dst.m_offset - src.m_offset;
1236 }
1237
getDifferenceBetweenLabels(JmpSrc src,JmpDst dst)1238 static int getDifferenceBetweenLabels(JmpSrc src, JmpDst dst)
1239 {
1240 return dst.m_offset - src.m_offset;
1241 }
1242
patchImmediate(intptr_t where,int32_t value)1243 static void patchImmediate(intptr_t where, int32_t value)
1244 {
1245 reinterpret_cast<int32_t*>(where)[-1] = value;
1246 }
1247
patchPointer(intptr_t where,intptr_t value)1248 static void patchPointer(intptr_t where, intptr_t value)
1249 {
1250 reinterpret_cast<intptr_t*>(where)[-1] = value;
1251 }
1252
patchBranchOffset(intptr_t where,void * destination)1253 static void patchBranchOffset(intptr_t where, void* destination)
1254 {
1255 intptr_t offset = reinterpret_cast<intptr_t>(destination) - where;
1256 ASSERT(offset == static_cast<int32_t>(offset));
1257 reinterpret_cast<int32_t*>(where)[-1] = static_cast<int32_t>(offset);
1258 }
1259
executableCopy(ExecutablePool * allocator)1260 void* executableCopy(ExecutablePool* allocator)
1261 {
1262 void* copy = m_formatter.executableCopy(allocator);
1263 ASSERT(copy);
1264 return copy;
1265 }
1266
1267 private:
1268
1269 class X86InstructionFormatter {
1270
1271 static const int maxInstructionSize = 16;
1272
1273 public:
1274
1275 // Legacy prefix bytes:
1276 //
1277 // These are emmitted prior to the instruction.
1278
prefix(OneByteOpcodeID pre)1279 void prefix(OneByteOpcodeID pre)
1280 {
1281 m_buffer.putByte(pre);
1282 }
1283
1284 // Word-sized operands / no operand instruction formatters.
1285 //
1286 // In addition to the opcode, the following operand permutations are supported:
1287 // * None - instruction takes no operands.
1288 // * One register - the low three bits of the RegisterID are added into the opcode.
1289 // * 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).
1290 // * Three argument ModRM - a register, and a register and an offset describing a memory operand.
1291 // * Five argument ModRM - a register, and a base register, an index, scale, and offset describing a memory operand.
1292 //
1293 // For 32-bit x86 targets, the address operand may also be provided as a void*.
1294 // On 64-bit targets REX prefixes will be planted as necessary, where high numbered registers are used.
1295 //
1296 // The twoByteOp methods plant two-byte Intel instructions sequences (first opcode byte 0x0F).
1297
oneByteOp(OneByteOpcodeID opcode)1298 void oneByteOp(OneByteOpcodeID opcode)
1299 {
1300 m_buffer.ensureSpace(maxInstructionSize);
1301 m_buffer.putByteUnchecked(opcode);
1302 }
1303
oneByteOp(OneByteOpcodeID opcode,RegisterID reg)1304 void oneByteOp(OneByteOpcodeID opcode, RegisterID reg)
1305 {
1306 m_buffer.ensureSpace(maxInstructionSize);
1307 emitRexIfNeeded(0, 0, reg);
1308 m_buffer.putByteUnchecked(opcode + (reg & 7));
1309 }
1310
oneByteOp(OneByteOpcodeID opcode,int reg,RegisterID rm)1311 void oneByteOp(OneByteOpcodeID opcode, int reg, RegisterID rm)
1312 {
1313 m_buffer.ensureSpace(maxInstructionSize);
1314 emitRexIfNeeded(reg, 0, rm);
1315 m_buffer.putByteUnchecked(opcode);
1316 registerModRM(reg, rm);
1317 }
1318
oneByteOp(OneByteOpcodeID opcode,int reg,RegisterID base,int offset)1319 void oneByteOp(OneByteOpcodeID opcode, int reg, RegisterID base, int offset)
1320 {
1321 m_buffer.ensureSpace(maxInstructionSize);
1322 emitRexIfNeeded(reg, 0, base);
1323 m_buffer.putByteUnchecked(opcode);
1324 memoryModRM(reg, base, offset);
1325 }
1326
oneByteOp_disp32(OneByteOpcodeID opcode,int reg,RegisterID base,int offset)1327 void oneByteOp_disp32(OneByteOpcodeID opcode, int reg, RegisterID base, int offset)
1328 {
1329 m_buffer.ensureSpace(maxInstructionSize);
1330 emitRexIfNeeded(reg, 0, base);
1331 m_buffer.putByteUnchecked(opcode);
1332 memoryModRM_disp32(reg, base, offset);
1333 }
1334
oneByteOp(OneByteOpcodeID opcode,int reg,RegisterID base,RegisterID index,int scale,int offset)1335 void oneByteOp(OneByteOpcodeID opcode, int reg, RegisterID base, RegisterID index, int scale, int offset)
1336 {
1337 m_buffer.ensureSpace(maxInstructionSize);
1338 emitRexIfNeeded(reg, index, base);
1339 m_buffer.putByteUnchecked(opcode);
1340 memoryModRM(reg, base, index, scale, offset);
1341 }
1342
1343 #if !PLATFORM(X86_64)
oneByteOp(OneByteOpcodeID opcode,int reg,void * address)1344 void oneByteOp(OneByteOpcodeID opcode, int reg, void* address)
1345 {
1346 m_buffer.ensureSpace(maxInstructionSize);
1347 m_buffer.putByteUnchecked(opcode);
1348 memoryModRM(reg, address);
1349 }
1350 #endif
1351
twoByteOp(TwoByteOpcodeID opcode)1352 void twoByteOp(TwoByteOpcodeID opcode)
1353 {
1354 m_buffer.ensureSpace(maxInstructionSize);
1355 m_buffer.putByteUnchecked(OP_2BYTE_ESCAPE);
1356 m_buffer.putByteUnchecked(opcode);
1357 }
1358
twoByteOp(TwoByteOpcodeID opcode,int reg,RegisterID rm)1359 void twoByteOp(TwoByteOpcodeID opcode, int reg, RegisterID rm)
1360 {
1361 m_buffer.ensureSpace(maxInstructionSize);
1362 emitRexIfNeeded(reg, 0, rm);
1363 m_buffer.putByteUnchecked(OP_2BYTE_ESCAPE);
1364 m_buffer.putByteUnchecked(opcode);
1365 registerModRM(reg, rm);
1366 }
1367
twoByteOp(TwoByteOpcodeID opcode,int reg,RegisterID base,int offset)1368 void twoByteOp(TwoByteOpcodeID opcode, int reg, RegisterID base, int offset)
1369 {
1370 m_buffer.ensureSpace(maxInstructionSize);
1371 emitRexIfNeeded(reg, 0, base);
1372 m_buffer.putByteUnchecked(OP_2BYTE_ESCAPE);
1373 m_buffer.putByteUnchecked(opcode);
1374 memoryModRM(reg, base, offset);
1375 }
1376
twoByteOp(TwoByteOpcodeID opcode,int reg,RegisterID base,RegisterID index,int scale,int offset)1377 void twoByteOp(TwoByteOpcodeID opcode, int reg, RegisterID base, RegisterID index, int scale, int offset)
1378 {
1379 m_buffer.ensureSpace(maxInstructionSize);
1380 emitRexIfNeeded(reg, index, base);
1381 m_buffer.putByteUnchecked(OP_2BYTE_ESCAPE);
1382 m_buffer.putByteUnchecked(opcode);
1383 memoryModRM(reg, base, index, scale, offset);
1384 }
1385
1386 #if PLATFORM(X86_64)
1387 // Quad-word-sized operands:
1388 //
1389 // Used to format 64-bit operantions, planting a REX.w prefix.
1390 // When planting d64 or f64 instructions, not requiring a REX.w prefix,
1391 // the normal (non-'64'-postfixed) formatters should be used.
1392
oneByteOp64(OneByteOpcodeID opcode)1393 void oneByteOp64(OneByteOpcodeID opcode)
1394 {
1395 m_buffer.ensureSpace(maxInstructionSize);
1396 emitRexW(0, 0, 0);
1397 m_buffer.putByteUnchecked(opcode);
1398 }
1399
oneByteOp64(OneByteOpcodeID opcode,RegisterID reg)1400 void oneByteOp64(OneByteOpcodeID opcode, RegisterID reg)
1401 {
1402 m_buffer.ensureSpace(maxInstructionSize);
1403 emitRexW(0, 0, reg);
1404 m_buffer.putByteUnchecked(opcode + (reg & 7));
1405 }
1406
oneByteOp64(OneByteOpcodeID opcode,int reg,RegisterID rm)1407 void oneByteOp64(OneByteOpcodeID opcode, int reg, RegisterID rm)
1408 {
1409 m_buffer.ensureSpace(maxInstructionSize);
1410 emitRexW(reg, 0, rm);
1411 m_buffer.putByteUnchecked(opcode);
1412 registerModRM(reg, rm);
1413 }
1414
oneByteOp64(OneByteOpcodeID opcode,int reg,RegisterID base,int offset)1415 void oneByteOp64(OneByteOpcodeID opcode, int reg, RegisterID base, int offset)
1416 {
1417 m_buffer.ensureSpace(maxInstructionSize);
1418 emitRexW(reg, 0, base);
1419 m_buffer.putByteUnchecked(opcode);
1420 memoryModRM(reg, base, offset);
1421 }
1422
oneByteOp64_disp32(OneByteOpcodeID opcode,int reg,RegisterID base,int offset)1423 void oneByteOp64_disp32(OneByteOpcodeID opcode, int reg, RegisterID base, int offset)
1424 {
1425 m_buffer.ensureSpace(maxInstructionSize);
1426 emitRexW(reg, 0, base);
1427 m_buffer.putByteUnchecked(opcode);
1428 memoryModRM_disp32(reg, base, offset);
1429 }
1430
oneByteOp64(OneByteOpcodeID opcode,int reg,RegisterID base,RegisterID index,int scale,int offset)1431 void oneByteOp64(OneByteOpcodeID opcode, int reg, RegisterID base, RegisterID index, int scale, int offset)
1432 {
1433 m_buffer.ensureSpace(maxInstructionSize);
1434 emitRexW(reg, index, base);
1435 m_buffer.putByteUnchecked(opcode);
1436 memoryModRM(reg, base, index, scale, offset);
1437 }
1438
twoByteOp64(TwoByteOpcodeID opcode,int reg,RegisterID rm)1439 void twoByteOp64(TwoByteOpcodeID opcode, int reg, RegisterID rm)
1440 {
1441 m_buffer.ensureSpace(maxInstructionSize);
1442 emitRexW(reg, 0, rm);
1443 m_buffer.putByteUnchecked(OP_2BYTE_ESCAPE);
1444 m_buffer.putByteUnchecked(opcode);
1445 registerModRM(reg, rm);
1446 }
1447 #endif
1448
1449 // Byte-operands:
1450 //
1451 // These methods format byte operations. Byte operations differ from the normal
1452 // formatters in the circumstances under which they will decide to emit REX prefixes.
1453 // These should be used where any register operand signifies a byte register.
1454 //
1455 // The disctinction is due to the handling of register numbers in the range 4..7 on
1456 // x86-64. These register numbers may either represent the second byte of the first
1457 // four registers (ah..bh) or the first byte of the second four registers (spl..dil).
1458 //
1459 // Since ah..bh cannot be used in all permutations of operands (specifically cannot
1460 // be accessed where a REX prefix is present), these are likely best treated as
1461 // deprecated. In order to ensure the correct registers spl..dil are selected a
1462 // REX prefix will be emitted for any byte register operand in the range 4..15.
1463 //
1464 // These formatters may be used in instructions where a mix of operand sizes, in which
1465 // case an unnecessary REX will be emitted, for example:
1466 // movzbl %al, %edi
1467 // In this case a REX will be planted since edi is 7 (and were this a byte operand
1468 // a REX would be required to specify dil instead of bh). Unneeded REX prefixes will
1469 // be silently ignored by the processor.
1470 //
1471 // Address operands should still be checked using regRequiresRex(), while byteRegRequiresRex()
1472 // is provided to check byte register operands.
1473
oneByteOp8(OneByteOpcodeID opcode,GroupOpcodeID groupOp,RegisterID rm)1474 void oneByteOp8(OneByteOpcodeID opcode, GroupOpcodeID groupOp, RegisterID rm)
1475 {
1476 m_buffer.ensureSpace(maxInstructionSize);
1477 emitRexIf(byteRegRequiresRex(rm), 0, 0, rm);
1478 m_buffer.putByteUnchecked(opcode);
1479 registerModRM(groupOp, rm);
1480 }
1481
twoByteOp8(TwoByteOpcodeID opcode,RegisterID reg,RegisterID rm)1482 void twoByteOp8(TwoByteOpcodeID opcode, RegisterID reg, RegisterID rm)
1483 {
1484 m_buffer.ensureSpace(maxInstructionSize);
1485 emitRexIf(byteRegRequiresRex(reg)|byteRegRequiresRex(rm), reg, 0, rm);
1486 m_buffer.putByteUnchecked(OP_2BYTE_ESCAPE);
1487 m_buffer.putByteUnchecked(opcode);
1488 registerModRM(reg, rm);
1489 }
1490
twoByteOp8(TwoByteOpcodeID opcode,GroupOpcodeID groupOp,RegisterID rm)1491 void twoByteOp8(TwoByteOpcodeID opcode, GroupOpcodeID groupOp, RegisterID rm)
1492 {
1493 m_buffer.ensureSpace(maxInstructionSize);
1494 emitRexIf(byteRegRequiresRex(rm), 0, 0, rm);
1495 m_buffer.putByteUnchecked(OP_2BYTE_ESCAPE);
1496 m_buffer.putByteUnchecked(opcode);
1497 registerModRM(groupOp, rm);
1498 }
1499
1500 // Immediates:
1501 //
1502 // An immedaite should be appended where appropriate after an op has been emitted.
1503 // The writes are unchecked since the opcode formatters above will have ensured space.
1504
immediate8(int imm)1505 void immediate8(int imm)
1506 {
1507 m_buffer.putByteUnchecked(imm);
1508 }
1509
immediate32(int imm)1510 void immediate32(int imm)
1511 {
1512 m_buffer.putIntUnchecked(imm);
1513 }
1514
immediate64(int64_t imm)1515 void immediate64(int64_t imm)
1516 {
1517 m_buffer.putInt64Unchecked(imm);
1518 }
1519
immediateRel32()1520 JmpSrc immediateRel32()
1521 {
1522 m_buffer.putIntUnchecked(0);
1523 return JmpSrc(m_buffer.size());
1524 }
1525
1526 // Administrative methods:
1527
size()1528 size_t size() const { return m_buffer.size(); }
isAligned(int alignment)1529 bool isAligned(int alignment) const { return m_buffer.isAligned(alignment); }
data()1530 void* data() const { return m_buffer.data(); }
executableCopy(ExecutablePool * allocator)1531 void* executableCopy(ExecutablePool* allocator) { return m_buffer.executableCopy(allocator); }
1532
1533 private:
1534
1535 // Internals; ModRm and REX formatters.
1536
1537 static const RegisterID noBase = X86::ebp;
1538 static const RegisterID hasSib = X86::esp;
1539 static const RegisterID noIndex = X86::esp;
1540 #if PLATFORM(X86_64)
1541 static const RegisterID noBase2 = X86::r13;
1542 static const RegisterID hasSib2 = X86::r12;
1543
1544 // Registers r8 & above require a REX prefixe.
regRequiresRex(int reg)1545 inline bool regRequiresRex(int reg)
1546 {
1547 return (reg >= X86::r8);
1548 }
1549
1550 // Byte operand register spl & above require a REX prefix (to prevent the 'H' registers be accessed).
byteRegRequiresRex(int reg)1551 inline bool byteRegRequiresRex(int reg)
1552 {
1553 return (reg >= X86::esp);
1554 }
1555
1556 // Format a REX prefix byte.
emitRex(bool w,int r,int x,int b)1557 inline void emitRex(bool w, int r, int x, int b)
1558 {
1559 m_buffer.putByteUnchecked(PRE_REX | ((int)w << 3) | ((r>>3)<<2) | ((x>>3)<<1) | (b>>3));
1560 }
1561
1562 // Used to plant a REX byte with REX.w set (for 64-bit operations).
emitRexW(int r,int x,int b)1563 inline void emitRexW(int r, int x, int b)
1564 {
1565 emitRex(true, r, x, b);
1566 }
1567
1568 // Used for operations with byte operands - use byteRegRequiresRex() to check register operands,
1569 // regRequiresRex() to check other registers (i.e. address base & index).
emitRexIf(bool condition,int r,int x,int b)1570 inline void emitRexIf(bool condition, int r, int x, int b)
1571 {
1572 if (condition) emitRex(false, r, x, b);
1573 }
1574
1575 // Used for word sized operations, will plant a REX prefix if necessary (if any register is r8 or above).
emitRexIfNeeded(int r,int x,int b)1576 inline void emitRexIfNeeded(int r, int x, int b)
1577 {
1578 emitRexIf(regRequiresRex(r) || regRequiresRex(x) || regRequiresRex(b), r, x, b);
1579 }
1580 #else
1581 // No REX prefix bytes on 32-bit x86.
regRequiresRex(int)1582 inline bool regRequiresRex(int) { return false; }
byteRegRequiresRex(int)1583 inline bool byteRegRequiresRex(int) { return false; }
emitRexIf(bool,int,int,int)1584 inline void emitRexIf(bool, int, int, int) {}
emitRexIfNeeded(int,int,int)1585 inline void emitRexIfNeeded(int, int, int) {}
1586 #endif
1587
1588 enum ModRmMode {
1589 ModRmMemoryNoDisp,
1590 ModRmMemoryDisp8,
1591 ModRmMemoryDisp32,
1592 ModRmRegister,
1593 };
1594
putModRm(ModRmMode mode,int reg,RegisterID rm)1595 void putModRm(ModRmMode mode, int reg, RegisterID rm)
1596 {
1597 m_buffer.putByteUnchecked((mode << 6) | ((reg & 7) << 3) | (rm & 7));
1598 }
1599
putModRmSib(ModRmMode mode,int reg,RegisterID base,RegisterID index,int scale)1600 void putModRmSib(ModRmMode mode, int reg, RegisterID base, RegisterID index, int scale)
1601 {
1602 ASSERT(mode != ModRmRegister);
1603
1604 // Encode sacle of (1,2,4,8) -> (0,1,2,3)
1605 int shift = 0;
1606 while (scale >>= 1)
1607 shift++;
1608
1609 putModRm(mode, reg, hasSib);
1610 m_buffer.putByteUnchecked((shift << 6) | ((index & 7) << 3) | (base & 7));
1611 }
1612
registerModRM(int reg,RegisterID rm)1613 void registerModRM(int reg, RegisterID rm)
1614 {
1615 putModRm(ModRmRegister, reg, rm);
1616 }
1617
memoryModRM(int reg,RegisterID base,int offset)1618 void memoryModRM(int reg, RegisterID base, int offset)
1619 {
1620 // A base of esp or r12 would be interpreted as a sib, so force a sib with no index & put the base in there.
1621 #if PLATFORM(X86_64)
1622 if ((base == hasSib) || (base == hasSib2)) {
1623 #else
1624 if (base == hasSib) {
1625 #endif
1626 if (!offset) // No need to check if the base is noBase, since we know it is hasSib!
1627 putModRmSib(ModRmMemoryNoDisp, reg, base, noIndex, 0);
1628 else if (CAN_SIGN_EXTEND_8_32(offset)) {
1629 putModRmSib(ModRmMemoryDisp8, reg, base, noIndex, 0);
1630 m_buffer.putByteUnchecked(offset);
1631 } else {
1632 putModRmSib(ModRmMemoryDisp32, reg, base, noIndex, 0);
1633 m_buffer.putIntUnchecked(offset);
1634 }
1635 } else {
1636 #if PLATFORM(X86_64)
1637 if (!offset && (base != noBase) && (base != noBase2))
1638 #else
1639 if (!offset && (base != noBase))
1640 #endif
1641 putModRm(ModRmMemoryNoDisp, reg, base);
1642 else if (CAN_SIGN_EXTEND_8_32(offset)) {
1643 putModRm(ModRmMemoryDisp8, reg, base);
1644 m_buffer.putByteUnchecked(offset);
1645 } else {
1646 putModRm(ModRmMemoryDisp32, reg, base);
1647 m_buffer.putIntUnchecked(offset);
1648 }
1649 }
1650 }
1651
1652 void memoryModRM_disp32(int reg, RegisterID base, int offset)
1653 {
1654 // A base of esp or r12 would be interpreted as a sib, so force a sib with no index & put the base in there.
1655 #if PLATFORM(X86_64)
1656 if ((base == hasSib) || (base == hasSib2)) {
1657 #else
1658 if (base == hasSib) {
1659 #endif
1660 putModRmSib(ModRmMemoryDisp32, reg, base, noIndex, 0);
1661 m_buffer.putIntUnchecked(offset);
1662 } else {
1663 putModRm(ModRmMemoryDisp32, reg, base);
1664 m_buffer.putIntUnchecked(offset);
1665 }
1666 }
1667
1668 void memoryModRM(int reg, RegisterID base, RegisterID index, int scale, int offset)
1669 {
1670 ASSERT(index != noIndex);
1671
1672 #if PLATFORM(X86_64)
1673 if (!offset && (base != noBase) && (base != noBase2))
1674 #else
1675 if (!offset && (base != noBase))
1676 #endif
1677 putModRmSib(ModRmMemoryNoDisp, reg, base, index, scale);
1678 else if (CAN_SIGN_EXTEND_8_32(offset)) {
1679 putModRmSib(ModRmMemoryDisp8, reg, base, index, scale);
1680 m_buffer.putByteUnchecked(offset);
1681 } else {
1682 putModRmSib(ModRmMemoryDisp32, reg, base, index, scale);
1683 m_buffer.putIntUnchecked(offset);
1684 }
1685 }
1686
1687 #if !PLATFORM(X86_64)
1688 void memoryModRM(int reg, void* address)
1689 {
1690 // noBase + ModRmMemoryNoDisp means noBase + ModRmMemoryDisp32!
1691 putModRm(ModRmMemoryNoDisp, reg, noBase);
1692 m_buffer.putIntUnchecked(reinterpret_cast<int32_t>(address));
1693 }
1694 #endif
1695
1696 AssemblerBuffer m_buffer;
1697 } m_formatter;
1698 };
1699
1700 } // namespace JSC
1701
1702 #endif // ENABLE(ASSEMBLER) && PLATFORM(X86)
1703
1704 #endif // X86Assembler_h
1705