Merge pull request #2869 from BrzVlad/feature-mod-union-opt
[mono.git] / mono / arch / amd64 / amd64-codegen.h
index 7ca557d6d21f198907afee6147cf67945bad524f..26d73ce31c49214d27052cc77e2f929f8b436829 100644 (file)
  * 
  * Copyright (C)  2000 Intel Corporation.  All rights reserved.
  * Copyright (C)  2001, 2002 Ximian, Inc.
+ * Licensed under the MIT license. See LICENSE file in the project root for full license information.
  */
 
 #ifndef AMD64_H
 #define AMD64_H
 
+// Conventions in this file:
+
+// body: implementation. other macros call this one
+// disp: displacement
+// inst: instruction
+// is_half: short if true, byte if false (then why is it named is_half...?)
+// imm: immediate
+// mem: read from (immediate-supplied address?)
+// membase: read from address in a base register plus a displacement
+// memindex: SIP addressing: (address in base register) + (displacement in index register)<<(shift)
+// reg: register, encode modR/M bits 00
+// regp: register, encode modR/M bits 11
+// size: Expected 1,2,4 or 8
+// widen: extends from 1 or 2 bytes
+
 #include <glib.h>
 
 typedef enum {
@@ -67,6 +83,32 @@ typedef enum
   AMD64_REX_W = 8  /* Opeartion is 64-bits instead of 32 (default) or 16 (with 0x66 prefix) */
 } AMD64_REX_Bits;
 
+#if defined(__default_codegen__)
+
+#define amd64_codegen_pre(inst)
+#define amd64_codegen_post(inst)
+
+#elif defined(__native_client_codegen__)
+
+#define amd64_codegen_pre(inst) guint8* _codegen_start = (inst); amd64_nacl_instruction_pre();
+#define amd64_codegen_post(inst) (amd64_nacl_instruction_post(&_codegen_start, &(inst)), _codegen_start);
+
+/* Because of rex prefixes, etc, call sequences are not constant size.  */
+/* These pre- and post-sequence hooks remedy this by aligning the call  */
+/* sequence after we emit it, since we will know the exact size then.   */
+#define amd64_call_sequence_pre(inst) guint8* _code_start = (inst);
+#define amd64_call_sequence_post(inst) \
+  (mono_nacl_align_call(&_code_start, &(inst)), _code_start);
+
+/* Native client can load/store using one of the following registers     */
+/* as a base: rip, r15, rbp, rsp.  Any other base register needs to have */
+/* its upper 32 bits cleared and reference memory using r15 as the base. */
+#define amd64_is_valid_nacl_base(reg) \
+  ((reg) == AMD64_RIP || (reg) == AMD64_R15 || \
+   (reg) == AMD64_RBP || (reg) == AMD64_RSP)
+
+#endif /*__native_client_codegen__*/
+
 #ifdef TARGET_WIN32
 #define AMD64_ARG_REG1 AMD64_RCX
 #define AMD64_ARG_REG2 AMD64_RDX
@@ -88,6 +130,16 @@ typedef enum
 
 #define AMD64_CALLEE_SAVED_REGS ((1<<AMD64_RDI) | (1<<AMD64_RSI) | (1<<AMD64_RBX) | (1<<AMD64_R12) | (1<<AMD64_R13) | (1<<AMD64_R14) | (1<<AMD64_R15) | (1<<AMD64_RBP))
 #define AMD64_IS_CALLEE_SAVED_REG(reg) (AMD64_CALLEE_SAVED_REGS & (1 << (reg)))
+#elif defined(__native_client_codegen__)
+/* AMD64 Native Client code may not write R15 */
+#define AMD64_CALLEE_REGS ((1<<AMD64_RAX) | (1<<AMD64_RCX) | (1<<AMD64_RDX) | (1<<AMD64_RSI) | (1<<AMD64_RDI) | (1<<AMD64_R8) | (1<<AMD64_R9) | (1<<AMD64_R10))
+#define AMD64_IS_CALLEE_REG(reg)  (AMD64_CALLEE_REGS & (1 << (reg)))
+
+#define AMD64_ARGUMENT_REGS ((1<<AMD64_RDI) | (1<<AMD64_RSI) | (1<<AMD64_RDX) | (1<<AMD64_RCX) | (1<<AMD64_R8) | (1<<AMD64_R9))
+#define AMD64_IS_ARGUMENT_REG(reg) (AMD64_ARGUMENT_REGS & (1 << (reg)))
+
+#define AMD64_CALLEE_SAVED_REGS ((1<<AMD64_RBX) | (1<<AMD64_R12) | (1<<AMD64_R13) | (1<<AMD64_R14) | (1<<AMD64_RBP))
+#define AMD64_IS_CALLEE_SAVED_REG(reg) (AMD64_CALLEE_SAVED_REGS & (1 << (reg)))
 #else
 #define AMD64_CALLEE_REGS ((1<<AMD64_RAX) | (1<<AMD64_RCX) | (1<<AMD64_RDX) | (1<<AMD64_RSI) | (1<<AMD64_RDI) | (1<<AMD64_R8) | (1<<AMD64_R9) | (1<<AMD64_R10))
 #define AMD64_IS_CALLEE_REG(reg)  (AMD64_CALLEE_REGS & (1 << (reg)))
@@ -100,6 +152,7 @@ typedef enum
 #endif
 
 #define AMD64_REX(bits) ((unsigned char)(0x40 | (bits)))
+#if defined(__default_codegen__)
 #define amd64_emit_rex(inst, width, reg_modrm, reg_index, reg_rm_base_opcode) do \
        { \
                unsigned char _amd64_rex_bits = \
@@ -109,9 +162,21 @@ typedef enum
                        (((reg_rm_base_opcode) > 7) ? AMD64_REX_B : 0); \
                if ((_amd64_rex_bits != 0) || (((width) == 1))) *(inst)++ = AMD64_REX(_amd64_rex_bits); \
        } while (0)
+#elif defined(__native_client_codegen__)
+#define amd64_emit_rex(inst, width, reg_modrm, reg_index, reg_rm_base_opcode) do \
+       { \
+               unsigned char _amd64_rex_bits = \
+                       (((width) > 4) ? AMD64_REX_W : 0) | \
+                       (((reg_modrm) > 7) ? AMD64_REX_R : 0) | \
+                       (((reg_index) > 7) ? AMD64_REX_X : 0) | \
+                       (((reg_rm_base_opcode) > 7) ? AMD64_REX_B : 0); \
+               amd64_nacl_tag_rex((inst)); \
+               if ((_amd64_rex_bits != 0) || (((width) == 1))) *(inst)++ = AMD64_REX(_amd64_rex_bits); \
+       } while (0)
+#endif
 
 typedef union {
-       gsize val;
+       guint64 val;
        unsigned char b [8];
 } amd64_imm_buf;
 
