2008-12-15 Gavin Barraclough <barraclough@apple.com>
authorbarraclough@apple.com <barraclough@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Mon, 15 Dec 2008 23:38:19 +0000 (23:38 +0000)
committerbarraclough@apple.com <barraclough@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Mon, 15 Dec 2008 23:38:19 +0000 (23:38 +0000)
        Reviewed by Geoff Garen.

        Add support to X86Assembler emitting instructions that access all 16 registers on x86-64.
        Add a new formating class, that is reponsible for both emitting the opcode bytes and the
        ModRm  bytes of an instruction in a single call; this can insert the REX byte as necessary
        before the opcode, but has access to the register numbers to build the REX.

        * assembler/AssemblerBuffer.h:
        (JSC::AssemblerBuffer::isAligned):
        (JSC::AssemblerBuffer::data):
        * assembler/MacroAssembler.h:
        (JSC::MacroAssembler::addPtr):
        (JSC::MacroAssembler::add32):
        (JSC::MacroAssembler::and32):
        (JSC::MacroAssembler::or32):
        (JSC::MacroAssembler::sub32):
        (JSC::MacroAssembler::xor32):
        (JSC::MacroAssembler::loadPtr):
        (JSC::MacroAssembler::load32):
        (JSC::MacroAssembler::load16):
        (JSC::MacroAssembler::storePtr):
        (JSC::MacroAssembler::storePtrWithRepatch):
        (JSC::MacroAssembler::store32):
        (JSC::MacroAssembler::pop):
        (JSC::MacroAssembler::push):
        (JSC::MacroAssembler::compareImm32ForBranch):
        (JSC::MacroAssembler::compareImm32ForBranchEquality):
        (JSC::MacroAssembler::testImm32):
        (JSC::MacroAssembler::jae32):
        (JSC::MacroAssembler::jb32):
        (JSC::MacroAssembler::je16):
        (JSC::MacroAssembler::jg32):
        (JSC::MacroAssembler::jnePtr):
        (JSC::MacroAssembler::jne32):
        (JSC::MacroAssembler::jump):
        * assembler/X86Assembler.h:
        (JSC::X86::):
        (JSC::X86Assembler::):
        (JSC::X86Assembler::size):
        (JSC::X86Assembler::push_r):
        (JSC::X86Assembler::pop_r):
        (JSC::X86Assembler::push_i32):
        (JSC::X86Assembler::push_m):
        (JSC::X86Assembler::pop_m):
        (JSC::X86Assembler::addl_rr):
        (JSC::X86Assembler::addl_mr):
        (JSC::X86Assembler::addl_ir):
        (JSC::X86Assembler::addq_ir):
        (JSC::X86Assembler::addl_im):
        (JSC::X86Assembler::andl_rr):
        (JSC::X86Assembler::andl_ir):
        (JSC::X86Assembler::orl_rr):
        (JSC::X86Assembler::orl_mr):
        (JSC::X86Assembler::orl_ir):
        (JSC::X86Assembler::subl_rr):
        (JSC::X86Assembler::subl_mr):
        (JSC::X86Assembler::subl_ir):
        (JSC::X86Assembler::subl_im):
        (JSC::X86Assembler::xorl_rr):
        (JSC::X86Assembler::xorl_ir):
        (JSC::X86Assembler::sarl_i8r):
        (JSC::X86Assembler::sarl_CLr):
        (JSC::X86Assembler::shll_i8r):
        (JSC::X86Assembler::shll_CLr):
        (JSC::X86Assembler::imull_rr):
        (JSC::X86Assembler::imull_i32r):
        (JSC::X86Assembler::idivl_r):
        (JSC::X86Assembler::cmpl_rr):
        (JSC::X86Assembler::cmpl_rm):
        (JSC::X86Assembler::cmpl_mr):
        (JSC::X86Assembler::cmpl_ir):
        (JSC::X86Assembler::cmpl_ir_force32):
        (JSC::X86Assembler::cmpl_im):
        (JSC::X86Assembler::cmpl_im_force32):
        (JSC::X86Assembler::cmpw_rm):
        (JSC::X86Assembler::testl_rr):
        (JSC::X86Assembler::testl_i32r):
        (JSC::X86Assembler::testl_i32m):
        (JSC::X86Assembler::testq_rr):
        (JSC::X86Assembler::testq_i32r):
        (JSC::X86Assembler::testb_i8r):
        (JSC::X86Assembler::sete_r):
        (JSC::X86Assembler::setz_r):
        (JSC::X86Assembler::setne_r):
        (JSC::X86Assembler::setnz_r):
        (JSC::X86Assembler::cdq):
        (JSC::X86Assembler::xchgl_rr):
        (JSC::X86Assembler::movl_rr):
        (JSC::X86Assembler::movl_rm):
        (JSC::X86Assembler::movl_mr):
        (JSC::X86Assembler::movl_i32r):
        (JSC::X86Assembler::movl_i32m):
        (JSC::X86Assembler::movq_rr):
        (JSC::X86Assembler::movq_rm):
        (JSC::X86Assembler::movq_mr):
        (JSC::X86Assembler::movzwl_mr):
        (JSC::X86Assembler::movzbl_rr):
        (JSC::X86Assembler::leal_mr):
        (JSC::X86Assembler::call):
        (JSC::X86Assembler::jmp):
        (JSC::X86Assembler::jmp_r):
        (JSC::X86Assembler::jmp_m):
        (JSC::X86Assembler::jne):
        (JSC::X86Assembler::jnz):
        (JSC::X86Assembler::je):
        (JSC::X86Assembler::jl):
        (JSC::X86Assembler::jb):
        (JSC::X86Assembler::jle):
        (JSC::X86Assembler::jbe):
        (JSC::X86Assembler::jge):
        (JSC::X86Assembler::jg):
        (JSC::X86Assembler::ja):
        (JSC::X86Assembler::jae):
        (JSC::X86Assembler::jo):
        (JSC::X86Assembler::jp):
        (JSC::X86Assembler::js):
        (JSC::X86Assembler::addsd_rr):
        (JSC::X86Assembler::addsd_mr):
        (JSC::X86Assembler::cvtsi2sd_rr):
        (JSC::X86Assembler::cvttsd2si_rr):
        (JSC::X86Assembler::movd_rr):
        (JSC::X86Assembler::movsd_rm):
        (JSC::X86Assembler::movsd_mr):
        (JSC::X86Assembler::mulsd_rr):
        (JSC::X86Assembler::mulsd_mr):
        (JSC::X86Assembler::pextrw_irr):
        (JSC::X86Assembler::subsd_rr):
        (JSC::X86Assembler::subsd_mr):
        (JSC::X86Assembler::ucomis_rr):
        (JSC::X86Assembler::int3):
        (JSC::X86Assembler::ret):
        (JSC::X86Assembler::predictNotTaken):
        (JSC::X86Assembler::label):
        (JSC::X86Assembler::align):
        (JSC::X86Assembler::link):
        (JSC::X86Assembler::executableCopy):
        (JSC::X86Assembler::X86InstructionFormater::prefix):
        (JSC::X86Assembler::X86InstructionFormater::oneByteOp):
        (JSC::X86Assembler::X86InstructionFormater::twoByteOp):
        (JSC::X86Assembler::X86InstructionFormater::oneByteOp64):
        (JSC::X86Assembler::X86InstructionFormater::oneByteOp8):
        (JSC::X86Assembler::X86InstructionFormater::twoByteOp8):
        (JSC::X86Assembler::X86InstructionFormater::instructionImmediate8):
        (JSC::X86Assembler::X86InstructionFormater::instructionImmediate32):
        (JSC::X86Assembler::X86InstructionFormater::instructionRel32):
        (JSC::X86Assembler::X86InstructionFormater::size):
        (JSC::X86Assembler::X86InstructionFormater::isAligned):
        (JSC::X86Assembler::X86InstructionFormater::data):
        (JSC::X86Assembler::X86InstructionFormater::executableCopy):
        (JSC::X86Assembler::X86InstructionFormater::registerModRM):
        (JSC::X86Assembler::X86InstructionFormater::memoryModRM):
        * jit/JIT.cpp:
        (JSC::JIT::privateCompileMainPass):
        (JSC::JIT::privateCompile):
        (JSC::JIT::privateCompileCTIMachineTrampolines):
        * jit/JITArithmetic.cpp:
        (JSC::JIT::putDoubleResultToJSNumberCellOrJSImmediate):
        (JSC::JIT::compileBinaryArithOp):
        * jit/JITCall.cpp:
        (JSC::JIT::compileOpCall):
        (JSC::JIT::compileOpCallSlowCase):
        * jit/JITPropertyAccess.cpp:
        (JSC::JIT::compileGetByIdHotPath):
        (JSC::JIT::compilePutByIdHotPath):
        (JSC::JIT::privateCompilePutByIdTransition):
        (JSC::JIT::privateCompilePatchGetArrayLength):
        (JSC::JIT::privateCompileGetByIdProto):
        (JSC::JIT::privateCompileGetByIdProtoList):
        (JSC::JIT::privateCompileGetByIdChainList):
        (JSC::JIT::privateCompileGetByIdChain):

git-svn-id: https://svn.webkit.org/repository/webkit/trunk@39316 268f45cc-cd09-0410-ab3c-d52691b4dbfc

JavaScriptCore/ChangeLog
JavaScriptCore/assembler/AssemblerBuffer.h
JavaScriptCore/assembler/MacroAssembler.h
JavaScriptCore/assembler/X86Assembler.h
JavaScriptCore/jit/JIT.cpp
JavaScriptCore/jit/JITArithmetic.cpp
JavaScriptCore/jit/JITCall.cpp
JavaScriptCore/jit/JITPropertyAccess.cpp

index f2b02f1..577e2b1 100644 (file)
@@ -1,3 +1,176 @@
+2008-12-15  Gavin Barraclough  <barraclough@apple.com>
+
+        Reviewed by Geoff Garen.
+
+        Add support to X86Assembler emitting instructions that access all 16 registers on x86-64.
+        Add a new formating class, that is reponsible for both emitting the opcode bytes and the
+        ModRm  bytes of an instruction in a single call; this can insert the REX byte as necessary
+        before the opcode, but has access to the register numbers to build the REX.
+
+        * assembler/AssemblerBuffer.h:
+        (JSC::AssemblerBuffer::isAligned):
+        (JSC::AssemblerBuffer::data):
+        * assembler/MacroAssembler.h:
+        (JSC::MacroAssembler::addPtr):
+        (JSC::MacroAssembler::add32):
+        (JSC::MacroAssembler::and32):
+        (JSC::MacroAssembler::or32):
+        (JSC::MacroAssembler::sub32):
+        (JSC::MacroAssembler::xor32):
+        (JSC::MacroAssembler::loadPtr):
+        (JSC::MacroAssembler::load32):
+        (JSC::MacroAssembler::load16):
+        (JSC::MacroAssembler::storePtr):
+        (JSC::MacroAssembler::storePtrWithRepatch):
+        (JSC::MacroAssembler::store32):
+        (JSC::MacroAssembler::pop):
+        (JSC::MacroAssembler::push):
+        (JSC::MacroAssembler::compareImm32ForBranch):
+        (JSC::MacroAssembler::compareImm32ForBranchEquality):
+        (JSC::MacroAssembler::testImm32):
+        (JSC::MacroAssembler::jae32):
+        (JSC::MacroAssembler::jb32):
+        (JSC::MacroAssembler::je16):
+        (JSC::MacroAssembler::jg32):
+        (JSC::MacroAssembler::jnePtr):
+        (JSC::MacroAssembler::jne32):
+        (JSC::MacroAssembler::jump):
+        * assembler/X86Assembler.h:
+        (JSC::X86::):
+        (JSC::X86Assembler::):
+        (JSC::X86Assembler::size):
+        (JSC::X86Assembler::push_r):
+        (JSC::X86Assembler::pop_r):
+        (JSC::X86Assembler::push_i32):
+        (JSC::X86Assembler::push_m):
+        (JSC::X86Assembler::pop_m):
+        (JSC::X86Assembler::addl_rr):
+        (JSC::X86Assembler::addl_mr):
+        (JSC::X86Assembler::addl_ir):
+        (JSC::X86Assembler::addq_ir):
+        (JSC::X86Assembler::addl_im):
+        (JSC::X86Assembler::andl_rr):
+        (JSC::X86Assembler::andl_ir):
+        (JSC::X86Assembler::orl_rr):
+        (JSC::X86Assembler::orl_mr):
+        (JSC::X86Assembler::orl_ir):
+        (JSC::X86Assembler::subl_rr):
+        (JSC::X86Assembler::subl_mr):
+        (JSC::X86Assembler::subl_ir):
+        (JSC::X86Assembler::subl_im):
+        (JSC::X86Assembler::xorl_rr):
+        (JSC::X86Assembler::xorl_ir):
+        (JSC::X86Assembler::sarl_i8r):
+        (JSC::X86Assembler::sarl_CLr):
+        (JSC::X86Assembler::shll_i8r):
+        (JSC::X86Assembler::shll_CLr):
+        (JSC::X86Assembler::imull_rr):
+        (JSC::X86Assembler::imull_i32r):
+        (JSC::X86Assembler::idivl_r):
+        (JSC::X86Assembler::cmpl_rr):
+        (JSC::X86Assembler::cmpl_rm):
+        (JSC::X86Assembler::cmpl_mr):
+        (JSC::X86Assembler::cmpl_ir):
+        (JSC::X86Assembler::cmpl_ir_force32):
+        (JSC::X86Assembler::cmpl_im):
+        (JSC::X86Assembler::cmpl_im_force32):
+        (JSC::X86Assembler::cmpw_rm):
+        (JSC::X86Assembler::testl_rr):
+        (JSC::X86Assembler::testl_i32r):
+        (JSC::X86Assembler::testl_i32m):
+        (JSC::X86Assembler::testq_rr):
+        (JSC::X86Assembler::testq_i32r):
+        (JSC::X86Assembler::testb_i8r):
+        (JSC::X86Assembler::sete_r):
+        (JSC::X86Assembler::setz_r):
+        (JSC::X86Assembler::setne_r):
+        (JSC::X86Assembler::setnz_r):
+        (JSC::X86Assembler::cdq):
+        (JSC::X86Assembler::xchgl_rr):
+        (JSC::X86Assembler::movl_rr):
+        (JSC::X86Assembler::movl_rm):
+        (JSC::X86Assembler::movl_mr):
+        (JSC::X86Assembler::movl_i32r):
+        (JSC::X86Assembler::movl_i32m):
+        (JSC::X86Assembler::movq_rr):
+        (JSC::X86Assembler::movq_rm):
+        (JSC::X86Assembler::movq_mr):
+        (JSC::X86Assembler::movzwl_mr):
+        (JSC::X86Assembler::movzbl_rr):
+        (JSC::X86Assembler::leal_mr):
+        (JSC::X86Assembler::call):
+        (JSC::X86Assembler::jmp):
+        (JSC::X86Assembler::jmp_r):
+        (JSC::X86Assembler::jmp_m):
+        (JSC::X86Assembler::jne):
+        (JSC::X86Assembler::jnz):
+        (JSC::X86Assembler::je):
+        (JSC::X86Assembler::jl):
+        (JSC::X86Assembler::jb):
+        (JSC::X86Assembler::jle):
+        (JSC::X86Assembler::jbe):
+        (JSC::X86Assembler::jge):
+        (JSC::X86Assembler::jg):
+        (JSC::X86Assembler::ja):
+        (JSC::X86Assembler::jae):
+        (JSC::X86Assembler::jo):
+        (JSC::X86Assembler::jp):
+        (JSC::X86Assembler::js):
+        (JSC::X86Assembler::addsd_rr):
+        (JSC::X86Assembler::addsd_mr):
+        (JSC::X86Assembler::cvtsi2sd_rr):
+        (JSC::X86Assembler::cvttsd2si_rr):
+        (JSC::X86Assembler::movd_rr):
+        (JSC::X86Assembler::movsd_rm):
+        (JSC::X86Assembler::movsd_mr):
+        (JSC::X86Assembler::mulsd_rr):
+        (JSC::X86Assembler::mulsd_mr):
+        (JSC::X86Assembler::pextrw_irr):
+        (JSC::X86Assembler::subsd_rr):
+        (JSC::X86Assembler::subsd_mr):
+        (JSC::X86Assembler::ucomis_rr):
+        (JSC::X86Assembler::int3):
+        (JSC::X86Assembler::ret):
+        (JSC::X86Assembler::predictNotTaken):
+        (JSC::X86Assembler::label):
+        (JSC::X86Assembler::align):
+        (JSC::X86Assembler::link):
+        (JSC::X86Assembler::executableCopy):
+        (JSC::X86Assembler::X86InstructionFormater::prefix):
+        (JSC::X86Assembler::X86InstructionFormater::oneByteOp):
+        (JSC::X86Assembler::X86InstructionFormater::twoByteOp):
+        (JSC::X86Assembler::X86InstructionFormater::oneByteOp64):
+        (JSC::X86Assembler::X86InstructionFormater::oneByteOp8):
+        (JSC::X86Assembler::X86InstructionFormater::twoByteOp8):
+        (JSC::X86Assembler::X86InstructionFormater::instructionImmediate8):
+        (JSC::X86Assembler::X86InstructionFormater::instructionImmediate32):
+        (JSC::X86Assembler::X86InstructionFormater::instructionRel32):
+        (JSC::X86Assembler::X86InstructionFormater::size):
+        (JSC::X86Assembler::X86InstructionFormater::isAligned):
+        (JSC::X86Assembler::X86InstructionFormater::data):
+        (JSC::X86Assembler::X86InstructionFormater::executableCopy):
+        (JSC::X86Assembler::X86InstructionFormater::registerModRM):
+        (JSC::X86Assembler::X86InstructionFormater::memoryModRM):
+        * jit/JIT.cpp:
+        (JSC::JIT::privateCompileMainPass):
+        (JSC::JIT::privateCompile):
+        (JSC::JIT::privateCompileCTIMachineTrampolines):
+        * jit/JITArithmetic.cpp:
+        (JSC::JIT::putDoubleResultToJSNumberCellOrJSImmediate):
+        (JSC::JIT::compileBinaryArithOp):
+        * jit/JITCall.cpp:
+        (JSC::JIT::compileOpCall):
+        (JSC::JIT::compileOpCallSlowCase):
+        * jit/JITPropertyAccess.cpp:
+        (JSC::JIT::compileGetByIdHotPath):
+        (JSC::JIT::compilePutByIdHotPath):
+        (JSC::JIT::privateCompilePutByIdTransition):
+        (JSC::JIT::privateCompilePatchGetArrayLength):
+        (JSC::JIT::privateCompileGetByIdProto):
+        (JSC::JIT::privateCompileGetByIdProtoList):
+        (JSC::JIT::privateCompileGetByIdChainList):
+        (JSC::JIT::privateCompileGetByIdChain):
+
 2008-12-15  Darin Adler  <darin@apple.com>
 
         * interpreter/RegisterFile.h: Tweak include formatting.
