2 * Copyright (C) 2008 Apple Inc. All rights reserved.
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions
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.
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.
26 #ifndef X86Assembler_h
27 #define X86Assembler_h
29 #if ENABLE(MASM) && PLATFORM(X86)
31 #include <wtf/Assertions.h>
32 #include <wtf/AlwaysInline.h>
43 JITCodeBuffer(int size)
44 : m_buffer(static_cast<char*>(fastMalloc(size)))
55 void ensureSpace(int space)
57 if (m_index > m_size - space)
61 void putByteUnchecked(int value)
63 m_buffer[m_index] = value;
67 void putByte(int value)
69 if (m_index > m_size - 4)
71 putByteUnchecked(value);
74 void putShortUnchecked(int value)
76 *(short*)(&m_buffer[m_index]) = value;
80 void putShort(int value)
82 if (m_index > m_size - 4)
84 putShortUnchecked(value);
87 void putIntUnchecked(int value)
89 *(int*)(&m_buffer[m_index]) = value;
93 void putInt(int value)
95 if (m_index > m_size - 4)
97 putIntUnchecked(value);
102 return m_buffer + m_index;
115 JITCodeBuffer* reset()
126 void* result = fastMalloc(m_index);
131 return memcpy(result, m_buffer, m_index);
137 m_size += m_size / 2;
138 m_buffer = static_cast<char*>(fastRealloc(m_buffer, m_size));
146 #define MODRM(type, reg, rm) ((type << 6) | (reg << 3) | (rm))
147 #define SIB(type, reg, rm) MODRM(type, reg, rm)
148 #define CAN_SIGN_EXTEND_8_32(value) (value == ((int)(signed char)value))
171 OP_2BYTE_ESCAPE = 0x0F,
175 PRE_PREDICT_BRANCH_NOT_TAKEN = 0x2E,
180 PRE_OPERAND_SIZE = 0x66,
181 OP_GROUP1_EvIz = 0x81,
182 OP_GROUP1_EvIb = 0x83,
187 OP_GROUP1A_Ev = 0x8F,
189 OP_GROUP2_EvIb = 0xC1,
191 OP_GROUP11_EvIz = 0xC7,
193 OP_GROUP2_Ev1 = 0xD1,
194 OP_GROUP2_EvCL = 0xD3,
195 OP_CALL_rel32 = 0xE8,
198 OP_GROUP3_EvIz = 0xF7, // OP_GROUP3_Ev has an immediate, when instruction is a test.
203 OP2_JAE_rel32 = 0x83,
205 OP2_JNE_rel32 = 0x85,
206 OP2_JBE_rel32 = 0x86,
208 OP2_JGE_rel32 = 0x8D,
209 OP2_JLE_rel32 = 0x8E,
211 OP2_MOVZX_GvEw = 0xB7,
235 static const int MAX_INSTRUCTION_SIZE = 16;
237 X86Assembler(JITCodeBuffer* m_buffer)
245 m_buffer->putByte(OP_INT3);
248 void emitPushl_r(RegisterID reg)
250 m_buffer->putByte(OP_PUSH_EAX + reg);
253 void emitPushl_m(int offset, RegisterID base)
255 m_buffer->putByte(OP_GROUP5_Ev);
256 emitModRm_opm(GROUP5_OP_PUSH, base, offset);
259 void emitPopl_r(RegisterID reg)
261 m_buffer->putByte(OP_POP_EAX + reg);
264 void emitPopl_m(int offset, RegisterID base)
266 m_buffer->putByte(OP_GROUP1A_Ev);
267 emitModRm_opm(GROUP1A_OP_POP, base, offset);
270 void emitMovl_rr(RegisterID src, RegisterID dst)
272 m_buffer->putByte(OP_MOV_EvGv);
273 emitModRm_rr(src, dst);
276 void emitAddl_rr(RegisterID src, RegisterID dst)
278 m_buffer->putByte(OP_ADD_EvGv);
279 emitModRm_rr(src, dst);
282 void emitAddl_i8r(int imm, RegisterID dst)
284 m_buffer->putByte(OP_GROUP1_EvIb);
285 emitModRm_opr(GROUP1_OP_ADD, dst);
286 m_buffer->putByte(imm);
289 void emitAddl_i32r(int imm, RegisterID dst)
291 m_buffer->putByte(OP_GROUP1_EvIz);
292 emitModRm_opr(GROUP1_OP_ADD, dst);
293 m_buffer->putInt(imm);
296 void emitAddl_mr(int offset, RegisterID base, RegisterID dst)
298 m_buffer->putByte(OP_ADD_GvEv);
299 emitModRm_rm(dst, base, offset);
302 void emitAndl_rr(RegisterID src, RegisterID dst)
304 m_buffer->putByte(OP_AND_EvGv);
305 emitModRm_rr(src, dst);
308 void emitAndl_i32r(int imm, RegisterID dst)
310 m_buffer->putByte(OP_GROUP1_EvIz);
311 emitModRm_opr(GROUP1_OP_AND, dst);
312 m_buffer->putInt(imm);
315 void emitCmpl_i8r(int imm, RegisterID dst)
317 m_buffer->putByte(OP_GROUP1_EvIb);
318 emitModRm_opr(GROUP1_OP_CMP, dst);
319 m_buffer->putByte(imm);
322 void emitCmpl_rr(RegisterID src, RegisterID dst)
324 m_buffer->putByte(OP_CMP_EvGv);
325 emitModRm_rr(src, dst);
328 void emitCmpl_rm(RegisterID src, int offset, RegisterID base)
330 m_buffer->putByte(OP_CMP_EvGv);
331 emitModRm_rm(src, base, offset);
334 void emitCmpl_i32r(int imm, RegisterID dst)
336 m_buffer->putByte(OP_GROUP1_EvIz);
337 emitModRm_opr(GROUP1_OP_CMP, dst);
338 m_buffer->putInt(imm);
341 void emitCmpl_i32m(int imm, RegisterID dst)
343 m_buffer->putByte(OP_GROUP1_EvIz);
344 emitModRm_opm(GROUP1_OP_CMP, dst);
345 m_buffer->putInt(imm);
348 void emitCmpl_i32m(int imm, int offset, RegisterID dst)
350 m_buffer->putByte(OP_GROUP1_EvIz);
351 emitModRm_opm(GROUP1_OP_CMP, dst, offset);
352 m_buffer->putInt(imm);
355 void emitCmpl_i32m(int imm, void* addr)
357 m_buffer->putByte(OP_GROUP1_EvIz);
358 emitModRm_opm(GROUP1_OP_CMP, addr);
359 m_buffer->putInt(imm);
362 void emitCmpw_rm(RegisterID src, RegisterID base, RegisterID index, int scale)
364 m_buffer->putByte(PRE_OPERAND_SIZE);
365 m_buffer->putByte(OP_CMP_EvGv);
366 emitModRm_rmsib(src, base, index, scale);
369 void emitOrl_rr(RegisterID src, RegisterID dst)
371 m_buffer->putByte(OP_OR_EvGv);
372 emitModRm_rr(src, dst);
375 void emitOrl_i8r(int imm, RegisterID dst)
377 m_buffer->putByte(OP_GROUP1_EvIb);
378 emitModRm_opr(GROUP1_OP_OR, dst);
379 m_buffer->putByte(imm);
382 void emitSubl_rr(RegisterID src, RegisterID dst)
384 m_buffer->putByte(OP_SUB_EvGv);
385 emitModRm_rr(src, dst);
388 void emitSubl_i8r(int imm, RegisterID dst)
390 m_buffer->putByte(OP_GROUP1_EvIb);
391 emitModRm_opr(GROUP1_OP_SUB, dst);
392 m_buffer->putByte(imm);
395 void emitSubl_i32r(int imm, RegisterID dst)
397 m_buffer->putByte(OP_GROUP1_EvIz);
398 emitModRm_opr(GROUP1_OP_SUB, dst);
399 m_buffer->putInt(imm);
402 void emitSubl_mr(int offset, RegisterID base, RegisterID dst)
404 m_buffer->putByte(OP_SUB_GvEv);
405 emitModRm_rm(dst, base, offset);
408 void emitTestl_i32r(int imm, RegisterID dst)
410 m_buffer->ensureSpace(MAX_INSTRUCTION_SIZE);
411 m_buffer->putByteUnchecked(OP_GROUP3_EvIz);
412 emitModRm_opr_Unchecked(GROUP3_OP_TEST, dst);
413 m_buffer->putIntUnchecked(imm);
416 void emitTestl_rr(RegisterID src, RegisterID dst)
418 m_buffer->putByte(OP_TEST_EvGv);
419 emitModRm_rr(src, dst);
422 void emitXorl_i8r(int imm, RegisterID dst)
424 m_buffer->putByte(OP_GROUP1_EvIb);
425 emitModRm_opr(GROUP1_OP_XOR, dst);
426 m_buffer->putByte(imm);
429 void emitXorl_rr(RegisterID src, RegisterID dst)
431 m_buffer->putByte(OP_XOR_EvGv);
432 emitModRm_rr(src, dst);
435 void emitSarl_i8r(int imm, RegisterID dst)
438 m_buffer->putByte(OP_GROUP2_Ev1);
439 emitModRm_opr(GROUP2_OP_SAR, dst);
441 m_buffer->putByte(OP_GROUP2_EvIb);
442 emitModRm_opr(GROUP2_OP_SAR, dst);
443 m_buffer->putByte(imm);
447 void emitSarl_CLr(RegisterID dst)
449 m_buffer->putByte(OP_GROUP2_EvCL);
450 emitModRm_opr(GROUP2_OP_SAR, dst);
453 void emitShl_i8r(int imm, RegisterID dst)
456 m_buffer->putByte(OP_GROUP2_Ev1);
457 emitModRm_opr(GROUP2_OP_SHL, dst);
459 m_buffer->putByte(OP_GROUP2_EvIb);
460 emitModRm_opr(GROUP2_OP_SHL, dst);
461 m_buffer->putByte(imm);
465 void emitShll_CLr(RegisterID dst)
467 m_buffer->putByte(OP_GROUP2_EvCL);
468 emitModRm_opr(GROUP2_OP_SHL, dst);
471 void emitMull_rr(RegisterID src, RegisterID dst)
473 m_buffer->putByte(OP_2BYTE_ESCAPE);
474 m_buffer->putByte(OP2_MUL_GvEv);
475 emitModRm_rr(dst, src);
478 void emitIdivl_r(RegisterID dst)
480 m_buffer->putByte(OP_GROUP3_Ev);
481 emitModRm_opr(GROUP3_OP_IDIV, dst);
486 m_buffer->putByte(OP_CDQ);
489 void emitMovl_mr(RegisterID base, RegisterID dst)
491 m_buffer->putByte(OP_MOV_GvEv);
492 emitModRm_rm(dst, base);
495 void emitMovl_mr(int offset, RegisterID base, RegisterID dst)
497 m_buffer->ensureSpace(MAX_INSTRUCTION_SIZE);
498 m_buffer->putByteUnchecked(OP_MOV_GvEv);
499 emitModRm_rm_Unchecked(dst, base, offset);
502 void emitMovl_mr(void* addr, RegisterID dst)
504 m_buffer->putByte(OP_MOV_GvEv);
505 emitModRm_rm(dst, addr);
508 void emitMovl_mr(int offset, RegisterID base, RegisterID index, int scale, RegisterID dst)
510 m_buffer->putByte(OP_MOV_GvEv);
511 emitModRm_rmsib(dst, base, index, scale, offset);
514 void emitMovzwl_mr(int offset, RegisterID base, RegisterID dst)
516 m_buffer->putByte(OP_2BYTE_ESCAPE);
517 m_buffer->putByte(OP2_MOVZX_GvEw);
518 emitModRm_rm(dst, base, offset);
521 void emitMovzwl_mr(RegisterID base, RegisterID index, int scale, RegisterID dst)
523 m_buffer->putByte(OP_2BYTE_ESCAPE);
524 m_buffer->putByte(OP2_MOVZX_GvEw);
525 emitModRm_rmsib(dst, base, index, scale);
528 void emitMovzwl_mr(int offset, RegisterID base, RegisterID index, int scale, RegisterID dst)
530 m_buffer->putByte(OP_2BYTE_ESCAPE);
531 m_buffer->putByte(OP2_MOVZX_GvEw);
532 emitModRm_rmsib(dst, base, index, scale, offset);
535 void emitMovl_rm(RegisterID src, RegisterID base)
537 m_buffer->putByte(OP_MOV_EvGv);
538 emitModRm_rm(src, base);
541 void emitMovl_rm(RegisterID src, int offset, RegisterID base)
543 m_buffer->ensureSpace(MAX_INSTRUCTION_SIZE);
544 m_buffer->putByteUnchecked(OP_MOV_EvGv);
545 emitModRm_rm_Unchecked(src, base, offset);
548 void emitMovl_rm(RegisterID src, int offset, RegisterID base, RegisterID index, int scale)
550 m_buffer->putByte(OP_MOV_EvGv);
551 emitModRm_rmsib(src, base, index, scale, offset);
554 void emitMovl_i32r(int imm, RegisterID dst)
556 m_buffer->putByte(OP_GROUP11_EvIz);
557 emitModRm_opr(GROUP11_MOV, dst);
558 m_buffer->putInt(imm);
561 void emitMovl_i32m(int imm, int offset, RegisterID base)
563 m_buffer->ensureSpace(MAX_INSTRUCTION_SIZE);
564 m_buffer->putByteUnchecked(OP_GROUP11_EvIz);
565 emitModRm_opm_Unchecked(GROUP11_MOV, base, offset);
566 m_buffer->putIntUnchecked(imm);
569 void emitMovl_i32m(int imm, void* addr)
571 m_buffer->putByte(OP_GROUP11_EvIz);
572 emitModRm_opm(GROUP11_MOV, addr);
573 m_buffer->putInt(imm);
576 void emitLeal_mr(int offset, RegisterID base, RegisterID dst)
578 m_buffer->putByte(OP_LEA);
579 emitModRm_rm(dst, base, offset);
584 m_buffer->putByte(OP_RET);
587 void emitJmpN_r(RegisterID dst)
589 m_buffer->putByte(OP_GROUP5_Ev);
590 emitModRm_opr(GROUP5_OP_JMPN, dst);
593 void emitJmpN_m(int offset, RegisterID base)
595 m_buffer->putByte(OP_GROUP5_Ev);
596 emitModRm_opm(GROUP5_OP_JMPN, base, offset);
599 void emitCallN_r(RegisterID dst)
601 m_buffer->putByte(OP_GROUP5_Ev);
602 emitModRm_opr(GROUP5_OP_CALLN, dst);
605 // Opaque label types
608 friend class X86Assembler;
625 friend class X86Assembler;
641 // FIXME: make this point to a global label, linked later.
644 m_buffer->putByte(OP_CALL_rel32);
646 return JmpSrc(m_buffer->getOffset());
651 return JmpDst(m_buffer->getOffset());
654 JmpSrc emitUnlinkedJmp()
656 m_buffer->putByte(OP_JMP_rel32);
658 return JmpSrc(m_buffer->getOffset());
661 JmpSrc emitUnlinkedJne()
663 m_buffer->putByte(OP_2BYTE_ESCAPE);
664 m_buffer->putByte(OP2_JNE_rel32);
666 return JmpSrc(m_buffer->getOffset());
669 JmpSrc emitUnlinkedJe()
671 m_buffer->ensureSpace(MAX_INSTRUCTION_SIZE);
672 m_buffer->putByteUnchecked(OP_2BYTE_ESCAPE);
673 m_buffer->putByteUnchecked(OP2_JE_rel32);
674 m_buffer->putIntUnchecked(0);
675 return JmpSrc(m_buffer->getOffset());
678 JmpSrc emitUnlinkedJl()
680 m_buffer->putByte(OP_2BYTE_ESCAPE);
681 m_buffer->putByte(OP2_JL_rel32);
683 return JmpSrc(m_buffer->getOffset());
686 JmpSrc emitUnlinkedJb()
688 m_buffer->putByte(OP_2BYTE_ESCAPE);
689 m_buffer->putByte(OP2_JB_rel32);
691 return JmpSrc(m_buffer->getOffset());
694 JmpSrc emitUnlinkedJle()
696 m_buffer->putByte(OP_2BYTE_ESCAPE);
697 m_buffer->putByte(OP2_JLE_rel32);
699 return JmpSrc(m_buffer->getOffset());
702 JmpSrc emitUnlinkedJbe()
704 m_buffer->putByte(OP_2BYTE_ESCAPE);
705 m_buffer->putByte(OP2_JBE_rel32);
707 return JmpSrc(m_buffer->getOffset());
710 JmpSrc emitUnlinkedJge()
712 m_buffer->putByte(OP_2BYTE_ESCAPE);
713 m_buffer->putByte(OP2_JGE_rel32);
715 return JmpSrc(m_buffer->getOffset());
718 JmpSrc emitUnlinkedJae()
720 m_buffer->putByte(OP_2BYTE_ESCAPE);
721 m_buffer->putByte(OP2_JAE_rel32);
723 return JmpSrc(m_buffer->getOffset());
726 JmpSrc emitUnlinkedJo()
728 m_buffer->putByte(OP_2BYTE_ESCAPE);
729 m_buffer->putByte(OP2_JO_rel32);
731 return JmpSrc(m_buffer->getOffset());
734 void emitPredictionNotTaken()
736 m_buffer->putByte(PRE_PREDICT_BRANCH_NOT_TAKEN);
739 void link(JmpSrc from, JmpDst to)
741 ASSERT(to.m_offset != -1);
742 ASSERT(from.m_offset != -1);
744 ((int*)(((ptrdiff_t)(m_buffer->start())) + from.m_offset))[-1] = to.m_offset - from.m_offset;
747 static void linkAbsoluteAddress(void* code, JmpDst useOffset, JmpDst address)
749 ASSERT(useOffset.m_offset != -1);
750 ASSERT(address.m_offset != -1);
752 ((int*)(((ptrdiff_t)code) + useOffset.m_offset))[-1] = ((ptrdiff_t)code) + address.m_offset;
755 static void link(void* code, JmpSrc from, void* to)
757 ASSERT(from.m_offset != -1);
759 ((int*)((ptrdiff_t)code + from.m_offset))[-1] = (ptrdiff_t)to - ((ptrdiff_t)code + from.m_offset);
762 void* getRelocatedAddress(void* code, JmpSrc jump)
764 return reinterpret_cast<void*>((ptrdiff_t)code + jump.m_offset);
767 void* getRelocatedAddress(void* code, JmpDst jump)
769 return reinterpret_cast<void*>((ptrdiff_t)code + jump.m_offset);
774 return m_buffer->copy();
778 void emitModRm_rr(RegisterID reg, RegisterID rm)
780 m_buffer->ensureSpace(MAX_INSTRUCTION_SIZE);
781 emitModRm_rr_Unchecked(reg, rm);
784 void emitModRm_rr_Unchecked(RegisterID reg, RegisterID rm)
786 m_buffer->putByteUnchecked(MODRM(3, reg, rm));
789 void emitModRm_rm(RegisterID reg, void* addr)
791 m_buffer->putByte(MODRM(0, reg, NO_BASE));
792 m_buffer->putInt((int)addr);
795 void emitModRm_rm(RegisterID reg, RegisterID base)
798 m_buffer->putByte(MODRM(0, reg, HAS_SIB));
799 m_buffer->putByte(SIB(0, NO_SCALE, esp));
801 m_buffer->putByte(MODRM(0, reg, base));
804 void emitModRm_rm_Unchecked(RegisterID reg, RegisterID base, int offset)
807 if (CAN_SIGN_EXTEND_8_32(offset)) {
808 m_buffer->putByteUnchecked(MODRM(1, reg, HAS_SIB));
809 m_buffer->putByteUnchecked(SIB(0, NO_SCALE, esp));
810 m_buffer->putByteUnchecked(offset);
812 m_buffer->putByteUnchecked(MODRM(2, reg, HAS_SIB));
813 m_buffer->putByteUnchecked(SIB(0, NO_SCALE, esp));
814 m_buffer->putIntUnchecked(offset);
817 if (CAN_SIGN_EXTEND_8_32(offset)) {
818 m_buffer->putByteUnchecked(MODRM(1, reg, base));
819 m_buffer->putByteUnchecked(offset);
821 m_buffer->putByteUnchecked(MODRM(2, reg, base));
822 m_buffer->putIntUnchecked(offset);
827 void emitModRm_rm(RegisterID reg, RegisterID base, int offset)
829 m_buffer->ensureSpace(MAX_INSTRUCTION_SIZE);
830 emitModRm_rm_Unchecked(reg, base, offset);
833 void emitModRm_rmsib(RegisterID reg, RegisterID base, RegisterID index, int scale)
839 m_buffer->putByte(MODRM(0, reg, HAS_SIB));
840 m_buffer->putByte(SIB(shift, index, base));
843 void emitModRm_rmsib(RegisterID reg, RegisterID base, RegisterID index, int scale, int offset)
849 if (CAN_SIGN_EXTEND_8_32(offset)) {
850 m_buffer->putByte(MODRM(1, reg, HAS_SIB));
851 m_buffer->putByte(SIB(shift, index, base));
852 m_buffer->putByte(offset);
854 m_buffer->putByte(MODRM(2, reg, HAS_SIB));
855 m_buffer->putByte(SIB(shift, index, base));
856 m_buffer->putInt(offset);
860 void emitModRm_opr(OpcodeID opcode, RegisterID rm)
862 m_buffer->ensureSpace(MAX_INSTRUCTION_SIZE);
863 emitModRm_opr_Unchecked(opcode, rm);
866 void emitModRm_opr_Unchecked(OpcodeID opcode, RegisterID rm)
868 emitModRm_rr_Unchecked(static_cast<RegisterID>(opcode), rm);
871 void emitModRm_opm(OpcodeID opcode, RegisterID base)
873 emitModRm_rm(static_cast<RegisterID>(opcode), base);
876 void emitModRm_opm_Unchecked(OpcodeID opcode, RegisterID base, int offset)
878 emitModRm_rm_Unchecked(static_cast<RegisterID>(opcode), base, offset);
881 void emitModRm_opm(OpcodeID opcode, RegisterID base, int offset)
883 emitModRm_rm(static_cast<RegisterID>(opcode), base, offset);
886 void emitModRm_opm(OpcodeID opcode, void* addr)
888 emitModRm_rm(static_cast<RegisterID>(opcode), addr);
891 JITCodeBuffer* m_buffer;
896 #endif // ENABLE(MASM) && PLATFORM(X86)
898 #endif // X86Assembler_h