@@ -138,7 +203,7 @@ typedef union {
 #define x86_imm_emit64(inst,imm)     \
        do {    \
                        amd64_imm_buf imb;      \
-                       imb.val = (gsize) (imm);        \
+                       imb.val = (guint64) (imm);      \
                        *(inst)++ = imb.b [0];  \
                        *(inst)++ = imb.b [1];  \
                        *(inst)++ = imb.b [2];  \
@@ -158,14 +223,14 @@ typedef union {
                x86_membase_emit ((inst),(reg)&0x7, (basereg)&0x7, (disp)); \
 } while (0)
 
-#define amd64_alu_reg_imm_size(inst,opc,reg,imm,size)  \
+#define amd64_alu_reg_imm_size_body(inst,opc,reg,imm,size) \
        do {    \
                if (x86_is_imm8((imm))) {       \
                        amd64_emit_rex(inst, size, 0, 0, (reg)); \
                        *(inst)++ = (unsigned char)0x83;        \
                        x86_reg_emit ((inst), (opc), (reg));    \
                        x86_imm_emit8 ((inst), (imm));  \
-               } else if ((reg) == X86_EAX) {  \
+               } else if ((reg) == AMD64_RAX) {        \
                        amd64_emit_rex(inst, size, 0, 0, 0); \
                        *(inst)++ = (((unsigned char)(opc)) << 3) + 5;  \
                        x86_imm_emit32 ((inst), (imm)); \
@@ -177,29 +242,96 @@ typedef union {
                }       \
        } while (0)
 
-#define amd64_alu_reg_imm(inst,opc,reg,imm) amd64_alu_reg_imm_size((inst),(opc),(reg),(imm),8)
-
-#define amd64_alu_reg_reg_size(inst,opc,dreg,reg,size) \
+#define amd64_alu_reg_reg_size_body(inst,opc,dreg,reg,size)    \
        do {    \
                amd64_emit_rex(inst, size, (dreg), 0, (reg)); \
                *(inst)++ = (((unsigned char)(opc)) << 3) + 3;  \
                x86_reg_emit ((inst), (dreg), (reg));   \
        } while (0)
 
+#define amd64_test_reg_imm_size_body(inst,reg,imm,size) \
+       do { \
+               amd64_codegen_pre(inst); \
+               amd64_emit_rex ((inst),(size),0,0,(reg)); \
+               if ((reg) == AMD64_RAX) { \
+                       *(inst)++ = (unsigned char)0xa9; \
+               } \
+               else { \
+                       *(inst)++ = (unsigned char)0xf7;        \
+                       x86_reg_emit((inst), 0, (reg)); \
+               } \
+               x86_imm_emit32((inst), (imm));  \
+               amd64_codegen_post(inst); \
+       } while (0)
+
+#if defined(__default_codegen__)
+
+#define amd64_alu_reg_imm_size(inst,opc,reg,imm,size) \
+       amd64_alu_reg_imm_size_body((inst), (opc), (reg), (imm), (size))
+
+#define amd64_alu_reg_reg_size(inst,opc,dreg,reg,size) \
+               amd64_alu_reg_reg_size_body((inst), (opc), (dreg), (reg), (size))
+
+#define amd64_test_reg_imm_size(inst, reg, imm, size) \
+               amd64_test_reg_imm_size_body(inst, reg, imm, size)
+
+#elif defined(__native_client_codegen__)
+/* NaCl modules may not directly update RSP or RBP other than direct copies */
+/* between them. Instead the lower 4 bytes are updated and then added to R15 */
+#define amd64_is_nacl_stack_reg(reg) (((reg) == AMD64_RSP) || ((reg) == AMD64_RBP))
+
+#define amd64_alu_reg_imm_size(inst,opc,reg,imm,size)  \
+       do{ \
+               amd64_codegen_pre(inst);                \
+               if (amd64_is_nacl_stack_reg(reg)) { \
+                       if (((opc) != X86_ADD) && ((opc) != X86_SUB)) \
+                               g_assert_not_reached(); \
+                       amd64_alu_reg_imm_size_body((inst), (opc), (reg), (imm), 4); \
+                       /* Use LEA instead of ADD to preserve flags */ \
+                       amd64_lea_memindex_size((inst), (reg), (reg), 0, AMD64_R15, 0, 8); \
+               } else { \
+                       amd64_alu_reg_imm_size_body((inst), (opc), (reg), (imm), (size)); \
+               } \
+               amd64_codegen_post(inst);               \
+       } while(0)
+
+#define amd64_alu_reg_reg_size(inst,opc,dreg,reg,size) \
+       do { \
+               amd64_codegen_pre(inst);                \
+               if (amd64_is_nacl_stack_reg((dreg)) && ((reg) != AMD64_R15)) { \
+                       if (((opc) != X86_ADD && (opc) != X86_SUB)) \
+                               g_assert_not_reached(); \
+                       amd64_alu_reg_reg_size_body((inst), (opc), (dreg), (reg), 4); \
+                       /* Use LEA instead of ADD to preserve flags */ \
+                       amd64_lea_memindex_size((inst), (dreg), (dreg), 0, AMD64_R15, 0, 8); \
+               } else { \
+                       amd64_alu_reg_reg_size_body((inst), (opc), (dreg), (reg), (size)); \
+               } \
+               amd64_codegen_post(inst);               \
+       } while (0)
+
+#endif /*__native_client_codegen__*/
+
+#define amd64_alu_reg_imm(inst,opc,reg,imm) amd64_alu_reg_imm_size((inst),(opc),(reg),(imm),8)
+
 #define amd64_alu_reg_reg(inst,opc,dreg,reg) amd64_alu_reg_reg_size ((inst),(opc),(dreg),(reg),8)
 
+#define amd64_test_reg_imm(inst,reg,imm) amd64_test_reg_imm_size(inst,reg,imm,8)
+
 #define amd64_alu_reg_membase_size(inst,opc,reg,basereg,disp,size) \
        do { \
+               amd64_codegen_pre(inst);                                                  \
                amd64_emit_rex ((inst),(size),(reg),0,(basereg)); \
                *(inst)++ = (((unsigned char)(opc)) << 3) + 3;  \
                amd64_membase_emit (inst, reg, basereg, disp); \
+               amd64_codegen_post(inst);                                          \
 } while (0)
 
-
 #define amd64_mov_regp_reg(inst,regp,reg,size) \
        do {    \
+               amd64_codegen_pre(inst); \
                if ((size) == 2) \
-                       *(inst)++ = (unsigned char)0x66; \
+                       x86_prefix((inst), X86_OPERAND_PREFIX); \
                amd64_emit_rex(inst, (size), (reg), 0, (regp)); \
                switch ((size)) {       \
                case 1: *(inst)++ = (unsigned char)0x88; break; \
@@ -207,12 +339,14 @@ typedef union {
                default: assert (0);    \
                }       \
                x86_regp_emit ((inst), (reg), (regp));  \
+               amd64_codegen_post(inst); \
        } while (0)
 
 #define amd64_mov_membase_reg(inst,basereg,disp,reg,size)      \
        do {    \
+               amd64_codegen_pre(inst); \
                if ((size) == 2) \
-                       *(inst)++ = (unsigned char)0x66; \
+                       x86_prefix((inst), X86_OPERAND_PREFIX); \
                amd64_emit_rex(inst, (size), (reg), 0, (basereg)); \
                switch ((size)) {       \
                case 1: *(inst)++ = (unsigned char)0x88; break; \
@@ -220,27 +354,31 @@ typedef union {
                default: assert (0);    \
                }       \
                x86_membase_emit ((inst), ((reg)&0x7), ((basereg)&0x7), (disp));        \
+               amd64_codegen_post(inst); \
        } while (0)
 
 #define amd64_mov_mem_reg(inst,mem,reg,size)   \
        do {    \
+               amd64_codegen_pre(inst); \
                if ((size) == 2) \
-                       *(inst)++ = (unsigned char)0x66; \
+                       x86_prefix((inst), X86_OPERAND_PREFIX); \
                amd64_emit_rex(inst, (size), (reg), 0, 0); \
                switch ((size)) {       \
                case 1: *(inst)++ = (unsigned char)0x88; break; \
                case 2: case 4: case 8: *(inst)++ = (unsigned char)0x89; break; \
                default: assert (0);    \
                }       \
-        x86_address_byte ((inst), 0, (reg), 4); \
-        x86_address_byte ((inst), 0, 4, 5); \
-        x86_imm_emit32 ((inst), (mem)); \
+               x86_address_byte ((inst), 0, (reg), 4); \
+               x86_address_byte ((inst), 0, 4, 5); \
+               x86_imm_emit32 ((inst), (mem)); \
+               amd64_codegen_post(inst); \
        } while (0)
 
 #define amd64_mov_reg_reg(inst,dreg,reg,size)  \
        do {    \
+               amd64_codegen_pre(inst); \
                if ((size) == 2) \
-                       *(inst)++ = (unsigned char)0x66; \
+                       x86_prefix((inst), X86_OPERAND_PREFIX); \
                amd64_emit_rex(inst, (size), (dreg), 0, (reg)); \
                switch ((size)) {       \
                case 1: *(inst)++ = (unsigned char)0x8a; break; \
@@ -248,27 +386,43 @@ typedef union {
                default: assert (0);    \
                }       \
                x86_reg_emit ((inst), (dreg), (reg));   \
+               amd64_codegen_post(inst); \
        } while (0)
 
-#define amd64_mov_reg_mem(inst,reg,mem,size)   \
+#define amd64_mov_reg_mem_body(inst,reg,mem,size)      \
        do {    \
+               amd64_codegen_pre(inst); \
                if ((size) == 2) \
-                       *(inst)++ = (unsigned char)0x66; \
+                       x86_prefix((inst), X86_OPERAND_PREFIX); \
                amd64_emit_rex(inst, (size), (reg), 0, 0); \
                switch ((size)) {       \
                case 1: *(inst)++ = (unsigned char)0x8a; break; \
                case 2: case 4: case 8: *(inst)++ = (unsigned char)0x8b; break; \
                default: assert (0);    \
                }       \
-        x86_address_byte ((inst), 0, (reg), 4); \
-        x86_address_byte ((inst), 0, 4, 5); \
-        x86_imm_emit32 ((inst), (mem)); \
+               x86_address_byte ((inst), 0, (reg), 4); \
+               x86_address_byte ((inst), 0, 4, 5); \
+               x86_imm_emit32 ((inst), (mem)); \
+               amd64_codegen_post(inst); \
        } while (0)
 
-#define amd64_mov_reg_membase(inst,reg,basereg,disp,size)      \
+#if defined(__default_codegen__)
+#define amd64_mov_reg_mem(inst,reg,mem,size)   \
+       do {    \
+               amd64_mov_reg_mem_body((inst),(reg),(mem),(size)); \
+       } while (0)
+#elif defined(__native_client_codegen__)
+/* We have to re-base memory reads because memory isn't zero based. */
+#define amd64_mov_reg_mem(inst,reg,mem,size)   \
+       do {    \
+               amd64_mov_reg_membase((inst),(reg),AMD64_R15,(mem),(size)); \
+       } while (0)
+#endif /* __native_client_codegen__ */
+
+#define amd64_mov_reg_membase_body(inst,reg,basereg,disp,size) \
        do {    \
                if ((size) == 2) \
-                       *(inst)++ = (unsigned char)0x66; \
+                       x86_prefix((inst), X86_OPERAND_PREFIX); \
                amd64_emit_rex(inst, (size), (reg), 0, (basereg)); \
                switch ((size)) {       \
                case 1: *(inst)++ = (unsigned char)0x8a; break; \
@@ -278,8 +432,56 @@ typedef union {
                amd64_membase_emit ((inst), (reg), (basereg), (disp));  \
        } while (0)
 
+#define amd64_mov_reg_memindex_size_body(inst,reg,basereg,disp,indexreg,shift,size) \
+       do { \
+               amd64_emit_rex ((inst),(size),(reg),(indexreg),(basereg)); \
+               x86_mov_reg_memindex((inst),((reg)&0x7),((basereg)&0x7),(disp),((indexreg)&0x7),(shift),(size) == 8 ? 4 : (size)); \
+       } while (0)
+
+#if defined(__default_codegen__)
+
+#define amd64_mov_reg_memindex_size(inst,reg,basereg,disp,indexreg,shift,size) \
+       amd64_mov_reg_memindex_size_body((inst),(reg),(basereg),(disp),(indexreg),(shift),(size))
+#define amd64_mov_reg_membase(inst,reg,basereg,disp,size)      \
+       do {    \
+               amd64_mov_reg_membase_body((inst), (reg), (basereg), (disp), (size)); \
+       } while (0)
+
+#elif defined(__native_client_codegen__)
+
+#define amd64_mov_reg_memindex_size(inst,reg,basereg,disp,indexreg,shift,size) \
+       do { \
+               amd64_codegen_pre(inst); \
+               if (amd64_is_nacl_stack_reg((reg))) { \
+                       /* Clear upper 32 bits with mov of size 4 */ \
+                       amd64_mov_reg_memindex_size_body((inst), (reg), (basereg), (disp), (indexreg), (shift), 4); \
+                       /* Add %r15 using LEA to preserve flags */ \
+                       amd64_lea_memindex_size((inst), (reg), (reg), 0, AMD64_R15, 0, 8); \
+               } else { \
+                       amd64_mov_reg_memindex_size_body((inst), (reg), (basereg), (disp), (indexreg), (shift), (size)); \
+               } \
+               amd64_codegen_post(inst); \
+       } while(0)
+
+#define amd64_mov_reg_membase(inst,reg,basereg,disp,size)      \
+       do {    \
+               amd64_codegen_pre(inst); \
+               if (amd64_is_nacl_stack_reg((reg))) { \
+                       /* Clear upper 32 bits with mov of size 4 */ \
+                       amd64_mov_reg_membase_body((inst), (reg), (basereg), (disp), 4); \
+                       /* Add %r15 */ \
+                       amd64_lea_memindex_size((inst), (reg), (reg), 0, AMD64_R15, 0, 8); \
+               } else { \
+                       amd64_mov_reg_membase_body((inst), (reg), (basereg), (disp), (size)); \
+               } \
+               amd64_codegen_post(inst); \
+       } while (0)
+
+#endif /*__native_client_codegen__*/
+
 #define amd64_movzx_reg_membase(inst,reg,basereg,disp,size)    \
        do {    \
+               amd64_codegen_pre(inst); \
                amd64_emit_rex(inst, (size), (reg), 0, (basereg)); \
                switch ((size)) {       \
                case 1: *(inst)++ = (unsigned char)0x0f; *(inst)++ = (unsigned char)0xb6; break;        \
@@ -288,27 +490,34 @@ typedef union {
                default: assert (0);    \
                }       \
                x86_membase_emit ((inst), ((reg)&0x7), ((basereg)&0x7), (disp));        \
+               amd64_codegen_post(inst); \
        } while (0)
 
 #define amd64_movsxd_reg_mem(inst,reg,mem) \
     do {     \
-       amd64_emit_rex(inst,8,(reg),0,0); \
-       *(inst)++ = (unsigned char)0x63; \
-       x86_mem_emit ((inst), ((reg)&0x7), (mem)); \
+       amd64_codegen_pre(inst); \
+       amd64_emit_rex(inst,8,(reg),0,0); \
+       *(inst)++ = (unsigned char)0x63; \
+       x86_mem_emit ((inst), ((reg)&0x7), (mem)); \
+       amd64_codegen_post(inst); \
     } while (0)
 
 #define amd64_movsxd_reg_membase(inst,reg,basereg,disp) \
     do {     \
-       amd64_emit_rex(inst,8,(reg),0,(basereg)); \
-       *(inst)++ = (unsigned char)0x63; \
-       x86_membase_emit ((inst), ((reg)&0x7), ((basereg)&0x7), (disp)); \
+       amd64_codegen_pre(inst); \
+       amd64_emit_rex(inst,8,(reg),0,(basereg)); \
+       *(inst)++ = (unsigned char)0x63; \
+       x86_membase_emit ((inst), ((reg)&0x7), ((basereg)&0x7), (disp)); \
+       amd64_codegen_post(inst); \
     } while (0)
 
 #define amd64_movsxd_reg_reg(inst,dreg,reg) \
     do {     \
-       amd64_emit_rex(inst,8,(dreg),0,(reg)); \
-       *(inst)++ = (unsigned char)0x63; \
-          x86_reg_emit ((inst), (dreg), (reg));        \
+       amd64_codegen_pre(inst); \
+       amd64_emit_rex(inst,8,(dreg),0,(reg)); \
+       *(inst)++ = (unsigned char)0x63; \
+       x86_reg_emit ((inst), (dreg), (reg));   \
+       amd64_codegen_post(inst); \
     } while (0)
 
 /* Pretty much the only instruction that supports a 64-bit immediate. Optimize for common case of
@@ -316,18 +525,22 @@ typedef union {
  */
 #define amd64_mov_reg_imm_size(inst,reg,imm,size)      \
        do {    \
+               amd64_codegen_pre(inst); \
                amd64_emit_rex(inst, (size), 0, 0, (reg)); \
                *(inst)++ = (unsigned char)0xb8 + ((reg) & 0x7);        \
                if ((size) == 8) \
-                       x86_imm_emit64 ((inst), (gsize)(imm));  \
+                       x86_imm_emit64 ((inst), (guint64)(imm));        \
                else \
-                       x86_imm_emit32 ((inst), (int)(gsize)(imm));     \
+                       x86_imm_emit32 ((inst), (int)(guint64)(imm));   \
+               amd64_codegen_post(inst); \
        } while (0)
 
 #define amd64_mov_reg_imm(inst,reg,imm)        \
        do {    \
-               int _amd64_width_temp = ((gsize)(imm) == (gsize)(int)(gsize)(imm)); \
-        amd64_mov_reg_imm_size ((inst), (reg), (imm), (_amd64_width_temp ? 4 : 8)); \
+               int _amd64_width_temp = ((guint64)(imm) == (guint64)(int)(guint64)(imm)); \
+               amd64_codegen_pre(inst); \
+               amd64_mov_reg_imm_size ((inst), (reg), (imm), (_amd64_width_temp ? 4 : 8)); \
+               amd64_codegen_post(inst); \
        } while (0)
 
 #define amd64_set_reg_template(inst,reg) amd64_mov_reg_imm_size ((inst),(reg), 0, 8)
@@ -336,8 +549,9 @@ typedef union {
 
 #define amd64_mov_membase_imm(inst,basereg,disp,imm,size)      \
        do {    \
+               amd64_codegen_pre(inst); \
                if ((size) == 2) \
-                       *(inst)++ = (unsigned char)0x66; \
+                       x86_prefix((inst), X86_OPERAND_PREFIX); \
                amd64_emit_rex(inst, (size) == 1 ? 0 : (size), 0, 0, (basereg)); \
                if ((size) == 1) {      \
                        *(inst)++ = (unsigned char)0xc6;        \
@@ -352,36 +566,69 @@ typedef union {
                        x86_membase_emit ((inst), 0, (basereg) & 0x7, (disp));  \
                        x86_imm_emit32 ((inst), (imm)); \
                }       \
+               amd64_codegen_post(inst); \
        } while (0)
 
-#define amd64_lea_membase(inst,reg,basereg,disp)       \
+
+#define amd64_lea_membase_body(inst,reg,basereg,disp)  \
        do {    \
                amd64_emit_rex(inst, 8, (reg), 0, (basereg)); \
                *(inst)++ = (unsigned char)0x8d;        \
                amd64_membase_emit ((inst), (reg), (basereg), (disp));  \
        } while (0)
 
+#if defined(__default_codegen__)
+#define amd64_lea_membase(inst,reg,basereg,disp) \
+       amd64_lea_membase_body((inst), (reg), (basereg), (disp))
+#elif defined(__native_client_codegen__)
+/* NaCl modules may not write directly into RSP/RBP. Instead, use a */
+/*  32-bit LEA and add R15 to the effective address */
+#define amd64_lea_membase(inst,reg,basereg,disp) \
+       do { \
+               amd64_codegen_pre(inst); \
+               if (amd64_is_nacl_stack_reg(reg)) { \
+                       /* 32-bit LEA */ \
+                       amd64_emit_rex((inst), 4, (reg), 0, (basereg)); \
+                       *(inst)++ = (unsigned char)0x8d; \
+                       amd64_membase_emit((inst), (reg), (basereg), (disp)); \
+                       /* Use a 64-bit LEA instead of an ADD to preserve flags */ \
+                       amd64_lea_memindex_size((inst), (reg), (reg), 0, AMD64_R15, 0, 8); \
+               } else { \
+                       amd64_lea_membase_body((inst), (reg), (basereg), (disp)); \
+               } \
+               amd64_codegen_post(inst); \
+       } while (0)
+#endif /*__native_client_codegen__*/
+
 /* Instruction are implicitly 64-bits so don't generate REX for just the size. */
 #define amd64_push_reg(inst,reg)       \
        do {    \
+               amd64_codegen_pre(inst); \
                amd64_emit_rex(inst, 0, 0, 0, (reg)); \
                *(inst)++ = (unsigned char)0x50 + ((reg) & 0x7);        \
+               amd64_codegen_post(inst); \
        } while (0)
 
 /* Instruction is implicitly 64-bits so don't generate REX for just the size. */
 #define amd64_push_membase(inst,basereg,disp)  \
        do {    \
+               amd64_codegen_pre(inst); \
                amd64_emit_rex(inst, 0, 0, 0, (basereg)); \
                *(inst)++ = (unsigned char)0xff;        \
                x86_membase_emit ((inst), 6, (basereg) & 0x7, (disp));  \
+               amd64_codegen_post(inst); \
        } while (0)
 
-#define amd64_pop_reg(inst,reg)        \
+#define amd64_pop_reg_body(inst,reg)   \
        do {    \
+               amd64_codegen_pre(inst);  \
                amd64_emit_rex(inst, 0, 0, 0, (reg)); \
                *(inst)++ = (unsigned char)0x58 + ((reg) & 0x7);        \
+               amd64_codegen_post(inst);  \
        } while (0)
 
+#if defined(__default_codegen__)
+
 #define amd64_call_reg(inst,reg)       \
        do {    \
                amd64_emit_rex(inst, 0, 0, 0, (reg)); \
@@ -389,94 +636,203 @@ typedef union {
                x86_reg_emit ((inst), 2, ((reg) & 0x7));        \
        } while (0)
 
+
 #define amd64_ret(inst) do { *(inst)++ = (unsigned char)0xc3; } while (0)
 #define amd64_leave(inst) do { *(inst)++ = (unsigned char)0xc9; } while (0)
+
+#define amd64_pop_reg(inst,reg) amd64_pop_reg_body((inst), (reg))
+
+#elif defined(__native_client_codegen__)
+
+/* Size is ignored for Native Client jumps, we restrict jumping to 32-bits */
+#define amd64_jump_reg_size(inst,reg,size)                                \
+  do {                                                                    \
+    amd64_codegen_pre((inst));                                            \
+    amd64_alu_reg_imm_size((inst), X86_AND, (reg), (nacl_align_byte), 4); \
+    amd64_alu_reg_reg_size((inst), X86_ADD, (reg), AMD64_R15, 8);         \
+    amd64_emit_rex ((inst),0,0,0,(reg));                                  \
+    x86_jump_reg((inst),((reg)&0x7));                                     \
+    amd64_codegen_post((inst));                                           \
+  } while (0)
+
+/* Size is ignored for Native Client jumps, we restrict jumping to 32-bits */
+#define amd64_jump_mem_size(inst,mem,size)                                \
+  do {                                                                    \
+    amd64_codegen_pre((inst));                                            \
+    amd64_mov_reg_mem((inst), (mem), AMD64_R11, 4);                       \
+    amd64_jump_reg_size((inst), AMD64_R11, 4);                            \
+    amd64_codegen_post((inst));                                           \
+  } while (0)
+
+#define amd64_call_reg_internal(inst,reg)                                 \
+  do {                                                                    \
+    amd64_codegen_pre((inst));                                            \
+    amd64_alu_reg_imm_size((inst), X86_AND, (reg), (nacl_align_byte), 4); \
+    amd64_alu_reg_reg_size((inst), X86_ADD, (reg), AMD64_R15, 8);         \
+    amd64_emit_rex((inst), 0, 0, 0, (reg));                               \
+    x86_call_reg((inst), ((reg) & 0x7));                                  \
+    amd64_codegen_post((inst));                                           \
+  } while (0)
+
+#define amd64_call_reg(inst,reg)                                          \
+  do {                                                                    \
+    amd64_codegen_pre((inst));                                            \
+    amd64_call_sequence_pre(inst);                                        \
+    amd64_call_reg_internal((inst), (reg));                               \
+    amd64_call_sequence_post(inst);                                       \
+    amd64_codegen_post((inst));                                           \
+  } while (0)
+
+
+#define amd64_ret(inst)                                                   \
+  do {                                                                    \
+    amd64_codegen_pre(inst);                                             \
+    amd64_pop_reg_body((inst), AMD64_R11);                                \
+    amd64_jump_reg_size((inst), AMD64_R11, 8);                            \
+    amd64_codegen_post(inst);                                            \
+  } while (0)
+
+#define amd64_leave(inst)                                                 \
+  do {                                                                    \
+    amd64_codegen_pre(inst);                                             \
+    amd64_mov_reg_reg((inst), AMD64_RSP, AMD64_RBP, 8);                   \
+    amd64_pop_reg_body((inst), AMD64_R11);                                \
+    amd64_mov_reg_reg_size((inst), AMD64_RBP, AMD64_R11, 4);              \
+    amd64_alu_reg_reg_size((inst), X86_ADD, AMD64_RBP, AMD64_R15, 8);     \
+    amd64_codegen_post(inst);                                            \
+  } while (0)
+
+#define amd64_pop_reg(inst,reg) \
+       do { \
+               amd64_codegen_pre(inst); \
+               if (amd64_is_nacl_stack_reg((reg))) { \
+                       amd64_pop_reg_body((inst), AMD64_R11); \
+                       amd64_mov_reg_reg_size((inst), (reg), AMD64_R11, 4); \
+                       amd64_alu_reg_reg_size((inst), X86_ADD, (reg), AMD64_R15, 8); \
+               } else { \
+                       amd64_pop_reg_body((inst), (reg)); \
+               } \
+               amd64_codegen_post(inst); \
+       } while (0)
+
+#endif /*__native_client_codegen__*/
+
 #define amd64_movsd_reg_regp(inst,reg,regp)    \
        do {    \
-               *(inst)++ = (unsigned char)0xf2;        \
+               amd64_codegen_pre(inst); \
+               x86_prefix((inst), 0xf2); \
                amd64_emit_rex(inst, 0, (reg), 0, (regp)); \
                *(inst)++ = (unsigned char)0x0f;        \
                *(inst)++ = (unsigned char)0x10;        \
                x86_regp_emit ((inst), (reg) & 0x7, (regp) & 0x7);      \
+               amd64_codegen_post(inst); \
        } while (0)
 
 #define amd64_movsd_regp_reg(inst,regp,reg)    \
        do {    \
-               *(inst)++ = (unsigned char)0xf2;        \
+               amd64_codegen_pre(inst); \
+               x86_prefix((inst), 0xf2); \
                amd64_emit_rex(inst, 0, (reg), 0, (regp)); \
                *(inst)++ = (unsigned char)0x0f;        \
                *(inst)++ = (unsigned char)0x11;        \
                x86_regp_emit ((inst), (reg) & 0x7, (regp) & 0x7);      \
+               amd64_codegen_post(inst); \
        } while (0)
 
 #define amd64_movss_reg_regp(inst,reg,regp)    \
        do {    \
-               *(inst)++ = (unsigned char)0xf3;        \
+               amd64_codegen_pre(inst); \
+               x86_prefix((inst), 0xf3); \
                amd64_emit_rex(inst, 0, (reg), 0, (regp)); \
                *(inst)++ = (unsigned char)0x0f;        \
                *(inst)++ = (unsigned char)0x10;        \
                x86_regp_emit ((inst), (reg) & 0x7, (regp) & 0x7);      \
+               amd64_codegen_post(inst); \
        } while (0)
 
 #define amd64_movss_regp_reg(inst,regp,reg)    \
        do {    \
-               *(inst)++ = (unsigned char)0xf3;        \
+               amd64_codegen_pre(inst); \
+               x86_prefix((inst), 0xf3); \
                amd64_emit_rex(inst, 0, (reg), 0, (regp)); \
                *(inst)++ = (unsigned char)0x0f;        \
                *(inst)++ = (unsigned char)0x11;        \
                x86_regp_emit ((inst), (reg) & 0x7, (regp) & 0x7);      \
+               amd64_codegen_post(inst); \
        } while (0)
 
 #define amd64_movsd_reg_membase(inst,reg,basereg,disp) \
        do {    \
-               *(inst)++ = (unsigned char)0xf2;        \
+               amd64_codegen_pre(inst); \
+               x86_prefix((inst), 0xf2); \
                amd64_emit_rex(inst, 0, (reg), 0, (basereg)); \
                *(inst)++ = (unsigned char)0x0f;        \
                *(inst)++ = (unsigned char)0x10;        \
                x86_membase_emit ((inst), (reg) & 0x7, (basereg) & 0x7, (disp));        \
+               amd64_codegen_post(inst); \
        } while (0)
 
 #define amd64_movss_reg_membase(inst,reg,basereg,disp) \
        do {    \
-               *(inst)++ = (unsigned char)0xf3;        \
+               amd64_codegen_pre(inst); \
+               x86_prefix((inst), 0xf3); \
                amd64_emit_rex(inst, 0, (reg), 0, (basereg)); \
                *(inst)++ = (unsigned char)0x0f;        \
                *(inst)++ = (unsigned char)0x10;        \
                x86_membase_emit ((inst), (reg) & 0x7, (basereg) & 0x7, (disp));        \
+               amd64_codegen_post(inst); \
        } while (0)
 
 #define amd64_movsd_membase_reg(inst,basereg,disp,reg) \
        do {    \
-               *(inst)++ = (unsigned char)0xf2;        \
+               amd64_codegen_pre(inst); \
+               x86_prefix((inst), 0xf2); \
                amd64_emit_rex(inst, 0, (reg), 0, (basereg)); \
                *(inst)++ = (unsigned char)0x0f;        \
                *(inst)++ = (unsigned char)0x11;        \
                x86_membase_emit ((inst), (reg) & 0x7, (basereg) & 0x7, (disp));        \
+               amd64_codegen_post(inst); \
        } while (0)
 
 #define amd64_movss_membase_reg(inst,basereg,disp,reg) \
        do {    \
-               *(inst)++ = (unsigned char)0xf3;        \
+               amd64_codegen_pre(inst); \
+               x86_prefix((inst), 0xf3); \
                amd64_emit_rex(inst, 0, (reg), 0, (basereg)); \
                *(inst)++ = (unsigned char)0x0f;        \
                *(inst)++ = (unsigned char)0x11;        \
                x86_membase_emit ((inst), (reg) & 0x7, (basereg) & 0x7, (disp));        \
+               amd64_codegen_post(inst); \
        } while (0)
 
 /* The original inc_reg opcode is used as the REX prefix */
 #define amd64_inc_reg_size(inst,reg,size) \
-    do { \
-           amd64_emit_rex ((inst),(size),0,0,(reg)); \
-        *(inst)++ = (unsigned char)0xff; \
-        x86_reg_emit ((inst),0,(reg) & 0x7); \
-    } while (0)
+       do { \
+               amd64_codegen_pre(inst); \
+               amd64_emit_rex ((inst),(size),0,0,(reg)); \
+               *(inst)++ = (unsigned char)0xff; \
+               x86_reg_emit ((inst),0,(reg) & 0x7); \
+               amd64_codegen_post(inst); \
+       } while (0)
 
 #define amd64_dec_reg_size(inst,reg,size) \
-    do { \
-           amd64_emit_rex ((inst),(size),0,0,(reg)); \
-        *(inst)++ = (unsigned char)0xff; \
-        x86_reg_emit ((inst),1,(reg) & 0x7); \
-    } while (0)
+       do { \
+               amd64_codegen_pre(inst); \
+               amd64_emit_rex ((inst),(size),0,0,(reg)); \
+               *(inst)++ = (unsigned char)0xff; \
+               x86_reg_emit ((inst),1,(reg) & 0x7); \
+               amd64_codegen_post(inst); \
+       } while (0)
+
+#define amd64_fld_membase_size(inst,basereg,disp,is_double,size) do { \
+       amd64_codegen_pre(inst); \
+       amd64_emit_rex ((inst),0,0,0,(basereg)); \
+       *(inst)++ = (is_double) ? (unsigned char)0xdd : (unsigned char)0xd9;    \
+       amd64_membase_emit ((inst), 0, (basereg), (disp));      \
+       amd64_codegen_post(inst); \
+} while (0)
+
+#if defined (__default_codegen__)
 
 /* From the AMD64 Software Optimization Manual */
 #define amd64_padding_size(inst,size) \
@@ -489,12 +845,6 @@ typedef union {
                }; \
                } while (0)
 
-#define amd64_fld_membase_size(inst,basereg,disp,is_double,size) do { \
-       amd64_emit_rex ((inst),0,0,0,(basereg)); \
-    *(inst)++ = (is_double) ? (unsigned char)0xdd : (unsigned char)0xd9;       \
-       amd64_membase_emit ((inst), 0, (basereg), (disp));      \
-} while (0)
-
 #define amd64_call_membase_size(inst,basereg,disp,size) do { amd64_emit_rex ((inst),0,0,0,(basereg)); *(inst)++ = (unsigned char)0xff; amd64_membase_emit ((inst),2, (basereg),(disp)); } while (0)
 #define amd64_jump_membase_size(inst,basereg,disp,size) do { amd64_emit_rex ((inst),0,0,0,(basereg)); *(inst)++ = (unsigned char)0xff; amd64_membase_emit ((inst), 4, (basereg), (disp)); } while (0)
     
@@ -508,6 +858,98 @@ typedef union {
        } \
 } while (0)
 
+#elif defined(__native_client_codegen__)
+
+/* The 3-7 byte NOP sequences in amd64_padding_size below are all illegal in */
+/* 64-bit Native Client because they load into rSP/rBP or use duplicate */
+/* prefixes. Instead we use the NOPs recommended in Section 3.5.1.8 of the */
+/* Intel64 and IA-32 Architectures Optimization Reference Manual and */
+/* Section 4.13 of AMD Software Optimization Guide for Family 10h Processors. */
+
+#define amd64_padding_size(inst,size) \
+       do { \
+               unsigned char *code_start = (inst); \
+               switch ((size)) { \
+                       /* xchg %eax,%eax, recognized by hardware as a NOP */ \
+                       case 1: *(inst)++ = 0x90; break; \
+                       /* xchg %ax,%ax */ \
+                       case 2: *(inst)++ = 0x66; *(inst)++ = 0x90; \
+                               break; \
+                       /* nop (%rax) */ \
+                       case 3: *(inst)++ = 0x0f; *(inst)++ = 0x1f; \
+                               *(inst)++ = 0x00; \
+                               break; \
+                       /* nop 0x0(%rax) */ \
+                       case 4: *(inst)++ = 0x0f; *(inst)++ = 0x1f; \
+                               x86_address_byte ((inst), 1, 0, AMD64_RAX);     \
+                               x86_imm_emit8 ((inst), 0);      \
+                               break; \
+                       /* nop 0x0(%rax,%rax) */ \
+                       case 5: *(inst)++ = 0x0f; *(inst)++ = 0x1f; \
+                               x86_address_byte ((inst), 1, 0, 4);     \
+                               x86_address_byte ((inst), 0, AMD64_RAX, AMD64_RAX);     \
+                               x86_imm_emit8 ((inst), 0);      \
+                               break; \
+                       /* nopw 0x0(%rax,%rax) */ \
+                       case 6: *(inst)++ = 0x66; *(inst)++ = 0x0f; \
+                               *(inst)++ = 0x1f; \
+                               x86_address_byte ((inst), 1, 0, 4);     \
+                               x86_address_byte ((inst), 0, AMD64_RAX, AMD64_RAX);     \
+                               x86_imm_emit8 ((inst), 0);      \
+                               break; \
+                       /* nop 0x0(%rax) (32-bit displacement) */ \
+                       case 7: *(inst)++ = 0x0f; *(inst)++ = 0x1f; \
+                               x86_address_byte ((inst), 2, 0, AMD64_RAX);     \
+                               x86_imm_emit32((inst), 0); \
+                               break; \
+                       /* nop 0x0(%rax,%rax) (32-bit displacement) */ \
+                       case 8: *(inst)++ = 0x0f; *(inst)++ = 0x1f; \
+                               x86_address_byte ((inst), 2, 0, 4);     \
+                               x86_address_byte ((inst), 0, AMD64_RAX, AMD64_RAX);     \
+                               x86_imm_emit32 ((inst), 0);     \
+                               break; \
+                       default: \
+                               g_assert_not_reached(); \
+               } \
+               g_assert(code_start + (size) == (unsigned char *)(inst)); \
+       } while (0)
+
+
+/* Size is ignored for Native Client calls, we restrict jumping to 32-bits */
+#define amd64_call_membase_size(inst,basereg,disp,size)                   \
+  do {                                                                    \
+    amd64_codegen_pre((inst));                                            \
+    amd64_call_sequence_pre(inst);                                        \
+    amd64_mov_reg_membase((inst), AMD64_R11, (basereg), (disp), 4);       \
+    amd64_call_reg_internal((inst), AMD64_R11);                           \
+    amd64_call_sequence_post(inst);                                       \
+    amd64_codegen_post((inst));                                           \
+  } while (0)
+
+/* Size is ignored for Native Client jumps, we restrict jumping to 32-bits */
+#define amd64_jump_membase_size(inst,basereg,disp,size)                   \
+  do {                                                                    \
+    amd64_mov_reg_membase((inst), AMD64_R11, (basereg), (disp), 4);       \
+    amd64_jump_reg_size((inst), AMD64_R11, 4);                            \
+  } while (0)
+    
+/* On Native Client we can't jump more than INT_MAX in either direction */
+#define amd64_jump_code_size(inst,target,size)                            \
+  do {                                                                    \
+    /* x86_jump_code used twice in case of */                             \
+    /* relocation by amd64_codegen_post    */                             \
+    guint8* jump_start;                                                   \
+    amd64_codegen_pre(inst);                                              \
+    assert(amd64_is_imm32 ((gint64)(target) - (gint64)(inst)));           \
+    x86_jump_code((inst),(target));                                       \
+    inst = amd64_codegen_post(inst);                                      \
+    jump_start = (inst);                                                  \
+    x86_jump_code((inst),(target));                                       \
+    mono_amd64_patch(jump_start, (target));                               \
+} while (0)
+
+#endif /*__native_client_codegen__*/
+
 /*
  * SSE
  */
@@ -517,31 +959,39 @@ typedef union {
 /* Two opcode SSE defines */
 
 #define emit_sse_reg_reg_op2_size(inst,dreg,reg,op1,op2,size) do { \
+    amd64_codegen_pre(inst); \
     amd64_emit_rex ((inst), size, (dreg), 0, (reg)); \
     *(inst)++ = (unsigned char)(op1); \
     *(inst)++ = (unsigned char)(op2); \
     x86_reg_emit ((inst), (dreg), (reg)); \
+    amd64_codegen_post(inst); \
 } while (0)
 
 #define emit_sse_reg_reg_op2(inst,dreg,reg,op1,op2) emit_sse_reg_reg_op2_size ((inst), (dreg), (reg), (op1), (op2), 0)
 
 #define emit_sse_reg_reg_op2_imm(inst,dreg,reg,op1,op2,imm) do { \
+   amd64_codegen_pre(inst); \
    emit_sse_reg_reg_op2 ((inst), (dreg), (reg), (op1), (op2)); \
    x86_imm_emit8 ((inst), (imm)); \
+   amd64_codegen_post(inst); \
 } while (0)
 
 #define emit_sse_membase_reg_op2(inst,basereg,disp,reg,op1,op2) do { \
+    amd64_codegen_pre(inst); \
     amd64_emit_rex ((inst), 0, (reg), 0, (basereg)); \
     *(inst)++ = (unsigned char)(op1); \
     *(inst)++ = (unsigned char)(op2); \
     amd64_membase_emit ((inst), (reg), (basereg), (disp)); \
+    amd64_codegen_post(inst); \
 } while (0)
 
 #define emit_sse_reg_membase_op2(inst,dreg,basereg,disp,op1,op2) do { \
+    amd64_codegen_pre(inst); \
     amd64_emit_rex ((inst), 0, (dreg), 0, (basereg) == AMD64_RIP ? 0 : (basereg)); \
     *(inst)++ = (unsigned char)(op1); \
     *(inst)++ = (unsigned char)(op2); \
     amd64_membase_emit ((inst), (dreg), (basereg), (disp)); \
+    amd64_codegen_post(inst); \
 } while (0)
 
 /* Three opcode SSE defines */
@@ -553,45 +1003,55 @@ typedef union {
 } while (0)
 
 #define emit_sse_reg_reg_size(inst,dreg,reg,op1,op2,op3,size) do { \
+    amd64_codegen_pre(inst); \
     *(inst)++ = (unsigned char)(op1); \
        amd64_emit_rex ((inst), size, (dreg), 0, (reg)); \
     *(inst)++ = (unsigned char)(op2); \
     *(inst)++ = (unsigned char)(op3); \
     x86_reg_emit ((inst), (dreg), (reg)); \
+    amd64_codegen_post(inst); \
 } while (0)
 
 #define emit_sse_reg_reg(inst,dreg,reg,op1,op2,op3) emit_sse_reg_reg_size ((inst), (dreg), (reg), (op1), (op2), (op3), 0)
 
 #define emit_sse_reg_reg_imm(inst,dreg,reg,op1,op2,op3,imm) do { \
+   amd64_codegen_pre(inst); \
    emit_sse_reg_reg ((inst), (dreg), (reg), (op1), (op2), (op3)); \
    x86_imm_emit8 ((inst), (imm)); \
+   amd64_codegen_post(inst); \
 } while (0)
 
 #define emit_sse_membase_reg(inst,basereg,disp,reg,op1,op2,op3) do { \
-    *(inst)++ = (unsigned char)(op1); \
+    amd64_codegen_pre(inst); \
+    x86_prefix((inst), (unsigned char)(op1)); \
     amd64_emit_rex ((inst), 0, (reg), 0, (basereg)); \
     *(inst)++ = (unsigned char)(op2); \
     *(inst)++ = (unsigned char)(op3); \
     amd64_membase_emit ((inst), (reg), (basereg), (disp)); \
+    amd64_codegen_post(inst); \
 } while (0)
 
 #define emit_sse_reg_membase(inst,dreg,basereg,disp,op1,op2,op3) do { \
-    *(inst)++ = (unsigned char)(op1); \
+    amd64_codegen_pre(inst); \
+    x86_prefix((inst), (unsigned char)(op1)); \
     amd64_emit_rex ((inst), 0, (dreg), 0, (basereg) == AMD64_RIP ? 0 : (basereg)); \
     *(inst)++ = (unsigned char)(op2); \
     *(inst)++ = (unsigned char)(op3); \
     amd64_membase_emit ((inst), (dreg), (basereg), (disp)); \
+    amd64_codegen_post(inst); \
 } while (0)
 
 /* Four opcode SSE defines */
 
 #define emit_sse_reg_reg_op4_size(inst,dreg,reg,op1,op2,op3,op4,size) do { \
-    *(inst)++ = (unsigned char)(op1); \
-       amd64_emit_rex ((inst), size, (dreg), 0, (reg)); \
+    amd64_codegen_pre(inst); \
+    x86_prefix((inst), (unsigned char)(op1)); \
+    amd64_emit_rex ((inst), size, (dreg), 0, (reg)); \
     *(inst)++ = (unsigned char)(op2); \
     *(inst)++ = (unsigned char)(op3); \
     *(inst)++ = (unsigned char)(op4); \
     x86_reg_emit ((inst), (dreg), (reg)); \
+    amd64_codegen_post(inst); \
 } while (0)
 
 #define emit_sse_reg_reg_op4(inst,dreg,reg,op1,op2,op3,op4) emit_sse_reg_reg_op4_size ((inst), (dreg), (reg), (op1), (op2), (op3), (op4), 0)