index f68a5c2..8d3642c 100644 (file)
@@ -59,7 +59,7 @@ namespace JSC {
                 grow();
         }
 
-        bool isAligned(int alignment)
+        bool isAligned(int alignment) const
         {
             return !(m_size & (alignment - 1));
         }
@@ -105,7 +105,7 @@ namespace JSC {
             putIntUnchecked(value);
         }
 
-        void* data()
+        void* data() const
         {
             return m_buffer;
         }
index 8984353..ca92178 100644 (file)
@@ -363,15 +363,9 @@ public:
     void addPtr(Imm32 imm, RegisterID srcDest)
     {
 #if PLATFORM(X86_64)
-        if (CAN_SIGN_EXTEND_8_32(imm.m_value))
-            m_assembler.addq_i8r(imm.m_value, srcDest);
-        else
-            m_assembler.addq_i32r(imm.m_value, srcDest);
+        m_assembler.addq_ir(imm.m_value, srcDest);
 #else
-        if (CAN_SIGN_EXTEND_8_32(imm.m_value))
-            m_assembler.addl_i8r(imm.m_value, srcDest);
-        else
-            m_assembler.addl_i32r(imm.m_value, srcDest);
+        m_assembler.addl_ir(imm.m_value, srcDest);
 #endif
     }
 
@@ -388,18 +382,12 @@ public:
 
     void add32(Imm32 imm, RegisterID dest)
     {
-        if (CAN_SIGN_EXTEND_8_32(imm.m_value))
-            m_assembler.addl_i8r(imm.m_value, dest);
-        else
-            m_assembler.addl_i32r(imm.m_value, dest);
+        m_assembler.addl_ir(imm.m_value, dest);
     }
     
     void add32(Address src, RegisterID dest)
     {
-        if (src.offset)
-            m_assembler.addl_mr(src.offset, src.base, dest);
-        else
-            m_assembler.addl_mr(src.base, dest);
+        m_assembler.addl_mr(src.offset, src.base, dest);
     }
     
     void and32(RegisterID src, RegisterID dest)
@@ -409,10 +397,7 @@ public:
 
     void and32(Imm32 imm, RegisterID dest)
     {
-        if (CAN_SIGN_EXTEND_8_32(imm.m_value))
-            m_assembler.andl_i8r(imm.m_value, dest);
-        else
-            m_assembler.andl_i32r(imm.m_value, dest);
+        m_assembler.andl_ir(imm.m_value, dest);
     }
 
     void lshift32(Imm32 imm, RegisterID dest)
@@ -425,7 +410,7 @@ public:
         // On x86 we can only shift by ecx; if asked to shift by another register we'll
         // need rejig the shift amount into ecx first, and restore the registers afterwards.
         if (shift_amount != X86::ecx) {
-            m_assembler.xchgl_rr(shift_amount, X86::ecx);
+            swap(shift_amount, X86::ecx);
 
             // E.g. transform "shll %eax, %eax" -> "xchgl %eax, %ecx; shll %ecx, %ecx; xchgl %eax, %ecx"
             if (dest == shift_amount)
@@ -437,7 +422,7 @@ public:
             else
                 m_assembler.shll_CLr(dest);
         
-            m_assembler.xchgl_rr(shift_amount, X86::ecx);
+            swap(shift_amount, X86::ecx);
         } else
             m_assembler.shll_CLr(dest);
     }
@@ -473,10 +458,7 @@ public:
 
     void or32(Imm32 imm, RegisterID dest)
     {
-        if (CAN_SIGN_EXTEND_8_32(imm.m_value))
-            m_assembler.orl_i8r(imm.m_value, dest);
-        else
-            m_assembler.orl_i32r(imm.m_value, dest);
+            m_assembler.orl_ir(imm.m_value, dest);
     }
 
     void rshift32(Imm32 imm, RegisterID dest)
@@ -489,7 +471,7 @@ public:
         // On x86 we can only shift by ecx; if asked to shift by another register we'll
         // need rejig the shift amount into ecx first, and restore the registers afterwards.
         if (shift_amount != X86::ecx) {
-            m_assembler.xchgl_rr(shift_amount, X86::ecx);
+            swap(shift_amount, X86::ecx);
 
             // E.g. transform "shll %eax, %eax" -> "xchgl %eax, %ecx; shll %ecx, %ecx; xchgl %eax, %ecx"
             if (dest == shift_amount)
@@ -501,25 +483,19 @@ public:
             else
                 m_assembler.sarl_CLr(dest);
         
-            m_assembler.xchgl_rr(shift_amount, X86::ecx);
+            swap(shift_amount, X86::ecx);
         } else
             m_assembler.sarl_CLr(dest);
     }
 
     void sub32(Imm32 imm, RegisterID dest)
     {
-        if (CAN_SIGN_EXTEND_8_32(imm.m_value))
-            m_assembler.subl_i8r(imm.m_value, dest);
-        else
-            m_assembler.subl_i32r(imm.m_value, dest);
+        m_assembler.subl_ir(imm.m_value, dest);
     }
     
     void sub32(Address src, RegisterID dest)
     {
-        if (src.offset)
-            m_assembler.subl_mr(src.offset, src.base, dest);
-        else
-            m_assembler.subl_mr(src.base, dest);
+        m_assembler.subl_mr(src.offset, src.base, dest);
     }
 
     void xor32(RegisterID src, RegisterID dest)
@@ -529,10 +505,7 @@ public:
 
     void xor32(Imm32 imm, RegisterID dest)
     {
-        if (CAN_SIGN_EXTEND_8_32(imm.m_value))
-            m_assembler.xorl_i8r(imm.m_value, dest);
-        else
-            m_assembler.xorl_i32r(imm.m_value, dest);
+        m_assembler.xorl_ir(imm.m_value, dest);
     }
     
 
@@ -546,10 +519,7 @@ public:
     void loadPtr(ImplicitAddress address, RegisterID dest)
     {
 #if PLATFORM(X86_64)
-        if (address.offset)
-            m_assembler.movq_mr(address.offset, address.base, dest);
-        else
-            m_assembler.movq_mr(address.base, dest);
+        m_assembler.movq_mr(address.offset, address.base, dest);
 #else
     load32(address, dest);
 #endif
@@ -569,18 +539,12 @@ public:
 
     void load32(ImplicitAddress address, RegisterID dest)
     {
-        if (address.offset)
-            m_assembler.movl_mr(address.offset, address.base, dest);
-        else
-            m_assembler.movl_mr(address.base, dest);
+        m_assembler.movl_mr(address.offset, address.base, dest);
     }
 
     void load32(BaseIndex address, RegisterID dest)
     {
-        if (address.offset)
-            m_assembler.movl_mr(address.offset, address.base, address.index, address.scale, dest);
-        else
-            m_assembler.movl_mr(address.base, address.index, address.scale, dest);
+        m_assembler.movl_mr(address.offset, address.base, address.index, address.scale, dest);
     }
 
 #if !PLATFORM(X86_64)
@@ -592,34 +556,22 @@ public:
 
     void load16(BaseIndex address, RegisterID dest)
     {
-        if (address.offset)
-            m_assembler.movzwl_mr(address.offset, address.base, address.index, address.scale, dest);
-        else
-            m_assembler.movzwl_mr(address.base, address.index, address.scale, dest);
+        m_assembler.movzwl_mr(address.offset, address.base, address.index, address.scale, dest);
     }
 
     void storePtr(RegisterID src, ImplicitAddress address)
     {
 #if PLATFORM(X86_64)
-        if (address.offset)
-            m_assembler.movq_rm(src, address.offset, address.base);
-        else
-            m_assembler.movq_rm(src, address.base);
+        m_assembler.movq_rm(src, address.offset, address.base);
 #else
-        if (address.offset)
-            m_assembler.movl_rm(src, address.offset, address.base);
-        else
-            m_assembler.movl_rm(src, address.base);
+        m_assembler.movl_rm(src, address.offset, address.base);
 #endif
     }
     
 #if !PLATFORM(X86_64)
     void storePtr(ImmPtr imm, ImplicitAddress address)
     {
-        if (address.offset)
-            m_assembler.movl_i32m(reinterpret_cast<unsigned>(imm.m_value), address.offset, address.base);
-        else
-            m_assembler.movl_i32m(reinterpret_cast<unsigned>(imm.m_value), address.base);
+        m_assembler.movl_i32m(reinterpret_cast<unsigned>(imm.m_value), address.offset, address.base);
     }
 
     void storePtr(RegisterID src, BaseIndex address)
@@ -629,36 +581,24 @@ public:
 
     DataLabelPtr storePtrWithRepatch(Address address)
     {
-        if (address.offset)
-            m_assembler.movl_i32m(0, address.offset, address.base);
-        else
-            m_assembler.movl_i32m(0, address.base);
+        m_assembler.movl_i32m(0, address.offset, address.base);
         return DataLabelPtr(this);
     }
 #endif
 
     void store32(RegisterID src, ImplicitAddress address)
     {
-        if (address.offset)
-            m_assembler.movl_rm(src, address.offset, address.base);
-        else
-            m_assembler.movl_rm(src, address.base);
+        m_assembler.movl_rm(src, address.offset, address.base);
     }
 
     void store32(RegisterID src, BaseIndex address)
     {
-        if (address.offset)
-            m_assembler.movl_rm(src, address.offset, address.base, address.index, address.scale);
-        else
-            m_assembler.movl_rm(src, address.base, address.index, address.scale);
+        m_assembler.movl_rm(src, address.offset, address.base, address.index, address.scale);
     }
 
     void store32(Imm32 imm, ImplicitAddress address)
     {
-        if (address.offset)
-            m_assembler.movl_i32m(imm.m_value, address.offset, address.base);
-        else
-            m_assembler.movl_i32m(imm.m_value, address.base);
+        m_assembler.movl_i32m(imm.m_value, address.offset, address.base);
     }
     
 #if !PLATFORM(X86_64)
@@ -679,20 +619,12 @@ public:
     
     void pop(RegisterID dest)
     {
-#if PLATFORM(X86_64)
-        m_assembler.popq_r(dest);
-#else
-        m_assembler.popl_r(dest);
-#endif
+        m_assembler.pop_r(dest);
     }
 
     void push(RegisterID src)
     {
-#if PLATFORM(X86_64)
-        m_assembler.pushq_r(src);
-#else
-        m_assembler.pushl_r(src);
-#endif
+        m_assembler.push_r(src);
     }
 
     void pop()
@@ -754,6 +686,15 @@ public:
     }
 #endif
 
+    void swap(RegisterID reg1, RegisterID reg2)
+    {
+#if PLATFORM(X86_64)
+        m_assembler.xchgq_rr(reg1, reg2);
+#else
+        m_assembler.xchgl_rr(reg1, reg2);
+#endif
+    }
+
 
     // Forwards / external control flow operations:
     //
@@ -776,35 +717,20 @@ public:
 private:
     void compareImm32ForBranch(RegisterID left, int32_t right)
     {
-        if (CAN_SIGN_EXTEND_8_32(right))
-            m_assembler.cmpl_i8r(right, left);
-        else
-            m_assembler.cmpl_i32r(right, left);
+        m_assembler.cmpl_ir(right, left);
     }
 
     void compareImm32ForBranchEquality(RegisterID reg, int32_t imm)
     {
         if (!imm)
             m_assembler.testl_rr(reg, reg);
-        else if (CAN_SIGN_EXTEND_8_32(imm))
-            m_assembler.cmpl_i8r(imm, reg);
         else
-            m_assembler.cmpl_i32r(imm, reg);
+            m_assembler.cmpl_ir(imm, reg);
     }
 
     void compareImm32ForBranchEquality(Address address, int32_t imm)
     {
-        if (CAN_SIGN_EXTEND_8_32(imm)) {
-            if (address.offset)
-                m_assembler.cmpl_i8m(imm, address.offset, address.base);
-            else
-                m_assembler.cmpl_i8m(imm, address.base);
-        } else {
-            if (address.offset)
-                m_assembler.cmpl_i32m(imm, address.offset, address.base);
-            else
-                m_assembler.cmpl_i32m(imm, address.base);
-        }
+        m_assembler.cmpl_im(imm, address.offset, address.base);
     }
 
     void testImm32(RegisterID reg, Imm32 mask)
@@ -820,32 +746,18 @@ private:
 
     void testImm32(Address address, Imm32 mask)
     {
-        if (address.offset) {
-            if (mask.m_value == -1)
-                m_assembler.cmpl_i8m(0, address.offset, address.base);
-            else
-                m_assembler.testl_i32m(mask.m_value, address.offset, address.base);
-        } else {
-            if (mask.m_value == -1)
-                m_assembler.cmpl_i8m(0, address.base);
-            else
-                m_assembler.testl_i32m(mask.m_value, address.base);
-        }
+        if (mask.m_value == -1)
+            m_assembler.cmpl_im(0, address.offset, address.base);
+        else
+            m_assembler.testl_i32m(mask.m_value, address.offset, address.base);
     }
 
     void testImm32(BaseIndex address, Imm32 mask)
     {
-        if (address.offset) {
-            if (mask.m_value == -1)
-                m_assembler.cmpl_i8m(0, address.offset, address.base, address.index, address.scale);
-            else
-                m_assembler.testl_i32m(mask.m_value, address.offset, address.base, address.index, address.scale);
-        } else {
-            if (mask.m_value == -1)
-                m_assembler.cmpl_i8m(0, address.base, address.index, address.scale);
-            else
-                m_assembler.testl_i32m(mask.m_value, address.base, address.index, address.scale);
-        }
+        if (mask.m_value == -1)
+            m_assembler.cmpl_im(0, address.offset, address.base, address.index, address.scale);
+        else
+            m_assembler.testl_i32m(mask.m_value, address.offset, address.base, address.index, address.scale);
     }
 
 #if PLATFORM(X86_64)
@@ -870,28 +782,19 @@ public:
     
     Jump jae32(RegisterID left, Address right)
     {
-        if (right.offset)
-            m_assembler.cmpl_mr(right.offset, right.base, left);
-        else
-            m_assembler.cmpl_mr(right.base, left);
+        m_assembler.cmpl_mr(right.offset, right.base, left);
         return Jump(m_assembler.jae());
     }
     
     Jump jae32(Address left, RegisterID right)
     {
-        if (left.offset)
-            m_assembler.cmpl_rm(right, left.offset, left.base);
-        else
-            m_assembler.cmpl_rm(right, left.base);
+        m_assembler.cmpl_rm(right, left.offset, left.base);
         return Jump(m_assembler.jae());
     }
     
     Jump jb32(RegisterID left, Address right)
     {
-        if (right.offset)
-            m_assembler.cmpl_mr(right.offset, right.base, left);
-        else
-            m_assembler.cmpl_mr(right.base, left);
+        m_assembler.cmpl_mr(right.offset, right.base, left);
         return Jump(m_assembler.jb());
     }
     
@@ -928,11 +831,7 @@ public:
     
     Jump je16(RegisterID op1, BaseIndex op2)
     {
-        if (op2.offset)
-            m_assembler.cmpw_rm(op1, op2.base, op2.index, op2.scale);
-        else
-            m_assembler.cmpw_rm(op1, op2.offset, op2.base, op2.index, op2.scale);
-
+        m_assembler.cmpw_rm(op1, op2.offset, op2.base, op2.index, op2.scale);
         return Jump(m_assembler.je());
     }
     
@@ -944,10 +843,7 @@ public:
 
     Jump jg32(RegisterID reg, Address address)
     {
-        if (address.offset)
-            m_assembler.cmpl_mr(address.offset, address.base, reg);
-        else
-            m_assembler.cmpl_mr(address.base, reg);
+        m_assembler.cmpl_mr(address.offset, address.base, reg);
         return Jump(m_assembler.jg());
     }
 
@@ -990,10 +886,7 @@ public:
 #if !PLATFORM(X86_64)
     Jump jnePtr(RegisterID reg, Address address)
     {
-        if (address.offset)
-            m_assembler.cmpl_rm(reg, address.offset, address.base);
-        else
-            m_assembler.cmpl_rm(reg, address.base);
+        m_assembler.cmpl_rm(reg, address.offset, address.base);
         return Jump(m_assembler.jne());
     }
 
@@ -1023,10 +916,7 @@ public:
     
     Jump jne32(Address address, RegisterID reg)
     {
-        if (address.offset)
-            m_assembler.cmpl_rm(reg, address.offset, address.base);
-        else
-            m_assembler.cmpl_rm(reg, address.base);
+        m_assembler.cmpl_rm(reg, address.offset, address.base);
         return Jump(m_assembler.jne());
     }
     
@@ -1175,10 +1065,7 @@ public:
     // Address is a memory location containing the address to jump to
     void jump(Address address)
     {
-        if (address.offset)
-            m_assembler.jmp_m(address.offset, address.base);
-        else
-            m_assembler.jmp_m(address.base);
+        m_assembler.jmp_m(address.offset, address.base);
     }
 
 
