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))
169 typedef X86::RegisterID RegisterID;
175 OP_2BYTE_ESCAPE = 0x0F,
179 PRE_PREDICT_BRANCH_NOT_TAKEN = 0x2E,
184 PRE_OPERAND_SIZE = 0x66,
185 OP_IMUL_GvEvIz = 0x69,
186 OP_GROUP1_EvIz = 0x81,
187 OP_GROUP1_EvIb = 0x83,
192 OP_GROUP1A_Ev = 0x8F,
194 OP_GROUP2_EvIb = 0xC1,
196 OP_GROUP11_EvIz = 0xC7,
198 OP_GROUP2_Ev1 = 0xD1,
199 OP_GROUP2_EvCL = 0xD3,
200 OP_CALL_rel32 = 0xE8,
203 OP_GROUP3_EvIz = 0xF7, // OP_GROUP3_Ev has an immediate, when instruction is a test.
208 OP2_JAE_rel32 = 0x83,
210 OP2_JNE_rel32 = 0x85,
211 OP2_JBE_rel32 = 0x86,
213 OP2_JGE_rel32 = 0x8D,
214 OP2_JLE_rel32 = 0x8E,
215 OP2_IMUL_GvEv = 0xAF,
216 OP2_MOVZX_GvEw = 0xB7,
240 static const int MAX_INSTRUCTION_SIZE = 16;
242 X86Assembler(JITCodeBuffer* m_buffer)
250 m_buffer->putByte(OP_INT3);
253 void pushl_r(RegisterID reg)
255 m_buffer->putByte(OP_PUSH_EAX + reg);
258 void pushl_m(int offset, RegisterID base)
260 m_buffer->putByte(OP_GROUP5_Ev);
261 emitModRm_opm(GROUP5_OP_PUSH, base, offset);
264 void popl_r(RegisterID reg)
266 m_buffer->putByte(OP_POP_EAX + reg);
269 void popl_m(int offset, RegisterID base)
271 m_buffer->putByte(OP_GROUP1A_Ev);
272 emitModRm_opm(GROUP1A_OP_POP, base, offset);
275 void movl_rr(RegisterID src, RegisterID dst)
277 m_buffer->putByte(OP_MOV_EvGv);
278 emitModRm_rr(src, dst);
281 void addl_rr(RegisterID src, RegisterID dst)
283 m_buffer->putByte(OP_ADD_EvGv);
284 emitModRm_rr(src, dst);
287 void addl_i8r(int imm, RegisterID dst)
289 m_buffer->putByte(OP_GROUP1_EvIb);
290 emitModRm_opr(GROUP1_OP_ADD, dst);
291 m_buffer->putByte(imm);
294 void addl_i32r(int imm, RegisterID dst)
296 m_buffer->putByte(OP_GROUP1_EvIz);
297 emitModRm_opr(GROUP1_OP_ADD, dst);
298 m_buffer->putInt(imm);
301 void addl_mr(int offset, RegisterID base, RegisterID dst)
303 m_buffer->putByte(OP_ADD_GvEv);
304 emitModRm_rm(dst, base, offset);
307 void andl_rr(RegisterID src, RegisterID dst)
309 m_buffer->putByte(OP_AND_EvGv);
310 emitModRm_rr(src, dst);
313 void andl_i32r(int imm, RegisterID dst)
315 m_buffer->putByte(OP_GROUP1_EvIz);
316 emitModRm_opr(GROUP1_OP_AND, dst);
317 m_buffer->putInt(imm);
320 void cmpl_i8r(int imm, RegisterID dst)
322 m_buffer->putByte(OP_GROUP1_EvIb);
323 emitModRm_opr(GROUP1_OP_CMP, dst);
324 m_buffer->putByte(imm);
327 void cmpl_rr(RegisterID src, RegisterID dst)
329 m_buffer->putByte(OP_CMP_EvGv);
330 emitModRm_rr(src, dst);
333 void cmpl_rm(RegisterID src, int offset, RegisterID base)
335 m_buffer->putByte(OP_CMP_EvGv);
336 emitModRm_rm(src, base, offset);
339 void cmpl_i32r(int imm, RegisterID dst)
341 m_buffer->putByte(OP_GROUP1_EvIz);
342 emitModRm_opr(GROUP1_OP_CMP, dst);
343 m_buffer->putInt(imm);
346 void cmpl_i32m(int imm, RegisterID dst)
348 m_buffer->putByte(OP_GROUP1_EvIz);
349 emitModRm_opm(GROUP1_OP_CMP, dst);
350 m_buffer->putInt(imm);
353 void cmpl_i32m(int imm, int offset, RegisterID dst)
355 m_buffer->putByte(OP_GROUP1_EvIz);
356 emitModRm_opm(GROUP1_OP_CMP, dst, offset);
357 m_buffer->putInt(imm);
360 void cmpl_i32m(int imm, void* addr)
362 m_buffer->putByte(OP_GROUP1_EvIz);
363 emitModRm_opm(GROUP1_OP_CMP, addr);
364 m_buffer->putInt(imm);
367 void cmpw_rm(RegisterID src, RegisterID base, RegisterID index, int scale)
369 m_buffer->putByte(PRE_OPERAND_SIZE);
370 m_buffer->putByte(OP_CMP_EvGv);
371 emitModRm_rmsib(src, base, index, scale);
374 void orl_rr(RegisterID src, RegisterID dst)
376 m_buffer->putByte(OP_OR_EvGv);
377 emitModRm_rr(src, dst);
380 void orl_rr(int imm, RegisterID dst)
382 m_buffer->putByte(OP_GROUP1_EvIb);
383 emitModRm_opr(GROUP1_OP_OR, dst);
384 m_buffer->putByte(imm);
387 void subl_rr(RegisterID src, RegisterID dst)
389 m_buffer->putByte(OP_SUB_EvGv);
390 emitModRm_rr(src, dst);
393 void subl_i8r(int imm, RegisterID dst)
395 m_buffer->putByte(OP_GROUP1_EvIb);
396 emitModRm_opr(GROUP1_OP_SUB, dst);
397 m_buffer->putByte(imm);
400 void subl_i32r(int imm, RegisterID dst)
402 m_buffer->putByte(OP_GROUP1_EvIz);
403 emitModRm_opr(GROUP1_OP_SUB, dst);
404 m_buffer->putInt(imm);
407 void subl_mr(int offset, RegisterID base, RegisterID dst)
409 m_buffer->putByte(OP_SUB_GvEv);
410 emitModRm_rm(dst, base, offset);
413 void testl_i32r(int imm, RegisterID dst)
415 m_buffer->ensureSpace(MAX_INSTRUCTION_SIZE);
416 m_buffer->putByteUnchecked(OP_GROUP3_EvIz);
417 emitModRm_opr_Unchecked(GROUP3_OP_TEST, dst);
418 m_buffer->putIntUnchecked(imm);
421 void testl_rr(RegisterID src, RegisterID dst)
423 m_buffer->putByte(OP_TEST_EvGv);
424 emitModRm_rr(src, dst);
427 void xorl_i8r(int imm, RegisterID dst)
429 m_buffer->putByte(OP_GROUP1_EvIb);
430 emitModRm_opr(GROUP1_OP_XOR, dst);
431 m_buffer->putByte(imm);
434 void xorl_rr(RegisterID src, RegisterID dst)
436 m_buffer->putByte(OP_XOR_EvGv);
437 emitModRm_rr(src, dst);
440 void sarl_i8r(int imm, RegisterID dst)
443 m_buffer->putByte(OP_GROUP2_Ev1);
444 emitModRm_opr(GROUP2_OP_SAR, dst);
446 m_buffer->putByte(OP_GROUP2_EvIb);
447 emitModRm_opr(GROUP2_OP_SAR, dst);
448 m_buffer->putByte(imm);
452 void sarl_CLr(RegisterID dst)
454 m_buffer->putByte(OP_GROUP2_EvCL);
455 emitModRm_opr(GROUP2_OP_SAR, dst);
458 void shl_i8r(int imm, RegisterID dst)
461 m_buffer->putByte(OP_GROUP2_Ev1);
462 emitModRm_opr(GROUP2_OP_SHL, dst);
464 m_buffer->putByte(OP_GROUP2_EvIb);
465 emitModRm_opr(GROUP2_OP_SHL, dst);
466 m_buffer->putByte(imm);
470 void shll_CLr(RegisterID dst)
472 m_buffer->putByte(OP_GROUP2_EvCL);
473 emitModRm_opr(GROUP2_OP_SHL, dst);
476 void imull_rr(RegisterID src, RegisterID dst)
478 m_buffer->putByte(OP_2BYTE_ESCAPE);
479 m_buffer->putByte(OP2_IMUL_GvEv);
480 emitModRm_rr(dst, src);
483 void imull_i32r(RegisterID src, int32_t value, RegisterID dst)
485 m_buffer->putByte(OP_IMUL_GvEvIz);
486 emitModRm_rr(dst, src);
487 m_buffer->putInt(value);
490 void idivl_r(RegisterID dst)
492 m_buffer->putByte(OP_GROUP3_Ev);
493 emitModRm_opr(GROUP3_OP_IDIV, dst);
498 m_buffer->putByte(OP_CDQ);
501 void movl_mr(RegisterID base, RegisterID dst)
503 m_buffer->putByte(OP_MOV_GvEv);
504 emitModRm_rm(dst, base);
507 void movl_mr(int offset, RegisterID base, RegisterID dst)
509 m_buffer->ensureSpace(MAX_INSTRUCTION_SIZE);
510 m_buffer->putByteUnchecked(OP_MOV_GvEv);
511 emitModRm_rm_Unchecked(dst, base, offset);
514 void movl_mr(void* addr, RegisterID dst)
516 m_buffer->putByte(OP_MOV_GvEv);
517 emitModRm_rm(dst, addr);
520 void movl_mr(int offset, RegisterID base, RegisterID index, int scale, RegisterID dst)
522 m_buffer->putByte(OP_MOV_GvEv);
523 emitModRm_rmsib(dst, base, index, scale, offset);
526 void movzwl_mr(int offset, RegisterID base, RegisterID dst)
528 m_buffer->putByte(OP_2BYTE_ESCAPE);
529 m_buffer->putByte(OP2_MOVZX_GvEw);
530 emitModRm_rm(dst, base, offset);
533 void movzwl_mr(RegisterID base, RegisterID index, int scale, RegisterID dst)
535 m_buffer->putByte(OP_2BYTE_ESCAPE);
536 m_buffer->putByte(OP2_MOVZX_GvEw);
537 emitModRm_rmsib(dst, base, index, scale);
540 void movzwl_mr(int offset, RegisterID base, RegisterID index, int scale, RegisterID dst)
542 m_buffer->putByte(OP_2BYTE_ESCAPE);
543 m_buffer->putByte(OP2_MOVZX_GvEw);
544 emitModRm_rmsib(dst, base, index, scale, offset);
547 void movl_rm(RegisterID src, RegisterID base)
549 m_buffer->putByte(OP_MOV_EvGv);
550 emitModRm_rm(src, base);
553 void movl_rm(RegisterID src, int offset, RegisterID base)
555 m_buffer->ensureSpace(MAX_INSTRUCTION_SIZE);
556 m_buffer->putByteUnchecked(OP_MOV_EvGv);
557 emitModRm_rm_Unchecked(src, base, offset);
560 void movl_rm(RegisterID src, int offset, RegisterID base, RegisterID index, int scale)
562 m_buffer->putByte(OP_MOV_EvGv);
563 emitModRm_rmsib(src, base, index, scale, offset);
566 void movl_i32r(int imm, RegisterID dst)
568 m_buffer->putByte(OP_GROUP11_EvIz);
569 emitModRm_opr(GROUP11_MOV, dst);
570 m_buffer->putInt(imm);
573 void movl_i32m(int imm, int offset, RegisterID base)
575 m_buffer->ensureSpace(MAX_INSTRUCTION_SIZE);
576 m_buffer->putByteUnchecked(OP_GROUP11_EvIz);
577 emitModRm_opm_Unchecked(GROUP11_MOV, base, offset);
578 m_buffer->putIntUnchecked(imm);
581 void movl_i32m(int imm, void* addr)
583 m_buffer->putByte(OP_GROUP11_EvIz);
584 emitModRm_opm(GROUP11_MOV, addr);
585 m_buffer->putInt(imm);
588 void leal_mr(int offset, RegisterID base, RegisterID dst)
590 m_buffer->putByte(OP_LEA);
591 emitModRm_rm(dst, base, offset);
596 m_buffer->putByte(OP_RET);
599 void jmp_r(RegisterID dst)
601 m_buffer->putByte(OP_GROUP5_Ev);
602 emitModRm_opr(GROUP5_OP_JMPN, dst);
605 void jmp_m(int offset, RegisterID base)
607 m_buffer->putByte(OP_GROUP5_Ev);
608 emitModRm_opm(GROUP5_OP_JMPN, base, offset);
611 void call_r(RegisterID dst)
613 m_buffer->putByte(OP_GROUP5_Ev);
614 emitModRm_opr(GROUP5_OP_CALLN, dst);
617 // Opaque label types
620 friend class X86Assembler;
637 friend class X86Assembler;
653 // FIXME: make this point to a global label, linked later.
656 m_buffer->putByte(OP_CALL_rel32);
658 return JmpSrc(m_buffer->getOffset());
663 return JmpDst(m_buffer->getOffset());
666 JmpSrc emitUnlinkedJmp()
668 m_buffer->putByte(OP_JMP_rel32);
670 return JmpSrc(m_buffer->getOffset());
673 JmpSrc emitUnlinkedJne()
675 m_buffer->putByte(OP_2BYTE_ESCAPE);
676 m_buffer->putByte(OP2_JNE_rel32);
678 return JmpSrc(m_buffer->getOffset());
681 JmpSrc emitUnlinkedJe()
683 m_buffer->ensureSpace(MAX_INSTRUCTION_SIZE);
684 m_buffer->putByteUnchecked(OP_2BYTE_ESCAPE);
685 m_buffer->putByteUnchecked(OP2_JE_rel32);
686 m_buffer->putIntUnchecked(0);
687 return JmpSrc(m_buffer->getOffset());
690 JmpSrc emitUnlinkedJl()
692 m_buffer->putByte(OP_2BYTE_ESCAPE);
693 m_buffer->putByte(OP2_JL_rel32);
695 return JmpSrc(m_buffer->getOffset());
698 JmpSrc emitUnlinkedJb()
700 m_buffer->putByte(OP_2BYTE_ESCAPE);
701 m_buffer->putByte(OP2_JB_rel32);
703 return JmpSrc(m_buffer->getOffset());
706 JmpSrc emitUnlinkedJle()
708 m_buffer->putByte(OP_2BYTE_ESCAPE);
709 m_buffer->putByte(OP2_JLE_rel32);
711 return JmpSrc(m_buffer->getOffset());
714 JmpSrc emitUnlinkedJbe()
716 m_buffer->putByte(OP_2BYTE_ESCAPE);
717 m_buffer->putByte(OP2_JBE_rel32);
719 return JmpSrc(m_buffer->getOffset());
722 JmpSrc emitUnlinkedJge()
724 m_buffer->putByte(OP_2BYTE_ESCAPE);
725 m_buffer->putByte(OP2_JGE_rel32);
727 return JmpSrc(m_buffer->getOffset());
730 JmpSrc emitUnlinkedJae()
732 m_buffer->putByte(OP_2BYTE_ESCAPE);
733 m_buffer->putByte(OP2_JAE_rel32);
735 return JmpSrc(m_buffer->getOffset());
738 JmpSrc emitUnlinkedJo()
740 m_buffer->putByte(OP_2BYTE_ESCAPE);
741 m_buffer->putByte(OP2_JO_rel32);
743 return JmpSrc(m_buffer->getOffset());
746 void emitPredictionNotTaken()
748 m_buffer->putByte(PRE_PREDICT_BRANCH_NOT_TAKEN);
751 void link(JmpSrc from, JmpDst to)
753 ASSERT(to.m_offset != -1);
754 ASSERT(from.m_offset != -1);
756 ((int*)(((ptrdiff_t)(m_buffer->start())) + from.m_offset))[-1] = to.m_offset - from.m_offset;
759 static void linkAbsoluteAddress(void* code, JmpDst useOffset, JmpDst address)
761 ASSERT(useOffset.m_offset != -1);
762 ASSERT(address.m_offset != -1);
764 ((int*)(((ptrdiff_t)code) + useOffset.m_offset))[-1] = ((ptrdiff_t)code) + address.m_offset;
767 static void link(void* code, JmpSrc from, void* to)
769 ASSERT(from.m_offset != -1);
771 ((int*)((ptrdiff_t)code + from.m_offset))[-1] = (ptrdiff_t)to - ((ptrdiff_t)code + from.m_offset);
774 void* getRelocatedAddress(void* code, JmpSrc jump)
776 return reinterpret_cast<void*>((ptrdiff_t)code + jump.m_offset);
779 void* getRelocatedAddress(void* code, JmpDst jump)
781 return reinterpret_cast<void*>((ptrdiff_t)code + jump.m_offset);
786 return m_buffer->copy();
790 void emitConvertToFastCall()
792 movl_mr(4, X86::esp, X86::eax);
793 movl_mr(8, X86::esp, X86::edx);
794 movl_mr(12, X86::esp, X86::ecx);
797 void emitRestoreArgumentReference()
799 movl_rm(X86::esp, 0, X86::esp);
802 void emitConvertToFastCall() {};
803 void emitRestoreArgumentReference() {};
807 void emitModRm_rr(RegisterID reg, RegisterID rm)
809 m_buffer->ensureSpace(MAX_INSTRUCTION_SIZE);
810 emitModRm_rr_Unchecked(reg, rm);
813 void emitModRm_rr_Unchecked(RegisterID reg, RegisterID rm)
815 m_buffer->putByteUnchecked(MODRM(3, reg, rm));
818 void emitModRm_rm(RegisterID reg, void* addr)
820 m_buffer->putByte(MODRM(0, reg, X86::noBase));
821 m_buffer->putInt((int)addr);
824 void emitModRm_rm(RegisterID reg, RegisterID base)
826 if (base == X86::esp) {
827 m_buffer->putByte(MODRM(0, reg, X86::hasSib));
828 m_buffer->putByte(SIB(0, X86::noScale, X86::esp));
830 m_buffer->putByte(MODRM(0, reg, base));
833 void emitModRm_rm_Unchecked(RegisterID reg, RegisterID base, int offset)
835 if (base == X86::esp) {
836 if (CAN_SIGN_EXTEND_8_32(offset)) {
837 m_buffer->putByteUnchecked(MODRM(1, reg, X86::hasSib));
838 m_buffer->putByteUnchecked(SIB(0, X86::noScale, X86::esp));
839 m_buffer->putByteUnchecked(offset);
841 m_buffer->putByteUnchecked(MODRM(2, reg, X86::hasSib));
842 m_buffer->putByteUnchecked(SIB(0, X86::noScale, X86::esp));
843 m_buffer->putIntUnchecked(offset);
846 if (CAN_SIGN_EXTEND_8_32(offset)) {
847 m_buffer->putByteUnchecked(MODRM(1, reg, base));
848 m_buffer->putByteUnchecked(offset);
850 m_buffer->putByteUnchecked(MODRM(2, reg, base));
851 m_buffer->putIntUnchecked(offset);
856 void emitModRm_rm(RegisterID reg, RegisterID base, int offset)
858 m_buffer->ensureSpace(MAX_INSTRUCTION_SIZE);
859 emitModRm_rm_Unchecked(reg, base, offset);
862 void emitModRm_rmsib(RegisterID reg, RegisterID base, RegisterID index, int scale)
868 m_buffer->putByte(MODRM(0, reg, X86::hasSib));
869 m_buffer->putByte(SIB(shift, index, base));
872 void emitModRm_rmsib(RegisterID reg, RegisterID base, RegisterID index, int scale, int offset)
878 if (CAN_SIGN_EXTEND_8_32(offset)) {
879 m_buffer->putByte(MODRM(1, reg, X86::hasSib));
880 m_buffer->putByte(SIB(shift, index, base));
881 m_buffer->putByte(offset);
883 m_buffer->putByte(MODRM(2, reg, X86::hasSib));
884 m_buffer->putByte(SIB(shift, index, base));
885 m_buffer->putInt(offset);
889 void emitModRm_opr(OpcodeID opcode, RegisterID rm)
891 m_buffer->ensureSpace(MAX_INSTRUCTION_SIZE);
892 emitModRm_opr_Unchecked(opcode, rm);
895 void emitModRm_opr_Unchecked(OpcodeID opcode, RegisterID rm)
897 emitModRm_rr_Unchecked(static_cast<RegisterID>(opcode), rm);
900 void emitModRm_opm(OpcodeID opcode, RegisterID base)
902 emitModRm_rm(static_cast<RegisterID>(opcode), base);
905 void emitModRm_opm_Unchecked(OpcodeID opcode, RegisterID base, int offset)
907 emitModRm_rm_Unchecked(static_cast<RegisterID>(opcode), base, offset);
910 void emitModRm_opm(OpcodeID opcode, RegisterID base, int offset)
912 emitModRm_rm(static_cast<RegisterID>(opcode), base, offset);
915 void emitModRm_opm(OpcodeID opcode, void* addr)
917 emitModRm_rm(static_cast<RegisterID>(opcode), addr);
920 JITCodeBuffer* m_buffer;
925 #endif // ENABLE(MASM) && PLATFORM(X86)
927 #endif // X86Assembler_h