source: webkit/trunk/JavaScriptCore/assembler/X86Assembler.h@ 39428

Last change on this file since 39428 was 39428, checked in by [email protected], 16 years ago

2008-12-21 Gavin Barraclough <[email protected]>

Reviewed by Oliver Hunt & Cameron Zwarich.

Add support for call and property access repatching on x86-64.

No change in performance on current configurations (2x impovement on v8-tests with JIT enabled on x86-64).

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