index 7360876..ef2aeb9 100644 (file)
@@ -37,8 +37,6 @@
 
 namespace JSC {
 
-#define MODRM(type, reg, rm) ((type << 6) | (reg << 3) | (rm))
-#define SIB(type, reg, rm) MODRM(type, reg, rm)
 #define CAN_SIGN_EXTEND_8_32(value) (value == ((int)(signed char)value))
 
 namespace X86 {
@@ -52,9 +50,16 @@ namespace X86 {
         esi,
         edi,
 
-        noBase = ebp,
-        hasSib = esp,
-        noScale = esp,
+#if PLATFORM(X86_64)
+        r8,
+        r9,
+        r10,
+        r11,
+        r12,
+        r13,
+        r14,
+        r15,
+#endif
     } RegisterID;
 
     typedef enum {
@@ -87,7 +92,9 @@ public:
         OP_XOR_EvGv                     = 0x31,
         OP_CMP_EvGv                     = 0x39,
         OP_CMP_GvEv                     = 0x3B,
-        REX_W                           = 0x48,
+#if PLATFORM(X86_64)
+        PRE_REX                         = 0x40,
+#endif
         OP_PUSH_EAX                     = 0x50,
         OP_POP_EAX                      = 0x58,
         PRE_OPERAND_SIZE                = 0x66,
@@ -103,8 +110,6 @@ public:
         OP_LEA                          = 0x8D,
         OP_GROUP1A_Ev                   = 0x8F,
         OP_CDQ                          = 0x99,
-        OP_SETE                         = 0x94,
-        OP_SETNE                        = 0x95,
         OP_GROUP2_EvIb                  = 0xC1,
         OP_RET                          = 0xC3,
         OP_GROUP11_EvIz                 = 0xC7,
@@ -119,7 +124,9 @@ public:
         OP_GROUP3_Ev                    = 0xF7,
         OP_GROUP3_EvIz                  = 0xF7, // OP_GROUP3_Ev has an immediate, when instruction is a test. 
         OP_GROUP5_Ev                    = 0xFF,
+    } OneByteOpcodeID;
 
+    typedef enum {
         OP2_MOVSD_VsdWsd    = 0x10,
         OP2_MOVSD_WsdVsd    = 0x11,
         OP2_CVTSI2SD_VsdEd  = 0x2A,
@@ -142,11 +149,15 @@ public:
         OP2_JGE_rel32       = 0x8D,
         OP2_JLE_rel32       = 0x8E,
         OP2_JG_rel32        = 0x8F,
+        OP_SETE             = 0x94,
+        OP_SETNE            = 0x95,
         OP2_IMUL_GvEv       = 0xAF,
         OP2_MOVZX_GvEb      = 0xB6,
         OP2_MOVZX_GvEw      = 0xB7,
         OP2_PEXTRW_GdUdIb   = 0xC5,
+    } TwoByteOpcodeID;
 
+    typedef enum {
         GROUP1_OP_ADD = 0,
         GROUP1_OP_OR  = 1,
         GROUP1_OP_AND = 4,
@@ -167,12 +178,15 @@ public:
         GROUP5_OP_PUSH  = 6,
 
         GROUP11_MOV = 0,
-    } OpcodeID;
+    } GroupOpcodeID;
     
     // Opaque label types
     
+    class X86InstructionFormatter;
+
     class JmpSrc {
         friend class X86Assembler;
+        friend class X86InstructionFormatter;
     public:
         JmpSrc()
             : m_offset(-1)
@@ -190,6 +204,7 @@ public:
     
     class JmpDst {
         friend class X86Assembler;
+        friend class X86InstructionFormatter;
     public:
         JmpDst()
             : m_offset(-1)
@@ -205,955 +220,704 @@ public:
         int m_offset;
     };
 
-    static const int maxInstructionSize = 16;
-
     X86Assembler()
     {
     }
 
-    size_t size() const { return m_buffer.size(); }
-    
-    void int3()
-    {
-        m_buffer.putByte(OP_INT3);
-    }
-    
-#if PLATFORM(X86_64)
-    void pushq_r(RegisterID reg)
-    {
-        m_buffer.putByte(OP_PUSH_EAX + reg);
-    }
-
-    void popq_r(RegisterID reg)
-    {
-        m_buffer.putByte(OP_POP_EAX + reg);
-    }
-#else
-    void pushl_r(RegisterID reg)
-    {
-        m_buffer.putByte(OP_PUSH_EAX + reg);
-    }
-    
-    void pushl_m(int offset, RegisterID base)
-    {
-        m_buffer.putByte(OP_GROUP5_Ev);
-        modRm_opm(GROUP5_OP_PUSH, base, offset);
-    }
-
-    void pushl_i32(int imm)
-    {
-        m_buffer.putByte(OP_PUSH_Iz);
-        m_buffer.putInt(imm);
-    }
-    
-    void popl_r(RegisterID reg)
-    {
-        m_buffer.putByte(OP_POP_EAX + reg);
-    }
+    size_t size() const { return m_formatter.size(); }
 
-    void popl_m(int offset, RegisterID base)
-    {
-        m_buffer.putByte(OP_GROUP1A_Ev);
-        modRm_opm(GROUP1A_OP_POP, base, offset);
-    }
-#endif
-    
-    void movl_rr(RegisterID src, RegisterID dst)
-    {
-        m_buffer.putByte(OP_MOV_EvGv);
-        modRm_rr(src, dst);
-    }
-    
-#if PLATFORM(X86_64)
-    void movq_rr(RegisterID src, RegisterID dst)
-    {
-        m_buffer.putByte(REX_W);
-        m_buffer.putByte(OP_MOV_EvGv);
-        modRm_rr(src, dst);
-    }
-#endif
+    // Stack operations:
 
-    void addl_rr(RegisterID src, RegisterID dst)
+    void push_r(RegisterID reg)
     {
-        m_buffer.putByte(OP_ADD_EvGv);
-        modRm_rr(src, dst);
+        m_formatter.oneByteOp(OP_PUSH_EAX, reg);
     }
 
-#if !PLATFORM(X86_64)
-    void addl_i8m(int imm, void* addr)
+    void pop_r(RegisterID reg)
     {
-        m_buffer.putByte(OP_GROUP1_EvIb);
-        modRm_opm(GROUP1_OP_ADD, addr);
-        m_buffer.putByte(imm);
+        m_formatter.oneByteOp(OP_POP_EAX, reg);
     }
-#endif
 
-    void addl_i8r(int imm, RegisterID dst)
+    void push_i32(int imm)
     {
-        m_buffer.putByte(OP_GROUP1_EvIb);
-        modRm_opr(GROUP1_OP_ADD, dst);
-        m_buffer.putByte(imm);
+        m_formatter.oneByteOp(OP_PUSH_Iz);
+        m_formatter.immediate32(imm);
     }
 
-    void addl_i32r(int imm, RegisterID dst)
+    void push_m(int offset, RegisterID base)
     {
-        m_buffer.putByte(OP_GROUP1_EvIz);
-        modRm_opr(GROUP1_OP_ADD, dst);
-        m_buffer.putInt(imm);
+        m_formatter.oneByteOp(OP_GROUP5_Ev, GROUP5_OP_PUSH, base, offset);
     }
 
-#if PLATFORM(X86_64)
-    void addq_i8r(int imm, RegisterID dst)
+    void pop_m(int offset, RegisterID base)
     {
-        m_buffer.putByte(REX_W);
-        m_buffer.putByte(OP_GROUP1_EvIb);
-        modRm_opr(GROUP1_OP_ADD, dst);
-        m_buffer.putByte(imm);
+        m_formatter.oneByteOp(OP_GROUP1A_Ev, GROUP1A_OP_POP, base, offset);
     }
 
-    void addq_i32r(int imm, RegisterID dst)
-    {
-        m_buffer.putByte(REX_W);
-        m_buffer.putByte(OP_GROUP1_EvIz);
-        modRm_opr(GROUP1_OP_ADD, dst);
-        m_buffer.putInt(imm);
-    }
-#endif
+    // Arithmetic operations:
 
-    void addl_mr(RegisterID base, RegisterID dst)
+    void addl_rr(RegisterID src, RegisterID dst)
     {
-        m_buffer.putByte(OP_ADD_GvEv);
-        modRm_rm(dst, base);
+        m_formatter.oneByteOp(OP_ADD_EvGv, src, dst);
     }
 
     void addl_mr(int offset, RegisterID base, RegisterID dst)
     {
-        m_buffer.putByte(OP_ADD_GvEv);
-        modRm_rm(dst, base, offset);
-    }
-
-    void andl_rr(RegisterID src, RegisterID dst)
-    {
-        m_buffer.putByte(OP_AND_EvGv);
-        modRm_rr(src, dst);
+        m_formatter.oneByteOp(OP_ADD_GvEv, dst, base, offset);
     }
 
-    void andl_i8r(int imm, RegisterID dst)
+    void addl_ir(int imm, RegisterID dst)
     {
-        m_buffer.putByte(OP_GROUP1_EvIb);
-        modRm_opr(GROUP1_OP_AND, dst);
-        m_buffer.putByte(imm);
+        if (CAN_SIGN_EXTEND_8_32(imm)) {
+            m_formatter.oneByteOp(OP_GROUP1_EvIb, GROUP1_OP_ADD, dst);
+            m_formatter.immediate8(imm);
+        } else {
+            m_formatter.oneByteOp(OP_GROUP1_EvIz, GROUP1_OP_ADD, dst);
+            m_formatter.immediate32(imm);
+        }
     }
 
-    void andl_i32r(int imm, RegisterID dst)
+#if PLATFORM(X86_64)
+    void addq_ir(int imm, RegisterID dst)
     {
-        m_buffer.putByte(OP_GROUP1_EvIz);
-        modRm_opr(GROUP1_OP_AND, dst);
-        m_buffer.putInt(imm);
+        if (CAN_SIGN_EXTEND_8_32(imm)) {
+            m_formatter.oneByteOp64(OP_GROUP1_EvIb, GROUP1_OP_ADD, dst);
+            m_formatter.immediate8(imm);
+        } else {
+            m_formatter.oneByteOp64(OP_GROUP1_EvIz, GROUP1_OP_ADD, dst);
+            m_formatter.immediate32(imm);
+        }
     }
-
-    void cmpl_i8r(int imm, RegisterID dst)
+#else
+    void addl_im(int imm, void* addr)
     {
-        m_buffer.putByte(OP_GROUP1_EvIb);
-        modRm_opr(GROUP1_OP_CMP, dst);
-        m_buffer.putByte(imm);
+        if (CAN_SIGN_EXTEND_8_32(imm)) {
+            m_formatter.oneByteOp(OP_GROUP1_EvIb, GROUP1_OP_ADD, addr);
+            m_formatter.immediate8(imm);
+        } else {
+            m_formatter.oneByteOp(OP_GROUP1_EvIz, GROUP1_OP_ADD, addr);
+            m_formatter.immediate32(imm);
+        }
     }
+#endif
 
-    void cmpl_rr(RegisterID src, RegisterID dst)
+    void andl_rr(RegisterID src, RegisterID dst)
     {
-        m_buffer.putByte(OP_CMP_EvGv);
-        modRm_rr(src, dst);
+        m_formatter.oneByteOp(OP_AND_EvGv, src, dst);
     }
 
-    void cmpl_rm(RegisterID src, RegisterID base)
+    void andl_ir(int imm, RegisterID dst)
     {
-        m_buffer.putByte(OP_CMP_EvGv);
-        modRm_rm(src, base);
+        if (CAN_SIGN_EXTEND_8_32(imm)) {
+            m_formatter.oneByteOp(OP_GROUP1_EvIb, GROUP1_OP_AND, dst);
+            m_formatter.immediate8(imm);
+        } else {
+            m_formatter.oneByteOp(OP_GROUP1_EvIz, GROUP1_OP_AND, dst);
+            m_formatter.immediate32(imm);
+        }
     }
 
-    void cmpl_rm(RegisterID src, int offset, RegisterID base)
+    void orl_rr(RegisterID src, RegisterID dst)
     {
-        m_buffer.putByte(OP_CMP_EvGv);
-        modRm_rm(src, base, offset);
+        m_formatter.oneByteOp(OP_OR_EvGv, src, dst);
     }
 
-    void cmpl_mr(RegisterID base, RegisterID dst)
+    void orl_mr(int offset, RegisterID base, RegisterID dst)
     {
-        m_buffer.putByte(OP_CMP_GvEv);
-        modRm_rm(dst, base);
+        m_formatter.oneByteOp(OP_OR_GvEv, dst, base, offset);
     }
 
-    void cmpl_mr(int offset, RegisterID base, RegisterID dst)
+    void orl_ir(int imm, RegisterID dst)
     {
-        m_buffer.putByte(OP_CMP_GvEv);
-        modRm_rm(dst, base, offset);
+        if (CAN_SIGN_EXTEND_8_32(imm)) {
+            m_formatter.oneByteOp(OP_GROUP1_EvIb, GROUP1_OP_OR, dst);
+            m_formatter.immediate8(imm);
+        } else {
+            m_formatter.oneByteOp(OP_GROUP1_EvIz, GROUP1_OP_OR, dst);
+            m_formatter.immediate32(imm);
+        }
     }
 
-    void cmpl_i32r(int imm, RegisterID dst)
+    void subl_rr(RegisterID src, RegisterID dst)
     {
-        m_buffer.putByte(OP_GROUP1_EvIz);
-        modRm_opr(GROUP1_OP_CMP, dst);
-        m_buffer.putInt(imm);
+        m_formatter.oneByteOp(OP_SUB_EvGv, src, dst);
     }
 
-    void cmpl_i32m(int imm, RegisterID dst)
+    void subl_mr(int offset, RegisterID base, RegisterID dst)
     {
-        m_buffer.putByte(OP_GROUP1_EvIz);
-        modRm_opm(GROUP1_OP_CMP, dst);
-        m_buffer.putInt(imm);
+        m_formatter.oneByteOp(OP_SUB_GvEv, dst, base, offset);
     }
 
-    void cmpl_i32m(int imm, int offset, RegisterID dst)
+    void subl_ir(int imm, RegisterID dst)
     {
-        m_buffer.putByte(OP_GROUP1_EvIz);
-        modRm_opm(GROUP1_OP_CMP, dst, offset);
-        m_buffer.putInt(imm);
+        if (CAN_SIGN_EXTEND_8_32(imm)) {
+            m_formatter.oneByteOp(OP_GROUP1_EvIb, GROUP1_OP_SUB, dst);
+            m_formatter.immediate8(imm);
+        } else {
+            m_formatter.oneByteOp(OP_GROUP1_EvIz, GROUP1_OP_SUB, dst);
+            m_formatter.immediate32(imm);
+        }
     }
-
+    
 #if !PLATFORM(X86_64)
-    void cmpl_i32m(int imm, void* addr)
+    void subl_im(int imm, void* addr)
     {
-        m_buffer.putByte(OP_GROUP1_EvIz);
-        modRm_opm(GROUP1_OP_CMP, addr);
-        m_buffer.putInt(imm);
+        if (CAN_SIGN_EXTEND_8_32(imm)) {
+            m_formatter.oneByteOp(OP_GROUP1_EvIb, GROUP1_OP_SUB, addr);
+            m_formatter.immediate8(imm);
+        } else {
+            m_formatter.oneByteOp(OP_GROUP1_EvIz, GROUP1_OP_SUB, addr);
+            m_formatter.immediate32(imm);
+        }
     }
 #endif
 
-    void cmpl_i8m(int imm, RegisterID dst)
-    {
-        m_buffer.putByte(OP_GROUP1_EvIb);
-        modRm_opm(GROUP1_OP_CMP, dst);
-        m_buffer.putByte(imm);
-    }
-
-    void cmpl_i8m(int imm, int offset, RegisterID dst)
+    void xorl_rr(RegisterID src, RegisterID dst)
     {
-        m_buffer.putByte(OP_GROUP1_EvIb);
-        modRm_opm(GROUP1_OP_CMP, dst, offset);
-        m_buffer.putByte(imm);
+        m_formatter.oneByteOp(OP_XOR_EvGv, src, dst);
     }
 
-    void cmpl_i8m(int imm, RegisterID base, RegisterID index, int scale)
+    void xorl_ir(int imm, RegisterID dst)
     {
-        m_buffer.putByte(OP_GROUP1_EvIb);
-        modRm_opmsib(GROUP1_OP_CMP, base, index, scale);
-        m_buffer.putByte(imm);
+        if (CAN_SIGN_EXTEND_8_32(imm)) {
+            m_formatter.oneByteOp(OP_GROUP1_EvIb, GROUP1_OP_XOR, dst);
+            m_formatter.immediate8(imm);
+        } else {
+            m_formatter.oneByteOp(OP_GROUP1_EvIz, GROUP1_OP_XOR, dst);
+            m_formatter.immediate32(imm);
+        }
     }
 
-    void cmpl_i8m(int imm, int offset, RegisterID base, RegisterID index, int scale)
+    void sarl_i8r(int imm, RegisterID dst)
     {
-        m_buffer.putByte(OP_GROUP1_EvIb);
-        modRm_opmsib(GROUP1_OP_CMP, base, index, scale, offset);
-        m_buffer.putByte(imm);
+        if (imm == 1)
+            m_formatter.oneByteOp(OP_GROUP2_Ev1, GROUP2_OP_SAR, dst);
+        else {
+            m_formatter.oneByteOp(OP_GROUP2_EvIb, GROUP2_OP_SAR, dst);
+            m_formatter.immediate8(imm);
+        }
     }
 
-    void cmpw_rm(RegisterID src, RegisterID base, RegisterID index, int scale)
+    void sarl_CLr(RegisterID dst)
     {
-        m_buffer.putByte(PRE_OPERAND_SIZE);
-        m_buffer.putByte(OP_CMP_EvGv);
-        modRm_rmsib(src, base, index, scale);
+        m_formatter.oneByteOp(OP_GROUP2_EvCL, GROUP2_OP_SAR, dst);
     }
 
-    void cmpw_rm(RegisterID src, int offset, RegisterID base, RegisterID index, int scale)
+    void shll_i8r(int imm, RegisterID dst)
     {
-        m_buffer.putByte(PRE_OPERAND_SIZE);
-        m_buffer.putByte(OP_CMP_EvGv);
-        modRm_rmsib(src, base, index, scale, offset);
+        if (imm == 1)
+            m_formatter.oneByteOp(OP_GROUP2_Ev1, GROUP2_OP_SHL, dst);
+        else {
+            m_formatter.oneByteOp(OP_GROUP2_EvIb, GROUP2_OP_SHL, dst);
+            m_formatter.immediate8(imm);
+        }
     }
 
-    void sete_r(RegisterID dst)
+    void shll_CLr(RegisterID dst)
     {
-        m_buffer.putByte(OP_2BYTE_ESCAPE);
-        m_buffer.putByte(OP_SETE);
-        m_buffer.putByte(MODRM(3, 0, dst));
+        m_formatter.oneByteOp(OP_GROUP2_EvCL, GROUP2_OP_SHL, dst);
     }
 
-    void setz_r(RegisterID dst)
+    void imull_rr(RegisterID src, RegisterID dst)
     {
-        sete_r(dst);
+        m_formatter.twoByteOp(OP2_IMUL_GvEv, dst, src);
     }
-
-    void setne_r(RegisterID dst)
+    
+    void imull_i32r(RegisterID src, int32_t value, RegisterID dst)
     {
-        m_buffer.putByte(OP_2BYTE_ESCAPE);
-        m_buffer.putByte(OP_SETNE);
-        m_buffer.putByte(MODRM(3, 0, dst));
+        m_formatter.oneByteOp(OP_IMUL_GvEvIz, dst, src);
+        m_formatter.immediate32(value);
     }
 
-    void setnz_r(RegisterID dst)
+    void idivl_r(RegisterID dst)
     {
-        setne_r(dst);
+        m_formatter.oneByteOp(OP_GROUP3_Ev, GROUP3_OP_IDIV, dst);
     }
 
-    void orl_rr(RegisterID src, RegisterID dst)
-    {
-        m_buffer.putByte(OP_OR_EvGv);
-        modRm_rr(src, dst);
-    }
+    // Comparisons:
 
-    void orl_mr(int offset, RegisterID base, RegisterID dst)
+    void cmpl_rr(RegisterID src, RegisterID dst)
     {
-        m_buffer.putByte(OP_OR_GvEv);
-        modRm_rm(dst, base, offset);
+        m_formatter.oneByteOp(OP_CMP_EvGv, src, dst);
     }
 
-    void orl_i8r(int imm, RegisterID dst)
+    void cmpl_rm(RegisterID src, int offset, RegisterID base)
     {
-        m_buffer.putByte(OP_GROUP1_EvIb);
-        modRm_opr(GROUP1_OP_OR, dst);
-        m_buffer.putByte(imm);
+        m_formatter.oneByteOp(OP_CMP_EvGv, src, base, offset);
     }
 
-    void orl_i32r(int imm, RegisterID dst)
+    void cmpl_mr(int offset, RegisterID base, RegisterID src)
     {
-        m_buffer.putByte(OP_GROUP1_EvIz);
-        modRm_opr(GROUP1_OP_OR, dst);
-        m_buffer.putInt(imm);
+        m_formatter.oneByteOp(OP_CMP_GvEv, src, base, offset);
     }
 
-    void subl_rr(RegisterID src, RegisterID dst)
+    void cmpl_ir(int imm, RegisterID dst)
     {
-        m_buffer.putByte(OP_SUB_EvGv);
-        modRm_rr(src, dst);
+        if (CAN_SIGN_EXTEND_8_32(imm)) {
+            m_formatter.oneByteOp(OP_GROUP1_EvIb, GROUP1_OP_CMP, dst);
+            m_formatter.immediate8(imm);
+        } else {
+            m_formatter.oneByteOp(OP_GROUP1_EvIz, GROUP1_OP_CMP, dst);
+            m_formatter.immediate32(imm);
+        }
     }
 
-    void subl_i8r(int imm, RegisterID dst)
-    {
-        m_buffer.putByte(OP_GROUP1_EvIb);
-        modRm_opr(GROUP1_OP_SUB, dst);
-        m_buffer.putByte(imm);
-    }
-    
-#if !PLATFORM(X86_64)
-    void subl_i8m(int imm, void* addr)
+    void cmpl_ir_force32(int imm, RegisterID dst)
     {
-        m_buffer.putByte(OP_GROUP1_EvIb);
-        modRm_opm(GROUP1_OP_SUB, addr);
-        m_buffer.putByte(imm);
+        m_formatter.oneByteOp(OP_GROUP1_EvIz, GROUP1_OP_CMP, dst);
+        m_formatter.immediate32(imm);
     }
-#endif
 
-    void subl_i32r(int imm, RegisterID dst)
+    void cmpl_im(int imm, int offset, RegisterID base)
     {
-        m_buffer.putByte(OP_GROUP1_EvIz);
-        modRm_opr(GROUP1_OP_SUB, dst);
-        m_buffer.putInt(imm);
+        if (CAN_SIGN_EXTEND_8_32(imm)) {
+            m_formatter.oneByteOp(OP_GROUP1_EvIb, GROUP1_OP_CMP, base, offset);
+            m_formatter.immediate8(imm);
+        } else {
+            m_formatter.oneByteOp(OP_GROUP1_EvIz, GROUP1_OP_CMP, base, offset);
+            m_formatter.immediate32(imm);
+        }
     }
 
-    void subl_mr(RegisterID base, RegisterID dst)
+    void cmpl_im(int imm, int offset, RegisterID base, RegisterID index, int scale)
     {
-        m_buffer.putByte(OP_SUB_GvEv);
-        modRm_rm(dst, base);
+        if (CAN_SIGN_EXTEND_8_32(imm)) {
+            m_formatter.oneByteOp(OP_GROUP1_EvIb, GROUP1_OP_CMP, base, index, scale, offset);
+            m_formatter.immediate8(imm);
+        } else {
+            m_formatter.oneByteOp(OP_GROUP1_EvIz, GROUP1_OP_CMP, base, index, scale, offset);
+            m_formatter.immediate32(imm);
+        }
     }
 
-    void subl_mr(int offset, RegisterID base, RegisterID dst)
+    void cmpl_im_force32(int imm, int offset, RegisterID base)
     {
-        m_buffer.putByte(OP_SUB_GvEv);
-        modRm_rm(dst, base, offset);
+        m_formatter.oneByteOp(OP_GROUP1_EvIz, GROUP1_OP_CMP, base, offset);
+        m_formatter.immediate32(imm);
     }
 
-    void testb_i8r(int imm, RegisterID dst)
+#if !PLATFORM(X86_64)
+    void cmpl_im(int imm, void* addr)
     {
-        m_buffer.ensureSpace(maxInstructionSize);
-        m_buffer.putByteUnchecked(OP_GROUP3_EbIb);
-        modRm_opr_Unchecked(GROUP3_OP_TEST, dst);
-        m_buffer.putByteUnchecked(imm);
+        if (CAN_SIGN_EXTEND_8_32(imm)) {
+            m_formatter.oneByteOp(OP_GROUP1_EvIb, GROUP1_OP_CMP, addr);
+            m_formatter.immediate8(imm);
+        } else {
+            m_formatter.oneByteOp(OP_GROUP1_EvIz, GROUP1_OP_CMP, addr);
+            m_formatter.immediate32(imm);
+        }
     }
+#endif
 
-    void testl_i32r(int imm, RegisterID dst)
+    void cmpw_rm(RegisterID src, int offset, RegisterID base, RegisterID index, int scale)
     {
-        m_buffer.ensureSpace(maxInstructionSize);
-        m_buffer.putByteUnchecked(OP_GROUP3_EvIz);
-        modRm_opr_Unchecked(GROUP3_OP_TEST, dst);
-        m_buffer.putIntUnchecked(imm);
+        m_formatter.prefix(PRE_OPERAND_SIZE);
+        m_formatter.oneByteOp(OP_CMP_EvGv, src, base, index, scale, offset);
     }
 
-    void testl_i32m(int imm, RegisterID dst)
+    void testl_rr(RegisterID src, RegisterID dst)
     {
-        m_buffer.putByte(OP_GROUP3_EvIz);
-        modRm_opm(GROUP3_OP_TEST, dst);
-        m_buffer.putInt(imm);
+        m_formatter.oneByteOp(OP_TEST_EvGv, src, dst);
     }
-
-    void testl_i32m(int imm, int offset, RegisterID dst)
+    
+    void testl_i32r(int imm, RegisterID dst)
     {
-        m_buffer.putByte(OP_GROUP3_EvIz);
-        modRm_opm(GROUP3_OP_TEST, dst, offset);
-        m_buffer.putInt(imm);
+        m_formatter.oneByteOp(OP_GROUP3_EvIz, GROUP3_OP_TEST, dst);
+        m_formatter.immediate32(imm);
     }
 
-    void testl_i32m(int imm, RegisterID base, RegisterID index, int scale)
+    void testl_i32m(int imm, int offset, RegisterID base)
     {
-        m_buffer.putByte(OP_GROUP3_EvIz);
-        modRm_opmsib(GROUP3_OP_TEST, base, index, scale);
-        m_buffer.putInt(imm);
+        m_formatter.oneByteOp(OP_GROUP3_EvIz, GROUP3_OP_TEST, base, offset);
+        m_formatter.immediate32(imm);
     }
 
     void testl_i32m(int imm, int offset, RegisterID base, RegisterID index, int scale)
     {
-        m_buffer.putByte(OP_GROUP3_EvIz);
-        modRm_opmsib(GROUP3_OP_TEST, base, index, scale, offset);
-        m_buffer.putInt(imm);
+        m_formatter.oneByteOp(OP_GROUP3_EvIz, GROUP3_OP_TEST, base, index, scale, offset);
+        m_formatter.immediate32(imm);
     }
 
-    void testl_rr(RegisterID src, RegisterID dst)
-    {
-        m_buffer.putByte(OP_TEST_EvGv);
-        modRm_rr(src, dst);
-    }
-    
 #if PLATFORM(X86_64)
-    void testq_i32r(int imm, RegisterID dst)
+    void testq_rr(RegisterID src, RegisterID dst)
     {
-        m_buffer.ensureSpace(maxInstructionSize);
-        m_buffer.putByteUnchecked(REX_W);
-        m_buffer.putByteUnchecked(OP_GROUP3_EvIz);
-        modRm_opr_Unchecked(GROUP3_OP_TEST, dst);
-        m_buffer.putIntUnchecked(imm);
+        m_formatter.oneByteOp64(OP_TEST_EvGv, src, dst);
     }
 
-    void testq_rr(RegisterID src, RegisterID dst)
+    void testq_i32r(int imm, RegisterID dst)
     {
-        m_buffer.putByte(REX_W);
-        m_buffer.putByte(OP_TEST_EvGv);
-        modRm_rr(src, dst);
+        m_formatter.oneByteOp64(OP_GROUP1_EvIz, GROUP3_OP_TEST, dst);
+        m_formatter.immediate32(imm);
     }
 #endif 
 
-    void xorl_i8r(int imm, RegisterID dst)
+    void testb_i8r(int imm, RegisterID dst)
     {
-        m_buffer.putByte(OP_GROUP1_EvIb);
-        modRm_opr(GROUP1_OP_XOR, dst);
-        m_buffer.putByte(imm);
+        m_formatter.oneByteOp8(OP_GROUP3_EbIb, GROUP3_OP_TEST, dst);
+        m_formatter.immediate8(imm);
     }
 
-    void xorl_i32r(int imm, RegisterID dst)
+    void sete_r(RegisterID dst)
     {
-        m_buffer.putByte(OP_GROUP1_EvIz);
-        modRm_opr(GROUP1_OP_XOR, dst);
-        m_buffer.putInt(imm);
+        m_formatter.twoByteOp8(OP_SETE, (GroupOpcodeID)0, dst);
     }
 
-    void xorl_rr(RegisterID src, RegisterID dst)
+    void setz_r(RegisterID dst)
     {
-        m_buffer.putByte(OP_XOR_EvGv);
-        modRm_rr(src, dst);
+        sete_r(dst);
     }
 
-    void sarl_i8r(int imm, RegisterID dst)
+    void setne_r(RegisterID dst)
     {
-        if (imm == 1) {
-            m_buffer.putByte(OP_GROUP2_Ev1);
-            modRm_opr(GROUP2_OP_SAR, dst);
-        } else {
-            m_buffer.putByte(OP_GROUP2_EvIb);
-            modRm_opr(GROUP2_OP_SAR, dst);
-            m_buffer.putByte(imm);
-        }
+        m_formatter.twoByteOp8(OP_SETNE, (GroupOpcodeID)0, dst);
     }
 
-    void sarl_CLr(RegisterID dst)
+    void setnz_r(RegisterID dst)
     {
-        m_buffer.putByte(OP_GROUP2_EvCL);
-        modRm_opr(GROUP2_OP_SAR, dst);
+        setne_r(dst);
     }
 
-    void shll_i8r(int imm, RegisterID dst)
+    // Various move ops:
+
+    void cdq()
     {
-        if (imm == 1) {
-            m_buffer.putByte(OP_GROUP2_Ev1);
-            modRm_opr(GROUP2_OP_SHL, dst);
-        } else {
-            m_buffer.putByte(OP_GROUP2_EvIb);
-            modRm_opr(GROUP2_OP_SHL, dst);
-            m_buffer.putByte(imm);
-        }
+        m_formatter.oneByteOp(OP_CDQ);
     }
 
-    void shll_CLr(RegisterID dst)
+    void xchgl_rr(RegisterID src, RegisterID dst)
     {
-        m_buffer.putByte(OP_GROUP2_EvCL);
-        modRm_opr(GROUP2_OP_SHL, dst);
+        m_formatter.oneByteOp(OP_XCHG_EvGv, src, dst);
     }
 
-    void xchgl_rr(RegisterID src, RegisterID dst)
+#if PLATFORM(X86_64)
+    void xchgq_rr(RegisterID src, RegisterID dst)
     {
-        m_buffer.putByte(OP_XCHG_EvGv);
-        modRm_rr(src, dst);
+        m_formatter.oneByteOp64(OP_XCHG_EvGv, src, dst);
     }
+#endif
 
-    void imull_rr(RegisterID src, RegisterID dst)
+    void movl_rr(RegisterID src, RegisterID dst)
     {
-        m_buffer.putByte(OP_2BYTE_ESCAPE);
-        m_buffer.putByte(OP2_IMUL_GvEv);
-        modRm_rr(dst, src);
+        m_formatter.oneByteOp(OP_MOV_EvGv, src, dst);
     }
     
-    void imull_i32r(RegisterID src, int32_t value, RegisterID dst)
+    void movl_rm(RegisterID src, int offset, RegisterID base)
     {
-        m_buffer.putByte(OP_IMUL_GvEvIz);
-        modRm_rr(dst, src);
-        m_buffer.putInt(value);
+        m_formatter.oneByteOp(OP_MOV_EvGv, src, base, offset);
     }
 
-    void idivl_r(RegisterID dst)
+    void movl_rm(RegisterID src, int offset, RegisterID base, RegisterID index, int scale)
     {
-        m_buffer.putByte(OP_GROUP3_Ev);
-        modRm_opr(GROUP3_OP_IDIV, dst);
+        m_formatter.oneByteOp(OP_MOV_EvGv, src, base, index, scale, offset);
     }
-
-    void cdq()
+    
+    void movl_mr(int offset, RegisterID base, RegisterID dst)
     {
-        m_buffer.putByte(OP_CDQ);
+        m_formatter.oneByteOp(OP_MOV_GvEv, dst, base, offset);
     }
 
-    void movl_mr(RegisterID base, RegisterID dst)
+    void movl_mr(int offset, RegisterID base, RegisterID index, int scale, RegisterID dst)
     {
-        m_buffer.putByte(OP_MOV_GvEv);
-        modRm_rm(dst, base);
+        m_formatter.oneByteOp(OP_MOV_GvEv, dst, base, index, scale, offset);
     }
 
-    void movl_mr(int offset, RegisterID base, RegisterID dst)
+    void movl_i32r(int imm, RegisterID dst)
     {
-        m_buffer.ensureSpace(maxInstructionSize);
-        m_buffer.putByteUnchecked(OP_MOV_GvEv);
-        modRm_rm_Unchecked(dst, base, offset);
+        m_formatter.oneByteOp(OP_GROUP11_EvIz, GROUP11_MOV, dst);
+        m_formatter.immediate32(imm);
     }
 
-#if PLATFORM(X86_64)
-    void movq_mr(RegisterID base, RegisterID dst)
+    void movl_i32m(int imm, int offset, RegisterID base)
     {
-        m_buffer.putByte(REX_W);
-        m_buffer.putByte(OP_MOV_GvEv);
-        modRm_rm(dst, base);
+        m_formatter.oneByteOp(OP_GROUP11_EvIz, GROUP11_MOV, base, offset);
+        m_formatter.immediate32(imm);
     }
 
-    void movq_mr(int offset, RegisterID base, RegisterID dst)
+#if PLATFORM(X86_64)
+    void movq_rr(RegisterID src, RegisterID dst)
     {
-        m_buffer.ensureSpace(maxInstructionSize);
-        m_buffer.putByteUnchecked(REX_W);
-        m_buffer.putByteUnchecked(OP_MOV_GvEv);
-        modRm_rm_Unchecked(dst, base, offset);
+        m_formatter.oneByteOp64(OP_MOV_EvGv, src, dst);
     }
-#endif
 
-#if !PLATFORM(X86_64)
-    void movl_mr(void* addr, RegisterID dst)
+    void movq_rm(RegisterID src, int offset, RegisterID base)
     {
-        m_buffer.putByte(OP_MOV_GvEv);
-        modRm_rm(dst, addr);
+        m_formatter.oneByteOp64(OP_MOV_EvGv, src, base, offset);
     }
-#endif
 
-    void movl_mr(int offset, RegisterID base, RegisterID index, int scale, RegisterID dst)
+    void movq_mr(int offset, RegisterID base, RegisterID dst)
     {
-        m_buffer.putByte(OP_MOV_GvEv);
-        modRm_rmsib(dst, base, index, scale, offset);
+        m_formatter.oneByteOp64(OP_MOV_GvEv, dst, base, offset);
     }
-
-    void movl_mr(RegisterID base, RegisterID index, int scale, RegisterID dst)
+#else
+    void movl_mr(void* addr, RegisterID dst)
     {
-        m_buffer.putByte(OP_MOV_GvEv);
-        modRm_rmsib(dst, base, index, scale);
+        m_formatter.oneByteOp(OP_MOV_GvEv, dst, addr);
     }
 
-    void movzbl_rr(RegisterID src, RegisterID dst)
+    void movl_i32m(int imm, void* addr)
     {
-        m_buffer.putByte(OP_2BYTE_ESCAPE);
-        m_buffer.putByte(OP2_MOVZX_GvEb);
-        modRm_rr(dst, src);
+        m_formatter.oneByteOp(OP_GROUP11_EvIz, GROUP11_MOV, addr);
+        m_formatter.immediate32(imm);
     }
+#endif
 
     void movzwl_mr(int offset, RegisterID base, RegisterID dst)
     {
-        m_buffer.putByte(OP_2BYTE_ESCAPE);
-        m_buffer.putByte(OP2_MOVZX_GvEw);
-        modRm_rm(dst, base, offset);
-    }
-
-    void movzwl_mr(RegisterID base, RegisterID index, int scale, RegisterID dst)
-    {
-        m_buffer.putByte(OP_2BYTE_ESCAPE);
-        m_buffer.putByte(OP2_MOVZX_GvEw);
-        modRm_rmsib(dst, base, index, scale);
+        m_formatter.twoByteOp(OP2_MOVZX_GvEw, dst, base, offset);
     }
 
     void movzwl_mr(int offset, RegisterID base, RegisterID index, int scale, RegisterID dst)
     {
-        m_buffer.putByte(OP_2BYTE_ESCAPE);
-        m_buffer.putByte(OP2_MOVZX_GvEw);
-        modRm_rmsib(dst, base, index, scale, offset);
+        m_formatter.twoByteOp(OP2_MOVZX_GvEw, dst, base, index, scale, offset);
     }
 
-    void movl_rm(RegisterID src, RegisterID base)
+    void movzbl_rr(RegisterID src, RegisterID dst)
     {
-        m_buffer.putByte(OP_MOV_EvGv);
-        modRm_rm(src, base);
+        // In 64-bit, this may cause an unnecessary REX to be planted (if the dst register
+        // is in the range ESP-EDI, and the src would not have required a REX).  Unneeded
+        // REX prefixes are defined to be silently ignored by the processor.
+        m_formatter.twoByteOp8(OP2_MOVZX_GvEb, dst, src);
     }
 
-    void movl_rm(RegisterID src, int offset, RegisterID base)
+    void leal_mr(int offset, RegisterID base, RegisterID dst)
     {
-        m_buffer.ensureSpace(maxInstructionSize);
-        m_buffer.putByteUnchecked(OP_MOV_EvGv);
-        modRm_rm_Unchecked(src, base, offset);
+        m_formatter.oneByteOp(OP_LEA, dst, base, offset);
     }
 
-#if PLATFORM(X86_64)
-    void movq_rm(RegisterID src, RegisterID base)
+    // Flow control:
+
+    JmpSrc call()
     {
-        m_buffer.putByte(REX_W);
-        m_buffer.putByte(OP_MOV_EvGv);
-        modRm_rm(src, base);
+        m_formatter.oneByteOp(OP_CALL_rel32);
+        return m_formatter.immediateRel32();
     }
-
-    void movq_rm(RegisterID src, int offset, RegisterID base)
+    
+    JmpSrc call(RegisterID dst)
     {
-        m_buffer.ensureSpace(maxInstructionSize);
-        m_buffer.putByteUnchecked(REX_W);
-        m_buffer.putByteUnchecked(OP_MOV_EvGv);
-        modRm_rm_Unchecked(src, base, offset);
+        m_formatter.oneByteOp(OP_GROUP5_Ev, GROUP5_OP_CALLN, dst);
+        return JmpSrc(m_formatter.size());
     }
-#endif
 
-    void movl_rm(RegisterID src, RegisterID base, RegisterID index, int scale)
+    JmpSrc jmp()
     {
-        m_buffer.putByte(OP_MOV_EvGv);
-        modRm_rmsib(src, base, index, scale);
+        m_formatter.oneByteOp(OP_JMP_rel32);
+        return m_formatter.immediateRel32();
     }
     
-    void movl_rm(RegisterID src, int offset, RegisterID base, RegisterID index, int scale)
+    void jmp_r(RegisterID dst)
     {
-        m_buffer.putByte(OP_MOV_EvGv);
-        modRm_rmsib(src, base, index, scale, offset);
+        m_formatter.oneByteOp(OP_GROUP5_Ev, GROUP5_OP_JMPN, dst);
     }
     
-    void movl_i32r(int imm, RegisterID dst)
-    {
-        m_buffer.putByte(OP_GROUP11_EvIz);
-        modRm_opr(GROUP11_MOV, dst);
-        m_buffer.putInt(imm);
-    }
-
-    void movl_i32m(int imm, RegisterID base)
-    {
-        m_buffer.ensureSpace(maxInstructionSize);
-        m_buffer.putByteUnchecked(OP_GROUP11_EvIz);
-        modRm_opm_Unchecked(GROUP11_MOV, base);
-        m_buffer.putIntUnchecked(imm);
-    }
-
-    void movl_i32m(int imm, int offset, RegisterID base)
+    void jmp_m(int offset, RegisterID base)
     {
-        m_buffer.ensureSpace(maxInstructionSize);
-        m_buffer.putByteUnchecked(OP_GROUP11_EvIz);
-        modRm_opm_Unchecked(GROUP11_MOV, base, offset);
-        m_buffer.putIntUnchecked(imm);
+        m_formatter.oneByteOp(OP_GROUP5_Ev, GROUP5_OP_JMPN, base, offset);
     }
 
-#if !PLATFORM(X86_64)
-    void movl_i32m(int imm, void* addr)
+    JmpSrc jne()
     {
-        m_buffer.putByte(OP_GROUP11_EvIz);
-        modRm_opm(GROUP11_MOV, addr);
-        m_buffer.putInt(imm);
+        m_formatter.twoByteOp(OP2_JNE_rel32);
+        return m_formatter.immediateRel32();
     }
-#endif
-
-    void leal_mr(int offset, RegisterID base, RegisterID dst)
+    
+    JmpSrc jnz()
     {
-        m_buffer.putByte(OP_LEA);
-        modRm_rm(dst, base, offset);
+        return jne();
     }
 
-    void leal_mr(int offset, RegisterID index, int scale, RegisterID dst)
+    JmpSrc je()
     {
-        m_buffer.putByte(OP_LEA);
-        modRm_rmsib(dst, X86::noBase, index, scale, offset);
+        m_formatter.twoByteOp(OP2_JE_rel32);
+        return m_formatter.immediateRel32();
     }
-
-    void ret()
+    
+    JmpSrc jl()
     {
-        m_buffer.putByte(OP_RET);
+        m_formatter.twoByteOp(OP2_JL_rel32);
+        return m_formatter.immediateRel32();
     }
     
-    void jmp_r(RegisterID dst)
+    JmpSrc jb()
     {
-        m_buffer.putByte(OP_GROUP5_Ev);
-        modRm_opr(GROUP5_OP_JMPN, dst);
+        m_formatter.twoByteOp(OP2_JB_rel32);
+        return m_formatter.immediateRel32();
     }
     
-    void jmp_m(RegisterID base)
+    JmpSrc jle()
     {
-        m_buffer.putByte(OP_GROUP5_Ev);
-        modRm_opm(GROUP5_OP_JMPN, base);
+        m_formatter.twoByteOp(OP2_JLE_rel32);
+        return m_formatter.immediateRel32();
     }
     
-    void jmp_m(int offset, RegisterID base)
+    JmpSrc jbe()
     {
-        m_buffer.putByte(OP_GROUP5_Ev);
-        modRm_opm(GROUP5_OP_JMPN, base, offset);
+        m_formatter.twoByteOp(OP2_JBE_rel32);
+        return m_formatter.immediateRel32();
     }
     
-    void movsd_mr(int offset, RegisterID base, XMMRegisterID dst)
+    JmpSrc jge()
     {
-        m_buffer.putByte(PRE_SSE_F2);
-        m_buffer.putByte(OP_2BYTE_ESCAPE);
-        m_buffer.putByte(OP2_MOVSD_VsdWsd);
-        modRm_rm((RegisterID)dst, base, offset);
+        m_formatter.twoByteOp(OP2_JGE_rel32);
+        return m_formatter.immediateRel32();
     }
 
-    void movsd_rm(XMMRegisterID src, int offset, RegisterID base)
+    JmpSrc jg()
     {
-        m_buffer.putByte(PRE_SSE_F2);
-        m_buffer.putByte(OP_2BYTE_ESCAPE);
-        m_buffer.putByte(OP2_MOVSD_WsdVsd);
-        modRm_rm((RegisterID)src, base, offset);
+        m_formatter.twoByteOp(OP2_JG_rel32);
+        return m_formatter.immediateRel32();
     }
 
-    void movd_rr(XMMRegisterID src, RegisterID dst)
+    JmpSrc ja()
     {
-        m_buffer.putByte(PRE_SSE_66);
-        m_buffer.putByte(OP_2BYTE_ESCAPE);
-        m_buffer.putByte(OP2_MOVD_EdVd);
-        modRm_rr((RegisterID)src, dst);
+        m_formatter.twoByteOp(OP2_JA_rel32);
+        return m_formatter.immediateRel32();
     }
-
-    void cvtsi2sd_rr(RegisterID src, XMMRegisterID dst)
+    
+    JmpSrc jae()
     {
-        m_buffer.putByte(PRE_SSE_F2);
-        m_buffer.putByte(OP_2BYTE_ESCAPE);
-        m_buffer.putByte(OP2_CVTSI2SD_VsdEd);
-        modRm_rr((RegisterID)dst, src);
+        m_formatter.twoByteOp(OP2_JAE_rel32);
+        return m_formatter.immediateRel32();
     }
-
-    void cvttsd2si_rr(XMMRegisterID src, RegisterID dst)
+    
+    JmpSrc jo()
     {
-        m_buffer.putByte(PRE_SSE_F2);
-        m_buffer.putByte(OP_2BYTE_ESCAPE);
-        m_buffer.putByte(OP2_CVTTSD2SI_GdWsd);
-        modRm_rr(dst, (RegisterID)src);
+        m_formatter.twoByteOp(OP2_JO_rel32);
+        return m_formatter.immediateRel32();
     }
 
-    void addsd_mr(int offset, RegisterID base, XMMRegisterID dst)
+    JmpSrc jp()
     {
-        m_buffer.putByte(PRE_SSE_F2);
-        m_buffer.putByte(OP_2BYTE_ESCAPE);
-        m_buffer.putByte(OP2_ADDSD_VsdWsd);
-        modRm_rm((RegisterID)dst, base, offset);
+        m_formatter.twoByteOp(OP2_JP_rel32);
+        return m_formatter.immediateRel32();
     }
-
-    void subsd_mr(int offset, RegisterID base, XMMRegisterID dst)
+    
+    JmpSrc js()
     {
-        m_buffer.putByte(PRE_SSE_F2);
-        m_buffer.putByte(OP_2BYTE_ESCAPE);
-        m_buffer.putByte(OP2_SUBSD_VsdWsd);
-        modRm_rm((RegisterID)dst, base, offset);
+        m_formatter.twoByteOp(OP2_JS_rel32);
+        return m_formatter.immediateRel32();
     }
 
-    void mulsd_mr(int offset, RegisterID base, XMMRegisterID dst)
-    {
-        m_buffer.putByte(PRE_SSE_F2);
-        m_buffer.putByte(OP_2BYTE_ESCAPE);
-        m_buffer.putByte(OP2_MULSD_VsdWsd);
-        modRm_rm((RegisterID)dst, base, offset);
-    }
+    // SSE operations:
 
     void addsd_rr(XMMRegisterID src, XMMRegisterID dst)
     {
-        m_buffer.putByte(PRE_SSE_F2);
-        m_buffer.putByte(OP_2BYTE_ESCAPE);
-        m_buffer.putByte(OP2_ADDSD_VsdWsd);
-        modRm_rr((RegisterID)dst, (RegisterID)src);
+        m_formatter.prefix(PRE_SSE_F2);
+        m_formatter.twoByteOp(OP2_ADDSD_VsdWsd, (RegisterID)dst, (RegisterID)src);
     }
 
-    void subsd_rr(XMMRegisterID src, XMMRegisterID dst)
+    void addsd_mr(int offset, RegisterID base, XMMRegisterID dst)
     {
-        m_buffer.putByte(PRE_SSE_F2);
-        m_buffer.putByte(OP_2BYTE_ESCAPE);
-        m_buffer.putByte(OP2_SUBSD_VsdWsd);
-        modRm_rr((RegisterID)dst, (RegisterID)src);
+        m_formatter.prefix(PRE_SSE_F2);
+        m_formatter.twoByteOp(OP2_ADDSD_VsdWsd, (RegisterID)dst, base, offset);
     }
 
-    void mulsd_rr(XMMRegisterID src, XMMRegisterID dst)
+    void cvtsi2sd_rr(RegisterID src, XMMRegisterID dst)
     {
-        m_buffer.putByte(PRE_SSE_F2);
-        m_buffer.putByte(OP_2BYTE_ESCAPE);
-        m_buffer.putByte(OP2_MULSD_VsdWsd);
-        modRm_rr((RegisterID)dst, (RegisterID)src);
+        m_formatter.prefix(PRE_SSE_F2);
+        m_formatter.twoByteOp(OP2_CVTSI2SD_VsdEd, (RegisterID)dst, src);
     }
 
-    void ucomis_rr(XMMRegisterID src, XMMRegisterID dst)
+    void cvttsd2si_rr(XMMRegisterID src, RegisterID dst)
     {
-        m_buffer.putByte(PRE_SSE_66);
-        m_buffer.putByte(OP_2BYTE_ESCAPE);
-        m_buffer.putByte(OP2_UCOMISD_VsdWsd);
-        modRm_rr((RegisterID)dst, (RegisterID)src);
+        m_formatter.prefix(PRE_SSE_F2);
+        m_formatter.twoByteOp(OP2_CVTTSD2SI_GdWsd, dst, (RegisterID)src);
     }
 
-    void pextrw_irr(int whichWord, XMMRegisterID src, RegisterID dst)
+    void movd_rr(XMMRegisterID src, RegisterID dst)
     {
-        m_buffer.putByte(PRE_SSE_66);
-        m_buffer.putByte(OP_2BYTE_ESCAPE);
-        m_buffer.putByte(OP2_PEXTRW_GdUdIb);
-        modRm_rr(dst, (RegisterID)src);
-        m_buffer.putByte(whichWord);
+        m_formatter.prefix(PRE_SSE_66);
+        m_formatter.twoByteOp(OP2_MOVD_EdVd, (RegisterID)src, dst);
     }
 
-    JmpSrc call()
-    {
-        m_buffer.putByte(OP_CALL_rel32);
-        m_buffer.putInt(0); // FIXME: make this point to a global label, linked later.
-        return JmpSrc(m_buffer.size());
-    }
-    
-    JmpSrc call(RegisterID dst)
+    void movsd_rm(XMMRegisterID src, int offset, RegisterID base)
     {
-        m_buffer.putByte(OP_GROUP5_Ev);
-        modRm_opr(GROUP5_OP_CALLN, dst);
-        return JmpSrc(m_buffer.size());
+        m_formatter.prefix(PRE_SSE_F2);
+        m_formatter.twoByteOp(OP2_MOVSD_WsdVsd, (RegisterID)src, base, offset);
     }
 
-    JmpDst label()
-    {
-        return JmpDst(m_buffer.size());
-    }
-    
-    JmpDst align(int alignment)
+    void movsd_mr(int offset, RegisterID base, XMMRegisterID dst)
     {
-        while (!m_buffer.isAligned(alignment))
-            m_buffer.putByte(OP_HLT);
-
-        return label();
+        m_formatter.prefix(PRE_SSE_F2);
+        m_formatter.twoByteOp(OP2_MOVSD_VsdWsd, (RegisterID)dst, base, offset);
     }
 
-    JmpSrc jmp()
-    {
-        m_buffer.putByte(OP_JMP_rel32);
-        m_buffer.putInt(0);
-        return JmpSrc(m_buffer.size());
-    }
-    
-    JmpSrc jne()
-    {
-        m_buffer.putByte(OP_2BYTE_ESCAPE);
-        m_buffer.putByte(OP2_JNE_rel32);
-        m_buffer.putInt(0);
-        return JmpSrc(m_buffer.size());
-    }
-    
-    JmpSrc jnz()
+    void mulsd_rr(XMMRegisterID src, XMMRegisterID dst)
     {
-        return jne();
+        m_formatter.prefix(PRE_SSE_F2);
+        m_formatter.twoByteOp(OP2_MULSD_VsdWsd, (RegisterID)dst, (RegisterID)src);
     }
 
-    JmpSrc je()
-    {
-        m_buffer.ensureSpace(maxInstructionSize);
-        m_buffer.putByteUnchecked(OP_2BYTE_ESCAPE);
-        m_buffer.putByteUnchecked(OP2_JE_rel32);
-        m_buffer.putIntUnchecked(0);
-        return JmpSrc(m_buffer.size());
-    }
-    
-    JmpSrc jl()
-    {
-        m_buffer.putByte(OP_2BYTE_ESCAPE);
-        m_buffer.putByte(OP2_JL_rel32);
-        m_buffer.putInt(0);
-        return JmpSrc(m_buffer.size());
-    }
-    
-    JmpSrc jb()
-    {
-        m_buffer.putByte(OP_2BYTE_ESCAPE);
-        m_buffer.putByte(OP2_JB_rel32);
-        m_buffer.putInt(0);
-        return JmpSrc(m_buffer.size());
-    }
-    
-    JmpSrc jle()
+    void mulsd_mr(int offset, RegisterID base, XMMRegisterID dst)
     {
-        m_buffer.putByte(OP_2BYTE_ESCAPE);
-        m_buffer.putByte(OP2_JLE_rel32);
-        m_buffer.putInt(0);
-        return JmpSrc(m_buffer.size());
+        m_formatter.prefix(PRE_SSE_F2);
+        m_formatter.twoByteOp(OP2_MULSD_VsdWsd, (RegisterID)dst, base, offset);
     }
-    
-    JmpSrc jbe()
+
+    void pextrw_irr(int whichWord, XMMRegisterID src, RegisterID dst)
     {
-        m_buffer.putByte(OP_2BYTE_ESCAPE);
-        m_buffer.putByte(OP2_JBE_rel32);
-        m_buffer.putInt(0);
-        return JmpSrc(m_buffer.size());
+        m_formatter.prefix(PRE_SSE_66);
+        m_formatter.twoByteOp(OP2_PEXTRW_GdUdIb, (RegisterID)dst, (RegisterID)src);
+        m_formatter.immediate8(whichWord);
     }
-    
-    JmpSrc jge()
+
+    void subsd_rr(XMMRegisterID src, XMMRegisterID dst)
     {
-        m_buffer.putByte(OP_2BYTE_ESCAPE);
-        m_buffer.putByte(OP2_JGE_rel32);
-        m_buffer.putInt(0);
-        return JmpSrc(m_buffer.size());
+        m_formatter.prefix(PRE_SSE_F2);
+        m_formatter.twoByteOp(OP2_SUBSD_VsdWsd, (RegisterID)dst, (RegisterID)src);
     }
 
-    JmpSrc jg()
+    void subsd_mr(int offset, RegisterID base, XMMRegisterID dst)
     {
-        m_buffer.putByte(OP_2BYTE_ESCAPE);
-        m_buffer.putByte(OP2_JG_rel32);
-        m_buffer.putInt(0);
-        return JmpSrc(m_buffer.size());
+        m_formatter.prefix(PRE_SSE_F2);
+        m_formatter.twoByteOp(OP2_SUBSD_VsdWsd, (RegisterID)dst, base, offset);
     }
 
-    JmpSrc ja()
+    void ucomis_rr(XMMRegisterID src, XMMRegisterID dst)
     {
-        m_buffer.putByte(OP_2BYTE_ESCAPE);
-        m_buffer.putByte(OP2_JA_rel32);
-        m_buffer.putInt(0);
-        return JmpSrc(m_buffer.size());
+        m_formatter.prefix(PRE_SSE_66);
+        m_formatter.twoByteOp(OP2_UCOMISD_VsdWsd, (RegisterID)dst, (RegisterID)src);
     }
-    
-    JmpSrc jae()
+
+    // Misc instructions:
+
+    void int3()
     {
-        m_buffer.putByte(OP_2BYTE_ESCAPE);
-        m_buffer.putByte(OP2_JAE_rel32);
-        m_buffer.putInt(0);
-        return JmpSrc(m_buffer.size());
+        m_formatter.oneByteOp(OP_INT3);
     }
     
-    JmpSrc jo()
+    void ret()
     {
-        m_buffer.putByte(OP_2BYTE_ESCAPE);
-        m_buffer.putByte(OP2_JO_rel32);
-        m_buffer.putInt(0);
-        return JmpSrc(m_buffer.size());
+        m_formatter.oneByteOp(OP_RET);
     }
 
-    JmpSrc jp()
+    void predictNotTaken()
     {
-        m_buffer.putByte(OP_2BYTE_ESCAPE);
-        m_buffer.putByte(OP2_JP_rel32);
-        m_buffer.putInt(0);
-        return JmpSrc(m_buffer.size());
+        m_formatter.prefix(PRE_PREDICT_BRANCH_NOT_TAKEN);
     }
-    
-    JmpSrc js()
+
+    // Assembler admin methods:
+
+    JmpDst label()
     {
-        m_buffer.putByte(OP_2BYTE_ESCAPE);
-        m_buffer.putByte(OP2_JS_rel32);
-        m_buffer.putInt(0);
-        return JmpSrc(m_buffer.size());
+        return JmpDst(m_formatter.size());
     }
     
-    void predictNotTaken()
+    JmpDst align(int alignment)
     {
-        m_buffer.putByte(PRE_PREDICT_BRANCH_NOT_TAKEN);
+        while (!m_formatter.isAligned(alignment))
+            m_formatter.oneByteOp(OP_HLT);
+
+        return label();
     }
-    
+
+    // Linking & repatching:
+
     void link(JmpSrc from, JmpDst to)
     {
         ASSERT(to.m_offset != -1);
         ASSERT(from.m_offset != -1);
         
-        reinterpret_cast<int*>(reinterpret_cast<ptrdiff_t>(m_buffer.data()) + from.m_offset)[-1] = to.m_offset - from.m_offset;
+        reinterpret_cast<int*>(reinterpret_cast<ptrdiff_t>(m_formatter.data()) + from.m_offset)[-1] = to.m_offset - from.m_offset;
     }
     
     static void repatchAddress(void* code, JmpDst position, void* value)
@@ -1214,155 +978,382 @@ public:
     
     void* executableCopy(ExecutablePool* allocator)
     {
-        void* copy = m_buffer.executableCopy(allocator);
+        void* copy = m_formatter.executableCopy(allocator);
         ASSERT(copy);
         return copy;
     }
 
 private:
-    void modRm_rr(RegisterID reg, RegisterID rm)
-    {
-        m_buffer.ensureSpace(maxInstructionSize);
-        modRm_rr_Unchecked(reg, rm);
-    }
 
-    void modRm_rr_Unchecked(RegisterID reg, RegisterID rm)
-    {
-        m_buffer.putByteUnchecked(MODRM(3, reg, rm));
-    }
+    class X86InstructionFormatter {
+
+        static const int maxInstructionSize = 16;
+
+    public:
+
+        // Legacy prefix bytes:
+        //
+        // These are emmitted prior to the instruction.
+
+        void prefix(OneByteOpcodeID pre)
+        {
+            m_buffer.putByte(pre);
+        }
+
+        // Word-sized operands / no operand instruction formatters.
+        //
+        // In addition to the opcode, the following operand permutations are supported:
+        //   * None - instruction takes no operands.
+        //   * One register - the low three bits of the RegisterID are added into the opcode.
+        //   * 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).
+        //   * Three argument ModRM - a register, and a register and an offset describing a memory operand.
+        //   * Five argument ModRM - a register, and a base register, an index, scale, and offset describing a memory operand.
+        //
+        // For 32-bit x86 targets, the address operand may also be provided as a void*.
+        // On 64-bit targets REX prefixes will be planted as necessary, where high numbered registers are used.
+        //
+        // The twoByteOp methods plant two-byte Intel instructions sequences (first opcode byte 0x0F).
+
+        void oneByteOp(OneByteOpcodeID opcode)
+        {
+            m_buffer.ensureSpace(maxInstructionSize);
+            m_buffer.putByteUnchecked(opcode);
+        }
+
+        void oneByteOp(OneByteOpcodeID opcode, RegisterID reg)
+        {
+            m_buffer.ensureSpace(maxInstructionSize);
+            emitRexIfNeeded(reg, 0, 0);
+            m_buffer.putByteUnchecked(opcode + reg);
+        }
+
+        void oneByteOp(OneByteOpcodeID opcode, int reg, RegisterID rm)
+        {
+            m_buffer.ensureSpace(maxInstructionSize);
+            emitRexIfNeeded(reg, 0, rm);
+            m_buffer.putByteUnchecked(opcode);
+            registerModRM(reg, rm);
+        }
+
+        void oneByteOp(OneByteOpcodeID opcode, int reg, RegisterID base, int offset)
+        {
+            m_buffer.ensureSpace(maxInstructionSize);
+            emitRexIfNeeded(reg, 0, base);
+            m_buffer.putByteUnchecked(opcode);
+            memoryModRM(reg, base, offset);
+        }
+
+        void oneByteOp(OneByteOpcodeID opcode, int reg, RegisterID base, RegisterID index, int scale, int offset)
+        {
+            m_buffer.ensureSpace(maxInstructionSize);
+            emitRexIfNeeded(reg, index, base);
+            m_buffer.putByteUnchecked(opcode);
+            memoryModRM(reg, base, index, scale, offset);
+        }
 
 #if !PLATFORM(X86_64)
-    void modRm_rm(RegisterID reg, void* addr)
-    {
-        m_buffer.putByte(MODRM(0, reg, X86::noBase));
-        m_buffer.putInt((int)addr);
-    }
+        void oneByteOp(OneByteOpcodeID opcode, int reg, void* address)
+        {
+            m_buffer.ensureSpace(maxInstructionSize);
+            m_buffer.putByteUnchecked(opcode);
+            memoryModRM(reg, address);
+        }
 #endif
 
-    void modRm_rm_Unchecked(RegisterID reg, RegisterID base)
-    {
-        if (base == X86::esp) {
-            m_buffer.putByteUnchecked(MODRM(0, reg, X86::hasSib));
-            m_buffer.putByteUnchecked(SIB(0, X86::noScale, X86::esp));
-        } else {
-            m_buffer.putByteUnchecked(MODRM(0, reg, base));
+        void twoByteOp(TwoByteOpcodeID opcode)
+        {
+            m_buffer.ensureSpace(maxInstructionSize);
+            m_buffer.putByteUnchecked(OP_2BYTE_ESCAPE);
+            m_buffer.putByteUnchecked(opcode);
         }
-    }
 
-    void modRm_rm(RegisterID reg, RegisterID base)
-    {
-        if (base == X86::esp) {
-            m_buffer.putByte(MODRM(0, reg, X86::hasSib));
-            m_buffer.putByte(SIB(0, X86::noScale, X86::esp));
-        } else
-            m_buffer.putByte(MODRM(0, reg, base));
-    }
+        void twoByteOp(TwoByteOpcodeID opcode, int reg, RegisterID rm)
+        {
+            m_buffer.ensureSpace(maxInstructionSize);
+            emitRexIfNeeded(reg, 0, rm);
+            m_buffer.putByteUnchecked(OP_2BYTE_ESCAPE);
+            m_buffer.putByteUnchecked(opcode);
+            registerModRM(reg, rm);
+        }
 
-    void modRm_rm_Unchecked(RegisterID reg, RegisterID base, int offset)
-    {
-        if (base == X86::esp) {
-            if (CAN_SIGN_EXTEND_8_32(offset)) {
-                m_buffer.putByteUnchecked(MODRM(1, reg, X86::hasSib));
-                m_buffer.putByteUnchecked(SIB(0, X86::noScale, X86::esp));
-                m_buffer.putByteUnchecked(offset);
-            } else {
-                m_buffer.putByteUnchecked(MODRM(2, reg, X86::hasSib));
-                m_buffer.putByteUnchecked(SIB(0, X86::noScale, X86::esp));
-                m_buffer.putIntUnchecked(offset);
-            }
-        } else {
-            if (CAN_SIGN_EXTEND_8_32(offset)) {
-                m_buffer.putByteUnchecked(MODRM(1, reg, base));
-                m_buffer.putByteUnchecked(offset);
-            } else {
-                m_buffer.putByteUnchecked(MODRM(2, reg, base));
-                m_buffer.putIntUnchecked(offset);
-            }
+        void twoByteOp(TwoByteOpcodeID opcode, int reg, RegisterID base, int offset)
+        {
+            m_buffer.ensureSpace(maxInstructionSize);
+            emitRexIfNeeded(reg, 0, base);
+            m_buffer.putByteUnchecked(OP_2BYTE_ESCAPE);
+            m_buffer.putByteUnchecked(opcode);
+            memoryModRM(reg, base, offset);
         }
-    }
 
-    void modRm_rm(RegisterID reg, RegisterID base, int offset)
-    {
-        m_buffer.ensureSpace(maxInstructionSize);
-        modRm_rm_Unchecked(reg, base, offset);
-    }
+        void twoByteOp(TwoByteOpcodeID opcode, int reg, RegisterID base, RegisterID index, int scale, int offset)
+        {
+            m_buffer.ensureSpace(maxInstructionSize);
+            emitRexIfNeeded(reg, index, base);
+            m_buffer.putByteUnchecked(OP_2BYTE_ESCAPE);
+            m_buffer.putByteUnchecked(opcode);
+            memoryModRM(reg, base, index, scale, offset);
+        }
 
-    void modRm_rmsib(RegisterID reg, RegisterID base, RegisterID index, int scale)
-    {
-        int shift = 0;
-        while (scale >>= 1)
-            shift++;
-    
-        m_buffer.putByte(MODRM(0, reg, X86::hasSib));
-        m_buffer.putByte(SIB(shift, index, base));
-    }
+#if PLATFORM(X86_64)
+        // Quad-word-sized operands:
+        //
+        // Used to format 64-bit operantions, planting a REX.w prefix.
+        // When planting d64 or f64 instructions, not requiring a REX.w prefix,
+        // the normal (non-'64'-postfixed) formatters should be used.
 
-    void modRm_rmsib(RegisterID reg, RegisterID base, RegisterID index, int scale, int offset)
-    {
-        int shift = 0;
-        while (scale >>= 1)
-            shift++;
-    
-        if (CAN_SIGN_EXTEND_8_32(offset)) {
-            m_buffer.putByte(MODRM(1, reg, X86::hasSib));
-            m_buffer.putByte(SIB(shift, index, base));
-            m_buffer.putByte(offset);
-        } else {
-            m_buffer.putByte(MODRM(2, reg, X86::hasSib));
-            m_buffer.putByte(SIB(shift, index, base));
-            m_buffer.putInt(offset);
+        void oneByteOp64(OneByteOpcodeID opcode, int reg, RegisterID rm)
+        {
+            m_buffer.ensureSpace(maxInstructionSize);
+            emitRexW(reg, 0, rm);
+            m_buffer.putByteUnchecked(opcode);
+            registerModRM(reg, rm);
         }
-    }
 
-    void modRm_opr(OpcodeID opcodeID, RegisterID rm)
-    {
-        m_buffer.ensureSpace(maxInstructionSize);
-        modRm_opr_Unchecked(opcodeID, rm);
-    }
+        void oneByteOp64(OneByteOpcodeID opcode, int reg, RegisterID base, int offset)
+        {
+            m_buffer.ensureSpace(maxInstructionSize);
+            emitRexW(reg, 0, base);
+            m_buffer.putByteUnchecked(opcode);
+            memoryModRM(reg, base, offset);
+        }
 
-    void modRm_opr_Unchecked(OpcodeID opcodeID, RegisterID rm)
-    {
-        modRm_rr_Unchecked(static_cast<RegisterID>(opcodeID), rm);
-    }
+        void oneByteOp64(OneByteOpcodeID opcode, int reg, RegisterID base, RegisterID index, int scale, int offset)
+        {
+            m_buffer.ensureSpace(maxInstructionSize);
+            emitRexW(reg, index, base);
+            m_buffer.putByteUnchecked(opcode);
+            memoryModRM(reg, base, index, scale, offset);
+        }
+#endif
 
-    void modRm_opm(OpcodeID opcodeID, RegisterID base)
-    {
-        modRm_rm(static_cast<RegisterID>(opcodeID), base);
-    }
+        // Byte-operands:
+        //
+        // These methods format byte operations.  Byte operations differ from the normal
+        // formatters in the circumstances under which they will decide to emit REX prefixes.
+        // These should be used where any register operand signifies a byte register.
+        //
+        // The disctinction is due to the handling of register numbers in the range 4..7 on
+        // x86-64.  These register numbers may either represent the second byte of the first
+        // four registers (ah..bh) or the first byte of the second four registers (spl..dil).
+        //
+        // Since ah..bh cannot be used in all permutations of operands (specifically cannot
+        // be accessed where a REX prefix is present), these are likely best treated as
+        // deprecated.  In order to ensure the correct registers spl..dil are selected a
+        // REX prefix will be emitted for any byte register operand in the range 4..15.
+        //
+        // These formatters may be used in instructions where a mix of operand sizes, in which
+        // case an unnecessary REX will be emitted, for example:
+        //     movzbl %al, %edi
+        // In this case a REX will be planted since edi is 7 (and were this a byte operand
+        // a REX would be required to specify dil instead of bh).  Unneeded REX prefixes will
+        // be silently ignored by the processor.
+        //
+        // Address operands should still be checked using regRequiresRex(), while byteRegRequiresRex()
+        // is provided to check byte register operands.
+
+        void oneByteOp8(OneByteOpcodeID opcode, GroupOpcodeID groupOp, RegisterID rm)
+        {
+            m_buffer.ensureSpace(maxInstructionSize);
+            emitRexIf(byteRegRequiresRex(rm), 0, 0, rm);
+            m_buffer.putByteUnchecked(opcode);
+            registerModRM(groupOp, rm);
+        }
 
-    void modRm_opm_Unchecked(OpcodeID opcodeID, RegisterID base)
-    {
-        modRm_rm_Unchecked(static_cast<RegisterID>(opcodeID), base);
-    }
+        void twoByteOp8(TwoByteOpcodeID opcode, RegisterID reg, RegisterID rm)
+        {
+            m_buffer.ensureSpace(maxInstructionSize);
+            emitRexIf(byteRegRequiresRex(reg)|byteRegRequiresRex(rm), reg, 0, rm);
+            m_buffer.putByteUnchecked(OP_2BYTE_ESCAPE);
+            m_buffer.putByteUnchecked(opcode);
+            registerModRM(reg, rm);
+        }
 
-    void modRm_opm_Unchecked(OpcodeID opcodeID, RegisterID base, int offset)
-    {
-        modRm_rm_Unchecked(static_cast<RegisterID>(opcodeID), base, offset);
-    }
+        void twoByteOp8(TwoByteOpcodeID opcode, GroupOpcodeID groupOp, RegisterID rm)
+        {
+            m_buffer.ensureSpace(maxInstructionSize);
+            emitRexIf(byteRegRequiresRex(rm), 0, 0, rm);
+            m_buffer.putByteUnchecked(OP_2BYTE_ESCAPE);
+            m_buffer.putByteUnchecked(opcode);
+            registerModRM(groupOp, rm);
+        }
 
-    void modRm_opm(OpcodeID opcodeID, RegisterID base, int offset)
-    {
-        modRm_rm(static_cast<RegisterID>(opcodeID), base, offset);
-    }
+        // Immediates:
+        //
+        // An immedaite should be appended where appropriate after an op has been emitted.
+        // The writes are unchecked since the opcode formatters above will have ensured space.
 
-#if !PLATFORM(X86_64)
-    void modRm_opm(OpcodeID opcodeID, void* addr)
-    {
-        modRm_rm(static_cast<RegisterID>(opcodeID), addr);
-    }
+        void immediate8(int imm)
+        {
+            m_buffer.putByteUnchecked(imm);
+        }
+
+        void immediate32(int imm)
+        {
+            m_buffer.putIntUnchecked(imm);
+        }
+
+        JmpSrc immediateRel32()
+        {
+            m_buffer.putIntUnchecked(0);
+            return JmpSrc(m_buffer.size());
+        }
+
+        // Administrative methods:
+
+        size_t size() const { return m_buffer.size(); }
+        bool isAligned(int alignment) const { return m_buffer.isAligned(alignment); }
+        void* data() const { return m_buffer.data(); }
+        void* executableCopy(ExecutablePool* allocator) { return m_buffer.executableCopy(allocator); }
+
+    private:
+
+        // Internals; ModRm and REX formatters.
+
+        static const RegisterID noBase = X86::ebp;
+        static const RegisterID hasSib = X86::esp;
+        static const RegisterID noIndex = X86::esp;
+#if PLATFORM(X86_64)
+        static const RegisterID noBase2 = X86::r13;
+        static const RegisterID hasSib2 = X86::r12;
+
+        // Registers r8 & above require a REX prefixe.
+        inline bool regRequiresRex(int reg)
+        {
+            return (reg >= X86::r8);
+        }
+
+        // Byte operand register spl & above require a REX prefix (to prevent the 'H' registers be accessed).
+        inline bool byteRegRequiresRex(int reg)
+        {
+            return (reg >= X86::esp);
+        }
+
+        // Format a REX prefix byte.
+        inline void emitRex(bool w, int r, int x, int b)
+        {
+            m_buffer.putByteUnchecked(PRE_REX | ((int)w << 3) | ((r>>3)<<2) | ((x>>3)<<1) | (b>>3));
+        }
+
+        // Used to plant a REX byte with REX.w set (for 64-bit operations).
+        inline void emitRexW(int r, int x, int b)
+        {
+            emitRex(true, r, x, b);
+        }
+
+        // Used for operations with byte operands - use byteRegRequiresRex() to check register operands,
+        // regRequiresRex() to check other registers (i.e. address base & index).
+        inline void emitRexIf(bool condition, int r, int x, int b)
+        {
+            if (condition) emitRex(false, r, x, b);
+        }
+
+        // Used for word sized operations, will plant a REX prefix if necessary (if any register is r8 or above).
+        inline void emitRexIfNeeded(int r, int x, int b)
+        {
+            emitRexIf(regRequiresRex(r) || regRequiresRex(x) || regRequiresRex(b), r, x, b);
+        }
+#else
+        // No REX prefix bytes on 32-bit x86.
+        inline bool regRequiresRex(int) { return false; }
+        inline bool byteRegRequiresRex(int) { return false; }
+        inline void emitRexIf(bool, int, int, int) {}
+        inline void emitRexIfNeeded(int, int, int) {}
 #endif
 
-    void modRm_opmsib(OpcodeID opcodeID, RegisterID base, RegisterID index, int scale, int offset)
-    {
-        modRm_rmsib(static_cast<RegisterID>(opcodeID), base, index, scale, offset);
-    }
+        enum ModRmMode {
+            ModRmMemoryNoDisp,
+            ModRmMemoryDisp8,
+            ModRmMemoryDisp32,
+            ModRmRegister,
+        };
 
-    void modRm_opmsib(OpcodeID opcodeID, RegisterID base, RegisterID index, int scale)
-    {
-        modRm_rmsib(static_cast<RegisterID>(opcodeID), base, index, scale);
-    }
+        void putModRm(ModRmMode mode, int reg, RegisterID rm)
+        {
+            m_buffer.putByteUnchecked((mode << 6) | ((reg & 7) << 3) | (rm & 7));
+        }
+
+        void putModRmSib(ModRmMode mode, int reg, RegisterID base, RegisterID index, int scale)
+        {
+            ASSERT(mode != ModRmRegister);
+
+            // Encode sacle of (1,2,4,8) -> (0,1,2,3)
+            int shift = 0;
+            while (scale >>= 1)
+                shift++;
+
+            putModRm(mode, reg, hasSib);
+            m_buffer.putByteUnchecked((shift << 6) | ((index & 7) << 3) | (base & 7));
+        }
+
+        void registerModRM(int reg, RegisterID rm)
+        {
+            putModRm(ModRmRegister, reg, rm);
+        }
+
+        void memoryModRM(int reg, RegisterID base, int offset)
+        {
+            // A base of esp or r12 would be interpreted as a sib, so force a sib with no index & put the base in there.
+#if PLATFORM(X86_64)
+            if ((base == hasSib) || (base == hasSib2)) {
+#else
+            if (base == hasSib) {
+#endif
+                if (!offset) // No need to check if the base is noBase, since we know it is hasSib!
+                    putModRmSib(ModRmMemoryNoDisp, reg, base, noIndex, 0);
+                else if (CAN_SIGN_EXTEND_8_32(offset)) {
+                    putModRmSib(ModRmMemoryDisp8, reg, base, noIndex, 0);
+                    m_buffer.putByteUnchecked(offset);
+                } else {
+                    putModRmSib(ModRmMemoryDisp32, reg, base, noIndex, 0);
+                    m_buffer.putIntUnchecked(offset);
+                }
+            } else {
+#if PLATFORM(X86_64)
+                if (!offset && (base != noBase) && (base != noBase2))
+#else
+                if (!offset && (base != noBase))
+#endif
+                    putModRm(ModRmMemoryNoDisp, reg, base);
+                else if (CAN_SIGN_EXTEND_8_32(offset)) {
+                    putModRm(ModRmMemoryDisp8, reg, base);
+                    m_buffer.putByteUnchecked(offset);
+                } else {
+                    putModRm(ModRmMemoryDisp32, reg, base);
+                    m_buffer.putIntUnchecked(offset);
+                }
+            }
+        }
+    
+        void memoryModRM(int reg, RegisterID base, RegisterID index, int scale, int offset)
+        {
+            ASSERT(index != noIndex);
+
+#if PLATFORM(X86_64)
+            if (!offset && (base != noBase) && (base != noBase2))
+#else
+            if (!offset && (base != noBase))
+#endif
+                putModRmSib(ModRmMemoryNoDisp, reg, base, index, scale);
+            else if (CAN_SIGN_EXTEND_8_32(offset)) {
+                putModRmSib(ModRmMemoryDisp8, reg, base, index, scale);
+                m_buffer.putByteUnchecked(offset);
+            } else {
+                putModRmSib(ModRmMemoryDisp32, reg, base, index, scale);
+                m_buffer.putIntUnchecked(offset);
+            }
+        }
+
+#if !PLATFORM(X86_64)
+        void memoryModRM(int reg, void* address)
+        {
+            // noBase + ModRmMemoryNoDisp means noBase + ModRmMemoryDisp32!
+            putModRm(ModRmMemoryNoDisp, reg, noBase);
+            m_buffer.putIntUnchecked(reinterpret_cast<int32_t>(address));
+        }
+#endif
 
-    AssemblerBuffer m_buffer;
+        AssemblerBuffer m_buffer;
+    } m_formatter;
 };
 
 } // namespace JSC
index 83f2d57..32f7820 100644 (file)
@@ -279,7 +279,7 @@ void JIT::privateCompileMainPass()
             if (m_codeBlock->needsFullScopeChain())
                 emitCTICall(Interpreter::cti_op_end);
             emitGetVirtualRegister(currentInstruction[1].u.operand, X86::eax);
-            __ pushl_m(RegisterFile::ReturnPC * static_cast<int>(sizeof(Register)), callFrameRegister);
+            __ push_m(RegisterFile::ReturnPC * static_cast<int>(sizeof(Register)), callFrameRegister);
             __ ret();
             NEXT_OPCODE(op_end);
         }
@@ -518,7 +518,7 @@ void JIT::privateCompileMainPass()
             emitGetFromCallFrameHeader(RegisterFile::CallerFrame, callFrameRegister);
 
             // Return.
-            __ pushl_r(X86::edx);
+            __ push_r(X86::edx);
             __ ret();
 
             NEXT_OPCODE(op_ret);
@@ -932,10 +932,10 @@ void JIT::privateCompileMainPass()
         case op_throw: {
             emitPutJITStubArgFromVirtualRegister(currentInstruction[1].u.operand, 1, X86::ecx);
             emitCTICall(Interpreter::cti_op_throw);
-            __ addl_i8r(0x20, X86::esp);
-            __ popl_r(X86::ebx);
-            __ popl_r(X86::edi);
-            __ popl_r(X86::esi);
+            __ addl_ir(0x20, X86::esp);
+            __ pop_r(X86::ebx);
+            __ pop_r(X86::edi);
+            __ pop_r(X86::esi);
             __ ret();
             NEXT_OPCODE(op_throw);
         }
@@ -1723,8 +1723,8 @@ void JIT::privateCompile()
         store32(Imm32(m_interpreter->sampler()->encodeSample(m_codeBlock->instructions().begin())), m_interpreter->sampler()->sampleSlot());
 #endif
 
-    // Could use a popl_m, but would need to offset the following instruction if so.
-    __ popl_r(X86::ecx);
+    // Could use a pop_m, but would need to offset the following instruction if so.
+    __ pop_r(X86::ecx);
     emitPutToCallFrameHeader(X86::ecx, RegisterFile::ReturnPC);
 
     Jump slowRegisterFileCheck;
@@ -1829,18 +1829,18 @@ void JIT::privateCompileCTIMachineTrampolines()
     
     // Check eax is an array
     X86Assembler::JmpSrc array_failureCases1 = emitJumpIfNotJSCell(X86::eax);
-    __ cmpl_i32m(reinterpret_cast<unsigned>(m_interpreter->m_jsArrayVptr), X86::eax);
+    __ cmpl_im(reinterpret_cast<unsigned>(m_interpreter->m_jsArrayVptr), 0, X86::eax);
     X86Assembler::JmpSrc array_failureCases2 = __ jne();
 
     // Checks out okay! - get the length from the storage
     __ movl_mr(FIELD_OFFSET(JSArray, m_storage), X86::eax, X86::eax);
     __ movl_mr(FIELD_OFFSET(ArrayStorage, m_length), X86::eax, X86::eax);
 
-    __ cmpl_i32r(JSImmediate::maxImmediateInt, X86::eax);
+    __ cmpl_ir(JSImmediate::maxImmediateInt, X86::eax);
     X86Assembler::JmpSrc array_failureCases3 = __ ja();
 
     __ addl_rr(X86::eax, X86::eax);
-    __ addl_i8r(1, X86::eax);
+    __ addl_ir(1, X86::eax);
     
     __ ret();
 
@@ -1850,18 +1850,18 @@ void JIT::privateCompileCTIMachineTrampolines()
 
     // Check eax is a string
     X86Assembler::JmpSrc string_failureCases1 = emitJumpIfNotJSCell(X86::eax);
-    __ cmpl_i32m(reinterpret_cast<unsigned>(m_interpreter->m_jsStringVptr), X86::eax);
+    __ cmpl_im(reinterpret_cast<unsigned>(m_interpreter->m_jsStringVptr), 0, X86::eax);
     X86Assembler::JmpSrc string_failureCases2 = __ jne();
 
     // Checks out okay! - get the length from the Ustring.
     __ movl_mr(FIELD_OFFSET(JSString, m_value) + FIELD_OFFSET(UString, m_rep), X86::eax, X86::eax);
     __ movl_mr(FIELD_OFFSET(UString::Rep, len), X86::eax, X86::eax);
 
-    __ cmpl_i32r(JSImmediate::maxImmediateInt, X86::eax);
+    __ cmpl_ir(JSImmediate::maxImmediateInt, X86::eax);
     X86Assembler::JmpSrc string_failureCases3 = __ ja();
 
     __ addl_rr(X86::eax, X86::eax);
-    __ addl_i8r(1, X86::eax);
+    __ addl_ir(1, X86::eax);
     
     __ ret();
 
@@ -1874,18 +1874,18 @@ void JIT::privateCompileCTIMachineTrampolines()
     __ movl_mr(FIELD_OFFSET(FunctionBodyNode, m_code), X86::eax, X86::eax);
     __ testl_rr(X86::eax, X86::eax);
     X86Assembler::JmpSrc hasCodeBlock1 = __ jne();
-    __ popl_r(X86::ebx);
+    __ pop_r(X86::ebx);
     emitPutCTIParam(callFrameRegister, CTI_ARGS_callFrame);
     X86Assembler::JmpSrc callJSFunction1 = __ call();
     emitGetJITStubArg(1, X86::ecx);
     emitGetJITStubArg(3, X86::edx);
-    __ pushl_r(X86::ebx);
+    __ push_r(X86::ebx);
     __ link(hasCodeBlock1, __ label());
 
     // Check argCount matches callee arity.
     __ cmpl_rm(X86::edx, FIELD_OFFSET(CodeBlock, m_numParameters), X86::eax);
     X86Assembler::JmpSrc arityCheckOkay1 = __ je();
-    __ popl_r(X86::ebx);
+    __ pop_r(X86::ebx);
     emitPutJITStubArg(X86::ebx, 2);
     emitPutJITStubArg(X86::eax, 4);
     emitPutCTIParam(callFrameRegister, CTI_ARGS_callFrame);
@@ -1893,16 +1893,16 @@ void JIT::privateCompileCTIMachineTrampolines()
     __ movl_rr(X86::edx, callFrameRegister);
     emitGetJITStubArg(1, X86::ecx);
     emitGetJITStubArg(3, X86::edx);
-    __ pushl_r(X86::ebx);
+    __ push_r(X86::ebx);
     __ link(arityCheckOkay1, __ label());
 
     compileOpCallInitializeCallFrame();
 
-    __ popl_r(X86::ebx);
+    __ pop_r(X86::ebx);
     emitPutJITStubArg(X86::ebx, 2);
     emitPutCTIParam(callFrameRegister, CTI_ARGS_callFrame);
     X86Assembler::JmpSrc callDontLazyLinkCall = __ call();
-    __ pushl_r(X86::ebx);
+    __ push_r(X86::ebx);
 
     __ jmp_r(X86::eax);
 
@@ -1913,18 +1913,18 @@ void JIT::privateCompileCTIMachineTrampolines()
     __ movl_mr(FIELD_OFFSET(FunctionBodyNode, m_code), X86::eax, X86::eax);
     __ testl_rr(X86::eax, X86::eax);
     X86Assembler::JmpSrc hasCodeBlock2 = __ jne();
-    __ popl_r(X86::ebx);
+    __ pop_r(X86::ebx);
     emitPutCTIParam(callFrameRegister, CTI_ARGS_callFrame);
     X86Assembler::JmpSrc callJSFunction2 = __ call();
     emitGetJITStubArg(1, X86::ecx);
     emitGetJITStubArg(3, X86::edx);
-    __ pushl_r(X86::ebx);
+    __ push_r(X86::ebx);
     __ link(hasCodeBlock2, __ label());
 
     // Check argCount matches callee arity.
     __ cmpl_rm(X86::edx, FIELD_OFFSET(CodeBlock, m_numParameters), X86::eax);
     X86Assembler::JmpSrc arityCheckOkay2 = __ je();
-    __ popl_r(X86::ebx);
+    __ pop_r(X86::ebx);
     emitPutJITStubArg(X86::ebx, 2);
     emitPutJITStubArg(X86::eax, 4);
     emitPutCTIParam(callFrameRegister, CTI_ARGS_callFrame);
@@ -1932,16 +1932,16 @@ void JIT::privateCompileCTIMachineTrampolines()
     __ movl_rr(X86::edx, callFrameRegister);
     emitGetJITStubArg(1, X86::ecx);
     emitGetJITStubArg(3, X86::edx);
-    __ pushl_r(X86::ebx);
+    __ push_r(X86::ebx);
     __ link(arityCheckOkay2, __ label());
 
     compileOpCallInitializeCallFrame();
 
-    __ popl_r(X86::ebx);
+    __ pop_r(X86::ebx);
     emitPutJITStubArg(X86::ebx, 2);
     emitPutCTIParam(callFrameRegister, CTI_ARGS_callFrame);
     X86Assembler::JmpSrc callLazyLinkCall = __ call();
-    __ pushl_r(X86::ebx);
+    __ push_r(X86::ebx);
 
     __ jmp_r(X86::eax);
 
@@ -1952,18 +1952,18 @@ void JIT::privateCompileCTIMachineTrampolines()
     __ movl_mr(FIELD_OFFSET(FunctionBodyNode, m_code), X86::eax, X86::eax);
     __ testl_rr(X86::eax, X86::eax);
     X86Assembler::JmpSrc hasCodeBlock3 = __ jne();
-    __ popl_r(X86::ebx);
+    __ pop_r(X86::ebx);
     emitPutCTIParam(callFrameRegister, CTI_ARGS_callFrame);
     X86Assembler::JmpSrc callJSFunction3 = __ call();
     emitGetJITStubArg(1, X86::ecx);
     emitGetJITStubArg(3, X86::edx);
-    __ pushl_r(X86::ebx);
+    __ push_r(X86::ebx);
     __ link(hasCodeBlock3, __ label());
 
     // Check argCount matches callee arity.
     __ cmpl_rm(X86::edx, FIELD_OFFSET(CodeBlock, m_numParameters), X86::eax);
     X86Assembler::JmpSrc arityCheckOkay3 = __ je();
-    __ popl_r(X86::ebx);
+    __ pop_r(X86::ebx);
     emitPutJITStubArg(X86::ebx, 2);
     emitPutJITStubArg(X86::eax, 4);
     emitPutCTIParam(callFrameRegister, CTI_ARGS_callFrame);
@@ -1971,7 +1971,7 @@ void JIT::privateCompileCTIMachineTrampolines()
     __ movl_rr(X86::edx, callFrameRegister);
     emitGetJITStubArg(1, X86::ecx);
     emitGetJITStubArg(3, X86::edx);
-    __ pushl_r(X86::ebx);
+    __ push_r(X86::ebx);
     __ link(arityCheckOkay3, __ label());
 
     compileOpCallInitializeCallFrame();
index 3bd3fba..70c435e 100644 (file)
@@ -143,7 +143,7 @@ void JIT::putDoubleResultToJSNumberCellOrJSImmediate(X86::XMMRegisterID xmmSourc
     // ucomi will report that (0 == -0), and will report true if either input in NaN (result is unordered).
     __ link(__ jp(), resultLookedLikeImmButActuallyIsnt); // Actually was a NaN
     __ pextrw_irr(3, xmmSource, tempReg2);
-    __ cmpl_i32r(0x8000, tempReg2);
+    __ cmpl_ir(0x8000, tempReg2);
     __ link(__ je(), resultLookedLikeImmButActuallyIsnt); // Actually was -0
     // Yes it really really really is representable as a JSImmediate.
     emitFastArithIntToImmNoCheck(tempReg1);
@@ -170,7 +170,7 @@ void JIT::compileBinaryArithOp(OpcodeID opcodeID, unsigned dst, unsigned src1, u
         JmpSrc op2imm = __ jne();
         if (!types.second().definitelyIsNumber()) {
             emitJumpSlowCaseIfNotJSCell(X86::edx, src2);
-            __ cmpl_i32m(reinterpret_cast<unsigned>(numberStructure), FIELD_OFFSET(JSCell, m_structure), X86::edx);
+            __ cmpl_im(reinterpret_cast<unsigned>(numberStructure), FIELD_OFFSET(JSCell, m_structure), X86::edx);
             addSlowCase(__ jne());
         }
 
@@ -180,7 +180,7 @@ void JIT::compileBinaryArithOp(OpcodeID opcodeID, unsigned dst, unsigned src1, u
         JmpSrc op1imm = __ jne();
         if (!types.first().definitelyIsNumber()) {
             emitJumpSlowCaseIfNotJSCell(X86::eax, src1);
-            __ cmpl_i32m(reinterpret_cast<unsigned>(numberStructure), FIELD_OFFSET(JSCell, m_structure), X86::eax);
+            __ cmpl_im(reinterpret_cast<unsigned>(numberStructure), FIELD_OFFSET(JSCell, m_structure), X86::eax);
             addSlowCase(__ jne());
         }
 
@@ -217,7 +217,7 @@ void JIT::compileBinaryArithOp(OpcodeID opcodeID, unsigned dst, unsigned src1, u
         JmpSrc op1imm = __ jne();
         if (!types.first().definitelyIsNumber()) {
             emitJumpSlowCaseIfNotJSCell(X86::eax, src1);
-            __ cmpl_i32m(reinterpret_cast<unsigned>(numberStructure), FIELD_OFFSET(JSCell, m_structure), X86::eax);
+            __ cmpl_im(reinterpret_cast<unsigned>(numberStructure), FIELD_OFFSET(JSCell, m_structure), X86::eax);
             addSlowCase(__ jne());
         }
 
@@ -227,7 +227,7 @@ void JIT::compileBinaryArithOp(OpcodeID opcodeID, unsigned dst, unsigned src1, u
         JmpSrc op2imm = __ jne();
         if (!types.second().definitelyIsNumber()) {
             emitJumpSlowCaseIfNotJSCell(X86::edx, src2);
-            __ cmpl_i32m(reinterpret_cast<unsigned>(numberStructure), FIELD_OFFSET(JSCell, m_structure), X86::edx);
+            __ cmpl_im(reinterpret_cast<unsigned>(numberStructure), FIELD_OFFSET(JSCell, m_structure), X86::edx);
             addSlowCase(__ jne());
         }
 
index 5f5aca6..b0de33d 100644 (file)
@@ -217,14 +217,14 @@ void JIT::compileOpCall(OpcodeID opcodeID, Instruction* instruction, unsigned ca
         compileOpCallEvalSetupArgs(instruction);
 
         emitCTICall(Interpreter::cti_op_call_eval);
-        __ cmpl_i32r(asInteger(JSImmediate::impossibleValue()), X86::eax);
+        __ cmpl_ir(asInteger(JSImmediate::impossibleValue()), X86::eax);
         wasEval = __ jne();
     }
 
     // This plants a check for a cached JSFunction value, so we can plant a fast link to the callee.
     // This deliberately leaves the callee in ecx, used when setting up the stack frame below
     emitGetVirtualRegister(callee, X86::ecx);
-    __ cmpl_i32r(asInteger(JSImmediate::impossibleValue()), X86::ecx);
+    __ cmpl_ir_force32(asInteger(JSImmediate::impossibleValue()), X86::ecx);
     JmpDst addressOfLinkedFunctionCheck = __ label();
     addSlowCase(__ jne());
     ASSERT(X86Assembler::getDifferenceBetweenLabels(addressOfLinkedFunctionCheck, __ label()) == repatchOffsetOpCallCall);
@@ -252,7 +252,7 @@ void JIT::compileOpCall(OpcodeID opcodeID, Instruction* instruction, unsigned ca
     __ movl_i32m(argCount, (registerOffset + RegisterFile::ArgumentCount) * static_cast<int>(sizeof(Register)), X86::edi);
     __ movl_rm(X86::edi, (registerOffset + RegisterFile::CallerFrame) * static_cast<int>(sizeof(Register)), X86::edi);
     __ movl_rm(X86::edx, (registerOffset + RegisterFile::ScopeChain) * static_cast<int>(sizeof(Register)), X86::edi);
-    __ addl_i32r(registerOffset * sizeof(Register), X86::edi);
+    __ addl_ir(registerOffset * sizeof(Register), X86::edi);
 
     // Call to the callee
     m_callStructureStubCompilationInfo[callLinkInfoIndex].hotPathOther = emitNakedCall(reinterpret_cast<void*>(unreachable));
@@ -286,7 +286,7 @@ void JIT::compileOpCallSlowCase(Instruction* instruction, Vector<SlowCaseEntry>:
     // Fast check for JS function.
     __ testl_i32r(JSImmediate::TagMask, X86::ecx);
     JmpSrc callLinkFailNotObject = __ jne();
-    __ cmpl_i32m(reinterpret_cast<unsigned>(m_interpreter->m_jsFunctionVptr), X86::ecx);
+    __ cmpl_im(reinterpret_cast<unsigned>(m_interpreter->m_jsFunctionVptr), 0, X86::ecx);
     JmpSrc callLinkFailNotJSFunction = __ jne();
 
     // First, in the case of a construct, allocate the new object.
@@ -300,7 +300,7 @@ void JIT::compileOpCallSlowCase(Instruction* instruction, Vector<SlowCaseEntry>:
 
     // Speculatively roll the callframe, assuming argCount will match the arity.
     __ movl_rm(X86::edi, (RegisterFile::CallerFrame + registerOffset) * static_cast<int>(sizeof(Register)), X86::edi);
-    __ addl_i32r(registerOffset * static_cast<int>(sizeof(Register)), X86::edi);
+    __ addl_ir(registerOffset * static_cast<int>(sizeof(Register)), X86::edi);
 
     m_callStructureStubCompilationInfo[callLinkInfoIndex].callReturnLocation =
         emitNakedCall(m_interpreter->m_ctiVirtualCallPreLink);
@@ -319,7 +319,7 @@ void JIT::compileOpCallSlowCase(Instruction* instruction, Vector<SlowCaseEntry>:
     // Check for JSFunctions.
     __ testl_i32r(JSImmediate::TagMask, X86::ecx);
     JmpSrc isNotObject = __ jne();
-    __ cmpl_i32m(reinterpret_cast<unsigned>(m_interpreter->m_jsFunctionVptr), X86::ecx);
+    __ cmpl_im(reinterpret_cast<unsigned>(m_interpreter->m_jsFunctionVptr), 0, X86::ecx);
     JmpSrc isJSFunction = __ je();
 
     // This handles host functions
@@ -342,7 +342,7 @@ void JIT::compileOpCallSlowCase(Instruction* instruction, Vector<SlowCaseEntry>:
 
     // Speculatively roll the callframe, assuming argCount will match the arity.
     __ movl_rm(X86::edi, (RegisterFile::CallerFrame + registerOffset) * static_cast<int>(sizeof(Register)), X86::edi);
-    __ addl_i32r(registerOffset * static_cast<int>(sizeof(Register)), X86::edi);
+    __ addl_ir(registerOffset * static_cast<int>(sizeof(Register)), X86::edi);
     __ movl_i32r(argCount, X86::edx);
 
     emitNakedCall(m_interpreter->m_ctiVirtualCall);
index f50bb7c..031d1c2 100644 (file)
@@ -107,7 +107,7 @@ void JIT::compileGetByIdHotPath(int resultVReg, int baseVReg, Identifier*, unsig
     JmpDst hotPathBegin = __ label();
     m_propertyAccessCompilationInfo[propertyAccessInstructionIndex].hotPathBegin = hotPathBegin;
 
-    __ cmpl_i32m(repatchGetByIdDefaultStructure, FIELD_OFFSET(JSCell, m_structure), X86::eax);
+    __ cmpl_im_force32(repatchGetByIdDefaultStructure, FIELD_OFFSET(JSCell, m_structure), X86::eax);
     ASSERT(X86Assembler::getDifferenceBetweenLabels(hotPathBegin, __ label()) == repatchOffsetGetByIdStructure);
     addSlowCase(__ jne());
     ASSERT(X86Assembler::getDifferenceBetweenLabels(hotPathBegin, __ label()) == repatchOffsetGetByIdBranchToSlowCase);
@@ -158,7 +158,7 @@ void JIT::compilePutByIdHotPath(int baseVReg, Identifier*, int valueVReg, unsign
     m_propertyAccessCompilationInfo[propertyAccessInstructionIndex].hotPathBegin = hotPathBegin;
 
     // It is important that the following instruction plants a 32bit immediate, in order that it can be patched over.
-    __ cmpl_i32m(repatchGetByIdDefaultStructure, FIELD_OFFSET(JSCell, m_structure), X86::eax);
+    __ cmpl_im_force32(repatchGetByIdDefaultStructure, FIELD_OFFSET(JSCell, m_structure), X86::eax);
     ASSERT(X86Assembler::getDifferenceBetweenLabels(hotPathBegin, __ label()) == repatchOffsetPutByIdStructure);
     addSlowCase(__ jne());
 
@@ -201,29 +201,29 @@ void JIT::privateCompilePutByIdTransition(StructureStubInfo* stubInfo, Structure
     // Check eax is an object of the right Structure.
     __ testl_i32r(JSImmediate::TagMask, X86::eax);
     failureCases.append(__ jne());
-    __ cmpl_i32m(reinterpret_cast<uint32_t>(oldStructure), FIELD_OFFSET(JSCell, m_structure), X86::eax);
+    __ cmpl_im(reinterpret_cast<uint32_t>(oldStructure), FIELD_OFFSET(JSCell, m_structure), X86::eax);
     failureCases.append(__ jne());
     Vector<JmpSrc> successCases;
 
     //  ecx = baseObject
     __ movl_mr(FIELD_OFFSET(JSCell, m_structure), X86::eax, X86::ecx);
     // proto(ecx) = baseObject->structure()->prototype()
-    __ cmpl_i32m(ObjectType, FIELD_OFFSET(Structure, m_typeInfo) + FIELD_OFFSET(TypeInfo, m_type), X86::ecx);
+    __ cmpl_im(ObjectType, FIELD_OFFSET(Structure, m_typeInfo) + FIELD_OFFSET(TypeInfo, m_type), X86::ecx);
     failureCases.append(__ jne());
     __ movl_mr(FIELD_OFFSET(Structure, m_prototype), X86::ecx, X86::ecx);
     
     // ecx = baseObject->m_structure
     for (RefPtr<Structure>* it = chain->head(); *it; ++it) {
         // null check the prototype
-        __ cmpl_i32r(asInteger(jsNull()), X86::ecx);
+        __ cmpl_ir(asInteger(jsNull()), X86::ecx);
         successCases.append(__ je());
 
         // Check the structure id
-        __ cmpl_i32m(reinterpret_cast<uint32_t>(it->get()), FIELD_OFFSET(JSCell, m_structure), X86::ecx);
+        __ cmpl_im(reinterpret_cast<uint32_t>(it->get()), FIELD_OFFSET(JSCell, m_structure), X86::ecx);
         failureCases.append(__ jne());
         
         __ movl_mr(FIELD_OFFSET(JSCell, m_structure), X86::ecx, X86::ecx);
-        __ cmpl_i32m(ObjectType, FIELD_OFFSET(Structure, m_typeInfo) + FIELD_OFFSET(TypeInfo, m_type), X86::ecx);
+        __ cmpl_im(ObjectType, FIELD_OFFSET(Structure, m_typeInfo) + FIELD_OFFSET(TypeInfo, m_type), X86::ecx);
         failureCases.append(__ jne());
         __ movl_mr(FIELD_OFFSET(Structure, m_prototype), X86::ecx, X86::ecx);
     }
@@ -236,19 +236,19 @@ void JIT::privateCompilePutByIdTransition(StructureStubInfo* stubInfo, Structure
 
     // emit a call only if storage realloc is needed
     if (transitionWillNeedStorageRealloc(oldStructure, newStructure)) {
-        __ pushl_r(X86::edx);
-        __ pushl_i32(newStructure->propertyStorageCapacity());
-        __ pushl_i32(oldStructure->propertyStorageCapacity());
-        __ pushl_r(X86::eax);
+        __ push_r(X86::edx);
+        __ push_i32(newStructure->propertyStorageCapacity());
+        __ push_i32(oldStructure->propertyStorageCapacity());
+        __ push_r(X86::eax);
         callTarget = __ call();
-        __ addl_i32r(3 * sizeof(void*), X86::esp);
-        __ popl_r(X86::edx);
+        __ addl_ir(3 * sizeof(void*), X86::esp);
+        __ pop_r(X86::edx);
     }
 
     // Assumes m_refCount can be decremented easily, refcount decrement is safe as 
     // codeblock should ensure oldStructure->m_refCount > 0
-    __ subl_i8m(1, reinterpret_cast<void*>(oldStructure));
-    __ addl_i8m(1, reinterpret_cast<void*>(newStructure));
+    __ subl_im(1, reinterpret_cast<void*>(oldStructure));
+    __ addl_im(1, reinterpret_cast<void*>(newStructure));
     __ movl_i32m(reinterpret_cast<uint32_t>(newStructure), FIELD_OFFSET(JSCell, m_structure), X86::eax);
 
     // write the value
@@ -307,18 +307,18 @@ void JIT::privateCompilePatchGetArrayLength(void* returnAddress)
     ctiRepatchCallByReturnAddress(returnAddress, reinterpret_cast<void*>(Interpreter::cti_op_get_by_id_array_fail));
 
     // Check eax is an array
-    __ cmpl_i32m(reinterpret_cast<unsigned>(m_interpreter->m_jsArrayVptr), X86::eax);
+    __ cmpl_im(reinterpret_cast<unsigned>(m_interpreter->m_jsArrayVptr), 0, X86::eax);
     JmpSrc failureCases1 = __ jne();
 
     // Checks out okay! - get the length from the storage
     __ movl_mr(FIELD_OFFSET(JSArray, m_storage), X86::eax, X86::ecx);
     __ movl_mr(FIELD_OFFSET(ArrayStorage, m_length), X86::ecx, X86::ecx);
 
-    __ cmpl_i32r(JSImmediate::maxImmediateInt, X86::ecx);
+    __ cmpl_ir(JSImmediate::maxImmediateInt, X86::ecx);
     JmpSrc failureCases2 = __ ja();
 
     __ addl_rr(X86::ecx, X86::ecx);
-    __ addl_i8r(1, X86::ecx);
+    __ addl_ir(1, X86::ecx);
     __ movl_rr(X86::ecx, X86::eax);
     JmpSrc success = __ jmp();
 
@@ -380,7 +380,7 @@ void JIT::privateCompileGetByIdProto(StructureStubInfo* stubInfo, Structure* str
 
     // Check the prototype object's Structure had not changed.
     Structure** prototypeStructureAddress = &(protoObject->m_structure);
-    __ cmpl_i32m(reinterpret_cast<uint32_t>(prototypeStructure), prototypeStructureAddress);
+    __ cmpl_im(reinterpret_cast<uint32_t>(prototypeStructure), prototypeStructureAddress);
     JmpSrc failureCases2 = __ jne();
 
     // Checks out okay! - getDirectOffset
@@ -419,7 +419,7 @@ void JIT::privateCompileGetByIdProto(StructureStubInfo* stubInfo, Structure* str
 
     // Check the prototype object's Structure had not changed.
     Structure** prototypeStructureAddress = &(protoObject->m_structure);
-    __ cmpl_i32m(reinterpret_cast<uint32_t>(prototypeStructure), prototypeStructureAddress);
+    __ cmpl_im(reinterpret_cast<uint32_t>(prototypeStructure), prototypeStructureAddress);
     JmpSrc failureCases3 = __ jne();
 
     // Checks out okay! - getDirectOffset
@@ -482,7 +482,7 @@ void JIT::privateCompileGetByIdProtoList(StructureStubInfo* stubInfo, Polymorphi
 
     // Check the prototype object's Structure had not changed.
     Structure** prototypeStructureAddress = &(protoObject->m_structure);
-    __ cmpl_i32m(reinterpret_cast<uint32_t>(prototypeStructure), prototypeStructureAddress);
+    __ cmpl_im(reinterpret_cast<uint32_t>(prototypeStructure), prototypeStructureAddress);
     JmpSrc failureCases2 = __ jne();
 
     // Checks out okay! - getDirectOffset
@@ -529,7 +529,7 @@ void JIT::privateCompileGetByIdChainList(StructureStubInfo* stubInfo, Polymorphi
 
         // Check the prototype object's Structure had not changed.
         Structure** prototypeStructureAddress = &(protoObject->m_structure);
-        __ cmpl_i32m(reinterpret_cast<uint32_t>(currStructure), prototypeStructureAddress);
+        __ cmpl_im(reinterpret_cast<uint32_t>(currStructure), prototypeStructureAddress);
         bucketsOfFail.append(__ jne());
     }
     ASSERT(protoObject);
@@ -585,7 +585,7 @@ void JIT::privateCompileGetByIdChain(StructureStubInfo* stubInfo, Structure* str
 
         // Check the prototype object's Structure had not changed.
         Structure** prototypeStructureAddress = &(protoObject->m_structure);
-        __ cmpl_i32m(reinterpret_cast<uint32_t>(currStructure), prototypeStructureAddress);
+        __ cmpl_im(reinterpret_cast<uint32_t>(currStructure), prototypeStructureAddress);
         bucketsOfFail.append(__ jne());
     }
     ASSERT(protoObject);
@@ -632,7 +632,7 @@ void JIT::privateCompileGetByIdChain(StructureStubInfo* stubInfo, Structure* str
 
         // Check the prototype object's Structure had not changed.
         Structure** prototypeStructureAddress = &(protoObject->m_structure);
-        __ cmpl_i32m(reinterpret_cast<uint32_t>(currStructure), prototypeStructureAddress);
+        __ cmpl_im(reinterpret_cast<uint32_t>(currStructure), prototypeStructureAddress);
         bucketsOfFail.append(__ jne());
     }
     ASSERT(protoObject);