@@ -605,6 +1065,7 @@ typedef union {
 #define amd64_sse_andpd_reg_membase(inst,dreg,basereg,disp) emit_sse_reg_membase ((inst),(dreg),(basereg), (disp), 0x66, 0x0f, 0x54)
 
 #define amd64_sse_movsd_reg_reg(inst,dreg,reg) emit_sse_reg_reg ((inst), (dreg), (reg), 0xf2, 0x0f, 0x10)
+#define amd64_sse_movss_reg_reg(inst,dreg,reg) emit_sse_reg_reg ((inst), (dreg), (reg), 0xf3, 0x0f, 0x10)
 
 #define amd64_sse_movsd_reg_membase(inst,dreg,basereg,disp) emit_sse_reg_membase ((inst), (dreg), (basereg), (disp), 0xf2, 0x0f, 0x10)
 
@@ -615,14 +1076,17 @@ typedef union {
 #define amd64_sse_movss_reg_membase(inst,dreg,basereg,disp) emit_sse_reg_membase ((inst), (dreg), (basereg), (disp), 0xf3, 0x0f, 0x10)
 
 #define amd64_sse_comisd_reg_reg(inst,dreg,reg) emit_sse_reg_reg ((inst),(dreg),(reg),0x66,0x0f,0x2f)
+#define amd64_sse_comiss_reg_reg(inst,dreg,reg) emit_sse_reg_reg ((inst),(dreg),(reg),0x67,0x0f,0x2f)
 
 #define amd64_sse_comisd_reg_membase(inst,dreg,basereg,disp) emit_sse_reg_membase ((inst), (dreg), (basereg), (disp), 0x66, 0x0f, 0x2f)
 
 #define amd64_sse_ucomisd_reg_reg(inst,dreg,reg) emit_sse_reg_reg ((inst),(dreg),(reg),0x66,0x0f,0x2e)
 
 #define amd64_sse_cvtsd2si_reg_reg(inst,dreg,reg) emit_sse_reg_reg_size ((inst), (dreg), (reg), 0xf2, 0x0f, 0x2d, 8)
+#define amd64_sse_cvtss2si_reg_reg(inst,dreg,reg) emit_sse_reg_reg_size ((inst), (dreg), (reg), 0xf3, 0x0f, 0x2d, 8)
 
 #define amd64_sse_cvttsd2si_reg_reg_size(inst,dreg,reg,size) emit_sse_reg_reg_size ((inst), (dreg), (reg), 0xf2, 0x0f, 0x2c, (size))
+#define amd64_sse_cvtss2si_reg_reg_size(inst,dreg,reg,size) emit_sse_reg_reg_size ((inst), (dreg), (reg), 0xf3, 0x0f, 0x2c, (size))
 
 #define amd64_sse_cvttsd2si_reg_reg(inst,dreg,reg) amd64_sse_cvttsd2si_reg_reg_size ((inst), (dreg), (reg), 8)
 
@@ -630,17 +1094,25 @@ typedef union {
 
 #define amd64_sse_cvtsi2sd_reg_reg(inst,dreg,reg) amd64_sse_cvtsi2sd_reg_reg_size ((inst), (dreg), (reg), 8)
 
+#define amd64_sse_cvtsi2ss_reg_reg_size(inst,dreg,reg,size) emit_sse_reg_reg_size ((inst), (dreg), (reg), 0xf3, 0x0f, 0x2a, (size))
+
+#define amd64_sse_cvtsi2ss_reg_reg(inst,dreg,reg) amd64_sse_cvtsi2ss_reg_reg_size ((inst), (dreg), (reg), 8)
+
 #define amd64_sse_cvtsd2ss_reg_reg(inst,dreg,reg) emit_sse_reg_reg ((inst), (dreg), (reg), 0xf2, 0x0f, 0x5a)
 
 #define amd64_sse_cvtss2sd_reg_reg(inst,dreg,reg) emit_sse_reg_reg ((inst), (dreg), (reg), 0xf3, 0x0f, 0x5a)
 
 #define amd64_sse_addsd_reg_reg(inst,dreg,reg) emit_sse_reg_reg ((inst), (dreg), (reg), 0xf2, 0x0f, 0x58)
+#define amd64_sse_addss_reg_reg(inst,dreg,reg) emit_sse_reg_reg ((inst), (dreg), (reg), 0xf3, 0x0f, 0x58)
 
 #define amd64_sse_subsd_reg_reg(inst,dreg,reg) emit_sse_reg_reg ((inst), (dreg), (reg), 0xf2, 0x0f, 0x5c)
+#define amd64_sse_subss_reg_reg(inst,dreg,reg) emit_sse_reg_reg ((inst), (dreg), (reg), 0xf3, 0x0f, 0x5c)
 
 #define amd64_sse_mulsd_reg_reg(inst,dreg,reg) emit_sse_reg_reg ((inst), (dreg), (reg), 0xf2, 0x0f, 0x59)
+#define amd64_sse_mulss_reg_reg(inst,dreg,reg) emit_sse_reg_reg ((inst), (dreg), (reg), 0xf3, 0x0f, 0x59)
 
 #define amd64_sse_divsd_reg_reg(inst,dreg,reg) emit_sse_reg_reg ((inst), (dreg), (reg), 0xf2, 0x0f, 0x5e)
+#define amd64_sse_divss_reg_reg(inst,dreg,reg) emit_sse_reg_reg ((inst), (dreg), (reg), 0xf3, 0x0f, 0x5e)
 
 #define amd64_sse_sqrtsd_reg_reg(inst,dreg,reg) emit_sse_reg_reg((inst), (dreg), (reg), 0xf2, 0x0f, 0x51)
 
@@ -698,6 +1170,10 @@ typedef union {
 
 #define amd64_sse_pshufd_reg_reg_imm(inst,dreg,reg,imm) emit_sse_reg_reg_imm((inst), (dreg), (reg), 0x66, 0x0f, 0x70, (imm))
 
+#define amd64_sse_shufps_reg_reg_imm(inst,dreg,reg,imm) emit_sse_reg_reg_op2_imm((inst), (dreg), (reg), 0x0f, 0xC6, (imm))
+
+#define amd64_sse_shufpd_reg_reg_imm(inst,dreg,reg,imm) emit_sse_reg_reg_imm((inst), (dreg), (reg), 0x66, 0x0f, 0xC6, (imm))
+
 
 #define amd64_sse_addpd_reg_reg(inst,dreg,reg) emit_sse_reg_reg((inst), (dreg), (reg), 0x66, 0x0f, 0x58)
 
@@ -925,6 +1401,23 @@ typedef union {
 #define amd64_sse_psllq_reg_reg(inst, dreg, reg) emit_sse_reg_reg((inst), (dreg), (reg), 0x66, 0x0f, 0xf3)
 
 
+#define amd64_sse_cvtdq2pd_reg_reg(inst, dreg, reg) emit_sse_reg_reg((inst), (dreg), (reg), 0xF3, 0x0F, 0xE6)
+
+#define amd64_sse_cvtdq2ps_reg_reg(inst, dreg, reg) emit_sse_reg_reg_op2((inst), (dreg), (reg), 0x0F, 0x5B)
+
+#define amd64_sse_cvtpd2dq_reg_reg(inst, dreg, reg) emit_sse_reg_reg((inst), (dreg), (reg), 0xF2, 0x0F, 0xE6)
+
+#define amd64_sse_cvtpd2ps_reg_reg(inst, dreg, reg) emit_sse_reg_reg((inst), (dreg), (reg), 0x66, 0x0F, 0x5A)
+
+#define amd64_sse_cvtps2dq_reg_reg(inst, dreg, reg) emit_sse_reg_reg((inst), (dreg), (reg), 0x66, 0x0F, 0x5B)
+
+#define amd64_sse_cvtps2pd_reg_reg(inst, dreg, reg) emit_sse_reg_reg_op2((inst), (dreg), (reg), 0x0F, 0x5A)
+
+#define amd64_sse_cvttpd2dq_reg_reg(inst, dreg, reg) emit_sse_reg_reg((inst), (dreg), (reg), 0x66, 0x0F, 0xE6)
+
+#define amd64_sse_cvttps2dq_reg_reg(inst, dreg, reg) emit_sse_reg_reg((inst), (dreg), (reg), 0xF3, 0x0F, 0x5B)
+
+
 #define amd64_movd_xreg_reg_size(inst,dreg,sreg,size) emit_sse_reg_reg_size((inst), (dreg), (sreg), 0x66, 0x0f, 0x6e, (size))
 
 #define amd64_movd_reg_xreg_size(inst,dreg,sreg,size) emit_sse_reg_reg_size((inst), (sreg), (dreg), 0x66, 0x0f, 0x7e, (size))
@@ -954,189 +1447,244 @@ typedef union {
 /* Generated from x86-codegen.h */
 
 #define amd64_breakpoint_size(inst,size) do { x86_breakpoint(inst); } while (0)
-#define amd64_cld_size(inst,size) do { amd64_emit_rex ((inst),0,0,0,0); x86_cld(inst); } while (0)
-#define amd64_stosb_size(inst,size) do { amd64_emit_rex ((inst),(size),0,0,0); x86_stosb(inst); } while (0)
-#define amd64_stosl_size(inst,size) do { amd64_emit_rex ((inst),(size),0,0,0); x86_stosl(inst); } while (0)
-#define amd64_stosd_size(inst,size) do { amd64_emit_rex ((inst),(size),0,0,0); x86_stosd(inst); } while (0)
-#define amd64_movsb_size(inst,size) do { amd64_emit_rex ((inst),(size),0,0,0); x86_movsb(inst); } while (0)
-#define amd64_movsl_size(inst,size) do { amd64_emit_rex ((inst),(size),0,0,0); x86_movsl(inst); } while (0)
-#define amd64_movsd_size(inst,size) do { amd64_emit_rex ((inst),(size),0,0,0); x86_movsd(inst); } while (0)
-#define amd64_prefix_size(inst,p,size) do { amd64_emit_rex ((inst),0,0,0,0); x86_prefix((inst), p); } while (0)
-#define amd64_rdtsc_size(inst,size) do { amd64_emit_rex ((inst),(size),0,0,0); x86_rdtsc(inst); } while (0)
-#define amd64_cmpxchg_reg_reg_size(inst,dreg,reg,size) do { amd64_emit_rex ((inst),(size),(dreg),0,(reg)); x86_cmpxchg_reg_reg((inst),((dreg)&0x7),((reg)&0x7)); } while (0)
-#define amd64_cmpxchg_mem_reg_size(inst,mem,reg,size) do { amd64_emit_rex ((inst),(size),0,0,(reg)); x86_cmpxchg_mem_reg((inst),(mem),((reg)&0x7)); } while (0)
-#define amd64_cmpxchg_membase_reg_size(inst,basereg,disp,reg,size) do { amd64_emit_rex ((inst),(size),(reg),0,(basereg)); x86_cmpxchg_membase_reg((inst),((basereg)&0x7),(disp),((reg)&0x7)); } while (0)
-#define amd64_xchg_reg_reg_size(inst,dreg,reg,size) do { amd64_emit_rex ((inst),(size),(dreg),0,(reg)); x86_xchg_reg_reg((inst),((dreg)&0x7),((reg)&0x7),(size) == 8 ? 4 : (size)); } while (0)
-#define amd64_xchg_mem_reg_size(inst,mem,reg,size) do { amd64_emit_rex ((inst),(size),0,0,(reg)); x86_xchg_mem_reg((inst),(mem),((reg)&0x7),(size) == 8 ? 4 : (size)); } while (0)
-#define amd64_xchg_membase_reg_size(inst,basereg,disp,reg,size) do { amd64_emit_rex ((inst),(size),(reg),0,(basereg)); x86_xchg_membase_reg((inst),((basereg)&0x7),(disp),((reg)&0x7),(size) == 8 ? 4 : (size)); } while (0)
-#define amd64_inc_mem_size(inst,mem,size) do { amd64_emit_rex ((inst),(size),0,0,0); x86_inc_mem((inst),(mem)); } while (0)
-#define amd64_inc_membase_size(inst,basereg,disp,size) do { amd64_emit_rex ((inst),(size),0,0,(basereg)); x86_inc_membase((inst),((basereg)&0x7),(disp)); } while (0)
-//#define amd64_inc_reg_size(inst,reg,size) do { amd64_emit_rex ((inst),(size),0,0,(reg)); x86_inc_reg((inst),((reg)&0x7)); } while (0)
-#define amd64_dec_mem_size(inst,mem,size) do { amd64_emit_rex ((inst),(size),0,0,0); x86_dec_mem((inst),(mem)); } while (0)
-#define amd64_dec_membase_size(inst,basereg,disp,size) do { amd64_emit_rex ((inst),(size),0,0,(basereg)); x86_dec_membase((inst),((basereg)&0x7),(disp)); } while (0)
-//#define amd64_dec_reg_size(inst,reg,size) do { amd64_emit_rex ((inst),(size),0,0,(reg)); x86_dec_reg((inst),((reg)&0x7)); } while (0)
-#define amd64_not_mem_size(inst,mem,size) do { amd64_emit_rex ((inst),(size),0,0,0); x86_not_mem((inst),(mem)); } while (0)
-#define amd64_not_membase_size(inst,basereg,disp,size) do { amd64_emit_rex ((inst),(size),0,0,(basereg)); x86_not_membase((inst),((basereg)&0x7),(disp)); } while (0)
-#define amd64_not_reg_size(inst,reg,size) do { amd64_emit_rex ((inst),(size),0,0,(reg)); x86_not_reg((inst),((reg)&0x7)); } while (0)
-#define amd64_neg_mem_size(inst,mem,size) do { amd64_emit_rex ((inst),(size),0,0,0); x86_neg_mem((inst),(mem)); } while (0)
-#define amd64_neg_membase_size(inst,basereg,disp,size) do { amd64_emit_rex ((inst),(size),0,0,(basereg)); x86_neg_membase((inst),((basereg)&0x7),(disp)); } while (0)
-#define amd64_neg_reg_size(inst,reg,size) do { amd64_emit_rex ((inst),(size),0,0,(reg)); x86_neg_reg((inst),((reg)&0x7)); } while (0)
-#define amd64_nop_size(inst,size) do { x86_nop(inst); } while (0)
-//#define amd64_alu_reg_imm_size(inst,opc,reg,imm,size) do { amd64_emit_rex ((inst),(size),0,0,(reg)); x86_alu_reg_imm((inst),(opc),((reg)&0x7),(imm)); } while (0)
-#define amd64_alu_mem_imm_size(inst,opc,mem,imm,size) do { amd64_emit_rex ((inst),(size),0,0,0); x86_alu_mem_imm((inst),(opc),(mem),(imm)); } while (0)
-#define amd64_alu_membase_imm_size(inst,opc,basereg,disp,imm,size) do { amd64_emit_rex ((inst),(size),0,0,(basereg)); x86_alu_membase_imm((inst),(opc),((basereg)&0x7),(disp),(imm)); } while (0)
-#define amd64_alu_membase8_imm_size(inst,opc,basereg,disp,imm,size) do { amd64_emit_rex ((inst),(size),0,0,(basereg)); x86_alu_membase8_imm((inst),(opc),((basereg)&0x7),(disp),(imm)); } while (0)    
-#define amd64_alu_mem_reg_size(inst,opc,mem,reg,size) do { amd64_emit_rex ((inst),(size),0,0,(reg)); x86_alu_mem_reg((inst),(opc),(mem),((reg)&0x7)); } while (0)
-#define amd64_alu_membase_reg_size(inst,opc,basereg,disp,reg,size) do { amd64_emit_rex ((inst),(size),(reg),0,(basereg)); x86_alu_membase_reg((inst),(opc),((basereg)&0x7),(disp),((reg)&0x7)); } while (0)
-//#define amd64_alu_reg_reg_size(inst,opc,dreg,reg,size) do { amd64_emit_rex ((inst),(size),(dreg),0,(reg)); x86_alu_reg_reg((inst),(opc),((dreg)&0x7),((reg)&0x7)); } while (0)
-#define amd64_alu_reg8_reg8_size(inst,opc,dreg,reg,is_dreg_h,is_reg_h,size) do { amd64_emit_rex ((inst),(size),(dreg),0,(reg)); x86_alu_reg8_reg8((inst),(opc),((dreg)&0x7),((reg)&0x7),(is_dreg_h),(is_reg_h)); } while (0)
-#define amd64_alu_reg_mem_size(inst,opc,reg,mem,size) do { amd64_emit_rex ((inst),(size),0,0,(reg)); x86_alu_reg_mem((inst),(opc),((reg)&0x7),(mem)); } while (0)
-//#define amd64_alu_reg_membase_size(inst,opc,reg,basereg,disp,size) do { amd64_emit_rex ((inst),(size),(reg),0,(basereg)); x86_alu_reg_membase((inst),(opc),((reg)&0x7),((basereg)&0x7),(disp)); } while (0)
-#define amd64_test_reg_imm_size(inst,reg,imm,size) do { amd64_emit_rex ((inst),(size),0,0,(reg)); x86_test_reg_imm((inst),((reg)&0x7),(imm)); } while (0)
-#define amd64_test_mem_imm_size(inst,mem,imm,size) do { amd64_emit_rex ((inst),(size),0,0,0); x86_test_mem_imm((inst),(mem),(imm)); } while (0)
-#define amd64_test_membase_imm_size(inst,basereg,disp,imm,size) do { amd64_emit_rex ((inst),(size),0,0,(basereg)); x86_test_membase_imm((inst),((basereg)&0x7),(disp),(imm)); } while (0)
-#define amd64_test_reg_reg_size(inst,dreg,reg,size) do { amd64_emit_rex ((inst),(size),(dreg),0,(reg)); x86_test_reg_reg((inst),((dreg)&0x7),((reg)&0x7)); } while (0)
-#define amd64_test_mem_reg_size(inst,mem,reg,size) do { amd64_emit_rex ((inst),(size),0,0,(reg)); x86_test_mem_reg((inst),(mem),((reg)&0x7)); } while (0)
-#define amd64_test_membase_reg_size(inst,basereg,disp,reg,size) do { amd64_emit_rex ((inst),(size),(reg),0,(basereg)); x86_test_membase_reg((inst),((basereg)&0x7),(disp),((reg)&0x7)); } while (0)
-#define amd64_shift_reg_imm_size(inst,opc,reg,imm,size) do { amd64_emit_rex ((inst),(size),0,0,(reg)); x86_shift_reg_imm((inst),(opc),((reg)&0x7),(imm)); } while (0)
-#define amd64_shift_mem_imm_size(inst,opc,mem,imm,size) do { amd64_emit_rex ((inst),(size),0,0,(reg)); x86_shift_mem_imm((inst),(opc),(mem),(imm)); } while (0)
-#define amd64_shift_membase_imm_size(inst,opc,basereg,disp,imm,size) do { amd64_emit_rex ((inst),(size),(reg),0,(basereg)); x86_shift_membase_imm((inst),(opc),((basereg)&0x7),(disp),(imm)); } while (0)
-#define amd64_shift_reg_size(inst,opc,reg,size) do { amd64_emit_rex ((inst),(size),0,0,(reg)); x86_shift_reg((inst),(opc),((reg)&0x7)); } while (0)
-#define amd64_shift_mem_size(inst,opc,mem,size) do { amd64_emit_rex ((inst),(size),0,0,(reg)); x86_shift_mem((inst),(opc),(mem)); } while (0)
-#define amd64_shift_membase_size(inst,opc,basereg,disp,size) do { amd64_emit_rex ((inst),(size),0,0,(basereg)); x86_shift_membase((inst),(opc),((basereg)&0x7),(disp)); } while (0)
-#define amd64_shrd_reg_size(inst,dreg,reg,size) do { amd64_emit_rex ((inst),(size),(dreg),0,(reg)); x86_shrd_reg((inst),((dreg)&0x7),((reg)&0x7)); } while (0)
-#define amd64_shrd_reg_imm_size(inst,dreg,reg,shamt,size) do { amd64_emit_rex ((inst),(size),(dreg),0,(reg)); x86_shrd_reg_imm((inst),((dreg)&0x7),((reg)&0x7),(shamt)); } while (0)
-#define amd64_shld_reg_size(inst,dreg,reg,size) do { amd64_emit_rex ((inst),(size),(dreg),0,(reg)); x86_shld_reg((inst),((dreg)&0x7),((reg)&0x7)); } while (0)
-#define amd64_shld_reg_imm_size(inst,dreg,reg,shamt,size) do { amd64_emit_rex ((inst),(size),(dreg),0,(reg)); x86_shld_reg_imm((inst),((dreg)&0x7),((reg)&0x7),(shamt)); } while (0)
-#define amd64_mul_reg_size(inst,reg,is_signed,size) do { amd64_emit_rex ((inst),(size),0,0,(reg)); x86_mul_reg((inst),((reg)&0x7),(is_signed)); } while (0)
-#define amd64_mul_mem_size(inst,mem,is_signed,size) do { amd64_emit_rex ((inst),(size),0,0,0); x86_mul_mem((inst),(mem),(is_signed)); } while (0)
-#define amd64_mul_membase_size(inst,basereg,disp,is_signed,size) do { amd64_emit_rex ((inst),(size),0,0,(basereg)); x86_mul_membase((inst),((basereg)&0x7),(disp),(is_signed)); } while (0)
-#define amd64_imul_reg_reg_size(inst,dreg,reg,size) do { amd64_emit_rex ((inst),(size),(dreg),0,(reg)); x86_imul_reg_reg((inst),((dreg)&0x7),((reg)&0x7)); } while (0)
-#define amd64_imul_reg_mem_size(inst,reg,mem,size) do { amd64_emit_rex ((inst),(size),0,0,(reg)); x86_imul_reg_mem((inst),((reg)&0x7),(mem)); } while (0)
-#define amd64_imul_reg_membase_size(inst,reg,basereg,disp,size) do { amd64_emit_rex ((inst),(size),(reg),0,(basereg)); x86_imul_reg_membase((inst),((reg)&0x7),((basereg)&0x7),(disp)); } while (0)
-#define amd64_imul_reg_reg_imm_size(inst,dreg,reg,imm,size) do { amd64_emit_rex ((inst),(size),(dreg),0,(reg)); x86_imul_reg_reg_imm((inst),((dreg)&0x7),((reg)&0x7),(imm)); } while (0)
-#define amd64_imul_reg_mem_imm_size(inst,reg,mem,imm,size) do { amd64_emit_rex ((inst),(size),0,0,(reg)); x86_imul_reg_mem_imm((inst),((reg)&0x7),(mem),(imm)); } while (0)
-#define amd64_imul_reg_membase_imm_size(inst,reg,basereg,disp,imm,size) do { amd64_emit_rex ((inst),(size),(reg),0,(basereg)); x86_imul_reg_membase_imm((inst),((reg)&0x7),((basereg)&0x7),(disp),(imm)); } while (0)
-#define amd64_div_reg_size(inst,reg,is_signed,size) do { amd64_emit_rex ((inst),(size),0,0,(reg)); x86_div_reg((inst),((reg)&0x7),(is_signed)); } while (0)
-#define amd64_div_mem_size(inst,mem,is_signed,size) do { amd64_emit_rex ((inst),(size),0,0,0); x86_div_mem((inst),(mem),(is_signed)); } while (0)
-#define amd64_div_membase_size(inst,basereg,disp,is_signed,size) do { amd64_emit_rex ((inst),(size),0,0,(basereg)); x86_div_membase((inst),((basereg)&0x7),(disp),(is_signed)); } while (0)
-#define amd64_mov_mem_reg_size(inst,mem,reg,size) do { amd64_emit_rex ((inst),(size),0,0,(reg)); x86_mov_mem_reg((inst),(mem),((reg)&0x7),(size) == 8 ? 4 : (size)); } while (0)
-//#define amd64_mov_regp_reg_size(inst,regp,reg,size) do { amd64_emit_rex ((inst),(size),(regp),0,(reg)); x86_mov_regp_reg((inst),(regp),((reg)&0x7),(size) == 8 ? 4 : (size)); } while (0)
-//#define amd64_mov_membase_reg_size(inst,basereg,disp,reg,size) do { amd64_emit_rex ((inst),(size),(reg),0,(basereg)); x86_mov_membase_reg((inst),((basereg)&0x7),(disp),((reg)&0x7),(size) == 8 ? 4 : (size)); } while (0)
-#define amd64_mov_memindex_reg_size(inst,basereg,disp,indexreg,shift,reg,size) do { amd64_emit_rex ((inst),(size),(reg),(indexreg),(basereg)); x86_mov_memindex_reg((inst),((basereg)&0x7),(disp),((indexreg)&0x7),(shift),((reg)&0x7),(size) == 8 ? 4 : (size)); } while (0)
-#define amd64_mov_reg_reg_size(inst,dreg,reg,size) do { amd64_emit_rex ((inst),(size),(dreg),0,(reg)); x86_mov_reg_reg((inst),((dreg)&0x7),((reg)&0x7),(size) == 8 ? 4 : (size)); } while (0)
-//#define amd64_mov_reg_mem_size(inst,reg,mem,size) do { amd64_emit_rex ((inst),(size),0,0,(reg)); x86_mov_reg_mem((inst),((reg)&0x7),(mem),(size) == 8 ? 4 : (size)); } while (0)
-//#define amd64_mov_reg_membase_size(inst,reg,basereg,disp,size) do { amd64_emit_rex ((inst),(size),(reg),0,(basereg)); x86_mov_reg_membase((inst),((reg)&0x7),((basereg)&0x7),(disp),(size) == 8 ? 4 : (size)); } while (0)
-#define amd64_mov_reg_memindex_size(inst,reg,basereg,disp,indexreg,shift,size) do { amd64_emit_rex ((inst),(size),(reg),(indexreg),(basereg)); x86_mov_reg_memindex((inst),((reg)&0x7),((basereg)&0x7),(disp),((indexreg)&0x7),(shift),(size) == 8 ? 4 : (size)); } while (0)
-#define amd64_clear_reg_size(inst,reg,size) do { amd64_emit_rex ((inst),(size),0,0,(reg)); x86_clear_reg((inst),((reg)&0x7)); } while (0)
-//#define amd64_mov_reg_imm_size(inst,reg,imm,size) do { amd64_emit_rex ((inst),(size),0,0,(reg)); x86_mov_reg_imm((inst),((reg)&0x7),(imm)); } while (0)
-#define amd64_mov_mem_imm_size(inst,mem,imm,size) do { amd64_emit_rex ((inst),(size),0,0,0); x86_mov_mem_imm((inst),(mem),(imm),(size) == 8 ? 4 : (size)); } while (0)
-//#define amd64_mov_membase_imm_size(inst,basereg,disp,imm,size) do { amd64_emit_rex ((inst),(size),0,0,(basereg)); x86_mov_membase_imm((inst),((basereg)&0x7),(disp),(imm),(size) == 8 ? 4 : (size)); } while (0)
-#define amd64_mov_memindex_imm_size(inst,basereg,disp,indexreg,shift,imm,size) do { amd64_emit_rex ((inst),(size),0,(indexreg),(basereg)); x86_mov_memindex_imm((inst),((basereg)&0x7),(disp),((indexreg)&0x7),(shift),(imm),(size) == 8 ? 4 : (size)); } while (0)
-#define amd64_lea_mem_size(inst,reg,mem,size) do { amd64_emit_rex ((inst),(size),0,0,(reg)); x86_lea_mem((inst),((reg)&0x7),(mem)); } while (0)
-//#define amd64_lea_membase_size(inst,reg,basereg,disp,size) do { amd64_emit_rex ((inst),(size),0,0,(basereg)); x86_lea_membase((inst),((reg)&0x7),((basereg)&0x7),(disp)); } while (0)
-#define amd64_lea_memindex_size(inst,reg,basereg,disp,indexreg,shift,size) do { amd64_emit_rex ((inst),(size),(reg),(indexreg),(basereg)); x86_lea_memindex((inst),((reg)&0x7),((basereg)&0x7),(disp),((indexreg)&0x7),(shift)); } while (0)
-#define amd64_widen_reg_size(inst,dreg,reg,is_signed,is_half,size) do { amd64_emit_rex ((inst),(size),(dreg),0,(reg)); x86_widen_reg((inst),((dreg)&0x7),((reg)&0x7),(is_signed),(is_half)); } while (0)
-#define amd64_widen_mem_size(inst,dreg,mem,is_signed,is_half,size) do { amd64_emit_rex ((inst),(size),(dreg),0,0); x86_widen_mem((inst),((dreg)&0x7),(mem),(is_signed),(is_half)); } while (0)
-#define amd64_widen_membase_size(inst,dreg,basereg,disp,is_signed,is_half,size) do { amd64_emit_rex ((inst),(size),(dreg),0,(basereg)); x86_widen_membase((inst),((dreg)&0x7),((basereg)&0x7),(disp),(is_signed),(is_half)); } while (0)
-#define amd64_widen_memindex_size(inst,dreg,basereg,disp,indexreg,shift,is_signed,is_half,size) do { amd64_emit_rex ((inst),(size),(dreg),(indexreg),(basereg)); x86_widen_memindex((inst),((dreg)&0x7),((basereg)&0x7),(disp),((indexreg)&0x7),(shift),(is_signed),(is_half)); } while (0)
-#define amd64_cdq_size(inst,size) do { amd64_emit_rex ((inst),(size),0,0,0); x86_cdq(inst); } while (0)
-#define amd64_wait_size(inst,size) do { amd64_emit_rex ((inst),(size),0,0,0); x86_wait(inst); } while (0)
-#define amd64_fp_op_mem_size(inst,opc,mem,is_double,size) do { amd64_emit_rex ((inst),0,0,0,0); x86_fp_op_mem((inst),(opc),(mem),(is_double)); } while (0)
-#define amd64_fp_op_membase_size(inst,opc,basereg,disp,is_double,size) do { amd64_emit_rex ((inst),0,0,0,(basereg)); x86_fp_op_membase((inst),(opc),((basereg)&0x7),(disp),(is_double)); } while (0)
-#define amd64_fp_op_size(inst,opc,index,size) do { amd64_emit_rex ((inst),0,0,0,0); x86_fp_op((inst),(opc),(index)); } while (0)
-#define amd64_fp_op_reg_size(inst,opc,index,pop_stack,size) do { amd64_emit_rex ((inst),0,0,0,0); x86_fp_op_reg((inst),(opc),(index),(pop_stack)); } while (0)
-#define amd64_fp_int_op_membase_size(inst,opc,basereg,disp,is_int,size) do { amd64_emit_rex ((inst),0,0,0,(basereg)); x86_fp_int_op_membase((inst),(opc),((basereg)&0x7),(disp),(is_int)); } while (0)
-#define amd64_fstp_size(inst,index,size) do { amd64_emit_rex ((inst),0,0,0,0); x86_fstp((inst),(index)); } while (0)
-#define amd64_fcompp_size(inst,size) do { amd64_emit_rex ((inst),0,0,0,0); x86_fcompp(inst); } while (0)
-#define amd64_fucompp_size(inst,size) do { amd64_emit_rex ((inst),0,0,0,0); x86_fucompp(inst); } while (0)
-#define amd64_fnstsw_size(inst,size) do { amd64_emit_rex ((inst),0,0,0,0); x86_fnstsw(inst); } while (0)
-#define amd64_fnstcw_size(inst,mem,size) do { amd64_emit_rex ((inst),0,0,0,0); x86_fnstcw((inst),(mem)); } while (0)
-#define amd64_fnstcw_membase_size(inst,basereg,disp,size) do { amd64_emit_rex ((inst),(size),0,0,(basereg)); x86_fnstcw_membase((inst),((basereg)&0x7),(disp)); } while (0)
-#define amd64_fldcw_size(inst,mem,size) do { amd64_emit_rex ((inst),0,0,0,0); x86_fldcw((inst),(mem)); } while (0)
-#define amd64_fldcw_membase_size(inst,basereg,disp,size) do { amd64_emit_rex ((inst),0,0,0,(basereg)); x86_fldcw_membase((inst),((basereg)&0x7),(disp)); } while (0)
-#define amd64_fchs_size(inst,size) do { amd64_emit_rex ((inst),0,0,0,0); x86_fchs(inst); } while (0)
-#define amd64_frem_size(inst,size) do { amd64_emit_rex ((inst),0,0,0,0); x86_frem(inst); } while (0)
-#define amd64_fxch_size(inst,index,size) do { amd64_emit_rex ((inst),0,0,0,0); x86_fxch((inst),(index)); } while (0)
-#define amd64_fcomi_size(inst,index,size) do { amd64_emit_rex ((inst),0,0,0,0); x86_fcomi((inst),(index)); } while (0)
-#define amd64_fcomip_size(inst,index,size) do { amd64_emit_rex ((inst),0,0,0,0); x86_fcomip((inst),(index)); } while (0)
-#define amd64_fucomi_size(inst,index,size) do { amd64_emit_rex ((inst),0,0,0,0); x86_fucomi((inst),(index)); } while (0)
-#define amd64_fucomip_size(inst,index,size) do { amd64_emit_rex ((inst),0,0,0,0); x86_fucomip((inst),(index)); } while (0)
-#define amd64_fld_size(inst,mem,is_double,size) do { amd64_emit_rex ((inst),0,0,0,0); x86_fld((inst),(mem),(is_double)); } while (0)
-//#define amd64_fld_membase_size(inst,basereg,disp,is_double,size) do { amd64_emit_rex ((inst),0,0,0,(basereg)); x86_fld_membase((inst),((basereg)&0x7),(disp),(is_double)); } while (0)
-#define amd64_fld80_mem_size(inst,mem,size) do { amd64_emit_rex ((inst),0,0,0,0); x86_fld80_mem((inst),(mem)); } while (0)
-#define amd64_fld80_membase_size(inst,basereg,disp,size) do { amd64_emit_rex ((inst),(size),0,0,(basereg)); x86_fld80_membase((inst),((basereg)&0x7),(disp)); } while (0)
-#define amd64_fild_size(inst,mem,is_long,size) do { amd64_emit_rex ((inst),0,0,0,0); x86_fild((inst),(mem),(is_long)); } while (0)
-#define amd64_fild_membase_size(inst,basereg,disp,is_long,size) do { amd64_emit_rex ((inst),0,0,0,(basereg)); x86_fild_membase((inst),((basereg)&0x7),(disp),(is_long)); } while (0)
-#define amd64_fld_reg_size(inst,index,size) do { amd64_emit_rex ((inst),0,0,0,0); x86_fld_reg((inst),(index)); } while (0)
-#define amd64_fldz_size(inst,size) do { amd64_emit_rex ((inst),0,0,0,0); x86_fldz(inst); } while (0)
-#define amd64_fld1_size(inst,size) do { amd64_emit_rex ((inst),0,0,0,0); x86_fld1(inst); } while (0)
-#define amd64_fldpi_size(inst,size) do { amd64_emit_rex ((inst),0,0,0,0); x86_fldpi(inst); } while (0)
-#define amd64_fst_size(inst,mem,is_double,pop_stack,size) do { amd64_emit_rex ((inst),0,0,0,0); x86_fst((inst),(mem),(is_double),(pop_stack)); } while (0)
-#define amd64_fst_membase_size(inst,basereg,disp,is_double,pop_stack,size) do { amd64_emit_rex ((inst),0,0,0,(basereg)); x86_fst_membase((inst),((basereg)&0x7),(disp),(is_double),(pop_stack)); } while (0)
-#define amd64_fst80_mem_size(inst,mem,size) do { amd64_emit_rex ((inst),0,0,0,0); x86_fst80_mem((inst),(mem)); } while (0)
-#define amd64_fst80_membase_size(inst,basereg,disp,size) do { amd64_emit_rex ((inst),0,0,0,(basereg)); x86_fst80_membase((inst),((basereg)&0x7),(disp)); } while (0)
-#define amd64_fist_pop_size(inst,mem,is_long,size) do { amd64_emit_rex ((inst),0,0,0,0); x86_fist_pop((inst),(mem),(is_long)); } while (0)
-#define amd64_fist_pop_membase_size(inst,basereg,disp,is_long,size) do { amd64_emit_rex ((inst),0,0,0,(basereg)); x86_fist_pop_membase((inst),((basereg)&0x7),(disp),(is_long)); } while (0)
-#define amd64_fstsw_size(inst,size) do { amd64_emit_rex ((inst),(size),0,0,0); x86_fstsw(inst); } while (0)
-#define amd64_fist_membase_size(inst,basereg,disp,is_int,size) do { amd64_emit_rex ((inst),0,0,0,(basereg)); x86_fist_membase((inst),((basereg)&0x7),(disp),(is_int)); } while (0)
-//#define amd64_push_reg_size(inst,reg,size) do { amd64_emit_rex ((inst),(size),0,0,(reg)); x86_push_reg((inst),((reg)&0x7)); } while (0)
-#define amd64_push_regp_size(inst,reg,size) do { amd64_emit_rex ((inst),(size),0,0,(reg)); x86_push_regp((inst),((reg)&0x7)); } while (0)
-#define amd64_push_mem_size(inst,mem,size) do { amd64_emit_rex ((inst),(size),0,0,0); x86_push_mem((inst),(mem)); } while (0)
-//#define amd64_push_membase_size(inst,basereg,disp,size) do { amd64_emit_rex ((inst),(size),0,0,(basereg)); x86_push_membase((inst),((basereg)&0x7),(disp)); } while (0)
-#define amd64_push_memindex_size(inst,basereg,disp,indexreg,shift,size) do { amd64_emit_rex ((inst),(size),0,(indexreg),(basereg)); x86_push_memindex((inst),((basereg)&0x7),(disp),((indexreg)&0x7),(shift)); } while (0)
-#define amd64_push_imm_size(inst,imm,size) do { amd64_emit_rex ((inst),0,0,0,0); x86_push_imm((inst),(imm)); } while (0)
-//#define amd64_pop_reg_size(inst,reg,size) do { amd64_emit_rex ((inst),(size),0,0,(reg)); x86_pop_reg((inst),((reg)&0x7)); } while (0)
-#define amd64_pop_mem_size(inst,mem,size) do { amd64_emit_rex ((inst),(size),0,0,0); x86_pop_mem((inst),(mem)); } while (0)
-#define amd64_pop_membase_size(inst,basereg,disp,size) do { amd64_emit_rex ((inst),(size),0,0,(basereg)); x86_pop_membase((inst),((basereg)&0x7),(disp)); } while (0)
-#define amd64_pushad_size(inst,size) do { amd64_emit_rex ((inst),(size),0,0,0); x86_pushad(inst); } while (0)
-#define amd64_pushfd_size(inst,size) do { amd64_emit_rex ((inst),(size),0,0,0); x86_pushfd(inst); } while (0)
-#define amd64_popad_size(inst,size) do { amd64_emit_rex ((inst),(size),0,0,0); x86_popad(inst); } while (0)
-#define amd64_popfd_size(inst,size) do { amd64_emit_rex ((inst),(size),0,0,0); x86_popfd(inst); } while (0)
-#define amd64_loop_size(inst,imm,size) do { amd64_emit_rex ((inst),(size),0,0,0); x86_loop((inst),(imm)); } while (0)
-#define amd64_loope_size(inst,imm,size) do { amd64_emit_rex ((inst),(size),0,0,0); x86_loope((inst),(imm)); } while (0)
-#define amd64_loopne_size(inst,imm,size) do { amd64_emit_rex ((inst),(size),0,0,0); x86_loopne((inst),(imm)); } while (0)
-#define amd64_jump32_size(inst,imm,size) do { amd64_emit_rex ((inst),(size),0,0,0); x86_jump32((inst),(imm)); } while (0)
-#define amd64_jump8_size(inst,imm,size) do { amd64_emit_rex ((inst),(size),0,0,0); x86_jump8((inst),(imm)); } while (0)
+#define amd64_cld_size(inst,size) do { amd64_codegen_pre(inst); amd64_emit_rex ((inst),0,0,0,0); x86_cld(inst); amd64_codegen_post(inst); } while (0)
+#define amd64_stosb_size(inst,size) do { amd64_codegen_pre(inst); amd64_emit_rex ((inst),(size),0,0,0); x86_stosb(inst); amd64_codegen_post(inst); } while (0)
+#define amd64_stosl_size(inst,size) do { amd64_codegen_pre(inst); amd64_emit_rex ((inst),(size),0,0,0); x86_stosl(inst); amd64_codegen_post(inst); } while (0)
+#define amd64_stosd_size(inst,size) do { amd64_codegen_pre(inst); amd64_emit_rex ((inst),(size),0,0,0); x86_stosd(inst); amd64_codegen_post(inst); } while (0)
+#define amd64_movsb_size(inst,size) do { amd64_codegen_pre(inst); amd64_emit_rex ((inst),(size),0,0,0); x86_movsb(inst); amd64_codegen_post(inst); } while (0)
+#define amd64_movsl_size(inst,size) do { amd64_codegen_pre(inst); amd64_emit_rex ((inst),(size),0,0,0); x86_movsl(inst); amd64_codegen_post(inst); } while (0)
+#define amd64_movsd_size(inst,size) do { amd64_codegen_pre(inst); amd64_emit_rex ((inst),(size),0,0,0); x86_movsd(inst); amd64_codegen_post(inst); } while (0)
+#define amd64_prefix_size(inst,p,size) do { x86_prefix((inst), p); } while (0)
+#define amd64_rdtsc_size(inst,size) do { amd64_codegen_pre(inst); amd64_emit_rex ((inst),(size),0,0,0); x86_rdtsc(inst); amd64_codegen_post(inst); } while (0)
+#define amd64_cmpxchg_reg_reg_size(inst,dreg,reg,size) do { amd64_codegen_pre(inst); amd64_emit_rex ((inst),(size),(dreg),0,(reg)); x86_cmpxchg_reg_reg((inst),((dreg)&0x7),((reg)&0x7)); amd64_codegen_post(inst); } while (0)
+#define amd64_cmpxchg_mem_reg_size(inst,mem,reg,size) do { amd64_codegen_pre(inst); amd64_emit_rex ((inst),(size),0,0,(reg)); x86_cmpxchg_mem_reg((inst),(mem),((reg)&0x7)); amd64_codegen_post(inst); } while (0)
+#define amd64_cmpxchg_membase_reg_size(inst,basereg,disp,reg,size) do { amd64_codegen_pre(inst); amd64_emit_rex ((inst),(size),(reg),0,(basereg)); x86_cmpxchg_membase_reg((inst),((basereg)&0x7),(disp),((reg)&0x7)); amd64_codegen_post(inst); } while (0)
+#define amd64_xchg_reg_reg_size(inst,dreg,reg,size) do { amd64_codegen_pre(inst); amd64_emit_rex ((inst),(size),(dreg),0,(reg)); x86_xchg_reg_reg((inst),((dreg)&0x7),((reg)&0x7),(size) == 8 ? 4 : (size)); amd64_codegen_post(inst); } while (0)
+#define amd64_xchg_mem_reg_size(inst,mem,reg,size) do { amd64_codegen_pre(inst); amd64_emit_rex ((inst),(size),0,0,(reg)); x86_xchg_mem_reg((inst),(mem),((reg)&0x7),(size) == 8 ? 4 : (size)); amd64_codegen_post(inst); } while (0)
+#define amd64_xchg_membase_reg_size(inst,basereg,disp,reg,size) do { amd64_codegen_pre(inst); amd64_emit_rex ((inst),(size),(reg),0,(basereg)); x86_xchg_membase_reg((inst),((basereg)&0x7),(disp),((reg)&0x7),(size) == 8 ? 4 : (size)); amd64_codegen_post(inst); } while (0)
+#define amd64_inc_mem_size(inst,mem,size) do { amd64_codegen_pre(inst); amd64_emit_rex ((inst),(size),0,0,0); x86_inc_mem((inst),(mem)); amd64_codegen_post(inst); } while (0)
+#define amd64_inc_membase_size(inst,basereg,disp,size) do { amd64_codegen_pre(inst); amd64_emit_rex ((inst),(size),0,0,(basereg)); x86_inc_membase((inst),((basereg)&0x7),(disp)); amd64_codegen_post(inst); } while (0)
+//#define amd64_inc_reg_size(inst,reg,size) do { amd64_codegen_pre(inst); amd64_emit_rex ((inst),(size),0,0,(reg)); x86_inc_reg((inst),((reg)&0x7)); amd64_codegen_post(inst); } while (0)
+#define amd64_dec_mem_size(inst,mem,size) do { amd64_codegen_pre(inst); amd64_emit_rex ((inst),(size),0,0,0); x86_dec_mem((inst),(mem)); amd64_codegen_post(inst); } while (0)
+#define amd64_dec_membase_size(inst,basereg,disp,size) do { amd64_codegen_pre(inst); amd64_emit_rex ((inst),(size),0,0,(basereg)); x86_dec_membase((inst),((basereg)&0x7),(disp)); amd64_codegen_post(inst); } while (0)
+//#define amd64_dec_reg_size(inst,reg,size) do { amd64_codegen_pre(inst); amd64_emit_rex ((inst),(size),0,0,(reg)); x86_dec_reg((inst),((reg)&0x7)); amd64_codegen_post(inst); } while (0)
+#define amd64_not_mem_size(inst,mem,size) do { amd64_codegen_pre(inst); amd64_emit_rex ((inst),(size),0,0,0); x86_not_mem((inst),(mem)); amd64_codegen_post(inst); } while (0)
+#define amd64_not_membase_size(inst,basereg,disp,size) do { amd64_codegen_pre(inst); amd64_emit_rex ((inst),(size),0,0,(basereg)); x86_not_membase((inst),((basereg)&0x7),(disp)); amd64_codegen_post(inst); } while (0)
+#define amd64_not_reg_size(inst,reg,size) do { amd64_codegen_pre(inst); amd64_emit_rex ((inst),(size),0,0,(reg)); x86_not_reg((inst),((reg)&0x7)); amd64_codegen_post(inst); } while (0)
+#define amd64_neg_mem_size(inst,mem,size) do { amd64_codegen_pre(inst); amd64_emit_rex ((inst),(size),0,0,0); x86_neg_mem((inst),(mem)); amd64_codegen_post(inst); } while (0)
+#define amd64_neg_membase_size(inst,basereg,disp,size) do { amd64_codegen_pre(inst); amd64_emit_rex ((inst),(size),0,0,(basereg)); x86_neg_membase((inst),((basereg)&0x7),(disp)); amd64_codegen_post(inst); } while (0)
+#define amd64_neg_reg_size(inst,reg,size) do { amd64_codegen_pre(inst); amd64_emit_rex ((inst),(size),0,0,(reg)); x86_neg_reg((inst),((reg)&0x7)); amd64_codegen_post(inst); } while (0)
+#define amd64_nop_size(inst,size) do { amd64_codegen_pre(inst); x86_nop(inst); amd64_codegen_post(inst); } while (0)
+//#define amd64_alu_reg_imm_size(inst,opc,reg,imm,size) do { amd64_codegen_pre(inst); amd64_emit_rex ((inst),(size),0,0,(reg)); x86_alu_reg_imm((inst),(opc),((reg)&0x7),(imm)); amd64_codegen_post(inst); } while (0)
+#define amd64_alu_mem_imm_size(inst,opc,mem,imm,size) do { amd64_codegen_pre(inst); amd64_emit_rex ((inst),(size),0,0,0); x86_alu_mem_imm((inst),(opc),(mem),(imm)); amd64_codegen_post(inst); } while (0)
+#define amd64_alu_membase_imm_size(inst,opc,basereg,disp,imm,size) do { amd64_codegen_pre(inst); amd64_emit_rex ((inst),(size),0,0,(basereg)); x86_alu_membase_imm((inst),(opc),((basereg)&0x7),(disp),(imm)); amd64_codegen_post(inst); } while (0)
+#define amd64_alu_membase8_imm_size(inst,opc,basereg,disp,imm,size) do { amd64_codegen_pre(inst); amd64_emit_rex ((inst),(size),0,0,(basereg)); x86_alu_membase8_imm((inst),(opc),((basereg)&0x7),(disp),(imm)); amd64_codegen_post(inst); } while (0) 
+#define amd64_alu_mem_reg_size(inst,opc,mem,reg,size) do { amd64_codegen_pre(inst); amd64_emit_rex ((inst),(size),0,0,(reg)); x86_alu_mem_reg((inst),(opc),(mem),((reg)&0x7)); amd64_codegen_post(inst); } while (0)
+#define amd64_alu_membase_reg_size(inst,opc,basereg,disp,reg,size) do { amd64_codegen_pre(inst); amd64_emit_rex ((inst),(size),(reg),0,(basereg)); x86_alu_membase_reg((inst),(opc),((basereg)&0x7),(disp),((reg)&0x7)); amd64_codegen_post(inst); } while (0)
+//#define amd64_alu_reg_reg_size(inst,opc,dreg,reg,size) do { amd64_codegen_pre(inst); amd64_emit_rex ((inst),(size),(dreg),0,(reg)); x86_alu_reg_reg((inst),(opc),((dreg)&0x7),((reg)&0x7)); amd64_codegen_post(inst); } while (0)
+#define amd64_alu_reg8_reg8_size(inst,opc,dreg,reg,is_dreg_h,is_reg_h,size) do { amd64_codegen_pre(inst); amd64_emit_rex ((inst),(size),(dreg),0,(reg)); x86_alu_reg8_reg8((inst),(opc),((dreg)&0x7),((reg)&0x7),(is_dreg_h),(is_reg_h)); amd64_codegen_post(inst); } while (0)
+#define amd64_alu_reg_mem_size(inst,opc,reg,mem,size) do { amd64_codegen_pre(inst); amd64_emit_rex ((inst),(size),0,0,(reg)); x86_alu_reg_mem((inst),(opc),((reg)&0x7),(mem)); amd64_codegen_post(inst); } while (0)
+//#define amd64_alu_reg_membase_size(inst,opc,reg,basereg,disp,size) do { amd64_codegen_pre(inst); amd64_emit_rex ((inst),(size),(reg),0,(basereg)); x86_alu_reg_membase((inst),(opc),((reg)&0x7),((basereg)&0x7),(disp)); amd64_codegen_post(inst); } while (0)
+//#define amd64_test_reg_imm_size(inst,reg,imm,size) do { amd64_codegen_pre(inst); amd64_emit_rex ((inst),(size),0,0,(reg)); x86_test_reg_imm((inst),((reg)&0x7),(imm)); amd64_codegen_post(inst); } while (0)
+#define amd64_test_mem_imm_size(inst,mem,imm,size) do { amd64_codegen_pre(inst); amd64_emit_rex ((inst),(size),0,0,0); x86_test_mem_imm((inst),(mem),(imm)); amd64_codegen_post(inst); } while (0)
+#define amd64_test_membase_imm_size(inst,basereg,disp,imm,size) do { amd64_codegen_pre(inst); amd64_emit_rex ((inst),(size),0,0,(basereg)); x86_test_membase_imm((inst),((basereg)&0x7),(disp),(imm)); amd64_codegen_post(inst); } while (0)
+#define amd64_test_reg_reg_size(inst,dreg,reg,size) do { amd64_codegen_pre(inst); amd64_emit_rex ((inst),(size),(dreg),0,(reg)); x86_test_reg_reg((inst),((dreg)&0x7),((reg)&0x7)); amd64_codegen_post(inst); } while (0)
+#define amd64_test_mem_reg_size(inst,mem,reg,size) do { amd64_codegen_pre(inst); amd64_emit_rex ((inst),(size),0,0,(reg)); x86_test_mem_reg((inst),(mem),((reg)&0x7)); amd64_codegen_post(inst); } while (0)
+#define amd64_test_membase_reg_size(inst,basereg,disp,reg,size) do { amd64_codegen_pre(inst); amd64_emit_rex ((inst),(size),(reg),0,(basereg)); x86_test_membase_reg((inst),((basereg)&0x7),(disp),((reg)&0x7)); amd64_codegen_post(inst); } while (0)
+#define amd64_shift_reg_imm_size(inst,opc,reg,imm,size) do { amd64_codegen_pre(inst); amd64_emit_rex ((inst),(size),0,0,(reg)); x86_shift_reg_imm((inst),(opc),((reg)&0x7),(imm)); amd64_codegen_post(inst); } while (0)
+#define amd64_shift_mem_imm_size(inst,opc,mem,imm,size) do { amd64_codegen_pre(inst); amd64_emit_rex ((inst),(size),0,0,(reg)); x86_shift_mem_imm((inst),(opc),(mem),(imm)); amd64_codegen_post(inst); } while (0)
+#define amd64_shift_membase_imm_size(inst,opc,basereg,disp,imm,size) do { amd64_codegen_pre(inst); amd64_emit_rex ((inst),(size),(reg),0,(basereg)); x86_shift_membase_imm((inst),(opc),((basereg)&0x7),(disp),(imm)); amd64_codegen_post(inst); } while (0)
+#define amd64_shift_reg_size(inst,opc,reg,size) do { amd64_codegen_pre(inst); amd64_emit_rex ((inst),(size),0,0,(reg)); x86_shift_reg((inst),(opc),((reg)&0x7)); amd64_codegen_post(inst); } while (0)
+#define amd64_shift_mem_size(inst,opc,mem,size) do { amd64_codegen_pre(inst); amd64_emit_rex ((inst),(size),0,0,(reg)); x86_shift_mem((inst),(opc),(mem)); amd64_codegen_post(inst); } while (0)
+#define amd64_shift_membase_size(inst,opc,basereg,disp,size) do { amd64_codegen_pre(inst); amd64_emit_rex ((inst),(size),0,0,(basereg)); x86_shift_membase((inst),(opc),((basereg)&0x7),(disp)); amd64_codegen_post(inst); } while (0)
+#define amd64_shrd_reg_size(inst,dreg,reg,size) do { amd64_codegen_pre(inst); amd64_emit_rex ((inst),(size),(dreg),0,(reg)); x86_shrd_reg((inst),((dreg)&0x7),((reg)&0x7)); amd64_codegen_post(inst); } while (0)
+#define amd64_shrd_reg_imm_size(inst,dreg,reg,shamt,size) do { amd64_codegen_pre(inst); amd64_emit_rex ((inst),(size),(dreg),0,(reg)); x86_shrd_reg_imm((inst),((dreg)&0x7),((reg)&0x7),(shamt)); amd64_codegen_post(inst); } while (0)
+#define amd64_shld_reg_size(inst,dreg,reg,size) do { amd64_codegen_pre(inst); amd64_emit_rex ((inst),(size),(dreg),0,(reg)); x86_shld_reg((inst),((dreg)&0x7),((reg)&0x7)); amd64_codegen_post(inst); } while (0)
+#define amd64_shld_reg_imm_size(inst,dreg,reg,shamt,size) do { amd64_codegen_pre(inst); amd64_emit_rex ((inst),(size),(dreg),0,(reg)); x86_shld_reg_imm((inst),((dreg)&0x7),((reg)&0x7),(shamt)); amd64_codegen_post(inst); } while (0)
+#define amd64_mul_reg_size(inst,reg,is_signed,size) do { amd64_codegen_pre(inst); amd64_emit_rex ((inst),(size),0,0,(reg)); x86_mul_reg((inst),((reg)&0x7),(is_signed)); amd64_codegen_post(inst); } while (0)
+#define amd64_mul_mem_size(inst,mem,is_signed,size) do { amd64_codegen_pre(inst); amd64_emit_rex ((inst),(size),0,0,0); x86_mul_mem((inst),(mem),(is_signed)); amd64_codegen_post(inst); } while (0)
+#define amd64_mul_membase_size(inst,basereg,disp,is_signed,size) do { amd64_codegen_pre(inst); amd64_emit_rex ((inst),(size),0,0,(basereg)); x86_mul_membase((inst),((basereg)&0x7),(disp),(is_signed)); amd64_codegen_post(inst); } while (0)
+#define amd64_imul_reg_reg_size(inst,dreg,reg,size) do { amd64_codegen_pre(inst); amd64_emit_rex ((inst),(size),(dreg),0,(reg)); x86_imul_reg_reg((inst),((dreg)&0x7),((reg)&0x7)); amd64_codegen_post(inst); } while (0)
+#define amd64_imul_reg_mem_size(inst,reg,mem,size) do { amd64_codegen_pre(inst); amd64_emit_rex ((inst),(size),0,0,(reg)); x86_imul_reg_mem((inst),((reg)&0x7),(mem)); amd64_codegen_post(inst); } while (0)
+#define amd64_imul_reg_membase_size(inst,reg,basereg,disp,size) do { amd64_codegen_pre(inst); amd64_emit_rex ((inst),(size),(reg),0,(basereg)); x86_imul_reg_membase((inst),((reg)&0x7),((basereg)&0x7),(disp)); amd64_codegen_post(inst); } while (0)
+#define amd64_imul_reg_reg_imm_size(inst,dreg,reg,imm,size) do { amd64_codegen_pre(inst); amd64_emit_rex ((inst),(size),(dreg),0,(reg)); x86_imul_reg_reg_imm((inst),((dreg)&0x7),((reg)&0x7),(imm)); amd64_codegen_post(inst); } while (0)
+#define amd64_imul_reg_mem_imm_size(inst,reg,mem,imm,size) do { amd64_codegen_pre(inst); amd64_emit_rex ((inst),(size),0,0,(reg)); x86_imul_reg_mem_imm((inst),((reg)&0x7),(mem),(imm)); amd64_codegen_post(inst); } while (0)
+#define amd64_imul_reg_membase_imm_size(inst,reg,basereg,disp,imm,size) do { amd64_codegen_pre(inst); amd64_emit_rex ((inst),(size),(reg),0,(basereg)); x86_imul_reg_membase_imm((inst),((reg)&0x7),((basereg)&0x7),(disp),(imm)); amd64_codegen_post(inst); } while (0)
+#define amd64_div_reg_size(inst,reg,is_signed,size) do { amd64_codegen_pre(inst); amd64_emit_rex ((inst),(size),0,0,(reg)); x86_div_reg((inst),((reg)&0x7),(is_signed)); amd64_codegen_post(inst); } while (0)
+#define amd64_div_mem_size(inst,mem,is_signed,size) do { amd64_codegen_pre(inst); amd64_emit_rex ((inst),(size),0,0,0); x86_div_mem((inst),(mem),(is_signed)); amd64_codegen_post(inst); } while (0)
+#define amd64_div_membase_size(inst,basereg,disp,is_signed,size) do { amd64_codegen_pre(inst); amd64_emit_rex ((inst),(size),0,0,(basereg)); x86_div_membase((inst),((basereg)&0x7),(disp),(is_signed)); amd64_codegen_post(inst); } while (0)
+#define amd64_mov_mem_reg_size(inst,mem,reg,size) do { amd64_codegen_pre(inst); amd64_emit_rex ((inst),(size),0,0,(reg)); x86_mov_mem_reg((inst),(mem),((reg)&0x7),(size) == 8 ? 4 : (size)); amd64_codegen_post(inst); } while (0)
+//#define amd64_mov_regp_reg_size(inst,regp,reg,size) do { amd64_codegen_pre(inst); amd64_emit_rex ((inst),(size),(regp),0,(reg)); x86_mov_regp_reg((inst),(regp),((reg)&0x7),(size) == 8 ? 4 : (size)); amd64_codegen_post(inst); } while (0)
+//#define amd64_mov_membase_reg_size(inst,basereg,disp,reg,size) do { amd64_codegen_pre(inst); amd64_emit_rex ((inst),(size),(reg),0,(basereg)); x86_mov_membase_reg((inst),((basereg)&0x7),(disp),((reg)&0x7),(size) == 8 ? 4 : (size)); amd64_codegen_post(inst); } while (0)
+#define amd64_mov_memindex_reg_size(inst,basereg,disp,indexreg,shift,reg,size) do { amd64_codegen_pre(inst); amd64_emit_rex ((inst),(size),(reg),(indexreg),(basereg)); x86_mov_memindex_reg((inst),((basereg)&0x7),(disp),((indexreg)&0x7),(shift),((reg)&0x7),(size) == 8 ? 4 : (size)); amd64_codegen_post(inst); } while (0)
+#define amd64_mov_reg_reg_size(inst,dreg,reg,size) do { amd64_codegen_pre(inst); amd64_emit_rex ((inst),(size),(dreg),0,(reg)); x86_mov_reg_reg((inst),((dreg)&0x7),((reg)&0x7),(size) == 8 ? 4 : (size)); amd64_codegen_post(inst); } while (0)
+//#define amd64_mov_reg_mem_size(inst,reg,mem,size) do { amd64_codegen_pre(inst); amd64_emit_rex ((inst),(size),0,0,(reg)); x86_mov_reg_mem((inst),((reg)&0x7),(mem),(size) == 8 ? 4 : (size)); amd64_codegen_post(inst); } while (0)
+//#define amd64_mov_reg_membase_size(inst,reg,basereg,disp,size) do { amd64_codegen_pre(inst); amd64_emit_rex ((inst),(size),(reg),0,(basereg)); x86_mov_reg_membase((inst),((reg)&0x7),((basereg)&0x7),(disp),(size) == 8 ? 4 : (size)); amd64_codegen_post(inst); } while (0)
+//#define amd64_mov_reg_memindex_size(inst,reg,basereg,disp,indexreg,shift,size) do { amd64_codegen_pre(inst); amd64_emit_rex ((inst),(size),(reg),(indexreg),(basereg)); x86_mov_reg_memindex((inst),((reg)&0x7),((basereg)&0x7),(disp),((indexreg)&0x7),(shift),(size) == 8 ? 4 : (size)); amd64_codegen_post(inst); } while (0)
+#define amd64_clear_reg_size(inst,reg,size) do { amd64_codegen_pre(inst); amd64_emit_rex ((inst),(size),0,0,(reg)); x86_clear_reg((inst),((reg)&0x7)); amd64_codegen_post(inst); } while (0)
+//#define amd64_mov_reg_imm_size(inst,reg,imm,size) do { amd64_codegen_pre(inst); amd64_emit_rex ((inst),(size),0,0,(reg)); x86_mov_reg_imm((inst),((reg)&0x7),(imm)); amd64_codegen_post(inst); } while (0)
+#define amd64_mov_mem_imm_size(inst,mem,imm,size) do { amd64_codegen_pre(inst); amd64_emit_rex ((inst),(size),0,0,0); x86_mov_mem_imm((inst),(mem),(imm),(size) == 8 ? 4 : (size)); amd64_codegen_post(inst); } while (0)
+//#define amd64_mov_membase_imm_size(inst,basereg,disp,imm,size) do { amd64_codegen_pre(inst); amd64_emit_rex ((inst),(size),0,0,(basereg)); x86_mov_membase_imm((inst),((basereg)&0x7),(disp),(imm),(size) == 8 ? 4 : (size)); amd64_codegen_post(inst); } while (0)
+#define amd64_mov_memindex_imm_size(inst,basereg,disp,indexreg,shift,imm,size) do { amd64_codegen_pre(inst); amd64_emit_rex ((inst),(size),0,(indexreg),(basereg)); x86_mov_memindex_imm((inst),((basereg)&0x7),(disp),((indexreg)&0x7),(shift),(imm),(size) == 8 ? 4 : (size)); amd64_codegen_post(inst); } while (0)
+#define amd64_lea_mem_size(inst,reg,mem,size) do { amd64_codegen_pre(inst); amd64_emit_rex ((inst),(size),0,0,(reg)); x86_lea_mem((inst),((reg)&0x7),(mem)); amd64_codegen_post(inst); } while (0)
+//#define amd64_lea_membase_size(inst,reg,basereg,disp,size) do { amd64_codegen_pre(inst); amd64_emit_rex ((inst),(size),0,0,(basereg)); x86_lea_membase((inst),((reg)&0x7),((basereg)&0x7),(disp)); amd64_codegen_post(inst); } while (0)
+#define amd64_lea_memindex_size(inst,reg,basereg,disp,indexreg,shift,size) do { amd64_codegen_pre(inst); amd64_emit_rex ((inst),(size),(reg),(indexreg),(basereg)); x86_lea_memindex((inst),((reg)&0x7),((basereg)&0x7),(disp),((indexreg)&0x7),(shift)); amd64_codegen_post(inst); } while (0)
+#define amd64_widen_reg_size(inst,dreg,reg,is_signed,is_half,size) do { amd64_codegen_pre(inst); amd64_emit_rex ((inst),(size),(dreg),0,(reg)); x86_widen_reg((inst),((dreg)&0x7),((reg)&0x7),(is_signed),(is_half)); amd64_codegen_post(inst); } while (0)
+#define amd64_widen_mem_size(inst,dreg,mem,is_signed,is_half,size) do { amd64_codegen_pre(inst); amd64_emit_rex ((inst),(size),(dreg),0,0); x86_widen_mem((inst),((dreg)&0x7),(mem),(is_signed),(is_half)); amd64_codegen_post(inst); } while (0)
+#define amd64_widen_membase_size(inst,dreg,basereg,disp,is_signed,is_half,size) do { amd64_codegen_pre(inst); amd64_emit_rex ((inst),(size),(dreg),0,(basereg)); x86_widen_membase((inst),((dreg)&0x7),((basereg)&0x7),(disp),(is_signed),(is_half)); amd64_codegen_post(inst); } while (0)
+#define amd64_widen_memindex_size(inst,dreg,basereg,disp,indexreg,shift,is_signed,is_half,size) do { amd64_codegen_pre(inst); amd64_emit_rex ((inst),(size),(dreg),(indexreg),(basereg)); x86_widen_memindex((inst),((dreg)&0x7),((basereg)&0x7),(disp),((indexreg)&0x7),(shift),(is_signed),(is_half)); amd64_codegen_post(inst); } while (0)
+#define amd64_cdq_size(inst,size) do { amd64_codegen_pre(inst); amd64_emit_rex ((inst),(size),0,0,0); x86_cdq(inst); amd64_codegen_post(inst); } while (0)
+#define amd64_wait_size(inst,size) do { amd64_codegen_pre(inst); amd64_emit_rex ((inst),(size),0,0,0); x86_wait(inst); amd64_codegen_post(inst); } while (0)
+#define amd64_fp_op_mem_size(inst,opc,mem,is_double,size) do { amd64_codegen_pre(inst); amd64_emit_rex ((inst),0,0,0,0); x86_fp_op_mem((inst),(opc),(mem),(is_double)); amd64_codegen_post(inst); } while (0)
+#define amd64_fp_op_membase_size(inst,opc,basereg,disp,is_double,size) do { amd64_codegen_pre(inst); amd64_emit_rex ((inst),0,0,0,(basereg)); x86_fp_op_membase((inst),(opc),((basereg)&0x7),(disp),(is_double)); amd64_codegen_post(inst); } while (0)
+#define amd64_fp_op_size(inst,opc,index,size) do { amd64_codegen_pre(inst); amd64_emit_rex ((inst),0,0,0,0); x86_fp_op((inst),(opc),(index)); amd64_codegen_post(inst); } while (0)
+#define amd64_fp_op_reg_size(inst,opc,index,pop_stack,size) do { amd64_codegen_pre(inst); amd64_emit_rex ((inst),0,0,0,0); x86_fp_op_reg((inst),(opc),(index),(pop_stack)); amd64_codegen_post(inst); } while (0)
+#define amd64_fp_int_op_membase_size(inst,opc,basereg,disp,is_int,size) do { amd64_codegen_pre(inst); amd64_emit_rex ((inst),0,0,0,(basereg)); x86_fp_int_op_membase((inst),(opc),((basereg)&0x7),(disp),(is_int)); amd64_codegen_post(inst); } while (0)
+#define amd64_fstp_size(inst,index,size) do { amd64_codegen_pre(inst); amd64_emit_rex ((inst),0,0,0,0); x86_fstp((inst),(index)); amd64_codegen_post(inst); } while (0)
+#define amd64_fcompp_size(inst,size) do { amd64_codegen_pre(inst); amd64_emit_rex ((inst),0,0,0,0); x86_fcompp(inst); amd64_codegen_post(inst); } while (0)
+#define amd64_fucompp_size(inst,size) do { amd64_codegen_pre(inst); amd64_emit_rex ((inst),0,0,0,0); x86_fucompp(inst); amd64_codegen_post(inst); } while (0)
+#define amd64_fnstsw_size(inst,size) do { amd64_codegen_pre(inst); amd64_emit_rex ((inst),0,0,0,0); x86_fnstsw(inst); amd64_codegen_post(inst); } while (0)
+#define amd64_fnstcw_size(inst,mem,size) do { amd64_codegen_pre(inst); amd64_emit_rex ((inst),0,0,0,0); x86_fnstcw((inst),(mem)); amd64_codegen_post(inst); } while (0)
+#define amd64_fnstcw_membase_size(inst,basereg,disp,size) do { amd64_codegen_pre(inst); amd64_emit_rex ((inst),(size),0,0,(basereg)); x86_fnstcw_membase((inst),((basereg)&0x7),(disp)); amd64_codegen_post(inst); } while (0)
+#define amd64_fldcw_size(inst,mem,size) do { amd64_codegen_pre(inst); amd64_emit_rex ((inst),0,0,0,0); x86_fldcw((inst),(mem)); amd64_codegen_post(inst); } while (0)
+#define amd64_fldcw_membase_size(inst,basereg,disp,size) do { amd64_codegen_pre(inst); amd64_emit_rex ((inst),0,0,0,(basereg)); x86_fldcw_membase((inst),((basereg)&0x7),(disp)); amd64_codegen_post(inst); } while (0)
+#define amd64_fchs_size(inst,size) do { amd64_codegen_pre(inst); amd64_emit_rex ((inst),0,0,0,0); x86_fchs(inst); amd64_codegen_post(inst); } while (0)
+#define amd64_frem_size(inst,size) do { amd64_codegen_pre(inst); amd64_emit_rex ((inst),0,0,0,0); x86_frem(inst); amd64_codegen_post(inst); } while (0)
+#define amd64_fxch_size(inst,index,size) do { amd64_codegen_pre(inst); amd64_emit_rex ((inst),0,0,0,0); x86_fxch((inst),(index)); amd64_codegen_post(inst); } while (0)
+#define amd64_fcomi_size(inst,index,size) do { amd64_codegen_pre(inst); amd64_emit_rex ((inst),0,0,0,0); x86_fcomi((inst),(index)); amd64_codegen_post(inst); } while (0)
+#define amd64_fcomip_size(inst,index,size) do { amd64_codegen_pre(inst); amd64_emit_rex ((inst),0,0,0,0); x86_fcomip((inst),(index)); amd64_codegen_post(inst); } while (0)
+#define amd64_fucomi_size(inst,index,size) do { amd64_codegen_pre(inst); amd64_emit_rex ((inst),0,0,0,0); x86_fucomi((inst),(index)); amd64_codegen_post(inst); } while (0)
+#define amd64_fucomip_size(inst,index,size) do { amd64_codegen_pre(inst); amd64_emit_rex ((inst),0,0,0,0); x86_fucomip((inst),(index)); amd64_codegen_post(inst); } while (0)
+#define amd64_fld_size(inst,mem,is_double,size) do { amd64_codegen_pre(inst); amd64_emit_rex ((inst),0,0,0,0); x86_fld((inst),(mem),(is_double)); amd64_codegen_post(inst); } while (0)
+//#define amd64_fld_membase_size(inst,basereg,disp,is_double,size) do { amd64_codegen_pre(inst); amd64_emit_rex ((inst),0,0,0,(basereg)); x86_fld_membase((inst),((basereg)&0x7),(disp),(is_double)); amd64_codegen_post(inst); } while (0)
+#define amd64_fld80_mem_size(inst,mem,size) do { amd64_codegen_pre(inst); amd64_emit_rex ((inst),0,0,0,0); x86_fld80_mem((inst),(mem)); amd64_codegen_post(inst); } while (0)
+#define amd64_fld80_membase_size(inst,basereg,disp,size) do { amd64_codegen_pre(inst); amd64_emit_rex ((inst),(size),0,0,(basereg)); x86_fld80_membase((inst),((basereg)&0x7),(disp)); amd64_codegen_post(inst); } while (0)
+#define amd64_fild_size(inst,mem,is_long,size) do { amd64_codegen_pre(inst); amd64_emit_rex ((inst),0,0,0,0); x86_fild((inst),(mem),(is_long)); amd64_codegen_post(inst); } while (0)
+#define amd64_fild_membase_size(inst,basereg,disp,is_long,size) do { amd64_codegen_pre(inst); amd64_emit_rex ((inst),0,0,0,(basereg)); x86_fild_membase((inst),((basereg)&0x7),(disp),(is_long)); amd64_codegen_post(inst); } while (0)
+#define amd64_fld_reg_size(inst,index,size) do { amd64_codegen_pre(inst); amd64_emit_rex ((inst),0,0,0,0); x86_fld_reg((inst),(index)); amd64_codegen_post(inst); } while (0)
+#define amd64_fldz_size(inst,size) do { amd64_codegen_pre(inst); amd64_emit_rex ((inst),0,0,0,0); x86_fldz(inst); amd64_codegen_post(inst); } while (0)
+#define amd64_fld1_size(inst,size) do { amd64_codegen_pre(inst); amd64_emit_rex ((inst),0,0,0,0); x86_fld1(inst); amd64_codegen_post(inst); } while (0)
+#define amd64_fldpi_size(inst,size) do { amd64_codegen_pre(inst); amd64_emit_rex ((inst),0,0,0,0); x86_fldpi(inst); amd64_codegen_post(inst); } while (0)
+#define amd64_fst_size(inst,mem,is_double,pop_stack,size) do { amd64_codegen_pre(inst); amd64_emit_rex ((inst),0,0,0,0); x86_fst((inst),(mem),(is_double),(pop_stack)); amd64_codegen_post(inst); } while (0)
+#define amd64_fst_membase_size(inst,basereg,disp,is_double,pop_stack,size) do { amd64_codegen_pre(inst); amd64_emit_rex ((inst),0,0,0,(basereg)); x86_fst_membase((inst),((basereg)&0x7),(disp),(is_double),(pop_stack)); amd64_codegen_post(inst); } while (0)
+#define amd64_fst80_mem_size(inst,mem,size) do { amd64_codegen_pre(inst); amd64_emit_rex ((inst),0,0,0,0); x86_fst80_mem((inst),(mem)); amd64_codegen_post(inst); } while (0)
+#define amd64_fst80_membase_size(inst,basereg,disp,size) do { amd64_codegen_pre(inst); amd64_emit_rex ((inst),0,0,0,(basereg)); x86_fst80_membase((inst),((basereg)&0x7),(disp)); amd64_codegen_post(inst); } while (0)
+#define amd64_fist_pop_size(inst,mem,is_long,size) do { amd64_codegen_pre(inst); amd64_emit_rex ((inst),0,0,0,0); x86_fist_pop((inst),(mem),(is_long)); amd64_codegen_post(inst); } while (0)
+#define amd64_fist_pop_membase_size(inst,basereg,disp,is_long,size) do { amd64_codegen_pre(inst); amd64_emit_rex ((inst),0,0,0,(basereg)); x86_fist_pop_membase((inst),((basereg)&0x7),(disp),(is_long)); amd64_codegen_post(inst); } while (0)
+#define amd64_fstsw_size(inst,size) do { amd64_codegen_pre(inst); amd64_emit_rex ((inst),(size),0,0,0); x86_fstsw(inst); amd64_codegen_post(inst); } while (0)
+#define amd64_fist_membase_size(inst,basereg,disp,is_int,size) do { amd64_codegen_pre(inst); amd64_emit_rex ((inst),0,0,0,(basereg)); x86_fist_membase((inst),((basereg)&0x7),(disp),(is_int)); amd64_codegen_post(inst); } while (0)
+//#define amd64_push_reg_size(inst,reg,size) do { amd64_codegen_pre(inst); amd64_emit_rex ((inst),(size),0,0,(reg)); x86_push_reg((inst),((reg)&0x7)); amd64_codegen_post(inst); } while (0)
+#define amd64_push_regp_size(inst,reg,size) do { amd64_codegen_pre(inst); amd64_emit_rex ((inst),(size),0,0,(reg)); x86_push_regp((inst),((reg)&0x7)); amd64_codegen_post(inst); } while (0)
+#define amd64_push_mem_size(inst,mem,size) do { amd64_codegen_pre(inst); amd64_emit_rex ((inst),(size),0,0,0); x86_push_mem((inst),(mem)); amd64_codegen_post(inst); } while (0)
+//#define amd64_push_membase_size(inst,basereg,disp,size) do { amd64_codegen_pre(inst); amd64_emit_rex ((inst),(size),0,0,(basereg)); x86_push_membase((inst),((basereg)&0x7),(disp)); amd64_codegen_post(inst); } while (0)
+#define amd64_push_memindex_size(inst,basereg,disp,indexreg,shift,size) do { amd64_codegen_pre(inst); amd64_emit_rex ((inst),(size),0,(indexreg),(basereg)); x86_push_memindex((inst),((basereg)&0x7),(disp),((indexreg)&0x7),(shift)); amd64_codegen_post(inst); } while (0)
+#define amd64_push_imm_size(inst,imm,size) do { amd64_codegen_pre(inst); amd64_emit_rex ((inst),0,0,0,0); x86_push_imm((inst),(imm)); amd64_codegen_post(inst); } while (0)
+//#define amd64_pop_reg_size(inst,reg,size) do { amd64_codegen_pre(inst); amd64_emit_rex ((inst),(size),0,0,(reg)); x86_pop_reg((inst),((reg)&0x7)); amd64_codegen_post(inst); } while (0)
+#define amd64_pop_mem_size(inst,mem,size) do { amd64_codegen_pre(inst); amd64_emit_rex ((inst),(size),0,0,0); x86_pop_mem((inst),(mem)); amd64_codegen_post(inst); } while (0)
+#define amd64_pop_membase_size(inst,basereg,disp,size) do { amd64_codegen_pre(inst); amd64_emit_rex ((inst),(size),0,0,(basereg)); x86_pop_membase((inst),((basereg)&0x7),(disp)); amd64_codegen_post(inst); } while (0)
+#define amd64_pushad_size(inst,size) do { amd64_codegen_pre(inst); amd64_emit_rex ((inst),(size),0,0,0); x86_pushad(inst); amd64_codegen_post(inst); } while (0)
+#define amd64_pushfd_size(inst,size) do { amd64_codegen_pre(inst); amd64_emit_rex ((inst),(size),0,0,0); x86_pushfd(inst); amd64_codegen_post(inst); } while (0)
+#define amd64_popad_size(inst,size) do { amd64_codegen_pre(inst); amd64_emit_rex ((inst),(size),0,0,0); x86_popad(inst); amd64_codegen_post(inst); } while (0)
+#define amd64_popfd_size(inst,size) do { amd64_codegen_pre(inst); amd64_emit_rex ((inst),(size),0,0,0); x86_popfd(inst); amd64_codegen_post(inst); } while (0)
+#define amd64_loop_size(inst,imm,size) do { amd64_codegen_pre(inst); amd64_emit_rex ((inst),(size),0,0,0); x86_loop((inst),(imm)); amd64_codegen_post(inst); } while (0)
+#define amd64_loope_size(inst,imm,size) do { amd64_codegen_pre(inst); amd64_emit_rex ((inst),(size),0,0,0); x86_loope((inst),(imm)); amd64_codegen_post(inst); } while (0)
+#define amd64_loopne_size(inst,imm,size) do { amd64_codegen_pre(inst); amd64_emit_rex ((inst),(size),0,0,0); x86_loopne((inst),(imm)); amd64_codegen_post(inst); } while (0)
+#define amd64_jump32_size(inst,imm,size) do { amd64_codegen_pre(inst); amd64_emit_rex ((inst),(size),0,0,0); x86_jump32((inst),(imm)); amd64_codegen_post(inst); } while (0)
+#define amd64_jump8_size(inst,imm,size) do { amd64_codegen_pre(inst); amd64_emit_rex ((inst),(size),0,0,0); x86_jump8((inst),(imm)); amd64_codegen_post(inst); } while (0)
+#if !defined( __native_client_codegen__ )
+/* Defined above for Native Client, so they can be used in other macros */
 #define amd64_jump_reg_size(inst,reg,size) do { amd64_emit_rex ((inst),0,0,0,(reg)); x86_jump_reg((inst),((reg)&0x7)); } while (0)
 #define amd64_jump_mem_size(inst,mem,size) do { amd64_emit_rex ((inst),(size),0,0,0); x86_jump_mem((inst),(mem)); } while (0)
-#define amd64_jump_disp_size(inst,disp,size) do { amd64_emit_rex ((inst),0,0,0,0); x86_jump_disp((inst),(disp)); } while (0)
+#endif
+#define amd64_jump_disp_size(inst,disp,size) do { amd64_codegen_pre(inst); amd64_emit_rex ((inst),0,0,0,0); x86_jump_disp((inst),(disp)); amd64_codegen_post(inst); } while (0)
 #define amd64_branch8_size(inst,cond,imm,is_signed,size) do { x86_branch8((inst),(cond),(imm),(is_signed)); } while (0)
 #define amd64_branch32_size(inst,cond,imm,is_signed,size) do { x86_branch32((inst),(cond),(imm),(is_signed)); } while (0)
-#define amd64_branch_size(inst,cond,target,is_signed,size) do { amd64_emit_rex ((inst),(size),0,0,0); x86_branch((inst),(cond),(target),(is_signed)); } while (0)
-#define amd64_branch_disp_size(inst,cond,disp,is_signed,size) do { amd64_emit_rex ((inst),(size),0,0,0); x86_branch_disp((inst),(cond),(disp),(is_signed)); } while (0)
-#define amd64_set_reg_size(inst,cond,reg,is_signed,size) do { amd64_emit_rex((inst),1,0,0,(reg)); x86_set_reg((inst),(cond),((reg)&0x7),(is_signed)); } while (0)
-#define amd64_set_mem_size(inst,cond,mem,is_signed,size) do { x86_set_mem((inst),(cond),(mem),(is_signed)); } while (0)
-#define amd64_set_membase_size(inst,cond,basereg,disp,is_signed,size) do { amd64_emit_rex ((inst),0,0,0,(basereg)); x86_set_membase((inst),(cond),((basereg)&0x7),(disp),(is_signed)); } while (0)
+#define amd64_branch_size_body(inst,cond,target,is_signed,size) do { amd64_codegen_pre(inst); amd64_emit_rex ((inst),(size),0,0,0); x86_branch((inst),(cond),(target),(is_signed)); amd64_codegen_post(inst); } while (0)
+#if defined(__default_codegen__)
+#define amd64_branch_size(inst,cond,target,is_signed,size) do { amd64_branch_size_body((inst),(cond),(target),(is_signed),(size)); } while (0)
+#elif defined(__native_client_codegen__)
+#define amd64_branch_size(inst,cond,target,is_signed,size) \
+       do { \
+               /* amd64_branch_size_body used twice in     */ \
+               /* case of relocation by amd64_codegen_post */ \
+               guint8* branch_start; \
+               amd64_codegen_pre(inst); \
+               amd64_branch_size_body((inst),(cond),(target),(is_signed),(size)); \
+               inst = amd64_codegen_post(inst); \
+               branch_start = inst; \
+               amd64_branch_size_body((inst),(cond),(target),(is_signed),(size)); \
+               mono_amd64_patch(branch_start, (target)); \
+       } while (0)
+#endif
+
+#define amd64_branch_disp_size(inst,cond,disp,is_signed,size) do { amd64_codegen_pre(inst); amd64_emit_rex ((inst),(size),0,0,0); x86_branch_disp((inst),(cond),(disp),(is_signed)); amd64_codegen_post(inst); } while (0)
+#define amd64_set_reg_size(inst,cond,reg,is_signed,size) do { amd64_codegen_pre(inst); amd64_emit_rex((inst),1,0,0,(reg)); x86_set_reg((inst),(cond),((reg)&0x7),(is_signed)); amd64_codegen_post(inst); } while (0)
+#define amd64_set_mem_size(inst,cond,mem,is_signed,size) do { amd64_codegen_pre(inst); x86_set_mem((inst),(cond),(mem),(is_signed)); amd64_codegen_post(inst); } while (0)
+#define amd64_set_membase_size(inst,cond,basereg,disp,is_signed,size) do { amd64_codegen_pre(inst); amd64_emit_rex ((inst),0,0,0,(basereg)); x86_set_membase((inst),(cond),((basereg)&0x7),(disp),(is_signed)); amd64_codegen_post(inst); } while (0)
+//#define amd64_call_reg_size(inst,reg,size) do { amd64_codegen_pre(inst); amd64_emit_rex ((inst),(size),0,0,(reg)); x86_call_reg((inst),((reg)&0x7)); amd64_codegen_post(inst); } while (0)
+#define amd64_call_mem_size(inst,mem,size) do { amd64_codegen_pre(inst); amd64_emit_rex ((inst),(size),0,0,0); x86_call_mem((inst),(mem)); amd64_codegen_post(inst); } while (0)
+
+#if defined(__default_codegen__)
+
 #define amd64_call_imm_size(inst,disp,size) do { x86_call_imm((inst),(disp)); } while (0)
-//#define amd64_call_reg_size(inst,reg,size) do { amd64_emit_rex ((inst),(size),0,0,(reg)); x86_call_reg((inst),((reg)&0x7)); } while (0)
-#define amd64_call_mem_size(inst,mem,size) do { amd64_emit_rex ((inst),(size),0,0,0); x86_call_mem((inst),(mem)); } while (0)
 #define amd64_call_code_size(inst,target,size) do { x86_call_code((inst),(target)); } while (0)
-//#define amd64_ret_size(inst,size) do { amd64_emit_rex ((inst),(size),0,0,0); x86_ret(inst); } while (0)
-#define amd64_ret_imm_size(inst,imm,size) do { amd64_emit_rex ((inst),(size),0,0,0); x86_ret_imm((inst),(imm)); } while (0)
-#define amd64_cmov_reg_size(inst,cond,is_signed,dreg,reg,size) do { amd64_emit_rex ((inst),(size),(dreg),0,(reg)); x86_cmov_reg((inst),(cond),(is_signed),((dreg)&0x7),((reg)&0x7)); } while (0)
-#define amd64_cmov_mem_size(inst,cond,is_signed,reg,mem,size) do { amd64_emit_rex ((inst),(size),0,0,(reg)); x86_cmov_mem((inst),(cond),(is_signed),((reg)&0x7),(mem)); } while (0)
-#define amd64_cmov_membase_size(inst,cond,is_signed,reg,basereg,disp,size) do { amd64_emit_rex ((inst),(size),0,0,(basereg)); x86_cmov_membase((inst),(cond),(is_signed),((reg)&0x7),((basereg)&0x7),(disp)); } while (0)
-#define amd64_enter_size(inst,framesize) do { amd64_emit_rex ((inst),(size),0,0,0); x86_enter((inst),(framesize)); } while (0)
-//#define amd64_leave_size(inst,size) do { amd64_emit_rex ((inst),(size),0,0,0); x86_leave(inst); } while (0)
-#define amd64_sahf_size(inst,size) do { amd64_emit_rex ((inst),(size),0,0,0); x86_sahf(inst); } while (0)
-#define amd64_fsin_size(inst,size) do { x86_fsin(inst); } while (0)
-#define amd64_fcos_size(inst,size) do { x86_fcos(inst); } while (0)
-#define amd64_fabs_size(inst,size) do { x86_fabs(inst); } while (0)
-#define amd64_ftst_size(inst,size) do { x86_ftst(inst); } while (0)
-#define amd64_fxam_size(inst,size) do { x86_fxam(inst); } while (0)
-#define amd64_fpatan_size(inst,size) do { x86_fpatan(inst); } while (0)
-#define amd64_fprem_size(inst,size) do { x86_fprem(inst); } while (0)
-#define amd64_fprem1_size(inst,size) do { x86_fprem1(inst); } while (0)
-#define amd64_frndint_size(inst,size) do { x86_frndint(inst); } while (0)
-#define amd64_fsqrt_size(inst,size) do { x86_fsqrt(inst); } while (0)
-#define amd64_fptan_size(inst,size) do { x86_fptan(inst); } while (0)
-//#define amd64_padding_size(inst,size) do { x86_padding((inst),(size)); } while (0)
-#define amd64_prolog_size(inst,frame_size,reg_mask,size) do { amd64_emit_rex ((inst),(size),0,0,0); x86_prolog((inst),(frame_size),(reg_mask)); } while (0)
-#define amd64_epilog_size(inst,reg_mask,size) do { amd64_emit_rex ((inst),(size),0,0,0); x86_epilog((inst),(reg_mask)); } while (0)
-#define amd64_xadd_reg_reg_size(inst,dreg,reg,size) do { amd64_emit_rex ((inst),(size),(dreg),0,(reg)); x86_xadd_reg_reg ((inst), (dreg), (reg), (size)); } while (0)
-#define amd64_xadd_mem_reg_size(inst,mem,reg,size) do { amd64_emit_rex ((inst),(size),0,0,(reg)); x86_xadd_mem_reg((inst),(mem),((reg)&0x7), (size)); } while (0)
-#define amd64_xadd_membase_reg_size(inst,basereg,disp,reg,size) do { amd64_emit_rex ((inst),(size),(reg),0,(basereg)); x86_xadd_membase_reg((inst),((basereg)&0x7),(disp),((reg)&0x7),(size)); } while (0)
+
+#elif defined(__native_client_codegen__)
+/* Size is ignored for Native Client calls, we restrict jumping to 32-bits */
+#define amd64_call_imm_size(inst,disp,size)             \
+  do {                                                  \
+    amd64_codegen_pre((inst));                          \
+    amd64_call_sequence_pre((inst));                    \
+    x86_call_imm((inst),(disp));                        \
+    amd64_call_sequence_post((inst));                   \
+    amd64_codegen_post((inst));                         \
+  } while (0)
+
+/* x86_call_code is called twice below, first so we can get the size of the */
+/* call sequence, and again so the exact offset from "inst" is used, since  */
+/* the sequence could have moved from amd64_call_sequence_post.             */
+/* Size is ignored for Native Client jumps, we restrict jumping to 32-bits  */
+#define amd64_call_code_size(inst,target,size)          \
+  do {                                                  \
+    amd64_codegen_pre((inst));                          \
+    guint8* adjusted_start;                             \
+    guint8* call_start;                                 \
+    amd64_call_sequence_pre((inst));                    \
+    x86_call_code((inst),(target));                     \
+    adjusted_start = amd64_call_sequence_post((inst));  \
+    call_start = adjusted_start;                        \
+    x86_call_code(adjusted_start, (target));            \
+    amd64_codegen_post((inst));                         \
+    mono_amd64_patch(call_start, (target));             \
+  } while (0)
+
+#endif /*__native_client_codegen__*/
+
+//#define amd64_ret_size(inst,size) do { amd64_codegen_pre(inst); amd64_emit_rex ((inst),(size),0,0,0); x86_ret(inst); amd64_codegen_post(inst); } while (0)
+#define amd64_ret_imm_size(inst,imm,size) do { amd64_codegen_pre(inst); amd64_emit_rex ((inst),(size),0,0,0); x86_ret_imm((inst),(imm)); amd64_codegen_post(inst); } while (0)
+#define amd64_cmov_reg_size(inst,cond,is_signed,dreg,reg,size) do { amd64_codegen_pre(inst); amd64_emit_rex ((inst),(size),(dreg),0,(reg)); x86_cmov_reg((inst),(cond),(is_signed),((dreg)&0x7),((reg)&0x7)); amd64_codegen_post(inst); } while (0)
+#define amd64_cmov_mem_size(inst,cond,is_signed,reg,mem,size) do { amd64_codegen_pre(inst); amd64_emit_rex ((inst),(size),0,0,(reg)); x86_cmov_mem((inst),(cond),(is_signed),((reg)&0x7),(mem)); amd64_codegen_post(inst); } while (0)
+#define amd64_cmov_membase_size(inst,cond,is_signed,reg,basereg,disp,size) do { amd64_codegen_pre(inst); amd64_emit_rex ((inst),(size),0,0,(basereg)); x86_cmov_membase((inst),(cond),(is_signed),((reg)&0x7),((basereg)&0x7),(disp)); amd64_codegen_post(inst); } while (0)
+#define amd64_enter_size(inst,framesize) do { amd64_codegen_pre(inst); amd64_emit_rex ((inst),(size),0,0,0); x86_enter((inst),(framesize)); amd64_codegen_post(inst); } while (0)
+//#define amd64_leave_size(inst,size) do { amd64_codegen_pre(inst); amd64_emit_rex ((inst),(size),0,0,0); x86_leave(inst); amd64_codegen_post(inst); } while (0)
+#define amd64_sahf_size(inst,size) do { amd64_codegen_pre(inst); amd64_emit_rex ((inst),(size),0,0,0); x86_sahf(inst); amd64_codegen_post(inst); } while (0)
+#define amd64_fsin_size(inst,size) do { amd64_codegen_pre(inst); x86_fsin(inst); amd64_codegen_post(inst); } while (0)
+#define amd64_fcos_size(inst,size) do { amd64_codegen_pre(inst); x86_fcos(inst); amd64_codegen_post(inst); } while (0)
+#define amd64_fabs_size(inst,size) do { amd64_codegen_pre(inst); x86_fabs(inst); amd64_codegen_post(inst); } while (0)
+#define amd64_ftst_size(inst,size) do { amd64_codegen_pre(inst); x86_ftst(inst); amd64_codegen_post(inst); } while (0)
+#define amd64_fxam_size(inst,size) do { amd64_codegen_pre(inst); x86_fxam(inst); amd64_codegen_post(inst); } while (0)
+#define amd64_fpatan_size(inst,size) do { amd64_codegen_pre(inst); x86_fpatan(inst); amd64_codegen_post(inst); } while (0)
+#define amd64_fprem_size(inst,size) do { amd64_codegen_pre(inst); x86_fprem(inst); amd64_codegen_post(inst); } while (0)
+#define amd64_fprem1_size(inst,size) do { amd64_codegen_pre(inst); x86_fprem1(inst); amd64_codegen_post(inst); } while (0)
+#define amd64_frndint_size(inst,size) do { amd64_codegen_pre(inst); x86_frndint(inst); amd64_codegen_post(inst); } while (0)
+#define amd64_fsqrt_size(inst,size) do { amd64_codegen_pre(inst); x86_fsqrt(inst); amd64_codegen_post(inst); } while (0)
+#define amd64_fptan_size(inst,size) do { amd64_codegen_pre(inst); x86_fptan(inst); amd64_codegen_post(inst); } while (0)
+//#define amd64_padding_size(inst,size) do { amd64_codegen_pre(inst); x86_padding((inst),(size)); amd64_codegen_post(inst); } while (0)
+#define amd64_prolog_size(inst,frame_size,reg_mask,size) do { amd64_codegen_pre(inst); amd64_emit_rex ((inst),(size),0,0,0); x86_prolog((inst),(frame_size),(reg_mask)); amd64_codegen_post(inst); } while (0)
+#define amd64_epilog_size(inst,reg_mask,size) do { amd64_codegen_pre(inst); amd64_emit_rex ((inst),(size),0,0,0); x86_epilog((inst),(reg_mask)); amd64_codegen_post(inst); } while (0)
+#define amd64_xadd_reg_reg_size(inst,dreg,reg,size) do { amd64_codegen_pre(inst); amd64_emit_rex ((inst),(size),(dreg),0,(reg)); x86_xadd_reg_reg ((inst), (dreg), (reg), (size)); amd64_codegen_post(inst); } while (0)
+#define amd64_xadd_mem_reg_size(inst,mem,reg,size) do { amd64_codegen_pre(inst); amd64_emit_rex ((inst),(size),0,0,(reg)); x86_xadd_mem_reg((inst),(mem),((reg)&0x7), (size)); amd64_codegen_post(inst); } while (0)
+#define amd64_xadd_membase_reg_size(inst,basereg,disp,reg,size) do { amd64_codegen_pre(inst); amd64_emit_rex ((inst),(size),(reg),0,(basereg)); x86_xadd_membase_reg((inst),((basereg)&0x7),(disp),((reg)&0x7),(size)); amd64_codegen_post(inst); } while (0)
 
 
 
@@ -1182,7 +1730,7 @@ typedef union {
 #define amd64_alu_reg8_reg8(inst,opc,dreg,reg,is_dreg_h,is_reg_h) amd64_alu_reg8_reg8_size(inst,opc,dreg,reg,is_dreg_h,is_reg_h,8)
 #define amd64_alu_reg_mem(inst,opc,reg,mem) amd64_alu_reg_mem_size(inst,opc,reg,mem,8)
 #define amd64_alu_reg_membase(inst,opc,reg,basereg,disp) amd64_alu_reg_membase_size(inst,opc,reg,basereg,disp,8)
-#define amd64_test_reg_imm(inst,reg,imm) amd64_test_reg_imm_size(inst,reg,imm,8)
+//#define amd64_test_reg_imm(inst,reg,imm) amd64_test_reg_imm_size(inst,reg,imm,8)
 #define amd64_test_mem_imm(inst,mem,imm) amd64_test_mem_imm_size(inst,mem,imm,8)
 #define amd64_test_membase_imm(inst,basereg,disp,imm) amd64_test_membase_imm_size(inst,basereg,disp,imm,8)
 #define amd64_test_reg_reg(inst,dreg,reg) amd64_test_reg_reg_size(inst,dreg,reg,8)