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 *reinterpret_cast<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))
180 typedef X86::RegisterID RegisterID;
181 typedef X86::XMMRegisterID XMMRegisterID;
187 OP_2BYTE_ESCAPE = 0x0F,
191 PRE_PREDICT_BRANCH_NOT_TAKEN = 0x2E,
197 PRE_OPERAND_SIZE = 0x66,
200 OP_IMUL_GvEvIz = 0x69,
201 OP_GROUP1_EvIz = 0x81,
202 OP_GROUP1_EvIb = 0x83,
207 OP_GROUP1A_Ev = 0x8F,
211 OP_GROUP2_EvIb = 0xC1,
213 OP_GROUP11_EvIz = 0xC7,
215 OP_GROUP2_Ev1 = 0xD1,
216 OP_GROUP2_EvCL = 0xD3,
217 OP_CALL_rel32 = 0xE8,
221 OP_GROUP3_EvIz = 0xF7, // OP_GROUP3_Ev has an immediate, when instruction is a test.
224 OP2_MOVSD_VsdWsd = 0x10,
225 OP2_MOVSD_WsdVsd = 0x11,
226 OP2_CVTSI2SD_VsdEd = 0x2A,
227 OP2_CVTTSD2SI_GdWsd = 0x2C,
228 OP2_UCOMISD_VsdWsd = 0x2E,
229 OP2_ADDSD_VsdWsd = 0x58,
230 OP2_MULSD_VsdWsd = 0x59,
231 OP2_SUBSD_VsdWsd = 0x5C,
232 OP2_MOVD_EdVd = 0x7E,
235 OP2_JAE_rel32 = 0x83,
237 OP2_JNE_rel32 = 0x85,
238 OP2_JBE_rel32 = 0x86,
243 OP2_JGE_rel32 = 0x8D,
244 OP2_JLE_rel32 = 0x8E,
246 OP2_IMUL_GvEv = 0xAF,
247 OP2_MOVZX_GvEb = 0xB6,
248 OP2_MOVZX_GvEw = 0xB7,
249 OP2_PEXTRW_GdUdIb = 0xC5,
273 static const int MAX_INSTRUCTION_SIZE = 16;
275 X86Assembler(JITCodeBuffer* m_buffer)
283 m_buffer->putByte(OP_INT3);
286 void pushl_r(RegisterID reg)
288 m_buffer->putByte(OP_PUSH_EAX + reg);
291 void pushl_m(int offset, RegisterID base)
293 m_buffer->putByte(OP_GROUP5_Ev);
294 emitModRm_opm(GROUP5_OP_PUSH, base, offset);
297 void pushl_i32(int imm)
299 m_buffer->putByte(OP_PUSH_Iz);
300 m_buffer->putInt(imm);
303 void popl_r(RegisterID reg)
305 m_buffer->putByte(OP_POP_EAX + reg);
308 void popl_m(int offset, RegisterID base)
310 m_buffer->putByte(OP_GROUP1A_Ev);
311 emitModRm_opm(GROUP1A_OP_POP, base, offset);
314 void movl_rr(RegisterID src, RegisterID dst)
316 m_buffer->putByte(OP_MOV_EvGv);
317 emitModRm_rr(src, dst);
320 void addl_rr(RegisterID src, RegisterID dst)
322 m_buffer->putByte(OP_ADD_EvGv);
323 emitModRm_rr(src, dst);
326 void addl_i8r(int imm, RegisterID dst)
328 m_buffer->putByte(OP_GROUP1_EvIb);
329 emitModRm_opr(GROUP1_OP_ADD, dst);
330 m_buffer->putByte(imm);
333 void addl_i8m(int imm, void* addr)
335 m_buffer->putByte(OP_GROUP1_EvIb);
336 emitModRm_opm(GROUP1_OP_ADD, addr);
337 m_buffer->putByte(imm);
340 void addl_i32r(int imm, RegisterID dst)
342 m_buffer->putByte(OP_GROUP1_EvIz);
343 emitModRm_opr(GROUP1_OP_ADD, dst);
344 m_buffer->putInt(imm);
347 void addl_mr(int offset, RegisterID base, RegisterID dst)
349 m_buffer->putByte(OP_ADD_GvEv);
350 emitModRm_rm(dst, base, offset);
353 void andl_rr(RegisterID src, RegisterID dst)
355 m_buffer->putByte(OP_AND_EvGv);
356 emitModRm_rr(src, dst);
359 void andl_i32r(int imm, RegisterID dst)
361 m_buffer->putByte(OP_GROUP1_EvIz);
362 emitModRm_opr(GROUP1_OP_AND, dst);
363 m_buffer->putInt(imm);
366 void cmpl_i8r(int imm, RegisterID dst)
368 m_buffer->putByte(OP_GROUP1_EvIb);
369 emitModRm_opr(GROUP1_OP_CMP, dst);
370 m_buffer->putByte(imm);
373 void cmpl_rr(RegisterID src, RegisterID dst)
375 m_buffer->putByte(OP_CMP_EvGv);
376 emitModRm_rr(src, dst);
379 void cmpl_rm(RegisterID src, int offset, RegisterID base)
381 m_buffer->putByte(OP_CMP_EvGv);
382 emitModRm_rm(src, base, offset);
385 void cmpl_mr(int offset, RegisterID base, RegisterID dst)
387 m_buffer->putByte(OP_CMP_GvEv);
388 emitModRm_rm(dst, base, offset);
391 void cmpl_i32r(int imm, RegisterID dst)
393 m_buffer->putByte(OP_GROUP1_EvIz);
394 emitModRm_opr(GROUP1_OP_CMP, dst);
395 m_buffer->putInt(imm);
398 void cmpl_i32m(int imm, RegisterID dst)
400 m_buffer->putByte(OP_GROUP1_EvIz);
401 emitModRm_opm(GROUP1_OP_CMP, dst);
402 m_buffer->putInt(imm);
405 void cmpl_i32m(int imm, int offset, RegisterID dst)
407 m_buffer->putByte(OP_GROUP1_EvIz);
408 emitModRm_opm(GROUP1_OP_CMP, dst, offset);
409 m_buffer->putInt(imm);
412 void cmpl_i32m(int imm, void* addr)
414 m_buffer->putByte(OP_GROUP1_EvIz);
415 emitModRm_opm(GROUP1_OP_CMP, addr);
416 m_buffer->putInt(imm);
419 void cmpl_i8m(int imm, int offset, RegisterID base, RegisterID index, int scale)
421 m_buffer->putByte(OP_GROUP1_EvIb);
422 emitModRm_opmsib(GROUP1_OP_CMP, base, index, scale, offset);
423 m_buffer->putByte(imm);
426 void cmpw_rm(RegisterID src, RegisterID base, RegisterID index, int scale)
428 m_buffer->putByte(PRE_OPERAND_SIZE);
429 m_buffer->putByte(OP_CMP_EvGv);
430 emitModRm_rmsib(src, base, index, scale);
433 void sete_r(RegisterID dst)
435 m_buffer->putByte(OP_2BYTE_ESCAPE);
436 m_buffer->putByte(OP_SETE);
437 m_buffer->putByte(MODRM(3, 0, dst));
440 void setz_r(RegisterID dst)
445 void setne_r(RegisterID dst)
447 m_buffer->putByte(OP_2BYTE_ESCAPE);
448 m_buffer->putByte(OP_SETNE);
449 m_buffer->putByte(MODRM(3, 0, dst));
452 void setnz_r(RegisterID dst)
457 void orl_rr(RegisterID src, RegisterID dst)
459 m_buffer->putByte(OP_OR_EvGv);
460 emitModRm_rr(src, dst);
463 void orl_mr(int offset, RegisterID base, RegisterID dst)
465 m_buffer->putByte(OP_OR_GvEv);
466 emitModRm_rm(dst, base, offset);
469 void orl_i32r(int imm, RegisterID dst)
471 m_buffer->putByte(OP_GROUP1_EvIb);
472 emitModRm_opr(GROUP1_OP_OR, dst);
473 m_buffer->putByte(imm);
476 void subl_rr(RegisterID src, RegisterID dst)
478 m_buffer->putByte(OP_SUB_EvGv);
479 emitModRm_rr(src, dst);
482 void subl_i8r(int imm, RegisterID dst)
484 m_buffer->putByte(OP_GROUP1_EvIb);
485 emitModRm_opr(GROUP1_OP_SUB, dst);
486 m_buffer->putByte(imm);
489 void subl_i8m(int imm, void* addr)
491 m_buffer->putByte(OP_GROUP1_EvIb);
492 emitModRm_opm(GROUP1_OP_SUB, addr);
493 m_buffer->putByte(imm);
496 void subl_i32r(int imm, RegisterID dst)
498 m_buffer->putByte(OP_GROUP1_EvIz);
499 emitModRm_opr(GROUP1_OP_SUB, dst);
500 m_buffer->putInt(imm);
503 void subl_mr(int offset, RegisterID base, RegisterID dst)
505 m_buffer->putByte(OP_SUB_GvEv);
506 emitModRm_rm(dst, base, offset);
509 void testl_i32r(int imm, RegisterID dst)
511 m_buffer->ensureSpace(MAX_INSTRUCTION_SIZE);
512 m_buffer->putByteUnchecked(OP_GROUP3_EvIz);
513 emitModRm_opr_Unchecked(GROUP3_OP_TEST, dst);
514 m_buffer->putIntUnchecked(imm);
517 void testl_i32m(int imm, RegisterID dst)
519 m_buffer->putByte(OP_GROUP3_EvIz);
520 emitModRm_opm(GROUP3_OP_TEST, dst);
521 m_buffer->putInt(imm);
524 void testl_i32m(int imm, int offset, RegisterID dst)
526 m_buffer->putByte(OP_GROUP3_EvIz);
527 emitModRm_opm(GROUP3_OP_TEST, dst, offset);
528 m_buffer->putInt(imm);
531 void testl_rr(RegisterID src, RegisterID dst)
533 m_buffer->putByte(OP_TEST_EvGv);
534 emitModRm_rr(src, dst);
537 void xorl_i8r(int imm, RegisterID dst)
539 m_buffer->putByte(OP_GROUP1_EvIb);
540 emitModRm_opr(GROUP1_OP_XOR, dst);
541 m_buffer->putByte(imm);
544 void xorl_rr(RegisterID src, RegisterID dst)
546 m_buffer->putByte(OP_XOR_EvGv);
547 emitModRm_rr(src, dst);
550 void sarl_i8r(int imm, RegisterID dst)
553 m_buffer->putByte(OP_GROUP2_Ev1);
554 emitModRm_opr(GROUP2_OP_SAR, dst);
556 m_buffer->putByte(OP_GROUP2_EvIb);
557 emitModRm_opr(GROUP2_OP_SAR, dst);
558 m_buffer->putByte(imm);
562 void sarl_CLr(RegisterID dst)
564 m_buffer->putByte(OP_GROUP2_EvCL);
565 emitModRm_opr(GROUP2_OP_SAR, dst);
568 void shl_i8r(int imm, RegisterID dst)
571 m_buffer->putByte(OP_GROUP2_Ev1);
572 emitModRm_opr(GROUP2_OP_SHL, dst);
574 m_buffer->putByte(OP_GROUP2_EvIb);
575 emitModRm_opr(GROUP2_OP_SHL, dst);
576 m_buffer->putByte(imm);
580 void shll_CLr(RegisterID dst)
582 m_buffer->putByte(OP_GROUP2_EvCL);
583 emitModRm_opr(GROUP2_OP_SHL, dst);
586 void imull_rr(RegisterID src, RegisterID dst)
588 m_buffer->putByte(OP_2BYTE_ESCAPE);
589 m_buffer->putByte(OP2_IMUL_GvEv);
590 emitModRm_rr(dst, src);
593 void imull_i32r(RegisterID src, int32_t value, RegisterID dst)
595 m_buffer->putByte(OP_IMUL_GvEvIz);
596 emitModRm_rr(dst, src);
597 m_buffer->putInt(value);
600 void idivl_r(RegisterID dst)
602 m_buffer->putByte(OP_GROUP3_Ev);
603 emitModRm_opr(GROUP3_OP_IDIV, dst);
608 m_buffer->putByte(OP_CDQ);
611 void movl_mr(RegisterID base, RegisterID dst)
613 m_buffer->putByte(OP_MOV_GvEv);
614 emitModRm_rm(dst, base);
617 void movl_mr(int offset, RegisterID base, RegisterID dst)
619 m_buffer->ensureSpace(MAX_INSTRUCTION_SIZE);
620 m_buffer->putByteUnchecked(OP_MOV_GvEv);
621 emitModRm_rm_Unchecked(dst, base, offset);
624 void movl_mr(void* addr, RegisterID dst)
626 m_buffer->putByte(OP_MOV_GvEv);
627 emitModRm_rm(dst, addr);
630 void movl_mr(int offset, RegisterID base, RegisterID index, int scale, RegisterID dst)
632 m_buffer->putByte(OP_MOV_GvEv);
633 emitModRm_rmsib(dst, base, index, scale, offset);
636 void movzbl_rr(RegisterID src, RegisterID dst)
638 m_buffer->putByte(OP_2BYTE_ESCAPE);
639 m_buffer->putByte(OP2_MOVZX_GvEb);
640 emitModRm_rr(dst, src);
643 void movzwl_mr(int offset, RegisterID base, RegisterID dst)
645 m_buffer->putByte(OP_2BYTE_ESCAPE);
646 m_buffer->putByte(OP2_MOVZX_GvEw);
647 emitModRm_rm(dst, base, offset);
650 void movzwl_mr(RegisterID base, RegisterID index, int scale, RegisterID dst)
652 m_buffer->putByte(OP_2BYTE_ESCAPE);
653 m_buffer->putByte(OP2_MOVZX_GvEw);
654 emitModRm_rmsib(dst, base, index, scale);
657 void movzwl_mr(int offset, RegisterID base, RegisterID index, int scale, RegisterID dst)
659 m_buffer->putByte(OP_2BYTE_ESCAPE);
660 m_buffer->putByte(OP2_MOVZX_GvEw);
661 emitModRm_rmsib(dst, base, index, scale, offset);
664 void movl_rm(RegisterID src, RegisterID base)
666 m_buffer->putByte(OP_MOV_EvGv);
667 emitModRm_rm(src, base);
670 void movl_rm(RegisterID src, int offset, RegisterID base)
672 m_buffer->ensureSpace(MAX_INSTRUCTION_SIZE);
673 m_buffer->putByteUnchecked(OP_MOV_EvGv);
674 emitModRm_rm_Unchecked(src, base, offset);
677 void movl_rm(RegisterID src, int offset, RegisterID base, RegisterID index, int scale)
679 m_buffer->putByte(OP_MOV_EvGv);
680 emitModRm_rmsib(src, base, index, scale, offset);
683 void movl_i32r(int imm, RegisterID dst)
685 m_buffer->putByte(OP_GROUP11_EvIz);
686 emitModRm_opr(GROUP11_MOV, dst);
687 m_buffer->putInt(imm);
690 void movl_i32m(int imm, int offset, RegisterID base)
692 m_buffer->ensureSpace(MAX_INSTRUCTION_SIZE);
693 m_buffer->putByteUnchecked(OP_GROUP11_EvIz);
694 emitModRm_opm_Unchecked(GROUP11_MOV, base, offset);
695 m_buffer->putIntUnchecked(imm);
698 void movl_i32m(int imm, void* addr)
700 m_buffer->putByte(OP_GROUP11_EvIz);
701 emitModRm_opm(GROUP11_MOV, addr);
702 m_buffer->putInt(imm);
705 void leal_mr(int offset, RegisterID base, RegisterID dst)
707 m_buffer->putByte(OP_LEA);
708 emitModRm_rm(dst, base, offset);
711 void leal_mr(int offset, RegisterID index, int scale, RegisterID dst)
713 m_buffer->putByte(OP_LEA);
714 emitModRm_rmsib(dst, X86::noBase, index, scale, offset);
719 m_buffer->putByte(OP_RET);
722 void jmp_r(RegisterID dst)
724 m_buffer->putByte(OP_GROUP5_Ev);
725 emitModRm_opr(GROUP5_OP_JMPN, dst);
728 void jmp_m(int offset, RegisterID base)
730 m_buffer->putByte(OP_GROUP5_Ev);
731 emitModRm_opm(GROUP5_OP_JMPN, base, offset);
734 void movsd_mr(int offset, RegisterID base, XMMRegisterID dst)
736 m_buffer->putByte(PRE_SSE_F2);
737 m_buffer->putByte(OP_2BYTE_ESCAPE);
738 m_buffer->putByte(OP2_MOVSD_VsdWsd);
739 emitModRm_rm((RegisterID)dst, base, offset);
742 void movsd_rm(XMMRegisterID src, int offset, RegisterID base)
744 m_buffer->putByte(PRE_SSE_F2);
745 m_buffer->putByte(OP_2BYTE_ESCAPE);
746 m_buffer->putByte(OP2_MOVSD_WsdVsd);
747 emitModRm_rm((RegisterID)src, base, offset);
750 void movd_rr(XMMRegisterID src, RegisterID dst)
752 m_buffer->putByte(PRE_SSE_66);
753 m_buffer->putByte(OP_2BYTE_ESCAPE);
754 m_buffer->putByte(OP2_MOVD_EdVd);
755 emitModRm_rr((RegisterID)src, dst);
758 void cvtsi2sd_rr(RegisterID src, XMMRegisterID dst)
760 m_buffer->putByte(PRE_SSE_F2);
761 m_buffer->putByte(OP_2BYTE_ESCAPE);
762 m_buffer->putByte(OP2_CVTSI2SD_VsdEd);
763 emitModRm_rr((RegisterID)dst, src);
766 void cvttsd2si_rr(XMMRegisterID src, RegisterID dst)
768 m_buffer->putByte(PRE_SSE_F2);
769 m_buffer->putByte(OP_2BYTE_ESCAPE);
770 m_buffer->putByte(OP2_CVTTSD2SI_GdWsd);
771 emitModRm_rr(dst, (RegisterID)src);
774 void addsd_mr(int offset, RegisterID base, XMMRegisterID dst)
776 m_buffer->putByte(PRE_SSE_F2);
777 m_buffer->putByte(OP_2BYTE_ESCAPE);
778 m_buffer->putByte(OP2_ADDSD_VsdWsd);
779 emitModRm_rm((RegisterID)dst, base, offset);
782 void subsd_mr(int offset, RegisterID base, XMMRegisterID dst)
784 m_buffer->putByte(PRE_SSE_F2);
785 m_buffer->putByte(OP_2BYTE_ESCAPE);
786 m_buffer->putByte(OP2_SUBSD_VsdWsd);
787 emitModRm_rm((RegisterID)dst, base, offset);
790 void mulsd_mr(int offset, RegisterID base, XMMRegisterID dst)
792 m_buffer->putByte(PRE_SSE_F2);
793 m_buffer->putByte(OP_2BYTE_ESCAPE);
794 m_buffer->putByte(OP2_MULSD_VsdWsd);
795 emitModRm_rm((RegisterID)dst, base, offset);
798 void addsd_rr(XMMRegisterID src, XMMRegisterID dst)
800 m_buffer->putByte(PRE_SSE_F2);
801 m_buffer->putByte(OP_2BYTE_ESCAPE);
802 m_buffer->putByte(OP2_ADDSD_VsdWsd);
803 emitModRm_rr((RegisterID)dst, (RegisterID)src);
806 void subsd_rr(XMMRegisterID src, XMMRegisterID dst)
808 m_buffer->putByte(PRE_SSE_F2);
809 m_buffer->putByte(OP_2BYTE_ESCAPE);
810 m_buffer->putByte(OP2_SUBSD_VsdWsd);
811 emitModRm_rr((RegisterID)dst, (RegisterID)src);
814 void mulsd_rr(XMMRegisterID src, XMMRegisterID dst)
816 m_buffer->putByte(PRE_SSE_F2);
817 m_buffer->putByte(OP_2BYTE_ESCAPE);
818 m_buffer->putByte(OP2_MULSD_VsdWsd);
819 emitModRm_rr((RegisterID)dst, (RegisterID)src);
822 void ucomis_rr(XMMRegisterID src, XMMRegisterID dst)
824 m_buffer->putByte(PRE_SSE_66);
825 m_buffer->putByte(OP_2BYTE_ESCAPE);
826 m_buffer->putByte(OP2_UCOMISD_VsdWsd);
827 emitModRm_rr((RegisterID)dst, (RegisterID)src);
830 void pextrw_irr(int whichWord, XMMRegisterID src, RegisterID dst)
832 m_buffer->putByte(PRE_SSE_66);
833 m_buffer->putByte(OP_2BYTE_ESCAPE);
834 m_buffer->putByte(OP2_PEXTRW_GdUdIb);
835 emitModRm_rr(dst, (RegisterID)src);
836 m_buffer->putByte(whichWord);
839 // Opaque label types
842 friend class X86Assembler;
859 friend class X86Assembler;
875 // FIXME: make this point to a global label, linked later.
878 m_buffer->putByte(OP_CALL_rel32);
880 return JmpSrc(m_buffer->getOffset());
883 JmpSrc emitCall(RegisterID dst)
885 m_buffer->putByte(OP_GROUP5_Ev);
886 emitModRm_opr(GROUP5_OP_CALLN, dst);
887 return JmpSrc(m_buffer->getOffset());
892 return JmpDst(m_buffer->getOffset());
895 JmpSrc emitUnlinkedJmp()
897 m_buffer->putByte(OP_JMP_rel32);
899 return JmpSrc(m_buffer->getOffset());
902 JmpSrc emitUnlinkedJne()
904 m_buffer->putByte(OP_2BYTE_ESCAPE);
905 m_buffer->putByte(OP2_JNE_rel32);
907 return JmpSrc(m_buffer->getOffset());
910 JmpSrc emitUnlinkedJnz()
912 return emitUnlinkedJne();
915 JmpSrc emitUnlinkedJe()
917 m_buffer->ensureSpace(MAX_INSTRUCTION_SIZE);
918 m_buffer->putByteUnchecked(OP_2BYTE_ESCAPE);
919 m_buffer->putByteUnchecked(OP2_JE_rel32);
920 m_buffer->putIntUnchecked(0);
921 return JmpSrc(m_buffer->getOffset());
924 JmpSrc emitUnlinkedJl()
926 m_buffer->putByte(OP_2BYTE_ESCAPE);
927 m_buffer->putByte(OP2_JL_rel32);
929 return JmpSrc(m_buffer->getOffset());
932 JmpSrc emitUnlinkedJb()
934 m_buffer->putByte(OP_2BYTE_ESCAPE);
935 m_buffer->putByte(OP2_JB_rel32);
937 return JmpSrc(m_buffer->getOffset());
940 JmpSrc emitUnlinkedJle()
942 m_buffer->putByte(OP_2BYTE_ESCAPE);
943 m_buffer->putByte(OP2_JLE_rel32);
945 return JmpSrc(m_buffer->getOffset());
948 JmpSrc emitUnlinkedJbe()
950 m_buffer->putByte(OP_2BYTE_ESCAPE);
951 m_buffer->putByte(OP2_JBE_rel32);
953 return JmpSrc(m_buffer->getOffset());
956 JmpSrc emitUnlinkedJge()
958 m_buffer->putByte(OP_2BYTE_ESCAPE);
959 m_buffer->putByte(OP2_JGE_rel32);
961 return JmpSrc(m_buffer->getOffset());
964 JmpSrc emitUnlinkedJg()
966 m_buffer->putByte(OP_2BYTE_ESCAPE);
967 m_buffer->putByte(OP2_JG_rel32);
969 return JmpSrc(m_buffer->getOffset());
972 JmpSrc emitUnlinkedJa()
974 m_buffer->putByte(OP_2BYTE_ESCAPE);
975 m_buffer->putByte(OP2_JA_rel32);
977 return JmpSrc(m_buffer->getOffset());
980 JmpSrc emitUnlinkedJae()
982 m_buffer->putByte(OP_2BYTE_ESCAPE);
983 m_buffer->putByte(OP2_JAE_rel32);
985 return JmpSrc(m_buffer->getOffset());
988 JmpSrc emitUnlinkedJo()
990 m_buffer->putByte(OP_2BYTE_ESCAPE);
991 m_buffer->putByte(OP2_JO_rel32);
993 return JmpSrc(m_buffer->getOffset());
996 JmpSrc emitUnlinkedJp()
998 m_buffer->putByte(OP_2BYTE_ESCAPE);
999 m_buffer->putByte(OP2_JP_rel32);
1000 m_buffer->putInt(0);
1001 return JmpSrc(m_buffer->getOffset());
1004 JmpSrc emitUnlinkedJs()
1006 m_buffer->putByte(OP_2BYTE_ESCAPE);
1007 m_buffer->putByte(OP2_JS_rel32);
1008 m_buffer->putInt(0);
1009 return JmpSrc(m_buffer->getOffset());
1012 void emitPredictionNotTaken()
1014 m_buffer->putByte(PRE_PREDICT_BRANCH_NOT_TAKEN);
1017 void link(JmpSrc from, JmpDst to)
1019 ASSERT(to.m_offset != -1);
1020 ASSERT(from.m_offset != -1);
1022 reinterpret_cast<int*>(reinterpret_cast<ptrdiff_t>(m_buffer->start()) + from.m_offset)[-1] = to.m_offset - from.m_offset;
1025 static void linkAbsoluteAddress(void* code, JmpDst useOffset, JmpDst address)
1027 ASSERT(useOffset.m_offset != -1);
1028 ASSERT(address.m_offset != -1);
1030 reinterpret_cast<int*>(reinterpret_cast<ptrdiff_t>(code) + useOffset.m_offset)[-1] = reinterpret_cast<ptrdiff_t>(code) + address.m_offset;
1033 static void link(void* code, JmpSrc from, void* to)
1035 ASSERT(from.m_offset != -1);
1037 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);
1040 static void* getRelocatedAddress(void* code, JmpSrc jump)
1042 return reinterpret_cast<void*>(reinterpret_cast<ptrdiff_t>(code) + jump.m_offset);
1045 static void* getRelocatedAddress(void* code, JmpDst jump)
1047 return reinterpret_cast<void*>(reinterpret_cast<ptrdiff_t>(code) + jump.m_offset);
1050 static int getDifferenceBetweenLabels(JmpDst src, JmpDst dst)
1052 return dst.m_offset - src.m_offset;
1055 static int getDifferenceBetweenLabels(JmpDst src, JmpSrc dst)
1057 return dst.m_offset - src.m_offset;
1060 static void repatchImmediate(intptr_t where, int32_t value)
1062 reinterpret_cast<int32_t*>(where)[-1] = value;
1065 static void repatchDisplacement(intptr_t where, intptr_t value)
1067 reinterpret_cast<intptr_t*>(where)[-1] = value;
1070 static void repatchBranchOffset(intptr_t where, void* destination)
1072 reinterpret_cast<intptr_t*>(where)[-1] = (reinterpret_cast<intptr_t>(destination) - where);
1077 return m_buffer->copy();
1081 void emitConvertToFastCall()
1083 movl_mr(4, X86::esp, X86::eax);
1084 movl_mr(8, X86::esp, X86::edx);
1085 movl_mr(12, X86::esp, X86::ecx);
1088 void emitConvertToFastCall() {}
1091 #if USE(CTI_ARGUMENT)
1092 void emitRestoreArgumentReference()
1094 #if USE(FAST_CALL_CTI_ARGUMENT)
1095 movl_rr(X86::esp, X86::ecx);
1097 movl_rm(X86::esp, 0, X86::esp);
1101 void emitRestoreArgumentReferenceForTrampoline()
1103 #if USE(FAST_CALL_CTI_ARGUMENT)
1104 movl_rr(X86::esp, X86::ecx);
1105 addl_i32r(4, X86::ecx);
1109 void emitRestoreArgumentReference() {}
1110 void emitRestoreArgumentReferenceForTrampoline() {}
1114 void emitModRm_rr(RegisterID reg, RegisterID rm)
1116 m_buffer->ensureSpace(MAX_INSTRUCTION_SIZE);
1117 emitModRm_rr_Unchecked(reg, rm);
1120 void emitModRm_rr_Unchecked(RegisterID reg, RegisterID rm)
1122 m_buffer->putByteUnchecked(MODRM(3, reg, rm));
1125 void emitModRm_rm(RegisterID reg, void* addr)
1127 m_buffer->putByte(MODRM(0, reg, X86::noBase));
1128 m_buffer->putInt((int)addr);
1131 void emitModRm_rm(RegisterID reg, RegisterID base)
1133 if (base == X86::esp) {
1134 m_buffer->putByte(MODRM(0, reg, X86::hasSib));
1135 m_buffer->putByte(SIB(0, X86::noScale, X86::esp));
1137 m_buffer->putByte(MODRM(0, reg, base));
1140 void emitModRm_rm_Unchecked(RegisterID reg, RegisterID base, int offset)
1142 if (base == X86::esp) {
1143 if (CAN_SIGN_EXTEND_8_32(offset)) {
1144 m_buffer->putByteUnchecked(MODRM(1, reg, X86::hasSib));
1145 m_buffer->putByteUnchecked(SIB(0, X86::noScale, X86::esp));
1146 m_buffer->putByteUnchecked(offset);
1148 m_buffer->putByteUnchecked(MODRM(2, reg, X86::hasSib));
1149 m_buffer->putByteUnchecked(SIB(0, X86::noScale, X86::esp));
1150 m_buffer->putIntUnchecked(offset);
1153 if (CAN_SIGN_EXTEND_8_32(offset)) {
1154 m_buffer->putByteUnchecked(MODRM(1, reg, base));
1155 m_buffer->putByteUnchecked(offset);
1157 m_buffer->putByteUnchecked(MODRM(2, reg, base));
1158 m_buffer->putIntUnchecked(offset);
1163 void emitModRm_rm(RegisterID reg, RegisterID base, int offset)
1165 m_buffer->ensureSpace(MAX_INSTRUCTION_SIZE);
1166 emitModRm_rm_Unchecked(reg, base, offset);
1169 void emitModRm_rmsib(RegisterID reg, RegisterID base, RegisterID index, int scale)
1175 m_buffer->putByte(MODRM(0, reg, X86::hasSib));
1176 m_buffer->putByte(SIB(shift, index, base));
1179 void emitModRm_rmsib(RegisterID reg, RegisterID base, RegisterID index, int scale, int offset)
1185 if (CAN_SIGN_EXTEND_8_32(offset)) {
1186 m_buffer->putByte(MODRM(1, reg, X86::hasSib));
1187 m_buffer->putByte(SIB(shift, index, base));
1188 m_buffer->putByte(offset);
1190 m_buffer->putByte(MODRM(2, reg, X86::hasSib));
1191 m_buffer->putByte(SIB(shift, index, base));
1192 m_buffer->putInt(offset);
1196 void emitModRm_opr(OpcodeID opcode, RegisterID rm)
1198 m_buffer->ensureSpace(MAX_INSTRUCTION_SIZE);
1199 emitModRm_opr_Unchecked(opcode, rm);
1202 void emitModRm_opr_Unchecked(OpcodeID opcode, RegisterID rm)
1204 emitModRm_rr_Unchecked(static_cast<RegisterID>(opcode), rm);
1207 void emitModRm_opm(OpcodeID opcode, RegisterID base)
1209 emitModRm_rm(static_cast<RegisterID>(opcode), base);
1212 void emitModRm_opm_Unchecked(OpcodeID opcode, RegisterID base, int offset)
1214 emitModRm_rm_Unchecked(static_cast<RegisterID>(opcode), base, offset);
1217 void emitModRm_opm(OpcodeID opcode, RegisterID base, int offset)
1219 emitModRm_rm(static_cast<RegisterID>(opcode), base, offset);
1222 void emitModRm_opm(OpcodeID opcode, void* addr)
1224 emitModRm_rm(static_cast<RegisterID>(opcode), addr);
1227 void emitModRm_opmsib(OpcodeID opcode, RegisterID base, RegisterID index, int scale, int offset)
1229 emitModRm_rmsib(static_cast<RegisterID>(opcode), base, index, scale, offset);
1232 JITCodeBuffer* m_buffer;
1237 #endif // ENABLE(MASM) && PLATFORM(X86)
1239 #endif // X86Assembler_h