1/*
2 * Copyright (C) 2008, 2012 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 <Platform.h>
30
31#if ENABLE(ASSEMBLER) && (CPU(X86) || CPU(X86_64))
32
33#include "AssemblerBuffer.h"
34#include "AbstractMacroAssembler.h"
35#include "JITCompilationEffort.h"
36#include <stdint.h>
37#include <wtf/Assertions.h>
38#include <wtf/Vector.h>
39
40namespace JSC {
41
42inline bool CAN_SIGN_EXTEND_8_32(int32_t value) { return value == (int32_t)(signed char)value; }
43
44namespace X86Registers {
45 typedef enum {
46 eax,
47 ecx,
48 edx,
49 ebx,
50 esp,
51 ebp,
52 esi,
53 edi,
54
55#if CPU(X86_64)
56 r8,
57 r9,
58 r10,
59 r11,
60 r12,
61 r13,
62 r14,
63 r15,
64#endif
65 } RegisterID;
66
67 typedef enum {
68 xmm0,
69 xmm1,
70 xmm2,
71 xmm3,
72 xmm4,
73 xmm5,
74 xmm6,
75 xmm7,
76 } XMMRegisterID;
77}
78
79class X86Assembler {
80public:
81 typedef X86Registers::RegisterID RegisterID;
82 typedef X86Registers::XMMRegisterID XMMRegisterID;
83 typedef XMMRegisterID FPRegisterID;
84
85 typedef enum {
86 ConditionO,
87 ConditionNO,
88 ConditionB,
89 ConditionAE,
90 ConditionE,
91 ConditionNE,
92 ConditionBE,
93 ConditionA,
94 ConditionS,
95 ConditionNS,
96 ConditionP,
97 ConditionNP,
98 ConditionL,
99 ConditionGE,
100 ConditionLE,
101 ConditionG,
102
103 ConditionC = ConditionB,
104 ConditionNC = ConditionAE,
105 } Condition;
106
107private:
108 typedef enum {
109 OP_ADD_EvGv = 0x01,
110 OP_ADD_GvEv = 0x03,
111 OP_OR_EvGv = 0x09,
112 OP_OR_GvEv = 0x0B,
113 OP_2BYTE_ESCAPE = 0x0F,
114 OP_AND_EvGv = 0x21,
115 OP_AND_GvEv = 0x23,
116 OP_SUB_EvGv = 0x29,
117 OP_SUB_GvEv = 0x2B,
118 PRE_PREDICT_BRANCH_NOT_TAKEN = 0x2E,
119 OP_XOR_EvGv = 0x31,
120 OP_XOR_GvEv = 0x33,
121 OP_CMP_EvGv = 0x39,
122 OP_CMP_GvEv = 0x3B,
123#if CPU(X86_64)
124 PRE_REX = 0x40,
125#endif
126 OP_PUSH_EAX = 0x50,
127 OP_POP_EAX = 0x58,
128#if CPU(X86_64)
129 OP_MOVSXD_GvEv = 0x63,
130#endif
131 PRE_OPERAND_SIZE = 0x66,
132 PRE_SSE_66 = 0x66,
133 OP_PUSH_Iz = 0x68,
134 OP_IMUL_GvEvIz = 0x69,
135 OP_GROUP1_EbIb = 0x80,
136 OP_GROUP1_EvIz = 0x81,
137 OP_GROUP1_EvIb = 0x83,
138 OP_TEST_EbGb = 0x84,
139 OP_TEST_EvGv = 0x85,
140 OP_XCHG_EvGv = 0x87,
141 OP_MOV_EbGb = 0x88,
142 OP_MOV_EvGv = 0x89,
143 OP_MOV_GvEv = 0x8B,
144 OP_LEA = 0x8D,
145 OP_GROUP1A_Ev = 0x8F,
146 OP_NOP = 0x90,
147 OP_CDQ = 0x99,
148 OP_MOV_EAXOv = 0xA1,
149 OP_MOV_OvEAX = 0xA3,
150 OP_MOV_EAXIv = 0xB8,
151 OP_GROUP2_EvIb = 0xC1,
152 OP_RET = 0xC3,
153 OP_GROUP11_EvIb = 0xC6,
154 OP_GROUP11_EvIz = 0xC7,
155 OP_INT3 = 0xCC,
156 OP_GROUP2_Ev1 = 0xD1,
157 OP_GROUP2_EvCL = 0xD3,
158 OP_ESCAPE_DD = 0xDD,
159 OP_CALL_rel32 = 0xE8,
160 OP_JMP_rel32 = 0xE9,
161 PRE_SSE_F2 = 0xF2,
162 PRE_SSE_F3 = 0xF3,
163 OP_HLT = 0xF4,
164 OP_GROUP3_EbIb = 0xF6,
165 OP_GROUP3_Ev = 0xF7,
166 OP_GROUP3_EvIz = 0xF7, // OP_GROUP3_Ev has an immediate, when instruction is a test.
167 OP_GROUP5_Ev = 0xFF,
168 } OneByteOpcodeID;
169
170 typedef enum {
171 OP2_MOVSD_VsdWsd = 0x10,
172 OP2_MOVSD_WsdVsd = 0x11,
173 OP2_MOVSS_VsdWsd = 0x10,
174 OP2_MOVSS_WsdVsd = 0x11,
175 OP2_CVTSI2SD_VsdEd = 0x2A,
176 OP2_CVTTSD2SI_GdWsd = 0x2C,
177 OP2_UCOMISD_VsdWsd = 0x2E,
178 OP2_ADDSD_VsdWsd = 0x58,
179 OP2_MULSD_VsdWsd = 0x59,
180 OP2_CVTSD2SS_VsdWsd = 0x5A,
181 OP2_CVTSS2SD_VsdWsd = 0x5A,
182 OP2_SUBSD_VsdWsd = 0x5C,
183 OP2_DIVSD_VsdWsd = 0x5E,
184 OP2_SQRTSD_VsdWsd = 0x51,
185 OP2_ANDNPD_VpdWpd = 0x55,
186 OP2_XORPD_VpdWpd = 0x57,
187 OP2_MOVD_VdEd = 0x6E,
188 OP2_MOVD_EdVd = 0x7E,
189 OP2_JCC_rel32 = 0x80,
190 OP_SETCC = 0x90,
191 OP2_IMUL_GvEv = 0xAF,
192 OP2_MOVZX_GvEb = 0xB6,
193 OP2_MOVSX_GvEb = 0xBE,
194 OP2_MOVZX_GvEw = 0xB7,
195 OP2_MOVSX_GvEw = 0xBF,
196 OP2_PEXTRW_GdUdIb = 0xC5,
197 OP2_PSLLQ_UdqIb = 0x73,
198 OP2_PSRLQ_UdqIb = 0x73,
199 OP2_POR_VdqWdq = 0XEB,
200 } TwoByteOpcodeID;
201
202 TwoByteOpcodeID jccRel32(Condition cond)
203 {
204 return (TwoByteOpcodeID)(OP2_JCC_rel32 + cond);
205 }
206
207 TwoByteOpcodeID setccOpcode(Condition cond)
208 {
209 return (TwoByteOpcodeID)(OP_SETCC + cond);
210 }
211
212 typedef enum {
213 GROUP1_OP_ADD = 0,
214 GROUP1_OP_OR = 1,
215 GROUP1_OP_ADC = 2,
216 GROUP1_OP_AND = 4,
217 GROUP1_OP_SUB = 5,
218 GROUP1_OP_XOR = 6,
219 GROUP1_OP_CMP = 7,
220
221 GROUP1A_OP_POP = 0,
222
223 GROUP2_OP_ROL = 0,
224 GROUP2_OP_ROR = 1,
225 GROUP2_OP_RCL = 2,
226 GROUP2_OP_RCR = 3,
227
228 GROUP2_OP_SHL = 4,
229 GROUP2_OP_SHR = 5,
230 GROUP2_OP_SAR = 7,
231
232 GROUP3_OP_TEST = 0,
233 GROUP3_OP_NOT = 2,
234 GROUP3_OP_NEG = 3,
235 GROUP3_OP_IDIV = 7,
236
237 GROUP5_OP_CALLN = 2,
238 GROUP5_OP_JMPN = 4,
239 GROUP5_OP_PUSH = 6,
240
241 GROUP11_MOV = 0,
242
243 GROUP14_OP_PSLLQ = 6,
244 GROUP14_OP_PSRLQ = 2,
245
246 ESCAPE_DD_FSTP_doubleReal = 3,
247 } GroupOpcodeID;
248
249 class X86InstructionFormatter;
250public:
251
252 X86Assembler()
253 : m_indexOfLastWatchpoint(INT_MIN)
254 , m_indexOfTailOfLastWatchpoint(INT_MIN)
255 {
256 }
257
258 // Stack operations:
259
260 void push_r(RegisterID reg)
261 {
262 m_formatter.oneByteOp(opcode: OP_PUSH_EAX, reg);
263 }
264
265 void pop_r(RegisterID reg)
266 {
267 m_formatter.oneByteOp(opcode: OP_POP_EAX, reg);
268 }
269
270 void push_i32(int imm)
271 {
272 m_formatter.oneByteOp(opcode: OP_PUSH_Iz);
273 m_formatter.immediate32(imm);
274 }
275
276 void push_m(int offset, RegisterID base)
277 {
278 m_formatter.oneByteOp(opcode: OP_GROUP5_Ev, reg: GROUP5_OP_PUSH, base, offset);
279 }
280
281 void pop_m(int offset, RegisterID base)
282 {
283 m_formatter.oneByteOp(opcode: OP_GROUP1A_Ev, reg: GROUP1A_OP_POP, base, offset);
284 }
285
286 // Arithmetic operations:
287
288#if !CPU(X86_64)
289 void adcl_im(int imm, const void* addr)
290 {
291 if (CAN_SIGN_EXTEND_8_32(imm)) {
292 m_formatter.oneByteOp(OP_GROUP1_EvIb, GROUP1_OP_ADC, addr);
293 m_formatter.immediate8(imm);
294 } else {
295 m_formatter.oneByteOp(OP_GROUP1_EvIz, GROUP1_OP_ADC, addr);
296 m_formatter.immediate32(imm);
297 }
298 }
299#endif
300
301 void addl_rr(RegisterID src, RegisterID dst)
302 {
303 m_formatter.oneByteOp(opcode: OP_ADD_EvGv, reg: src, rm: dst);
304 }
305
306 void addl_mr(int offset, RegisterID base, RegisterID dst)
307 {
308 m_formatter.oneByteOp(opcode: OP_ADD_GvEv, reg: dst, base, offset);
309 }
310
311#if !CPU(X86_64)
312 void addl_mr(const void* addr, RegisterID dst)
313 {
314 m_formatter.oneByteOp(OP_ADD_GvEv, dst, addr);
315 }
316#endif
317
318 void addl_rm(RegisterID src, int offset, RegisterID base)
319 {
320 m_formatter.oneByteOp(opcode: OP_ADD_EvGv, reg: src, base, offset);
321 }
322
323 void addl_ir(int imm, RegisterID dst)
324 {
325 if (CAN_SIGN_EXTEND_8_32(value: imm)) {
326 m_formatter.oneByteOp(opcode: OP_GROUP1_EvIb, reg: GROUP1_OP_ADD, rm: dst);
327 m_formatter.immediate8(imm);
328 } else {
329 m_formatter.oneByteOp(opcode: OP_GROUP1_EvIz, reg: GROUP1_OP_ADD, rm: dst);
330 m_formatter.immediate32(imm);
331 }
332 }
333
334 void addl_im(int imm, int offset, RegisterID base)
335 {
336 if (CAN_SIGN_EXTEND_8_32(value: imm)) {
337 m_formatter.oneByteOp(opcode: OP_GROUP1_EvIb, reg: GROUP1_OP_ADD, base, offset);
338 m_formatter.immediate8(imm);
339 } else {
340 m_formatter.oneByteOp(opcode: OP_GROUP1_EvIz, reg: GROUP1_OP_ADD, base, offset);
341 m_formatter.immediate32(imm);
342 }
343 }
344
345#if CPU(X86_64)
346 void addq_rr(RegisterID src, RegisterID dst)
347 {
348 m_formatter.oneByteOp64(opcode: OP_ADD_EvGv, reg: src, rm: dst);
349 }
350
351 void addq_mr(int offset, RegisterID base, RegisterID dst)
352 {
353 m_formatter.oneByteOp64(opcode: OP_ADD_GvEv, reg: dst, base, offset);
354 }
355
356 void addq_ir(int imm, RegisterID dst)
357 {
358 if (CAN_SIGN_EXTEND_8_32(value: imm)) {
359 m_formatter.oneByteOp64(opcode: OP_GROUP1_EvIb, reg: GROUP1_OP_ADD, rm: dst);
360 m_formatter.immediate8(imm);
361 } else {
362 m_formatter.oneByteOp64(opcode: OP_GROUP1_EvIz, reg: GROUP1_OP_ADD, rm: dst);
363 m_formatter.immediate32(imm);
364 }
365 }
366
367 void addq_im(int imm, int offset, RegisterID base)
368 {
369 if (CAN_SIGN_EXTEND_8_32(value: imm)) {
370 m_formatter.oneByteOp64(opcode: OP_GROUP1_EvIb, reg: GROUP1_OP_ADD, base, offset);
371 m_formatter.immediate8(imm);
372 } else {
373 m_formatter.oneByteOp64(opcode: OP_GROUP1_EvIz, reg: GROUP1_OP_ADD, base, offset);
374 m_formatter.immediate32(imm);
375 }
376 }
377#else
378 void addl_im(int imm, const void* addr)
379 {
380 if (CAN_SIGN_EXTEND_8_32(imm)) {
381 m_formatter.oneByteOp(OP_GROUP1_EvIb, GROUP1_OP_ADD, addr);
382 m_formatter.immediate8(imm);
383 } else {
384 m_formatter.oneByteOp(OP_GROUP1_EvIz, GROUP1_OP_ADD, addr);
385 m_formatter.immediate32(imm);
386 }
387 }
388#endif
389
390 void andl_rr(RegisterID src, RegisterID dst)
391 {
392 m_formatter.oneByteOp(opcode: OP_AND_EvGv, reg: src, rm: dst);
393 }
394
395 void andl_mr(int offset, RegisterID base, RegisterID dst)
396 {
397 m_formatter.oneByteOp(opcode: OP_AND_GvEv, reg: dst, base, offset);
398 }
399
400 void andl_rm(RegisterID src, int offset, RegisterID base)
401 {
402 m_formatter.oneByteOp(opcode: OP_AND_EvGv, reg: src, base, offset);
403 }
404
405 void andl_ir(int imm, RegisterID dst)
406 {
407 if (CAN_SIGN_EXTEND_8_32(value: imm)) {
408 m_formatter.oneByteOp(opcode: OP_GROUP1_EvIb, reg: GROUP1_OP_AND, rm: dst);
409 m_formatter.immediate8(imm);
410 } else {
411 m_formatter.oneByteOp(opcode: OP_GROUP1_EvIz, reg: GROUP1_OP_AND, rm: dst);
412 m_formatter.immediate32(imm);
413 }
414 }
415
416 void andl_im(int imm, int offset, RegisterID base)
417 {
418 if (CAN_SIGN_EXTEND_8_32(value: imm)) {
419 m_formatter.oneByteOp(opcode: OP_GROUP1_EvIb, reg: GROUP1_OP_AND, base, offset);
420 m_formatter.immediate8(imm);
421 } else {
422 m_formatter.oneByteOp(opcode: OP_GROUP1_EvIz, reg: GROUP1_OP_AND, base, offset);
423 m_formatter.immediate32(imm);
424 }
425 }
426
427#if CPU(X86_64)
428 void andq_rr(RegisterID src, RegisterID dst)
429 {
430 m_formatter.oneByteOp64(opcode: OP_AND_EvGv, reg: src, rm: dst);
431 }
432
433 void andq_ir(int imm, RegisterID dst)
434 {
435 if (CAN_SIGN_EXTEND_8_32(value: imm)) {
436 m_formatter.oneByteOp64(opcode: OP_GROUP1_EvIb, reg: GROUP1_OP_AND, rm: dst);
437 m_formatter.immediate8(imm);
438 } else {
439 m_formatter.oneByteOp64(opcode: OP_GROUP1_EvIz, reg: GROUP1_OP_AND, rm: dst);
440 m_formatter.immediate32(imm);
441 }
442 }
443#else
444 void andl_im(int imm, const void* addr)
445 {
446 if (CAN_SIGN_EXTEND_8_32(imm)) {
447 m_formatter.oneByteOp(OP_GROUP1_EvIb, GROUP1_OP_AND, addr);
448 m_formatter.immediate8(imm);
449 } else {
450 m_formatter.oneByteOp(OP_GROUP1_EvIz, GROUP1_OP_AND, addr);
451 m_formatter.immediate32(imm);
452 }
453 }
454#endif
455
456 void negl_r(RegisterID dst)
457 {
458 m_formatter.oneByteOp(opcode: OP_GROUP3_Ev, reg: GROUP3_OP_NEG, rm: dst);
459 }
460
461#if CPU(X86_64)
462 void negq_r(RegisterID dst)
463 {
464 m_formatter.oneByteOp64(opcode: OP_GROUP3_Ev, reg: GROUP3_OP_NEG, rm: dst);
465 }
466#endif
467
468 void negl_m(int offset, RegisterID base)
469 {
470 m_formatter.oneByteOp(opcode: OP_GROUP3_Ev, reg: GROUP3_OP_NEG, base, offset);
471 }
472
473 void notl_r(RegisterID dst)
474 {
475 m_formatter.oneByteOp(opcode: OP_GROUP3_Ev, reg: GROUP3_OP_NOT, rm: dst);
476 }
477
478 void notl_m(int offset, RegisterID base)
479 {
480 m_formatter.oneByteOp(opcode: OP_GROUP3_Ev, reg: GROUP3_OP_NOT, base, offset);
481 }
482
483 void orl_rr(RegisterID src, RegisterID dst)
484 {
485 m_formatter.oneByteOp(opcode: OP_OR_EvGv, reg: src, rm: dst);
486 }
487
488 void orl_mr(int offset, RegisterID base, RegisterID dst)
489 {
490 m_formatter.oneByteOp(opcode: OP_OR_GvEv, reg: dst, base, offset);
491 }
492
493 void orl_rm(RegisterID src, int offset, RegisterID base)
494 {
495 m_formatter.oneByteOp(opcode: OP_OR_EvGv, reg: src, base, offset);
496 }
497
498 void orl_ir(int imm, RegisterID dst)
499 {
500 if (CAN_SIGN_EXTEND_8_32(value: imm)) {
501 m_formatter.oneByteOp(opcode: OP_GROUP1_EvIb, reg: GROUP1_OP_OR, rm: dst);
502 m_formatter.immediate8(imm);
503 } else {
504 m_formatter.oneByteOp(opcode: OP_GROUP1_EvIz, reg: GROUP1_OP_OR, rm: dst);
505 m_formatter.immediate32(imm);
506 }
507 }
508
509 void orl_im(int imm, int offset, RegisterID base)
510 {
511 if (CAN_SIGN_EXTEND_8_32(value: imm)) {
512 m_formatter.oneByteOp(opcode: OP_GROUP1_EvIb, reg: GROUP1_OP_OR, base, offset);
513 m_formatter.immediate8(imm);
514 } else {
515 m_formatter.oneByteOp(opcode: OP_GROUP1_EvIz, reg: GROUP1_OP_OR, base, offset);
516 m_formatter.immediate32(imm);
517 }
518 }
519
520#if CPU(X86_64)
521 void orq_rr(RegisterID src, RegisterID dst)
522 {
523 m_formatter.oneByteOp64(opcode: OP_OR_EvGv, reg: src, rm: dst);
524 }
525
526 void orq_ir(int imm, RegisterID dst)
527 {
528 if (CAN_SIGN_EXTEND_8_32(value: imm)) {
529 m_formatter.oneByteOp64(opcode: OP_GROUP1_EvIb, reg: GROUP1_OP_OR, rm: dst);
530 m_formatter.immediate8(imm);
531 } else {
532 m_formatter.oneByteOp64(opcode: OP_GROUP1_EvIz, reg: GROUP1_OP_OR, rm: dst);
533 m_formatter.immediate32(imm);
534 }
535 }
536#else
537 void orl_im(int imm, const void* addr)
538 {
539 if (CAN_SIGN_EXTEND_8_32(imm)) {
540 m_formatter.oneByteOp(OP_GROUP1_EvIb, GROUP1_OP_OR, addr);
541 m_formatter.immediate8(imm);
542 } else {
543 m_formatter.oneByteOp(OP_GROUP1_EvIz, GROUP1_OP_OR, addr);
544 m_formatter.immediate32(imm);
545 }
546 }
547
548 void orl_rm(RegisterID src, const void* addr)
549 {
550 m_formatter.oneByteOp(OP_OR_EvGv, src, addr);
551 }
552#endif
553
554 void subl_rr(RegisterID src, RegisterID dst)
555 {
556 m_formatter.oneByteOp(opcode: OP_SUB_EvGv, reg: src, rm: dst);
557 }
558
559 void subl_mr(int offset, RegisterID base, RegisterID dst)
560 {
561 m_formatter.oneByteOp(opcode: OP_SUB_GvEv, reg: dst, base, offset);
562 }
563
564 void subl_rm(RegisterID src, int offset, RegisterID base)
565 {
566 m_formatter.oneByteOp(opcode: OP_SUB_EvGv, reg: src, base, offset);
567 }
568
569 void subl_ir(int imm, RegisterID dst)
570 {
571 if (CAN_SIGN_EXTEND_8_32(value: imm)) {
572 m_formatter.oneByteOp(opcode: OP_GROUP1_EvIb, reg: GROUP1_OP_SUB, rm: dst);
573 m_formatter.immediate8(imm);
574 } else {
575 m_formatter.oneByteOp(opcode: OP_GROUP1_EvIz, reg: GROUP1_OP_SUB, rm: dst);
576 m_formatter.immediate32(imm);
577 }
578 }
579
580 void subl_im(int imm, int offset, RegisterID base)
581 {
582 if (CAN_SIGN_EXTEND_8_32(value: imm)) {
583 m_formatter.oneByteOp(opcode: OP_GROUP1_EvIb, reg: GROUP1_OP_SUB, base, offset);
584 m_formatter.immediate8(imm);
585 } else {
586 m_formatter.oneByteOp(opcode: OP_GROUP1_EvIz, reg: GROUP1_OP_SUB, base, offset);
587 m_formatter.immediate32(imm);
588 }
589 }
590
591#if CPU(X86_64)
592 void subq_rr(RegisterID src, RegisterID dst)
593 {
594 m_formatter.oneByteOp64(opcode: OP_SUB_EvGv, reg: src, rm: dst);
595 }
596
597 void subq_ir(int imm, RegisterID dst)
598 {
599 if (CAN_SIGN_EXTEND_8_32(value: imm)) {
600 m_formatter.oneByteOp64(opcode: OP_GROUP1_EvIb, reg: GROUP1_OP_SUB, rm: dst);
601 m_formatter.immediate8(imm);
602 } else {
603 m_formatter.oneByteOp64(opcode: OP_GROUP1_EvIz, reg: GROUP1_OP_SUB, rm: dst);
604 m_formatter.immediate32(imm);
605 }
606 }
607#else
608 void subl_im(int imm, const void* addr)
609 {
610 if (CAN_SIGN_EXTEND_8_32(imm)) {
611 m_formatter.oneByteOp(OP_GROUP1_EvIb, GROUP1_OP_SUB, addr);
612 m_formatter.immediate8(imm);
613 } else {
614 m_formatter.oneByteOp(OP_GROUP1_EvIz, GROUP1_OP_SUB, addr);
615 m_formatter.immediate32(imm);
616 }
617 }
618#endif
619
620 void xorl_rr(RegisterID src, RegisterID dst)
621 {
622 m_formatter.oneByteOp(opcode: OP_XOR_EvGv, reg: src, rm: dst);
623 }
624
625 void xorl_mr(int offset, RegisterID base, RegisterID dst)
626 {
627 m_formatter.oneByteOp(opcode: OP_XOR_GvEv, reg: dst, base, offset);
628 }
629
630 void xorl_rm(RegisterID src, int offset, RegisterID base)
631 {
632 m_formatter.oneByteOp(opcode: OP_XOR_EvGv, reg: src, base, offset);
633 }
634
635 void xorl_im(int imm, int offset, RegisterID base)
636 {
637 if (CAN_SIGN_EXTEND_8_32(value: imm)) {
638 m_formatter.oneByteOp(opcode: OP_GROUP1_EvIb, reg: GROUP1_OP_XOR, base, offset);
639 m_formatter.immediate8(imm);
640 } else {
641 m_formatter.oneByteOp(opcode: OP_GROUP1_EvIz, reg: GROUP1_OP_XOR, base, offset);
642 m_formatter.immediate32(imm);
643 }
644 }
645
646 void xorl_ir(int imm, RegisterID dst)
647 {
648 if (CAN_SIGN_EXTEND_8_32(value: imm)) {
649 m_formatter.oneByteOp(opcode: OP_GROUP1_EvIb, reg: GROUP1_OP_XOR, rm: dst);
650 m_formatter.immediate8(imm);
651 } else {
652 m_formatter.oneByteOp(opcode: OP_GROUP1_EvIz, reg: GROUP1_OP_XOR, rm: dst);
653 m_formatter.immediate32(imm);
654 }
655 }
656
657#if CPU(X86_64)
658 void xorq_rr(RegisterID src, RegisterID dst)
659 {
660 m_formatter.oneByteOp64(opcode: OP_XOR_EvGv, reg: src, rm: dst);
661 }
662
663 void xorq_ir(int imm, RegisterID dst)
664 {
665 if (CAN_SIGN_EXTEND_8_32(value: imm)) {
666 m_formatter.oneByteOp64(opcode: OP_GROUP1_EvIb, reg: GROUP1_OP_XOR, rm: dst);
667 m_formatter.immediate8(imm);
668 } else {
669 m_formatter.oneByteOp64(opcode: OP_GROUP1_EvIz, reg: GROUP1_OP_XOR, rm: dst);
670 m_formatter.immediate32(imm);
671 }
672 }
673
674 void xorq_rm(RegisterID src, int offset, RegisterID base)
675 {
676 m_formatter.oneByteOp64(opcode: OP_XOR_EvGv, reg: src, base, offset);
677 }
678
679 void rorq_i8r(int imm, RegisterID dst)
680 {
681 if (imm == 1)
682 m_formatter.oneByteOp64(opcode: OP_GROUP2_Ev1, reg: GROUP2_OP_ROR, rm: dst);
683 else {
684 m_formatter.oneByteOp64(opcode: OP_GROUP2_EvIb, reg: GROUP2_OP_ROR, rm: dst);
685 m_formatter.immediate8(imm);
686 }
687 }
688
689 void sarq_CLr(RegisterID dst)
690 {
691 m_formatter.oneByteOp64(opcode: OP_GROUP2_EvCL, reg: GROUP2_OP_SAR, rm: dst);
692 }
693
694 void sarq_i8r(int imm, RegisterID dst)
695 {
696 if (imm == 1)
697 m_formatter.oneByteOp64(opcode: OP_GROUP2_Ev1, reg: GROUP2_OP_SAR, rm: dst);
698 else {
699 m_formatter.oneByteOp64(opcode: OP_GROUP2_EvIb, reg: GROUP2_OP_SAR, rm: dst);
700 m_formatter.immediate8(imm);
701 }
702 }
703
704 void shrq_i8r(int imm, RegisterID dst)
705 {
706 // ### doesn't work when removing the "0 &&"
707 if (0 && imm == 1)
708 m_formatter.oneByteOp64(opcode: OP_GROUP2_Ev1, reg: GROUP2_OP_SHR, rm: dst);
709 else {
710 m_formatter.oneByteOp64(opcode: OP_GROUP2_EvIb, reg: GROUP2_OP_SHR, rm: dst);
711 m_formatter.immediate8(imm);
712 }
713 }
714
715 void shrq_CLr(RegisterID dst)
716 {
717 m_formatter.oneByteOp64(opcode: OP_GROUP2_EvCL, reg: GROUP2_OP_SHR, rm: dst);
718 }
719
720 void shlq_i8r(int imm, RegisterID dst)
721 {
722 // ### doesn't work when removing the "0 &&"
723 if (0 && imm == 1)
724 m_formatter.oneByteOp64(opcode: OP_GROUP2_Ev1, reg: GROUP2_OP_SHL, rm: dst);
725 else {
726 m_formatter.oneByteOp64(opcode: OP_GROUP2_EvIb, reg: GROUP2_OP_SHL, rm: dst);
727 m_formatter.immediate8(imm);
728 }
729 }
730
731 void shlq_CLr(RegisterID dst)
732 {
733 m_formatter.oneByteOp64(opcode: OP_GROUP2_EvCL, reg: GROUP2_OP_SHL, rm: dst);
734 }
735#endif
736
737 void sarl_i8r(int imm, RegisterID dst)
738 {
739 if (imm == 1)
740 m_formatter.oneByteOp(opcode: OP_GROUP2_Ev1, reg: GROUP2_OP_SAR, rm: dst);
741 else {
742 m_formatter.oneByteOp(opcode: OP_GROUP2_EvIb, reg: GROUP2_OP_SAR, rm: dst);
743 m_formatter.immediate8(imm);
744 }
745 }
746
747 void sarl_CLr(RegisterID dst)
748 {
749 m_formatter.oneByteOp(opcode: OP_GROUP2_EvCL, reg: GROUP2_OP_SAR, rm: dst);
750 }
751
752 void shrl_i8r(int imm, RegisterID dst)
753 {
754 if (imm == 1)
755 m_formatter.oneByteOp(opcode: OP_GROUP2_Ev1, reg: GROUP2_OP_SHR, rm: dst);
756 else {
757 m_formatter.oneByteOp(opcode: OP_GROUP2_EvIb, reg: GROUP2_OP_SHR, rm: dst);
758 m_formatter.immediate8(imm);
759 }
760 }
761
762 void shrl_CLr(RegisterID dst)
763 {
764 m_formatter.oneByteOp(opcode: OP_GROUP2_EvCL, reg: GROUP2_OP_SHR, rm: dst);
765 }
766
767 void shll_i8r(int imm, RegisterID dst)
768 {
769 if (imm == 1)
770 m_formatter.oneByteOp(opcode: OP_GROUP2_Ev1, reg: GROUP2_OP_SHL, rm: dst);
771 else {
772 m_formatter.oneByteOp(opcode: OP_GROUP2_EvIb, reg: GROUP2_OP_SHL, rm: dst);
773 m_formatter.immediate8(imm);
774 }
775 }
776
777 void shll_CLr(RegisterID dst)
778 {
779 m_formatter.oneByteOp(opcode: OP_GROUP2_EvCL, reg: GROUP2_OP_SHL, rm: dst);
780 }
781
782 void imull_rr(RegisterID src, RegisterID dst)
783 {
784 m_formatter.twoByteOp(opcode: OP2_IMUL_GvEv, reg: dst, rm: src);
785 }
786
787 void imull_mr(int offset, RegisterID base, RegisterID dst)
788 {
789 m_formatter.twoByteOp(opcode: OP2_IMUL_GvEv, reg: dst, base, offset);
790 }
791
792 void imull_i32r(RegisterID src, int32_t value, RegisterID dst)
793 {
794 m_formatter.oneByteOp(opcode: OP_IMUL_GvEvIz, reg: dst, rm: src);
795 m_formatter.immediate32(imm: value);
796 }
797
798 void idivl_r(RegisterID dst)
799 {
800 m_formatter.oneByteOp(opcode: OP_GROUP3_Ev, reg: GROUP3_OP_IDIV, rm: dst);
801 }
802
803 // Comparisons:
804
805 void cmpl_rr(RegisterID src, RegisterID dst)
806 {
807 m_formatter.oneByteOp(opcode: OP_CMP_EvGv, reg: src, rm: dst);
808 }
809
810 void cmpl_rm(RegisterID src, int offset, RegisterID base)
811 {
812 m_formatter.oneByteOp(opcode: OP_CMP_EvGv, reg: src, base, offset);
813 }
814
815 void cmpl_mr(int offset, RegisterID base, RegisterID src)
816 {
817 m_formatter.oneByteOp(opcode: OP_CMP_GvEv, reg: src, base, offset);
818 }
819
820 void cmpl_ir(int imm, RegisterID dst)
821 {
822 if (CAN_SIGN_EXTEND_8_32(value: imm)) {
823 m_formatter.oneByteOp(opcode: OP_GROUP1_EvIb, reg: GROUP1_OP_CMP, rm: dst);
824 m_formatter.immediate8(imm);
825 } else {
826 m_formatter.oneByteOp(opcode: OP_GROUP1_EvIz, reg: GROUP1_OP_CMP, rm: dst);
827 m_formatter.immediate32(imm);
828 }
829 }
830
831 void cmpl_ir_force32(int imm, RegisterID dst)
832 {
833 m_formatter.oneByteOp(opcode: OP_GROUP1_EvIz, reg: GROUP1_OP_CMP, rm: dst);
834 m_formatter.immediate32(imm);
835 }
836
837 void cmpl_im(int imm, int offset, RegisterID base)
838 {
839 if (CAN_SIGN_EXTEND_8_32(value: imm)) {
840 m_formatter.oneByteOp(opcode: OP_GROUP1_EvIb, reg: GROUP1_OP_CMP, base, offset);
841 m_formatter.immediate8(imm);
842 } else {
843 m_formatter.oneByteOp(opcode: OP_GROUP1_EvIz, reg: GROUP1_OP_CMP, base, offset);
844 m_formatter.immediate32(imm);
845 }
846 }
847
848 void cmpb_im(int imm, int offset, RegisterID base)
849 {
850 m_formatter.oneByteOp(opcode: OP_GROUP1_EbIb, reg: GROUP1_OP_CMP, base, offset);
851 m_formatter.immediate8(imm);
852 }
853
854 void cmpb_im(int imm, int offset, RegisterID base, RegisterID index, int scale)
855 {
856 m_formatter.oneByteOp(opcode: OP_GROUP1_EbIb, reg: GROUP1_OP_CMP, base, index, scale, offset);
857 m_formatter.immediate8(imm);
858 }
859
860#if CPU(X86)
861 void cmpb_im(int imm, const void* addr)
862 {
863 m_formatter.oneByteOp(OP_GROUP1_EbIb, GROUP1_OP_CMP, addr);
864 m_formatter.immediate8(imm);
865 }
866#endif
867
868 void cmpl_im(int imm, int offset, RegisterID base, RegisterID index, int scale)
869 {
870 if (CAN_SIGN_EXTEND_8_32(value: imm)) {
871 m_formatter.oneByteOp(opcode: OP_GROUP1_EvIb, reg: GROUP1_OP_CMP, base, index, scale, offset);
872 m_formatter.immediate8(imm);
873 } else {
874 m_formatter.oneByteOp(opcode: OP_GROUP1_EvIz, reg: GROUP1_OP_CMP, base, index, scale, offset);
875 m_formatter.immediate32(imm);
876 }
877 }
878
879 void cmpl_im_force32(int imm, int offset, RegisterID base)
880 {
881 m_formatter.oneByteOp(opcode: OP_GROUP1_EvIz, reg: GROUP1_OP_CMP, base, offset);
882 m_formatter.immediate32(imm);
883 }
884
885#if CPU(X86_64)
886 void cmpq_rr(RegisterID src, RegisterID dst)
887 {
888 m_formatter.oneByteOp64(opcode: OP_CMP_EvGv, reg: src, rm: dst);
889 }
890
891 void cmpq_rm(RegisterID src, int offset, RegisterID base)
892 {
893 m_formatter.oneByteOp64(opcode: OP_CMP_EvGv, reg: src, base, offset);
894 }
895
896 void cmpq_mr(int offset, RegisterID base, RegisterID src)
897 {
898 m_formatter.oneByteOp64(opcode: OP_CMP_GvEv, reg: src, base, offset);
899 }
900
901 void cmpq_ir(int imm, RegisterID dst)
902 {
903 if (CAN_SIGN_EXTEND_8_32(value: imm)) {
904 m_formatter.oneByteOp64(opcode: OP_GROUP1_EvIb, reg: GROUP1_OP_CMP, rm: dst);
905 m_formatter.immediate8(imm);
906 } else {
907 m_formatter.oneByteOp64(opcode: OP_GROUP1_EvIz, reg: GROUP1_OP_CMP, rm: dst);
908 m_formatter.immediate32(imm);
909 }
910 }
911
912 void cmpq_im(int imm, int offset, RegisterID base)
913 {
914 if (CAN_SIGN_EXTEND_8_32(value: imm)) {
915 m_formatter.oneByteOp64(opcode: OP_GROUP1_EvIb, reg: GROUP1_OP_CMP, base, offset);
916 m_formatter.immediate8(imm);
917 } else {
918 m_formatter.oneByteOp64(opcode: OP_GROUP1_EvIz, reg: GROUP1_OP_CMP, base, offset);
919 m_formatter.immediate32(imm);
920 }
921 }
922
923 void cmpq_im(int imm, int offset, RegisterID base, RegisterID index, int scale)
924 {
925 if (CAN_SIGN_EXTEND_8_32(value: imm)) {
926 m_formatter.oneByteOp64(opcode: OP_GROUP1_EvIb, reg: GROUP1_OP_CMP, base, index, scale, offset);
927 m_formatter.immediate8(imm);
928 } else {
929 m_formatter.oneByteOp64(opcode: OP_GROUP1_EvIz, reg: GROUP1_OP_CMP, base, index, scale, offset);
930 m_formatter.immediate32(imm);
931 }
932 }
933#else
934 void cmpl_rm(RegisterID reg, const void* addr)
935 {
936 m_formatter.oneByteOp(OP_CMP_EvGv, reg, addr);
937 }
938
939 void cmpl_im(int imm, const void* addr)
940 {
941 if (CAN_SIGN_EXTEND_8_32(imm)) {
942 m_formatter.oneByteOp(OP_GROUP1_EvIb, GROUP1_OP_CMP, addr);
943 m_formatter.immediate8(imm);
944 } else {
945 m_formatter.oneByteOp(OP_GROUP1_EvIz, GROUP1_OP_CMP, addr);
946 m_formatter.immediate32(imm);
947 }
948 }
949#endif
950
951 void cmpw_ir(int imm, RegisterID dst)
952 {
953 if (CAN_SIGN_EXTEND_8_32(value: imm)) {
954 m_formatter.prefix(pre: PRE_OPERAND_SIZE);
955 m_formatter.oneByteOp(opcode: OP_GROUP1_EvIb, reg: GROUP1_OP_CMP, rm: dst);
956 m_formatter.immediate8(imm);
957 } else {
958 m_formatter.prefix(pre: PRE_OPERAND_SIZE);
959 m_formatter.oneByteOp(opcode: OP_GROUP1_EvIz, reg: GROUP1_OP_CMP, rm: dst);
960 m_formatter.immediate16(imm);
961 }
962 }
963
964 void cmpw_rm(RegisterID src, int offset, RegisterID base, RegisterID index, int scale)
965 {
966 m_formatter.prefix(pre: PRE_OPERAND_SIZE);
967 m_formatter.oneByteOp(opcode: OP_CMP_EvGv, reg: src, base, index, scale, offset);
968 }
969
970 void cmpw_im(int imm, int offset, RegisterID base, RegisterID index, int scale)
971 {
972 if (CAN_SIGN_EXTEND_8_32(value: imm)) {
973 m_formatter.prefix(pre: PRE_OPERAND_SIZE);
974 m_formatter.oneByteOp(opcode: OP_GROUP1_EvIb, reg: GROUP1_OP_CMP, base, index, scale, offset);
975 m_formatter.immediate8(imm);
976 } else {
977 m_formatter.prefix(pre: PRE_OPERAND_SIZE);
978 m_formatter.oneByteOp(opcode: OP_GROUP1_EvIz, reg: GROUP1_OP_CMP, base, index, scale, offset);
979 m_formatter.immediate16(imm);
980 }
981 }
982
983 void testl_rr(RegisterID src, RegisterID dst)
984 {
985 m_formatter.oneByteOp(opcode: OP_TEST_EvGv, reg: src, rm: dst);
986 }
987
988 void testl_i32r(int imm, RegisterID dst)
989 {
990 m_formatter.oneByteOp(opcode: OP_GROUP3_EvIz, reg: GROUP3_OP_TEST, rm: dst);
991 m_formatter.immediate32(imm);
992 }
993
994 void testl_i32m(int imm, int offset, RegisterID base)
995 {
996 m_formatter.oneByteOp(opcode: OP_GROUP3_EvIz, reg: GROUP3_OP_TEST, base, offset);
997 m_formatter.immediate32(imm);
998 }
999
1000 void testb_rr(RegisterID src, RegisterID dst)
1001 {
1002 m_formatter.oneByteOp8(opcode: OP_TEST_EbGb, reg: src, rm: dst);
1003 }
1004
1005 void testb_im(int imm, int offset, RegisterID base)
1006 {
1007 m_formatter.oneByteOp(opcode: OP_GROUP3_EbIb, reg: GROUP3_OP_TEST, base, offset);
1008 m_formatter.immediate8(imm);
1009 }
1010
1011 void testb_im(int imm, int offset, RegisterID base, RegisterID index, int scale)
1012 {
1013 m_formatter.oneByteOp(opcode: OP_GROUP3_EbIb, reg: GROUP3_OP_TEST, base, index, scale, offset);
1014 m_formatter.immediate8(imm);
1015 }
1016
1017#if CPU(X86)
1018 void testb_im(int imm, const void* addr)
1019 {
1020 m_formatter.oneByteOp(OP_GROUP3_EbIb, GROUP3_OP_TEST, addr);
1021 m_formatter.immediate8(imm);
1022 }
1023#endif
1024
1025 void testl_i32m(int imm, int offset, RegisterID base, RegisterID index, int scale)
1026 {
1027 m_formatter.oneByteOp(opcode: OP_GROUP3_EvIz, reg: GROUP3_OP_TEST, base, index, scale, offset);
1028 m_formatter.immediate32(imm);
1029 }
1030
1031#if CPU(X86_64)
1032 void testq_rr(RegisterID src, RegisterID dst)
1033 {
1034 m_formatter.oneByteOp64(opcode: OP_TEST_EvGv, reg: src, rm: dst);
1035 }
1036
1037 void testq_rm(RegisterID src, int offset, RegisterID base)
1038 {
1039 m_formatter.oneByteOp64(opcode: OP_TEST_EvGv, reg: src, base, offset);
1040 }
1041
1042 void testq_i32r(int imm, RegisterID dst)
1043 {
1044 m_formatter.oneByteOp64(opcode: OP_GROUP3_EvIz, reg: GROUP3_OP_TEST, rm: dst);
1045 m_formatter.immediate32(imm);
1046 }
1047
1048 void testq_i32m(int imm, int offset, RegisterID base)
1049 {
1050 m_formatter.oneByteOp64(opcode: OP_GROUP3_EvIz, reg: GROUP3_OP_TEST, base, offset);
1051 m_formatter.immediate32(imm);
1052 }
1053
1054 void testq_i32m(int imm, int offset, RegisterID base, RegisterID index, int scale)
1055 {
1056 m_formatter.oneByteOp64(opcode: OP_GROUP3_EvIz, reg: GROUP3_OP_TEST, base, index, scale, offset);
1057 m_formatter.immediate32(imm);
1058 }
1059#endif
1060
1061 void testw_rr(RegisterID src, RegisterID dst)
1062 {
1063 m_formatter.prefix(pre: PRE_OPERAND_SIZE);
1064 m_formatter.oneByteOp(opcode: OP_TEST_EvGv, reg: src, rm: dst);
1065 }
1066
1067 void testb_i8r(int imm, RegisterID dst)
1068 {
1069 m_formatter.oneByteOp8(opcode: OP_GROUP3_EbIb, groupOp: GROUP3_OP_TEST, rm: dst);
1070 m_formatter.immediate8(imm);
1071 }
1072
1073 void setCC_r(Condition cond, RegisterID dst)
1074 {
1075 m_formatter.twoByteOp8(opcode: setccOpcode(cond), groupOp: (GroupOpcodeID)0, rm: dst);
1076 }
1077
1078 void sete_r(RegisterID dst)
1079 {
1080 m_formatter.twoByteOp8(opcode: setccOpcode(ConditionE), groupOp: (GroupOpcodeID)0, rm: dst);
1081 }
1082
1083 void setz_r(RegisterID dst)
1084 {
1085 sete_r(dst);
1086 }
1087
1088 void setne_r(RegisterID dst)
1089 {
1090 m_formatter.twoByteOp8(opcode: setccOpcode(ConditionNE), groupOp: (GroupOpcodeID)0, rm: dst);
1091 }
1092
1093 void setnz_r(RegisterID dst)
1094 {
1095 setne_r(dst);
1096 }
1097
1098 // Various move ops:
1099
1100 void cdq()
1101 {
1102 m_formatter.oneByteOp(opcode: OP_CDQ);
1103 }
1104
1105 void fstpl(int offset, RegisterID base)
1106 {
1107 m_formatter.oneByteOp(opcode: OP_ESCAPE_DD, reg: ESCAPE_DD_FSTP_doubleReal, base, offset);
1108 }
1109
1110 void xchgl_rr(RegisterID src, RegisterID dst)
1111 {
1112 m_formatter.oneByteOp(opcode: OP_XCHG_EvGv, reg: src, rm: dst);
1113 }
1114
1115#if CPU(X86_64)
1116 void xchgq_rr(RegisterID src, RegisterID dst)
1117 {
1118 m_formatter.oneByteOp64(opcode: OP_XCHG_EvGv, reg: src, rm: dst);
1119 }
1120#endif
1121
1122 void movl_rr(RegisterID src, RegisterID dst)
1123 {
1124 m_formatter.oneByteOp(opcode: OP_MOV_EvGv, reg: src, rm: dst);
1125 }
1126
1127 void movl_rm(RegisterID src, int offset, RegisterID base)
1128 {
1129 m_formatter.oneByteOp(opcode: OP_MOV_EvGv, reg: src, base, offset);
1130 }
1131
1132 void movl_rm_disp32(RegisterID src, int offset, RegisterID base)
1133 {
1134 m_formatter.oneByteOp_disp32(opcode: OP_MOV_EvGv, reg: src, base, offset);
1135 }
1136
1137 void movl_rm(RegisterID src, int offset, RegisterID base, RegisterID index, int scale)
1138 {
1139 m_formatter.oneByteOp(opcode: OP_MOV_EvGv, reg: src, base, index, scale, offset);
1140 }
1141
1142 void movl_mEAX(const void* addr)
1143 {
1144 m_formatter.oneByteOp(opcode: OP_MOV_EAXOv);
1145#if CPU(X86_64)
1146 m_formatter.immediate64(imm: reinterpret_cast<int64_t>(addr));
1147#else
1148 m_formatter.immediate32(reinterpret_cast<int>(addr));
1149#endif
1150 }
1151
1152 void movl_mr(int offset, RegisterID base, RegisterID dst)
1153 {
1154 m_formatter.oneByteOp(opcode: OP_MOV_GvEv, reg: dst, base, offset);
1155 }
1156
1157 void movl_mr_disp32(int offset, RegisterID base, RegisterID dst)
1158 {
1159 m_formatter.oneByteOp_disp32(opcode: OP_MOV_GvEv, reg: dst, base, offset);
1160 }
1161
1162 void movl_mr_disp8(int offset, RegisterID base, RegisterID dst)
1163 {
1164 m_formatter.oneByteOp_disp8(opcode: OP_MOV_GvEv, reg: dst, base, offset);
1165 }
1166
1167 void movl_mr(int offset, RegisterID base, RegisterID index, int scale, RegisterID dst)
1168 {
1169 m_formatter.oneByteOp(opcode: OP_MOV_GvEv, reg: dst, base, index, scale, offset);
1170 }
1171
1172 void movl_i32r(int imm, RegisterID dst)
1173 {
1174 m_formatter.oneByteOp(opcode: OP_MOV_EAXIv, reg: dst);
1175 m_formatter.immediate32(imm);
1176 }
1177
1178 void movl_i32m(int imm, int offset, RegisterID base)
1179 {
1180 m_formatter.oneByteOp(opcode: OP_GROUP11_EvIz, reg: GROUP11_MOV, base, offset);
1181 m_formatter.immediate32(imm);
1182 }
1183
1184 void movl_i32m(int imm, int offset, RegisterID base, RegisterID index, int scale)
1185 {
1186 m_formatter.oneByteOp(opcode: OP_GROUP11_EvIz, reg: GROUP11_MOV, base, index, scale, offset);
1187 m_formatter.immediate32(imm);
1188 }
1189
1190#if !CPU(X86_64)
1191 void movb_i8m(int imm, const void* addr)
1192 {
1193 ASSERT(-128 <= imm && imm < 128);
1194 m_formatter.oneByteOp(OP_GROUP11_EvIb, GROUP11_MOV, addr);
1195 m_formatter.immediate8(imm);
1196 }
1197#endif
1198
1199 void movb_i8m(int imm, int offset, RegisterID base)
1200 {
1201 ASSERT(-128 <= imm && imm < 128);
1202 m_formatter.oneByteOp(opcode: OP_GROUP11_EvIb, reg: GROUP11_MOV, base, offset);
1203 m_formatter.immediate8(imm);
1204 }
1205
1206 void movb_i8m(int imm, int offset, RegisterID base, RegisterID index, int scale)
1207 {
1208 ASSERT(-128 <= imm && imm < 128);
1209 m_formatter.oneByteOp(opcode: OP_GROUP11_EvIb, reg: GROUP11_MOV, base, index, scale, offset);
1210 m_formatter.immediate8(imm);
1211 }
1212
1213 void movb_rm(RegisterID src, int offset, RegisterID base, RegisterID index, int scale)
1214 {
1215 m_formatter.oneByteOp8(opcode: OP_MOV_EbGb, reg: src, base, index, scale, offset);
1216 }
1217
1218 void movw_rm(RegisterID src, int offset, RegisterID base, RegisterID index, int scale)
1219 {
1220 m_formatter.prefix(pre: PRE_OPERAND_SIZE);
1221 m_formatter.oneByteOp8(opcode: OP_MOV_EvGv, reg: src, base, index, scale, offset);
1222 }
1223
1224 void movl_EAXm(const void* addr)
1225 {
1226 m_formatter.oneByteOp(opcode: OP_MOV_OvEAX);
1227#if CPU(X86_64)
1228 m_formatter.immediate64(imm: reinterpret_cast<int64_t>(addr));
1229#else
1230 m_formatter.immediate32(reinterpret_cast<int>(addr));
1231#endif
1232 }
1233
1234#if CPU(X86_64)
1235 void movq_rr(RegisterID src, RegisterID dst)
1236 {
1237 m_formatter.oneByteOp64(opcode: OP_MOV_EvGv, reg: src, rm: dst);
1238 }
1239
1240 void movq_rm(RegisterID src, int offset, RegisterID base)
1241 {
1242 m_formatter.oneByteOp64(opcode: OP_MOV_EvGv, reg: src, base, offset);
1243 }
1244
1245 void movq_rm_disp32(RegisterID src, int offset, RegisterID base)
1246 {
1247 m_formatter.oneByteOp64_disp32(opcode: OP_MOV_EvGv, reg: src, base, offset);
1248 }
1249
1250 void movq_rm(RegisterID src, int offset, RegisterID base, RegisterID index, int scale)
1251 {
1252 m_formatter.oneByteOp64(opcode: OP_MOV_EvGv, reg: src, base, index, scale, offset);
1253 }
1254
1255 void movq_mEAX(const void* addr)
1256 {
1257 m_formatter.oneByteOp64(opcode: OP_MOV_EAXOv);
1258 m_formatter.immediate64(imm: reinterpret_cast<int64_t>(addr));
1259 }
1260
1261 void movq_EAXm(const void* addr)
1262 {
1263 m_formatter.oneByteOp64(opcode: OP_MOV_OvEAX);
1264 m_formatter.immediate64(imm: reinterpret_cast<int64_t>(addr));
1265 }
1266
1267 void movq_mr(int offset, RegisterID base, RegisterID dst)
1268 {
1269 m_formatter.oneByteOp64(opcode: OP_MOV_GvEv, reg: dst, base, offset);
1270 }
1271
1272 void movq_mr_disp32(int offset, RegisterID base, RegisterID dst)
1273 {
1274 m_formatter.oneByteOp64_disp32(opcode: OP_MOV_GvEv, reg: dst, base, offset);
1275 }
1276
1277 void movq_mr_disp8(int offset, RegisterID base, RegisterID dst)
1278 {
1279 m_formatter.oneByteOp64_disp8(opcode: OP_MOV_GvEv, reg: dst, base, offset);
1280 }
1281
1282 void movq_mr(int offset, RegisterID base, RegisterID index, int scale, RegisterID dst)
1283 {
1284 m_formatter.oneByteOp64(opcode: OP_MOV_GvEv, reg: dst, base, index, scale, offset);
1285 }
1286
1287 void movq_i32m(int imm, int offset, RegisterID base)
1288 {
1289 m_formatter.oneByteOp64(opcode: OP_GROUP11_EvIz, reg: GROUP11_MOV, base, offset);
1290 m_formatter.immediate32(imm);
1291 }
1292
1293 void movq_i64r(int64_t imm, RegisterID dst)
1294 {
1295 m_formatter.oneByteOp64(opcode: OP_MOV_EAXIv, reg: dst);
1296 m_formatter.immediate64(imm);
1297 }
1298
1299 void movsxd_rr(RegisterID src, RegisterID dst)
1300 {
1301 m_formatter.oneByteOp64(opcode: OP_MOVSXD_GvEv, reg: dst, rm: src);
1302 }
1303
1304
1305#else
1306 void movl_rm(RegisterID src, const void* addr)
1307 {
1308 if (src == X86Registers::eax)
1309 movl_EAXm(addr);
1310 else
1311 m_formatter.oneByteOp(OP_MOV_EvGv, src, addr);
1312 }
1313
1314 void movl_mr(const void* addr, RegisterID dst)
1315 {
1316 if (dst == X86Registers::eax)
1317 movl_mEAX(addr);
1318 else
1319 m_formatter.oneByteOp(OP_MOV_GvEv, dst, addr);
1320 }
1321
1322 void movl_i32m(int imm, const void* addr)
1323 {
1324 m_formatter.oneByteOp(OP_GROUP11_EvIz, GROUP11_MOV, addr);
1325 m_formatter.immediate32(imm);
1326 }
1327#endif
1328
1329 void movzwl_mr(int offset, RegisterID base, RegisterID dst)
1330 {
1331 m_formatter.twoByteOp(opcode: OP2_MOVZX_GvEw, reg: dst, base, offset);
1332 }
1333
1334 void movzwl_mr(int offset, RegisterID base, RegisterID index, int scale, RegisterID dst)
1335 {
1336 m_formatter.twoByteOp(opcode: OP2_MOVZX_GvEw, reg: dst, base, index, scale, offset);
1337 }
1338
1339 void movswl_mr(int offset, RegisterID base, RegisterID dst)
1340 {
1341 m_formatter.twoByteOp(opcode: OP2_MOVSX_GvEw, reg: dst, base, offset);
1342 }
1343
1344 void movswl_mr(int offset, RegisterID base, RegisterID index, int scale, RegisterID dst)
1345 {
1346 m_formatter.twoByteOp(opcode: OP2_MOVSX_GvEw, reg: dst, base, index, scale, offset);
1347 }
1348
1349 void movzbl_mr(int offset, RegisterID base, RegisterID dst)
1350 {
1351 m_formatter.twoByteOp(opcode: OP2_MOVZX_GvEb, reg: dst, base, offset);
1352 }
1353
1354 void movzbl_mr(int offset, RegisterID base, RegisterID index, int scale, RegisterID dst)
1355 {
1356 m_formatter.twoByteOp(opcode: OP2_MOVZX_GvEb, reg: dst, base, index, scale, offset);
1357 }
1358
1359 void movsbl_mr(int offset, RegisterID base, RegisterID dst)
1360 {
1361 m_formatter.twoByteOp(opcode: OP2_MOVSX_GvEb, reg: dst, base, offset);
1362 }
1363
1364 void movsbl_mr(int offset, RegisterID base, RegisterID index, int scale, RegisterID dst)
1365 {
1366 m_formatter.twoByteOp(opcode: OP2_MOVSX_GvEb, reg: dst, base, index, scale, offset);
1367 }
1368
1369 void movzbl_rr(RegisterID src, RegisterID dst)
1370 {
1371 // In 64-bit, this may cause an unnecessary REX to be planted (if the dst register
1372 // is in the range ESP-EDI, and the src would not have required a REX). Unneeded
1373 // REX prefixes are defined to be silently ignored by the processor.
1374 m_formatter.twoByteOp8(opcode: OP2_MOVZX_GvEb, reg: dst, rm: src);
1375 }
1376
1377 void leal_mr(int offset, RegisterID base, RegisterID dst)
1378 {
1379 m_formatter.oneByteOp(opcode: OP_LEA, reg: dst, base, offset);
1380 }
1381
1382 void leal_mr(int offset, RegisterID base, RegisterID index, int scale, RegisterID dst)
1383 {
1384 m_formatter.oneByteOp(opcode: OP_LEA, reg: dst, base, index, scale, offset);
1385 }
1386
1387#if CPU(X86_64)
1388 void leaq_mr(int offset, RegisterID base, RegisterID dst)
1389 {
1390 m_formatter.oneByteOp64(opcode: OP_LEA, reg: dst, base, offset);
1391 }
1392
1393 void leaq_mr(int offset, RegisterID base, RegisterID index, int scale, RegisterID dst)
1394 {
1395 m_formatter.oneByteOp64(opcode: OP_LEA, reg: dst, base, index, scale, offset);
1396 }
1397#endif
1398
1399 // Flow control:
1400
1401 AssemblerLabel call()
1402 {
1403 m_formatter.oneByteOp(opcode: OP_CALL_rel32);
1404 return m_formatter.immediateRel32();
1405 }
1406
1407 AssemblerLabel call(RegisterID dst)
1408 {
1409 m_formatter.oneByteOp(opcode: OP_GROUP5_Ev, reg: GROUP5_OP_CALLN, rm: dst);
1410 return m_formatter.label();
1411 }
1412
1413 void call_m(int offset, RegisterID base)
1414 {
1415 m_formatter.oneByteOp(opcode: OP_GROUP5_Ev, reg: GROUP5_OP_CALLN, base, offset);
1416 }
1417
1418 AssemblerLabel jmp()
1419 {
1420 m_formatter.oneByteOp(opcode: OP_JMP_rel32);
1421 return m_formatter.immediateRel32();
1422 }
1423
1424 // Return a AssemblerLabel so we have a label to the jump, so we can use this
1425 // To make a tail recursive call on x86-64. The MacroAssembler
1426 // really shouldn't wrap this as a Jump, since it can't be linked. :-/
1427 AssemblerLabel jmp_r(RegisterID dst)
1428 {
1429 m_formatter.oneByteOp(opcode: OP_GROUP5_Ev, reg: GROUP5_OP_JMPN, rm: dst);
1430 return m_formatter.label();
1431 }
1432
1433 void jmp_m(int offset, RegisterID base)
1434 {
1435 m_formatter.oneByteOp(opcode: OP_GROUP5_Ev, reg: GROUP5_OP_JMPN, base, offset);
1436 }
1437
1438#if !CPU(X86_64)
1439 void jmp_m(const void* address)
1440 {
1441 m_formatter.oneByteOp(OP_GROUP5_Ev, GROUP5_OP_JMPN, address);
1442 }
1443#endif
1444
1445 AssemblerLabel jne()
1446 {
1447 m_formatter.twoByteOp(opcode: jccRel32(cond: ConditionNE));
1448 return m_formatter.immediateRel32();
1449 }
1450
1451 AssemblerLabel jnz()
1452 {
1453 return jne();
1454 }
1455
1456 AssemblerLabel je()
1457 {
1458 m_formatter.twoByteOp(opcode: jccRel32(cond: ConditionE));
1459 return m_formatter.immediateRel32();
1460 }
1461
1462 AssemblerLabel jz()
1463 {
1464 return je();
1465 }
1466
1467 AssemblerLabel jl()
1468 {
1469 m_formatter.twoByteOp(opcode: jccRel32(cond: ConditionL));
1470 return m_formatter.immediateRel32();
1471 }
1472
1473 AssemblerLabel jb()
1474 {
1475 m_formatter.twoByteOp(opcode: jccRel32(cond: ConditionB));
1476 return m_formatter.immediateRel32();
1477 }
1478
1479 AssemblerLabel jle()
1480 {
1481 m_formatter.twoByteOp(opcode: jccRel32(cond: ConditionLE));
1482 return m_formatter.immediateRel32();
1483 }
1484
1485 AssemblerLabel jbe()
1486 {
1487 m_formatter.twoByteOp(opcode: jccRel32(cond: ConditionBE));
1488 return m_formatter.immediateRel32();
1489 }
1490
1491 AssemblerLabel jge()
1492 {
1493 m_formatter.twoByteOp(opcode: jccRel32(cond: ConditionGE));
1494 return m_formatter.immediateRel32();
1495 }
1496
1497 AssemblerLabel jg()
1498 {
1499 m_formatter.twoByteOp(opcode: jccRel32(cond: ConditionG));
1500 return m_formatter.immediateRel32();
1501 }
1502
1503 AssemblerLabel ja()
1504 {
1505 m_formatter.twoByteOp(opcode: jccRel32(cond: ConditionA));
1506 return m_formatter.immediateRel32();
1507 }
1508
1509 AssemblerLabel jae()
1510 {
1511 m_formatter.twoByteOp(opcode: jccRel32(cond: ConditionAE));
1512 return m_formatter.immediateRel32();
1513 }
1514
1515 AssemblerLabel jo()
1516 {
1517 m_formatter.twoByteOp(opcode: jccRel32(cond: ConditionO));
1518 return m_formatter.immediateRel32();
1519 }
1520
1521 AssemblerLabel jnp()
1522 {
1523 m_formatter.twoByteOp(opcode: jccRel32(cond: ConditionNP));
1524 return m_formatter.immediateRel32();
1525 }
1526
1527 AssemblerLabel jp()
1528 {
1529 m_formatter.twoByteOp(opcode: jccRel32(cond: ConditionP));
1530 return m_formatter.immediateRel32();
1531 }
1532
1533 AssemblerLabel js()
1534 {
1535 m_formatter.twoByteOp(opcode: jccRel32(cond: ConditionS));
1536 return m_formatter.immediateRel32();
1537 }
1538
1539 AssemblerLabel jCC(Condition cond)
1540 {
1541 m_formatter.twoByteOp(opcode: jccRel32(cond));
1542 return m_formatter.immediateRel32();
1543 }
1544
1545 // SSE operations:
1546
1547 void addsd_rr(XMMRegisterID src, XMMRegisterID dst)
1548 {
1549 m_formatter.prefix(pre: PRE_SSE_F2);
1550 m_formatter.twoByteOp(opcode: OP2_ADDSD_VsdWsd, reg: (RegisterID)dst, rm: (RegisterID)src);
1551 }
1552
1553 void addsd_mr(int offset, RegisterID base, XMMRegisterID dst)
1554 {
1555 m_formatter.prefix(pre: PRE_SSE_F2);
1556 m_formatter.twoByteOp(opcode: OP2_ADDSD_VsdWsd, reg: (RegisterID)dst, base, offset);
1557 }
1558
1559#if !CPU(X86_64)
1560 void addsd_mr(const void* address, XMMRegisterID dst)
1561 {
1562 m_formatter.prefix(PRE_SSE_F2);
1563 m_formatter.twoByteOp(OP2_ADDSD_VsdWsd, (RegisterID)dst, address);
1564 }
1565#endif
1566
1567 void cvtsi2sd_rr(RegisterID src, XMMRegisterID dst)
1568 {
1569 m_formatter.prefix(pre: PRE_SSE_F2);
1570 m_formatter.twoByteOp(opcode: OP2_CVTSI2SD_VsdEd, reg: (RegisterID)dst, rm: src);
1571 }
1572
1573 void cvtsi2sd_mr(int offset, RegisterID base, XMMRegisterID dst)
1574 {
1575 m_formatter.prefix(pre: PRE_SSE_F2);
1576 m_formatter.twoByteOp(opcode: OP2_CVTSI2SD_VsdEd, reg: (RegisterID)dst, base, offset);
1577 }
1578
1579#if !CPU(X86_64)
1580 void cvtsi2sd_mr(const void* address, XMMRegisterID dst)
1581 {
1582 m_formatter.prefix(PRE_SSE_F2);
1583 m_formatter.twoByteOp(OP2_CVTSI2SD_VsdEd, (RegisterID)dst, address);
1584 }
1585#endif
1586
1587#if CPU(X86_64)
1588 void cvtsiq2sd_rr(RegisterID src, FPRegisterID dst)
1589 {
1590 m_formatter.prefix(pre: PRE_SSE_F2);
1591 m_formatter.twoByteOp64(opcode: OP2_CVTSI2SD_VsdEd, reg: (RegisterID)dst, rm: src);
1592 }
1593
1594#endif
1595
1596 void cvttsd2si_rr(XMMRegisterID src, RegisterID dst)
1597 {
1598 m_formatter.prefix(pre: PRE_SSE_F2);
1599 m_formatter.twoByteOp(opcode: OP2_CVTTSD2SI_GdWsd, reg: dst, rm: (RegisterID)src);
1600 }
1601
1602 void cvtsd2ss_rr(XMMRegisterID src, XMMRegisterID dst)
1603 {
1604 m_formatter.prefix(pre: PRE_SSE_F2);
1605 m_formatter.twoByteOp(opcode: OP2_CVTSD2SS_VsdWsd, reg: dst, rm: (RegisterID)src);
1606 }
1607
1608 void cvtss2sd_rr(XMMRegisterID src, XMMRegisterID dst)
1609 {
1610 m_formatter.prefix(pre: PRE_SSE_F3);
1611 m_formatter.twoByteOp(opcode: OP2_CVTSS2SD_VsdWsd, reg: dst, rm: (RegisterID)src);
1612 }
1613
1614#if CPU(X86_64)
1615 void cvttsd2siq_rr(XMMRegisterID src, RegisterID dst)
1616 {
1617 m_formatter.prefix(pre: PRE_SSE_F2);
1618 m_formatter.twoByteOp64(opcode: OP2_CVTTSD2SI_GdWsd, reg: dst, rm: (RegisterID)src);
1619 }
1620#endif
1621
1622 void movd_rr(XMMRegisterID src, RegisterID dst)
1623 {
1624 m_formatter.prefix(pre: PRE_SSE_66);
1625 m_formatter.twoByteOp(opcode: OP2_MOVD_EdVd, reg: (RegisterID)src, rm: dst);
1626 }
1627
1628 void movd_rr(RegisterID src, XMMRegisterID dst)
1629 {
1630 m_formatter.prefix(pre: PRE_SSE_66);
1631 m_formatter.twoByteOp(opcode: OP2_MOVD_VdEd, reg: (RegisterID)dst, rm: src);
1632 }
1633
1634#if CPU(X86_64)
1635 void movq_rr(XMMRegisterID src, RegisterID dst)
1636 {
1637 m_formatter.prefix(pre: PRE_SSE_66);
1638 m_formatter.twoByteOp64(opcode: OP2_MOVD_EdVd, reg: (RegisterID)src, rm: dst);
1639 }
1640
1641 void movq_rr(RegisterID src, XMMRegisterID dst)
1642 {
1643 m_formatter.prefix(pre: PRE_SSE_66);
1644 m_formatter.twoByteOp64(opcode: OP2_MOVD_VdEd, reg: (RegisterID)dst, rm: src);
1645 }
1646#endif
1647
1648 void movsd_rr(XMMRegisterID src, XMMRegisterID dst)
1649 {
1650 m_formatter.prefix(pre: PRE_SSE_F2);
1651 m_formatter.twoByteOp(opcode: OP2_MOVSD_VsdWsd, reg: (RegisterID)dst, rm: (RegisterID)src);
1652 }
1653
1654 void movsd_rm(XMMRegisterID src, int offset, RegisterID base)
1655 {
1656 m_formatter.prefix(pre: PRE_SSE_F2);
1657 m_formatter.twoByteOp(opcode: OP2_MOVSD_WsdVsd, reg: (RegisterID)src, base, offset);
1658 }
1659
1660 void movsd_rm(XMMRegisterID src, int offset, RegisterID base, RegisterID index, int scale)
1661 {
1662 m_formatter.prefix(pre: PRE_SSE_F2);
1663 m_formatter.twoByteOp(opcode: OP2_MOVSD_WsdVsd, reg: (RegisterID)src, base, index, scale, offset);
1664 }
1665
1666 void movss_rm(XMMRegisterID src, int offset, RegisterID base, RegisterID index, int scale)
1667 {
1668 m_formatter.prefix(pre: PRE_SSE_F3);
1669 m_formatter.twoByteOp(opcode: OP2_MOVSD_WsdVsd, reg: (RegisterID)src, base, index, scale, offset);
1670 }
1671
1672 void movsd_mr(int offset, RegisterID base, XMMRegisterID dst)
1673 {
1674 m_formatter.prefix(pre: PRE_SSE_F2);
1675 m_formatter.twoByteOp(opcode: OP2_MOVSD_VsdWsd, reg: (RegisterID)dst, base, offset);
1676 }
1677
1678 void movsd_mr(int offset, RegisterID base, RegisterID index, int scale, XMMRegisterID dst)
1679 {
1680 m_formatter.prefix(pre: PRE_SSE_F2);
1681 m_formatter.twoByteOp(opcode: OP2_MOVSD_VsdWsd, reg: dst, base, index, scale, offset);
1682 }
1683
1684 void movss_mr(int offset, RegisterID base, RegisterID index, int scale, XMMRegisterID dst)
1685 {
1686 m_formatter.prefix(pre: PRE_SSE_F3);
1687 m_formatter.twoByteOp(opcode: OP2_MOVSD_VsdWsd, reg: dst, base, index, scale, offset);
1688 }
1689
1690#if !CPU(X86_64)
1691 void movsd_mr(const void* address, XMMRegisterID dst)
1692 {
1693 m_formatter.prefix(PRE_SSE_F2);
1694 m_formatter.twoByteOp(OP2_MOVSD_VsdWsd, (RegisterID)dst, address);
1695 }
1696 void movsd_rm(XMMRegisterID src, const void* address)
1697 {
1698 m_formatter.prefix(PRE_SSE_F2);
1699 m_formatter.twoByteOp(OP2_MOVSD_WsdVsd, (RegisterID)src, address);
1700 }
1701#endif
1702
1703 void mulsd_rr(XMMRegisterID src, XMMRegisterID dst)
1704 {
1705 m_formatter.prefix(pre: PRE_SSE_F2);
1706 m_formatter.twoByteOp(opcode: OP2_MULSD_VsdWsd, reg: (RegisterID)dst, rm: (RegisterID)src);
1707 }
1708
1709 void mulsd_mr(int offset, RegisterID base, XMMRegisterID dst)
1710 {
1711 m_formatter.prefix(pre: PRE_SSE_F2);
1712 m_formatter.twoByteOp(opcode: OP2_MULSD_VsdWsd, reg: (RegisterID)dst, base, offset);
1713 }
1714
1715 void pextrw_irr(int whichWord, XMMRegisterID src, RegisterID dst)
1716 {
1717 m_formatter.prefix(pre: PRE_SSE_66);
1718 m_formatter.twoByteOp(opcode: OP2_PEXTRW_GdUdIb, reg: (RegisterID)dst, rm: (RegisterID)src);
1719 m_formatter.immediate8(imm: whichWord);
1720 }
1721
1722 void psllq_i8r(int imm, XMMRegisterID dst)
1723 {
1724 m_formatter.prefix(pre: PRE_SSE_66);
1725 m_formatter.twoByteOp8(opcode: OP2_PSLLQ_UdqIb, groupOp: GROUP14_OP_PSLLQ, rm: (RegisterID)dst);
1726 m_formatter.immediate8(imm);
1727 }
1728
1729 void psrlq_i8r(int imm, XMMRegisterID dst)
1730 {
1731 m_formatter.prefix(pre: PRE_SSE_66);
1732 m_formatter.twoByteOp8(opcode: OP2_PSRLQ_UdqIb, groupOp: GROUP14_OP_PSRLQ, rm: (RegisterID)dst);
1733 m_formatter.immediate8(imm);
1734 }
1735
1736 void por_rr(XMMRegisterID src, XMMRegisterID dst)
1737 {
1738 m_formatter.prefix(pre: PRE_SSE_66);
1739 m_formatter.twoByteOp(opcode: OP2_POR_VdqWdq, reg: (RegisterID)dst, rm: (RegisterID)src);
1740 }
1741
1742 void subsd_rr(XMMRegisterID src, XMMRegisterID dst)
1743 {
1744 m_formatter.prefix(pre: PRE_SSE_F2);
1745 m_formatter.twoByteOp(opcode: OP2_SUBSD_VsdWsd, reg: (RegisterID)dst, rm: (RegisterID)src);
1746 }
1747
1748 void subsd_mr(int offset, RegisterID base, XMMRegisterID dst)
1749 {
1750 m_formatter.prefix(pre: PRE_SSE_F2);
1751 m_formatter.twoByteOp(opcode: OP2_SUBSD_VsdWsd, reg: (RegisterID)dst, base, offset);
1752 }
1753
1754 void ucomisd_rr(XMMRegisterID src, XMMRegisterID dst)
1755 {
1756 m_formatter.prefix(pre: PRE_SSE_66);
1757 m_formatter.twoByteOp(opcode: OP2_UCOMISD_VsdWsd, reg: (RegisterID)dst, rm: (RegisterID)src);
1758 }
1759
1760 void ucomisd_mr(int offset, RegisterID base, XMMRegisterID dst)
1761 {
1762 m_formatter.prefix(pre: PRE_SSE_66);
1763 m_formatter.twoByteOp(opcode: OP2_UCOMISD_VsdWsd, reg: (RegisterID)dst, base, offset);
1764 }
1765
1766 void divsd_rr(XMMRegisterID src, XMMRegisterID dst)
1767 {
1768 m_formatter.prefix(pre: PRE_SSE_F2);
1769 m_formatter.twoByteOp(opcode: OP2_DIVSD_VsdWsd, reg: (RegisterID)dst, rm: (RegisterID)src);
1770 }
1771
1772 void divsd_mr(int offset, RegisterID base, XMMRegisterID dst)
1773 {
1774 m_formatter.prefix(pre: PRE_SSE_F2);
1775 m_formatter.twoByteOp(opcode: OP2_DIVSD_VsdWsd, reg: (RegisterID)dst, base, offset);
1776 }
1777
1778 void xorpd_rr(XMMRegisterID src, XMMRegisterID dst)
1779 {
1780 m_formatter.prefix(pre: PRE_SSE_66);
1781 m_formatter.twoByteOp(opcode: OP2_XORPD_VpdWpd, reg: (RegisterID)dst, rm: (RegisterID)src);
1782 }
1783
1784 void andnpd_rr(XMMRegisterID src, XMMRegisterID dst)
1785 {
1786 m_formatter.prefix(pre: PRE_SSE_66);
1787 m_formatter.twoByteOp(opcode: OP2_ANDNPD_VpdWpd, reg: (RegisterID)dst, rm: (RegisterID)src);
1788 }
1789
1790 void sqrtsd_rr(XMMRegisterID src, XMMRegisterID dst)
1791 {
1792 m_formatter.prefix(pre: PRE_SSE_F2);
1793 m_formatter.twoByteOp(opcode: OP2_SQRTSD_VsdWsd, reg: (RegisterID)dst, rm: (RegisterID)src);
1794 }
1795
1796 // Misc instructions:
1797
1798 void int3()
1799 {
1800 m_formatter.oneByteOp(opcode: OP_INT3);
1801 }
1802
1803 void ret()
1804 {
1805 m_formatter.oneByteOp(opcode: OP_RET);
1806 }
1807
1808 void predictNotTaken()
1809 {
1810 m_formatter.prefix(pre: PRE_PREDICT_BRANCH_NOT_TAKEN);
1811 }
1812
1813 // Assembler admin methods:
1814
1815 size_t codeSize() const
1816 {
1817 return m_formatter.codeSize();
1818 }
1819
1820 AssemblerLabel labelForWatchpoint()
1821 {
1822 AssemblerLabel result = m_formatter.label();
1823 if (static_cast<int>(result.m_offset) != m_indexOfLastWatchpoint)
1824 result = label();
1825 m_indexOfLastWatchpoint = result.m_offset;
1826 m_indexOfTailOfLastWatchpoint = result.m_offset + maxJumpReplacementSize();
1827 return result;
1828 }
1829
1830 AssemblerLabel labelIgnoringWatchpoints()
1831 {
1832 return m_formatter.label();
1833 }
1834
1835 AssemblerLabel label()
1836 {
1837 AssemblerLabel result = m_formatter.label();
1838 while (UNLIKELY(static_cast<int>(result.m_offset) < m_indexOfTailOfLastWatchpoint)) {
1839 nop();
1840 result = m_formatter.label();
1841 }
1842 return result;
1843 }
1844
1845 AssemblerLabel align(int alignment)
1846 {
1847 while (!m_formatter.isAligned(alignment))
1848 m_formatter.oneByteOp(opcode: OP_HLT);
1849
1850 return label();
1851 }
1852
1853 // Linking & patching:
1854 //
1855 // 'link' and 'patch' methods are for use on unprotected code - such as the code
1856 // within the AssemblerBuffer, and code being patched by the patch buffer. Once
1857 // code has been finalized it is (platform support permitting) within a non-
1858 // writable region of memory; to modify the code in an execute-only execuable
1859 // pool the 'repatch' and 'relink' methods should be used.
1860
1861 void linkJump(AssemblerLabel from, AssemblerLabel to)
1862 {
1863 ASSERT(from.isSet());
1864 ASSERT(to.isSet());
1865
1866 char* code = reinterpret_cast<char*>(m_formatter.data());
1867 ASSERT(!loadPossiblyUnaligned<int32_t>(code, from.m_offset, -1));
1868 setRel32(from: code + from.m_offset, to: code + to.m_offset);
1869 }
1870
1871 template<typename T>
1872 T loadPossiblyUnaligned(char *ptr, size_t offset, int idx)
1873 {
1874 T *t_ptr = &reinterpret_cast<T*>(ptr + offset)[idx];
1875 T val;
1876 memcpy(&val, t_ptr, sizeof(T));
1877 return val;
1878 }
1879
1880 static void linkJump(void* code, AssemblerLabel from, void* to)
1881 {
1882 ASSERT(from.isSet());
1883
1884 setRel32(from: reinterpret_cast<char*>(code) + from.m_offset, to);
1885 }
1886
1887 static void linkCall(void* code, AssemblerLabel from, void* to)
1888 {
1889 ASSERT(from.isSet());
1890
1891 setRel32(from: reinterpret_cast<char*>(code) + from.m_offset, to);
1892 }
1893
1894 static void linkPointer(void* code, AssemblerLabel where, void* value)
1895 {
1896 ASSERT(where.isSet());
1897
1898 setPointer(where: reinterpret_cast<char*>(code) + where.m_offset, value);
1899 }
1900
1901 static void relinkJump(void* from, void* to)
1902 {
1903 setRel32(from, to);
1904 }
1905
1906 static void relinkCall(void* from, void* to)
1907 {
1908 setRel32(from, to);
1909 }
1910
1911 static void repatchCompact(void* where, int32_t value)
1912 {
1913 ASSERT(value >= std::numeric_limits<int8_t>::min());
1914 ASSERT(value <= std::numeric_limits<int8_t>::max());
1915 setInt8(where, value);
1916 }
1917
1918 static void repatchInt32(void* where, int32_t value)
1919 {
1920 setInt32(where, value);
1921 }
1922
1923 static void repatchPointer(void* where, void* value)
1924 {
1925 setPointer(where, value);
1926 }
1927
1928 static void* readPointer(void* where)
1929 {
1930 return reinterpret_cast<void**>(where)[-1];
1931 }
1932
1933 static void replaceWithJump(void* instructionStart, void* to)
1934 {
1935 uint8_t* ptr = reinterpret_cast<uint8_t*>(instructionStart);
1936 uint8_t* dstPtr = reinterpret_cast<uint8_t*>(to);
1937 intptr_t distance = (intptr_t)(dstPtr - (ptr + 5));
1938 ptr[0] = static_cast<uint8_t>(OP_JMP_rel32);
1939 *reinterpret_cast<int32_t*>(ptr + 1) = static_cast<int32_t>(distance);
1940 }
1941
1942 static ptrdiff_t maxJumpReplacementSize()
1943 {
1944 return 5;
1945 }
1946
1947#if CPU(X86_64)
1948 static void revertJumpTo_movq_i64r(void* instructionStart, int64_t imm, RegisterID dst)
1949 {
1950 const int rexBytes = 1;
1951 const int opcodeBytes = 1;
1952 ASSERT(rexBytes + opcodeBytes <= maxJumpReplacementSize());
1953 uint8_t* ptr = reinterpret_cast<uint8_t*>(instructionStart);
1954 ptr[0] = PRE_REX | (1 << 3) | (dst >> 3);
1955 ptr[1] = OP_MOV_EAXIv | (dst & 7);
1956
1957 union {
1958 uint64_t asWord;
1959 uint8_t asBytes[8];
1960 } u;
1961 u.asWord = imm;
1962 for (unsigned i = rexBytes + opcodeBytes; i < static_cast<unsigned>(maxJumpReplacementSize()); ++i)
1963 ptr[i] = u.asBytes[i - rexBytes - opcodeBytes];
1964 }
1965#endif
1966
1967 static void revertJumpTo_cmpl_ir_force32(void* instructionStart, int32_t imm, RegisterID dst)
1968 {
1969 const int opcodeBytes = 1;
1970 const int modRMBytes = 1;
1971 ASSERT(opcodeBytes + modRMBytes <= maxJumpReplacementSize());
1972 uint8_t* ptr = reinterpret_cast<uint8_t*>(instructionStart);
1973 ptr[0] = OP_GROUP1_EvIz;
1974 ptr[1] = (X86InstructionFormatter::ModRmRegister << 6) | (GROUP1_OP_CMP << 3) | dst;
1975 union {
1976 uint32_t asWord;
1977 uint8_t asBytes[4];
1978 } u;
1979 u.asWord = imm;
1980 for (unsigned i = opcodeBytes + modRMBytes; i < static_cast<unsigned>(maxJumpReplacementSize()); ++i)
1981 ptr[i] = u.asBytes[i - opcodeBytes - modRMBytes];
1982 }
1983
1984 static void revertJumpTo_cmpl_im_force32(void* instructionStart, int32_t imm, int offset, RegisterID dst)
1985 {
1986 ASSERT_UNUSED(offset, !offset);
1987 const int opcodeBytes = 1;
1988 const int modRMBytes = 1;
1989 ASSERT(opcodeBytes + modRMBytes <= maxJumpReplacementSize());
1990 uint8_t* ptr = reinterpret_cast<uint8_t*>(instructionStart);
1991 ptr[0] = OP_GROUP1_EvIz;
1992 ptr[1] = (X86InstructionFormatter::ModRmMemoryNoDisp << 6) | (GROUP1_OP_CMP << 3) | dst;
1993 union {
1994 uint32_t asWord;
1995 uint8_t asBytes[4];
1996 } u;
1997 u.asWord = imm;
1998 for (unsigned i = opcodeBytes + modRMBytes; i < static_cast<unsigned>(maxJumpReplacementSize()); ++i)
1999 ptr[i] = u.asBytes[i - opcodeBytes - modRMBytes];
2000 }
2001
2002 static void replaceWithLoad(void* instructionStart)
2003 {
2004 uint8_t* ptr = reinterpret_cast<uint8_t*>(instructionStart);
2005#if CPU(X86_64)
2006 if ((*ptr & ~15) == PRE_REX)
2007 ptr++;
2008#endif
2009 switch (*ptr) {
2010 case OP_MOV_GvEv:
2011 break;
2012 case OP_LEA:
2013 *ptr = OP_MOV_GvEv;
2014 break;
2015 default:
2016 RELEASE_ASSERT_NOT_REACHED();
2017 }
2018 }
2019
2020 static void replaceWithAddressComputation(void* instructionStart)
2021 {
2022 uint8_t* ptr = reinterpret_cast<uint8_t*>(instructionStart);
2023#if CPU(X86_64)
2024 if ((*ptr & ~15) == PRE_REX)
2025 ptr++;
2026#endif
2027 switch (*ptr) {
2028 case OP_MOV_GvEv:
2029 *ptr = OP_LEA;
2030 break;
2031 case OP_LEA:
2032 break;
2033 default:
2034 RELEASE_ASSERT_NOT_REACHED();
2035 }
2036 }
2037
2038 static unsigned getCallReturnOffset(AssemblerLabel call)
2039 {
2040 ASSERT(call.isSet());
2041 return call.m_offset;
2042 }
2043
2044 static void* getRelocatedAddress(void* code, AssemblerLabel label)
2045 {
2046 ASSERT(label.isSet());
2047 return reinterpret_cast<void*>(reinterpret_cast<ptrdiff_t>(code) + label.m_offset);
2048 }
2049
2050 static int getDifferenceBetweenLabels(AssemblerLabel a, AssemblerLabel b)
2051 {
2052 return b.m_offset - a.m_offset;
2053 }
2054
2055 PassRefPtr<ExecutableMemoryHandle> executableCopy(JSGlobalData& globalData, void* ownerUID, JITCompilationEffort effort)
2056 {
2057 return m_formatter.executableCopy(globalData, ownerUID, effort);
2058 }
2059
2060 unsigned debugOffset() { return m_formatter.debugOffset(); }
2061
2062 void nop()
2063 {
2064 m_formatter.oneByteOp(opcode: OP_NOP);
2065 }
2066
2067 // This is a no-op on x86
2068 ALWAYS_INLINE static void cacheFlush(void*, size_t) { }
2069
2070private:
2071
2072 static void setPointer(void* where, void* value)
2073 {
2074 reinterpret_cast<void**>(where)[-1] = value;
2075 }
2076
2077 static void setInt32(void* where, int32_t value)
2078 {
2079 storePossiblyUnaligned<int32_t>(where, idx: -1, value);
2080 }
2081
2082 template <typename T>
2083 static void storePossiblyUnaligned(void *where, int idx, T value)
2084 {
2085 T *ptr = &reinterpret_cast<T*>(where)[idx];
2086 memcpy(ptr, &value, sizeof(T));
2087 }
2088
2089 static void setInt8(void* where, int8_t value)
2090 {
2091 reinterpret_cast<int8_t*>(where)[-1] = value;
2092 }
2093
2094 static void setRel32(void* from, void* to)
2095 {
2096 intptr_t offset = reinterpret_cast<intptr_t>(to) - reinterpret_cast<intptr_t>(from);
2097 ASSERT(offset == static_cast<int32_t>(offset));
2098
2099 setInt32(where: from, value: offset);
2100 }
2101
2102 class X86InstructionFormatter {
2103
2104 static const int maxInstructionSize = 16;
2105
2106 public:
2107
2108 enum ModRmMode {
2109 ModRmMemoryNoDisp,
2110 ModRmMemoryDisp8,
2111 ModRmMemoryDisp32,
2112 ModRmRegister,
2113 };
2114
2115 // Legacy prefix bytes:
2116 //
2117 // These are emmitted prior to the instruction.
2118
2119 void prefix(OneByteOpcodeID pre)
2120 {
2121 m_buffer.putByte(value: pre);
2122 }
2123
2124 // Word-sized operands / no operand instruction formatters.
2125 //
2126 // In addition to the opcode, the following operand permutations are supported:
2127 // * None - instruction takes no operands.
2128 // * One register - the low three bits of the RegisterID are added into the opcode.
2129 // * 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).
2130 // * Three argument ModRM - a register, and a register and an offset describing a memory operand.
2131 // * Five argument ModRM - a register, and a base register, an index, scale, and offset describing a memory operand.
2132 //
2133 // For 32-bit x86 targets, the address operand may also be provided as a void*.
2134 // On 64-bit targets REX prefixes will be planted as necessary, where high numbered registers are used.
2135 //
2136 // The twoByteOp methods plant two-byte Intel instructions sequences (first opcode byte 0x0F).
2137
2138 void oneByteOp(OneByteOpcodeID opcode)
2139 {
2140 m_buffer.ensureSpace(space: maxInstructionSize);
2141 m_buffer.putByteUnchecked(value: opcode);
2142 }
2143
2144 void oneByteOp(OneByteOpcodeID opcode, RegisterID reg)
2145 {
2146 m_buffer.ensureSpace(space: maxInstructionSize);
2147 emitRexIfNeeded(r: 0, x: 0, b: reg);
2148 m_buffer.putByteUnchecked(value: opcode + (reg & 7));
2149 }
2150
2151 void oneByteOp(OneByteOpcodeID opcode, int reg, RegisterID rm)
2152 {
2153 m_buffer.ensureSpace(space: maxInstructionSize);
2154 emitRexIfNeeded(r: reg, x: 0, b: rm);
2155 m_buffer.putByteUnchecked(value: opcode);
2156 registerModRM(reg, rm);
2157 }
2158
2159 void oneByteOp(OneByteOpcodeID opcode, int reg, RegisterID base, int offset)
2160 {
2161 m_buffer.ensureSpace(space: maxInstructionSize);
2162 emitRexIfNeeded(r: reg, x: 0, b: base);
2163 m_buffer.putByteUnchecked(value: opcode);
2164 memoryModRM(reg, base, offset);
2165 }
2166
2167 void oneByteOp_disp32(OneByteOpcodeID opcode, int reg, RegisterID base, int offset)
2168 {
2169 m_buffer.ensureSpace(space: maxInstructionSize);
2170 emitRexIfNeeded(r: reg, x: 0, b: base);
2171 m_buffer.putByteUnchecked(value: opcode);
2172 memoryModRM_disp32(reg, base, offset);
2173 }
2174
2175 void oneByteOp_disp8(OneByteOpcodeID opcode, int reg, RegisterID base, int offset)
2176 {
2177 m_buffer.ensureSpace(space: maxInstructionSize);
2178 emitRexIfNeeded(r: reg, x: 0, b: base);
2179 m_buffer.putByteUnchecked(value: opcode);
2180 memoryModRM_disp8(reg, base, offset);
2181 }
2182
2183 void oneByteOp(OneByteOpcodeID opcode, int reg, RegisterID base, RegisterID index, int scale, int offset)
2184 {
2185 m_buffer.ensureSpace(space: maxInstructionSize);
2186 emitRexIfNeeded(r: reg, x: index, b: base);
2187 m_buffer.putByteUnchecked(value: opcode);
2188 memoryModRM(reg, base, index, scale, offset);
2189 }
2190
2191#if !CPU(X86_64)
2192 void oneByteOp(OneByteOpcodeID opcode, int reg, const void* address)
2193 {
2194 m_buffer.ensureSpace(maxInstructionSize);
2195 m_buffer.putByteUnchecked(opcode);
2196 memoryModRM(reg, address);
2197 }
2198#endif
2199
2200 void twoByteOp(TwoByteOpcodeID opcode)
2201 {
2202 m_buffer.ensureSpace(space: maxInstructionSize);
2203 m_buffer.putByteUnchecked(value: OP_2BYTE_ESCAPE);
2204 m_buffer.putByteUnchecked(value: opcode);
2205 }
2206
2207 void twoByteOp(TwoByteOpcodeID opcode, int reg, RegisterID rm)
2208 {
2209 m_buffer.ensureSpace(space: maxInstructionSize);
2210 emitRexIfNeeded(r: reg, x: 0, b: rm);
2211 m_buffer.putByteUnchecked(value: OP_2BYTE_ESCAPE);
2212 m_buffer.putByteUnchecked(value: opcode);
2213 registerModRM(reg, rm);
2214 }
2215
2216 void twoByteOp(TwoByteOpcodeID opcode, int reg, RegisterID base, int offset)
2217 {
2218 m_buffer.ensureSpace(space: maxInstructionSize);
2219 emitRexIfNeeded(r: reg, x: 0, b: base);
2220 m_buffer.putByteUnchecked(value: OP_2BYTE_ESCAPE);
2221 m_buffer.putByteUnchecked(value: opcode);
2222 memoryModRM(reg, base, offset);
2223 }
2224
2225 void twoByteOp(TwoByteOpcodeID opcode, int reg, RegisterID base, RegisterID index, int scale, int offset)
2226 {
2227 m_buffer.ensureSpace(space: maxInstructionSize);
2228 emitRexIfNeeded(r: reg, x: index, b: base);
2229 m_buffer.putByteUnchecked(value: OP_2BYTE_ESCAPE);
2230 m_buffer.putByteUnchecked(value: opcode);
2231 memoryModRM(reg, base, index, scale, offset);
2232 }
2233
2234#if !CPU(X86_64)
2235 void twoByteOp(TwoByteOpcodeID opcode, int reg, const void* address)
2236 {
2237 m_buffer.ensureSpace(maxInstructionSize);
2238 m_buffer.putByteUnchecked(OP_2BYTE_ESCAPE);
2239 m_buffer.putByteUnchecked(opcode);
2240 memoryModRM(reg, address);
2241 }
2242#endif
2243
2244#if CPU(X86_64)
2245 // Quad-word-sized operands:
2246 //
2247 // Used to format 64-bit operantions, planting a REX.w prefix.
2248 // When planting d64 or f64 instructions, not requiring a REX.w prefix,
2249 // the normal (non-'64'-postfixed) formatters should be used.
2250
2251 void oneByteOp64(OneByteOpcodeID opcode)
2252 {
2253 m_buffer.ensureSpace(space: maxInstructionSize);
2254 emitRexW(r: 0, x: 0, b: 0);
2255 m_buffer.putByteUnchecked(value: opcode);
2256 }
2257
2258 void oneByteOp64(OneByteOpcodeID opcode, RegisterID reg)
2259 {
2260 m_buffer.ensureSpace(space: maxInstructionSize);
2261 emitRexW(r: 0, x: 0, b: reg);
2262 m_buffer.putByteUnchecked(value: opcode + (reg & 7));
2263 }
2264
2265 void oneByteOp64(OneByteOpcodeID opcode, int reg, RegisterID rm)
2266 {
2267 m_buffer.ensureSpace(space: maxInstructionSize);
2268 emitRexW(r: reg, x: 0, b: rm);
2269 m_buffer.putByteUnchecked(value: opcode);
2270 registerModRM(reg, rm);
2271 }
2272
2273 void oneByteOp64(OneByteOpcodeID opcode, int reg, RegisterID base, int offset)
2274 {
2275 m_buffer.ensureSpace(space: maxInstructionSize);
2276 emitRexW(r: reg, x: 0, b: base);
2277 m_buffer.putByteUnchecked(value: opcode);
2278 memoryModRM(reg, base, offset);
2279 }
2280
2281 void oneByteOp64_disp32(OneByteOpcodeID opcode, int reg, RegisterID base, int offset)
2282 {
2283 m_buffer.ensureSpace(space: maxInstructionSize);
2284 emitRexW(r: reg, x: 0, b: base);
2285 m_buffer.putByteUnchecked(value: opcode);
2286 memoryModRM_disp32(reg, base, offset);
2287 }
2288
2289 void oneByteOp64_disp8(OneByteOpcodeID opcode, int reg, RegisterID base, int offset)
2290 {
2291 m_buffer.ensureSpace(space: maxInstructionSize);
2292 emitRexW(r: reg, x: 0, b: base);
2293 m_buffer.putByteUnchecked(value: opcode);
2294 memoryModRM_disp8(reg, base, offset);
2295 }
2296
2297 void oneByteOp64(OneByteOpcodeID opcode, int reg, RegisterID base, RegisterID index, int scale, int offset)
2298 {
2299 m_buffer.ensureSpace(space: maxInstructionSize);
2300 emitRexW(r: reg, x: index, b: base);
2301 m_buffer.putByteUnchecked(value: opcode);
2302 memoryModRM(reg, base, index, scale, offset);
2303 }
2304
2305 void twoByteOp64(TwoByteOpcodeID opcode, int reg, RegisterID rm)
2306 {
2307 m_buffer.ensureSpace(space: maxInstructionSize);
2308 emitRexW(r: reg, x: 0, b: rm);
2309 m_buffer.putByteUnchecked(value: OP_2BYTE_ESCAPE);
2310 m_buffer.putByteUnchecked(value: opcode);
2311 registerModRM(reg, rm);
2312 }
2313#endif
2314
2315 // Byte-operands:
2316 //
2317 // These methods format byte operations. Byte operations differ from the normal
2318 // formatters in the circumstances under which they will decide to emit REX prefixes.
2319 // These should be used where any register operand signifies a byte register.
2320 //
2321 // The disctinction is due to the handling of register numbers in the range 4..7 on
2322 // x86-64. These register numbers may either represent the second byte of the first
2323 // four registers (ah..bh) or the first byte of the second four registers (spl..dil).
2324 //
2325 // Since ah..bh cannot be used in all permutations of operands (specifically cannot
2326 // be accessed where a REX prefix is present), these are likely best treated as
2327 // deprecated. In order to ensure the correct registers spl..dil are selected a
2328 // REX prefix will be emitted for any byte register operand in the range 4..15.
2329 //
2330 // These formatters may be used in instructions where a mix of operand sizes, in which
2331 // case an unnecessary REX will be emitted, for example:
2332 // movzbl %al, %edi
2333 // In this case a REX will be planted since edi is 7 (and were this a byte operand
2334 // a REX would be required to specify dil instead of bh). Unneeded REX prefixes will
2335 // be silently ignored by the processor.
2336 //
2337 // Address operands should still be checked using regRequiresRex(), while byteRegRequiresRex()
2338 // is provided to check byte register operands.
2339
2340 void oneByteOp8(OneByteOpcodeID opcode, GroupOpcodeID groupOp, RegisterID rm)
2341 {
2342 m_buffer.ensureSpace(space: maxInstructionSize);
2343 emitRexIf(condition: byteRegRequiresRex(reg: rm), r: 0, x: 0, b: rm);
2344 m_buffer.putByteUnchecked(value: opcode);
2345 registerModRM(reg: groupOp, rm);
2346 }
2347
2348 void oneByteOp8(OneByteOpcodeID opcode, int reg, RegisterID rm)
2349 {
2350 m_buffer.ensureSpace(space: maxInstructionSize);
2351 emitRexIf(condition: byteRegRequiresRex(reg) || byteRegRequiresRex(reg: rm), r: reg, x: 0, b: rm);
2352 m_buffer.putByteUnchecked(value: opcode);
2353 registerModRM(reg, rm);
2354 }
2355
2356 void oneByteOp8(OneByteOpcodeID opcode, int reg, RegisterID base, RegisterID index, int scale, int offset)
2357 {
2358 m_buffer.ensureSpace(space: maxInstructionSize);
2359 emitRexIf(condition: byteRegRequiresRex(reg) || regRequiresRex(reg: index) || regRequiresRex(reg: base), r: reg, x: index, b: base);
2360 m_buffer.putByteUnchecked(value: opcode);
2361 memoryModRM(reg, base, index, scale, offset);
2362 }
2363
2364 void twoByteOp8(TwoByteOpcodeID opcode, RegisterID reg, RegisterID rm)
2365 {
2366 m_buffer.ensureSpace(space: maxInstructionSize);
2367 emitRexIf(condition: byteRegRequiresRex(reg)|byteRegRequiresRex(reg: rm), r: reg, x: 0, b: rm);
2368 m_buffer.putByteUnchecked(value: OP_2BYTE_ESCAPE);
2369 m_buffer.putByteUnchecked(value: opcode);
2370 registerModRM(reg, rm);
2371 }
2372
2373 void twoByteOp8(TwoByteOpcodeID opcode, GroupOpcodeID groupOp, RegisterID rm)
2374 {
2375 m_buffer.ensureSpace(space: maxInstructionSize);
2376 emitRexIf(condition: byteRegRequiresRex(reg: rm), r: 0, x: 0, b: rm);
2377 m_buffer.putByteUnchecked(value: OP_2BYTE_ESCAPE);
2378 m_buffer.putByteUnchecked(value: opcode);
2379 registerModRM(reg: groupOp, rm);
2380 }
2381
2382 // Immediates:
2383 //
2384 // An immedaite should be appended where appropriate after an op has been emitted.
2385 // The writes are unchecked since the opcode formatters above will have ensured space.
2386
2387 void immediate8(int imm)
2388 {
2389 m_buffer.putByteUnchecked(value: imm);
2390 }
2391
2392 void immediate16(int imm)
2393 {
2394 m_buffer.putShortUnchecked(value: imm);
2395 }
2396
2397 void immediate32(int imm)
2398 {
2399 m_buffer.putIntUnchecked(value: imm);
2400 }
2401
2402 void immediate64(int64_t imm)
2403 {
2404 m_buffer.putInt64Unchecked(value: imm);
2405 }
2406
2407 AssemblerLabel immediateRel32()
2408 {
2409 m_buffer.putIntUnchecked(value: 0);
2410 return label();
2411 }
2412
2413 // Administrative methods:
2414
2415 size_t codeSize() const { return m_buffer.codeSize(); }
2416 AssemblerLabel label() const { return m_buffer.label(); }
2417 bool isAligned(int alignment) const { return m_buffer.isAligned(alignment); }
2418 void* data() const { return m_buffer.data(); }
2419
2420 PassRefPtr<ExecutableMemoryHandle> executableCopy(JSGlobalData& globalData, void* ownerUID, JITCompilationEffort effort)
2421 {
2422 return m_buffer.executableCopy(globalData, ownerUID, effort);
2423 }
2424
2425 unsigned debugOffset() { return m_buffer.debugOffset(); }
2426
2427 private:
2428
2429 // Internals; ModRm and REX formatters.
2430
2431 static const RegisterID noBase = X86Registers::ebp;
2432 static const RegisterID hasSib = X86Registers::esp;
2433 static const RegisterID noIndex = X86Registers::esp;
2434#if CPU(X86_64)
2435 static const RegisterID noBase2 = X86Registers::r13;
2436 static const RegisterID hasSib2 = X86Registers::r12;
2437
2438 // Registers r8 & above require a REX prefixe.
2439 inline bool regRequiresRex(int reg)
2440 {
2441 return (reg >= X86Registers::r8);
2442 }
2443
2444 // Byte operand register spl & above require a REX prefix (to prevent the 'H' registers be accessed).
2445 inline bool byteRegRequiresRex(int reg)
2446 {
2447 return (reg >= X86Registers::esp);
2448 }
2449
2450 // Format a REX prefix byte.
2451 inline void emitRex(bool w, int r, int x, int b)
2452 {
2453 ASSERT(r >= 0);
2454 ASSERT(x >= 0);
2455 ASSERT(b >= 0);
2456 m_buffer.putByteUnchecked(value: PRE_REX | ((int)w << 3) | ((r>>3)<<2) | ((x>>3)<<1) | (b>>3));
2457 }
2458
2459 // Used to plant a REX byte with REX.w set (for 64-bit operations).
2460 inline void emitRexW(int r, int x, int b)
2461 {
2462 emitRex(w: true, r, x, b);
2463 }
2464
2465 // Used for operations with byte operands - use byteRegRequiresRex() to check register operands,
2466 // regRequiresRex() to check other registers (i.e. address base & index).
2467 inline void emitRexIf(bool condition, int r, int x, int b)
2468 {
2469 if (condition) emitRex(w: false, r, x, b);
2470 }
2471
2472 // Used for word sized operations, will plant a REX prefix if necessary (if any register is r8 or above).
2473 inline void emitRexIfNeeded(int r, int x, int b)
2474 {
2475 emitRexIf(condition: regRequiresRex(reg: r) || regRequiresRex(reg: x) || regRequiresRex(reg: b), r, x, b);
2476 }
2477#else
2478 // No REX prefix bytes on 32-bit x86.
2479 inline bool regRequiresRex(int) { return false; }
2480 inline bool byteRegRequiresRex(int) { return false; }
2481 inline void emitRexIf(bool, int, int, int) {}
2482 inline void emitRexIfNeeded(int, int, int) {}
2483#endif
2484
2485 void putModRm(ModRmMode mode, int reg, RegisterID rm)
2486 {
2487 m_buffer.putByteUnchecked(value: (mode << 6) | ((reg & 7) << 3) | (rm & 7));
2488 }
2489
2490 void putModRmSib(ModRmMode mode, int reg, RegisterID base, RegisterID index, int scale)
2491 {
2492 ASSERT(mode != ModRmRegister);
2493
2494 putModRm(mode, reg, rm: hasSib);
2495 m_buffer.putByteUnchecked(value: (scale << 6) | ((index & 7) << 3) | (base & 7));
2496 }
2497
2498 void registerModRM(int reg, RegisterID rm)
2499 {
2500 putModRm(mode: ModRmRegister, reg, rm);
2501 }
2502
2503 void memoryModRM(int reg, RegisterID base, int offset)
2504 {
2505 // A base of esp or r12 would be interpreted as a sib, so force a sib with no index & put the base in there.
2506#if CPU(X86_64)
2507 if ((base == hasSib) || (base == hasSib2)) {
2508#else
2509 if (base == hasSib) {
2510#endif
2511 if (!offset) // No need to check if the base is noBase, since we know it is hasSib!
2512 putModRmSib(mode: ModRmMemoryNoDisp, reg, base, index: noIndex, scale: 0);
2513 else if (CAN_SIGN_EXTEND_8_32(value: offset)) {
2514 putModRmSib(mode: ModRmMemoryDisp8, reg, base, index: noIndex, scale: 0);
2515 m_buffer.putByteUnchecked(value: offset);
2516 } else {
2517 putModRmSib(mode: ModRmMemoryDisp32, reg, base, index: noIndex, scale: 0);
2518 m_buffer.putIntUnchecked(value: offset);
2519 }
2520 } else {
2521#if CPU(X86_64)
2522 if (!offset && (base != noBase) && (base != noBase2))
2523#else
2524 if (!offset && (base != noBase))
2525#endif
2526 putModRm(mode: ModRmMemoryNoDisp, reg, rm: base);
2527 else if (CAN_SIGN_EXTEND_8_32(value: offset)) {
2528 putModRm(mode: ModRmMemoryDisp8, reg, rm: base);
2529 m_buffer.putByteUnchecked(value: offset);
2530 } else {
2531 putModRm(mode: ModRmMemoryDisp32, reg, rm: base);
2532 m_buffer.putIntUnchecked(value: offset);
2533 }
2534 }
2535 }
2536
2537 void memoryModRM_disp8(int reg, RegisterID base, int offset)
2538 {
2539 // A base of esp or r12 would be interpreted as a sib, so force a sib with no index & put the base in there.
2540 ASSERT(CAN_SIGN_EXTEND_8_32(offset));
2541#if CPU(X86_64)
2542 if ((base == hasSib) || (base == hasSib2)) {
2543#else
2544 if (base == hasSib) {
2545#endif
2546 putModRmSib(mode: ModRmMemoryDisp8, reg, base, index: noIndex, scale: 0);
2547 m_buffer.putByteUnchecked(value: offset);
2548 } else {
2549 putModRm(mode: ModRmMemoryDisp8, reg, rm: base);
2550 m_buffer.putByteUnchecked(value: offset);
2551 }
2552 }
2553
2554 void memoryModRM_disp32(int reg, RegisterID base, int offset)
2555 {
2556 // A base of esp or r12 would be interpreted as a sib, so force a sib with no index & put the base in there.
2557#if CPU(X86_64)
2558 if ((base == hasSib) || (base == hasSib2)) {
2559#else
2560 if (base == hasSib) {
2561#endif
2562 putModRmSib(mode: ModRmMemoryDisp32, reg, base, index: noIndex, scale: 0);
2563 m_buffer.putIntUnchecked(value: offset);
2564 } else {
2565 putModRm(mode: ModRmMemoryDisp32, reg, rm: base);
2566 m_buffer.putIntUnchecked(value: offset);
2567 }
2568 }
2569
2570 void memoryModRM(int reg, RegisterID base, RegisterID index, int scale, int offset)
2571 {
2572 ASSERT(index != noIndex);
2573
2574#if CPU(X86_64)
2575 if (!offset && (base != noBase) && (base != noBase2))
2576#else
2577 if (!offset && (base != noBase))
2578#endif
2579 putModRmSib(mode: ModRmMemoryNoDisp, reg, base, index, scale);
2580 else if (CAN_SIGN_EXTEND_8_32(value: offset)) {
2581 putModRmSib(mode: ModRmMemoryDisp8, reg, base, index, scale);
2582 m_buffer.putByteUnchecked(value: offset);
2583 } else {
2584 putModRmSib(mode: ModRmMemoryDisp32, reg, base, index, scale);
2585 m_buffer.putIntUnchecked(value: offset);
2586 }
2587 }
2588
2589#if !CPU(X86_64)
2590 void memoryModRM(int reg, const void* address)
2591 {
2592 // noBase + ModRmMemoryNoDisp means noBase + ModRmMemoryDisp32!
2593 putModRm(ModRmMemoryNoDisp, reg, noBase);
2594 m_buffer.putIntUnchecked(reinterpret_cast<int32_t>(address));
2595 }
2596#endif
2597
2598 AssemblerBuffer m_buffer;
2599 } m_formatter;
2600 int m_indexOfLastWatchpoint;
2601 int m_indexOfTailOfLastWatchpoint;
2602};
2603
2604} // namespace JSC
2605
2606#endif // ENABLE(ASSEMBLER) && CPU(X86)
2607
2608#endif // X86Assembler_h
2609

source code of qtdeclarative/src/3rdparty/masm/assembler/X86Assembler.h