Merged PR72 fix.
[cacao.git] / src / vm / jit / x86_64 / codegen.h
index a1c1a2f8496ea10ebb358f77dae697d85a387e8c..8262812b0420187411b3e08da0558cae58094cb0 100644 (file)
@@ -1,6 +1,6 @@
 /* src/vm/jit/x86_64/codegen.h - code generation macros for x86_64
 
-   Copyright (C) 1996-2005, 2006 R. Grafl, A. Krall, C. Kruegel,
+   Copyright (C) 1996-2005, 2006, 2007 R. Grafl, A. Krall, C. Kruegel,
    C. Oates, R. Obermaisser, M. Platter, M. Probst, S. Ring,
    E. Steiner, C. Thalinger, D. Thuernbeck, P. Tomsich, C. Ullrich,
    J. Wenninger, Institut f. Computersprachen - TU Wien
    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
    02110-1301, USA.
 
-   Contact: cacao@cacaojvm.org
-
-   Authors: Andreas Krall
-            Christian Thalinger
-
-   Changes:
-
-   $Id: codegen.h 4615 2006-03-15 16:36:43Z twisti $
-
 */
 
 
 
 #include "vm/types.h"
 
-#include "vm/jit/jit.h"
-
-
-/* some defines ***************************************************************/
-
-#define PATCHER_CALL_SIZE    5          /* size in bytes of a patcher call    */
-
-
-/* macros to create code ******************************************************/
-
-/* immediate data union */
-
-typedef union {
-    s4 i;
-    s8 l;
-    float f;
-    double d;
-    void *a;
-    u1 b[8];
-} x86_64_imm_buf;
-
-
-/* opcodes for alu instructions */
-
-typedef enum {
-    X86_64_ADD = 0,
-    X86_64_OR  = 1,
-    X86_64_ADC = 2,
-    X86_64_SBB = 3,
-    X86_64_AND = 4,
-    X86_64_SUB = 5,
-    X86_64_XOR = 6,
-    X86_64_CMP = 7,
-    X86_64_NALU
-} X86_64_ALU_Opcode;
-
-
-typedef enum {
-    X86_64_ROL = 0,
-    X86_64_ROR = 1,
-    X86_64_RCL = 2,
-    X86_64_RCR = 3,
-    X86_64_SHL = 4,
-    X86_64_SHR = 5,
-    X86_64_SAR = 7,
-    X86_64_NSHIFT = 8
-} X86_64_Shift_Opcode;
-
-
-typedef enum {
-    X86_64_CC_O = 0,
-    X86_64_CC_NO = 1,
-    X86_64_CC_B = 2, X86_64_CC_C = 2, X86_64_CC_NAE = 2,
-    X86_64_CC_BE = 6, X86_64_CC_NA = 6,
-    X86_64_CC_AE = 3, X86_64_CC_NB = 3, X86_64_CC_NC = 3,
-    X86_64_CC_E = 4, X86_64_CC_Z = 4,
-    X86_64_CC_NE = 5, X86_64_CC_NZ = 5,
-    X86_64_CC_A = 7, X86_64_CC_NBE = 7,
-    X86_64_CC_S = 8, X86_64_CC_LZ = 8,
-    X86_64_CC_NS = 9, X86_64_CC_GEZ = 9,
-    X86_64_CC_P = 0x0a, X86_64_CC_PE = 0x0a,
-    X86_64_CC_NP = 0x0b, X86_64_CC_PO = 0x0b,
-    X86_64_CC_L = 0x0c, X86_64_CC_NGE = 0x0c,
-    X86_64_CC_GE = 0x0d, X86_64_CC_NL = 0x0d,
-    X86_64_CC_LE = 0x0e, X86_64_CC_NG = 0x0e,
-    X86_64_CC_G = 0x0f, X86_64_CC_NLE = 0x0f,
-    X86_64_NCC
-} X86_64_CC;
-
-
-#define IS_IMM8(imm) \
-    (((long) (imm) >= -128) && ((long) (imm) <= 127))
-
-
-#define IS_IMM32(imm) \
-    (((long) (imm) >= (-2147483647-1)) && ((long) (imm) <= 2147483647))
-
-
-/* modrm and stuff */
-
-#define x86_64_address_byte(mod,reg,rm) \
-    *(cd->mcodeptr++) = ((((mod) & 0x03) << 6) | (((reg) & 0x07) << 3) | ((rm) & 0x07));
-
+#include "vm/jit/x86_64/emit.h"
 
-#define x86_64_emit_reg(reg,rm) \
-    x86_64_address_byte(3,(reg),(rm));
-
-
-#define x86_64_emit_rex(size,reg,index,rm) \
-    if (((size) == 1) || ((reg) > 7) || ((index) > 7) || ((rm) > 7)) { \
-        *(cd->mcodeptr++) = (0x40 | (((size) & 0x01) << 3) | ((((reg) >> 3) & 0x01) << 2) | ((((index) >> 3) & 0x01) << 1) | (((rm) >> 3) & 0x01)); \
-    }
+#include "vm/jit/jit.h"
 
 
-#define x86_64_emit_byte_rex(reg,index,rm) \
-    *(cd->mcodeptr++) = (0x40 | ((((reg) >> 3) & 0x01) << 2) | ((((index) >> 3) & 0x01) << 1) | (((rm) >> 3) & 0x01));
+/* additional functions and macros to generate code ***************************/
 
+/* MCODECHECK(icnt) */
 
-#define x86_64_emit_mem(r,disp) \
+#define MCODECHECK(icnt) \
     do { \
-        x86_64_address_byte(0,(r),5); \
-        x86_64_emit_imm32((disp)); \
+        if ((cd->mcodeptr + (icnt)) > cd->mcodeend) \
+            codegen_increase(cd); \
     } while (0)
 
 
-#define x86_64_emit_membase(basereg,disp,dreg) \
+#define ALIGNCODENOP \
     do { \
-        if ((basereg) == REG_SP || (basereg) == R12) { \
-            if ((disp) == 0) { \
-                x86_64_address_byte(0,(dreg),REG_SP); \
-                x86_64_address_byte(0,REG_SP,REG_SP); \
-            } else if (IS_IMM8((disp))) { \
-                x86_64_address_byte(1,(dreg),REG_SP); \
-                x86_64_address_byte(0,REG_SP,REG_SP); \
-                x86_64_emit_imm8((disp)); \
-            } else { \
-                x86_64_address_byte(2,(dreg),REG_SP); \
-                x86_64_address_byte(0,REG_SP,REG_SP); \
-                x86_64_emit_imm32((disp)); \
-            } \
-            break; \
-        } \
-        if ((disp) == 0 && (basereg) != RBP && (basereg) != R13) { \
-            x86_64_address_byte(0,(dreg),(basereg)); \
-            break; \
-        } \
-        \
-        if ((basereg) == RIP) { \
-            x86_64_address_byte(0,(dreg),RBP); \
-            x86_64_emit_imm32((disp)); \
-            break; \
-        } \
-        \
-        if (IS_IMM8((disp))) { \
-            x86_64_address_byte(1,(dreg),(basereg)); \
-            x86_64_emit_imm8((disp)); \
-        } else { \
-            x86_64_address_byte(2,(dreg),(basereg)); \
-            x86_64_emit_imm32((disp)); \
-        } \
+        for (s1 = 0; s1 < (s4) (((ptrint) cd->mcodeptr) & 7); s1++) \
+            M_NOP; \
     } while (0)
 
 
-#define x86_64_emit_membase32(basereg,disp,dreg) \
+/* M_INTMOVE:
+    generates an integer-move from register a to b.
+    if a and b are the same int-register, no code will be generated.
+*/ 
+
+#define M_INTMOVE(reg,dreg) \
     do { \
-        if ((basereg) == REG_SP || (basereg) == R12) { \
-            x86_64_address_byte(2,(dreg),REG_SP); \
-            x86_64_address_byte(0,REG_SP,REG_SP); \
-            x86_64_emit_imm32((disp)); \
-        } else {\
-            x86_64_address_byte(2,(dreg),(basereg)); \
-            x86_64_emit_imm32((disp)); \
+        if ((reg) != (dreg)) { \
+            M_MOV(reg, dreg); \
         } \
     } while (0)
 
 
-#define x86_64_emit_memindex(reg,disp,basereg,indexreg,scale) \
-    do { \
-        if ((basereg) == -1) { \
-            x86_64_address_byte(0,(reg),4); \
-            x86_64_address_byte((scale),(indexreg),5); \
-            x86_64_emit_imm32((disp)); \
-        \
-        } else if ((disp) == 0 && (basereg) != RBP && (basereg) != R13) { \
-            x86_64_address_byte(0,(reg),4); \
-            x86_64_address_byte((scale),(indexreg),(basereg)); \
-        \
-        } else if (IS_IMM8((disp))) { \
-            x86_64_address_byte(1,(reg),4); \
-            x86_64_address_byte((scale),(indexreg),(basereg)); \
-            x86_64_emit_imm8 ((disp)); \
-        \
-        } else { \
-            x86_64_address_byte(2,(reg),4); \
-            x86_64_address_byte((scale),(indexreg),(basereg)); \
-            x86_64_emit_imm32((disp)); \
-        }    \
-     } while (0)
-
-
-#define x86_64_emit_imm8(imm) \
-    *(cd->mcodeptr++) = (u1) ((imm) & 0xff);
-
-
-#define x86_64_emit_imm16(imm) \
+/* M_FLTMOVE:
+    generates a floating-point-move from register a to b.
+    if a and b are the same float-register, no code will be generated
+*/ 
+
+#define M_FLTMOVE(reg,dreg) \
     do { \
-        x86_64_imm_buf imb; \
-        imb.i = (s4) (imm); \
-        *(cd->mcodeptr++) = imb.b[0]; \
-        *(cd->mcodeptr++) = imb.b[1]; \
+        if ((reg) != (dreg)) { \
+            M_FMOV(reg, dreg); \
+        } \
     } while (0)
 
 
-#define x86_64_emit_imm32(imm) \
+#define ICONST(r,c) \
     do { \
-        x86_64_imm_buf imb; \
-        imb.i = (s4) (imm); \
-        *(cd->mcodeptr++) = imb.b[0]; \
-        *(cd->mcodeptr++) = imb.b[1]; \
-        *(cd->mcodeptr++) = imb.b[2]; \
-        *(cd->mcodeptr++) = imb.b[3]; \
+        if ((c) == 0) \
+            M_CLR((d)); \
+        else \
+            M_IMOV_IMM((c), (d)); \
     } while (0)
+/*     do { \ */
+/*        M_IMOV_IMM((c), (d)); \ */
+/*     } while (0) */
 
 
-#define x86_64_emit_imm64(imm) \
+#define LCONST(r,c) \
     do { \
-        x86_64_imm_buf imb; \
-        imb.l = (s8) (imm); \
-        *(cd->mcodeptr++) = imb.b[0]; \
-        *(cd->mcodeptr++) = imb.b[1]; \
-        *(cd->mcodeptr++) = imb.b[2]; \
-        *(cd->mcodeptr++) = imb.b[3]; \
-        *(cd->mcodeptr++) = imb.b[4]; \
-        *(cd->mcodeptr++) = imb.b[5]; \
-        *(cd->mcodeptr++) = imb.b[6]; \
-        *(cd->mcodeptr++) = imb.b[7]; \
+        if ((c) == 0) \
+            M_CLR((d)); \
+        else \
+            M_MOV_IMM((c), (d)); \
     } while (0)
 
 
-/* additional functions and macros to generate code ***************************/
-
-#define CALCOFFSETBYTES(var, reg, val) \
-    if ((s4) (val) < -128 || (s4) (val) > 127) (var) += 4; \
-    else if ((s4) (val) != 0) (var) += 1; \
-    else if ((reg) == RBP || (reg) == RSP || (reg) == R12 || (reg) == R13) (var) += 1;
-
-
-#define CALCIMMEDIATEBYTES(var, val) \
-    if ((s4) (val) < -128 || (s4) (val) > 127) (var) += 4; \
-    else (var) += 1;
+/* branch defines *************************************************************/
 
+#define BRANCH_UNCONDITIONAL_SIZE    5  /* size in bytes of a branch          */
+#define BRANCH_CONDITIONAL_SIZE      6  /* size in bytes of a branch          */
 
-/* gen_nullptr_check(objreg) */
+#define BRANCH_NOPS \
+    do { \
+        M_NOP; \
+        M_NOP; \
+        M_NOP; \
+        M_NOP; \
+        M_NOP; \
+        M_NOP; \
+    } while (0)
 
-#define gen_nullptr_check(objreg) \
-       if (checknull) { \
-        M_TEST(objreg); \
-        M_BEQ(0); \
-           codegen_add_nullpointerexception_ref(cd, cd->mcodeptr); \
-       }
 
+/* patcher defines ************************************************************/
 
-#define gen_bound_check \
-    if (checkbounds) { \
-        M_CMP_MEMBASE(s1, OFFSET(java_arrayheader, size), s2); \
-        M_BAE(0); \
-        codegen_add_arrayindexoutofboundsexception_ref(cd, cd->mcodeptr, s2); \
-    }
+#define PATCHER_CALL_SIZE    2          /* size in bytes of a patcher call    */
 
+#define PATCHER_NOPS \
+    do { \
+        M_NOP; \
+        M_NOP; \
+    } while (0)
 
-#define gen_div_check(v) \
-    if (checknull) { \
-        if ((v)->flags & INMEMORY) { \
-            M_CMP_IMM_MEMBASE(0, REG_SP, src->regoff * 8); \
-        } else { \
-            M_TEST(src->regoff); \
-        } \
-        M_BEQ(0); \
-        codegen_add_arithmeticexception_ref(cd, cd->mcodeptr); \
-    }
 
+/* stub defines ***************************************************************/
 
-/* MCODECHECK(icnt) */
+#define COMPILERSTUB_CODESIZE    8
 
-#define MCODECHECK(icnt) \
-       if ((cd->mcodeptr + (icnt)) > (u1 *) cd->mcodeend) \
-        cd->mcodeptr = (u1 *) codegen_increase(cd, cd->mcodeptr)
 
-/* M_INTMOVE:
-    generates an integer-move from register a to b.
-    if a and b are the same int-register, no code will be generated.
-*/ 
+/* macros to create code ******************************************************/
 
-#define M_INTMOVE(reg,dreg) \
+#define M_BYTE1(a) \
     do { \
-        if ((reg) != (dreg)) { \
-            M_MOV(reg, dreg); \
-        } \
+        *(cd->mcodeptr) = (a); \
+        cd->mcodeptr++; \
     } while (0)
 
 
-/* M_FLTMOVE:
-    generates a floating-point-move from register a to b.
-    if a and b are the same float-register, no code will be generated
-*/ 
-
-#define M_FLTMOVE(reg,dreg) \
+#define M_BYTE2(a, b) \
     do { \
-        if ((reg) != (dreg)) { \
-            M_FMOV(reg, dreg); \
-        } \
+        M_BYTE1(a); \
+        M_BYTE1(b); \
     } while (0)
 
 
-/* var_to_reg_xxx:
-    this function generates code to fetch data from a pseudo-register
-    into a real register. 
-    If the pseudo-register has actually been assigned to a real 
-    register, no code will be emitted, since following operations
-    can use this register directly.
-    
-    v: pseudoregister to be fetched from
-    tempregnum: temporary register to be used if v is actually spilled to ram
+#define M_MOV(a,b)              emit_mov_reg_reg(cd, (a), (b))
+#define M_MOV_IMM(a,b)          emit_mov_imm_reg(cd, (u8) (a), (b))
 
-    return: the register number, where the operand can be found after 
-            fetching (this wil be either tempregnum or the register
-            number allready given to v)
-*/
+#define M_IMOV(a,b)             emit_movl_reg_reg(cd, (a), (b))
+#define M_IMOV_IMM(a,b)         emit_movl_imm_reg(cd, (u4) (a), (b))
 
-#define var_to_reg_int(regnr,v,tempnr) \
-    if ((v)->flags & INMEMORY) { \
-        COUNT_SPILLS; \
-        if ((v)->type == TYPE_INT) { \
-            x86_64_movl_membase_reg(cd, REG_SP, (v)->regoff * 8, tempnr); \
-        } else { \
-            x86_64_mov_membase_reg(cd, REG_SP, (v)->regoff * 8, tempnr); \
-        } \
-        regnr = tempnr; \
-    } else { \
-        regnr = (v)->regoff; \
-    }
+#define M_FMOV(a,b)             emit_movq_reg_reg(cd, (a), (b))
 
+#define M_ILD(a,b,disp)         emit_movl_membase_reg(cd, (b), (disp), (a))
+#define M_LLD(a,b,disp)         emit_mov_membase_reg(cd, (b), (disp), (a))
 
+#define M_ILD32(a,b,disp)       emit_movl_membase32_reg(cd, (b), (disp), (a))
+#define M_LLD32(a,b,disp)       emit_mov_membase32_reg(cd, (b), (disp), (a))
 
-#define var_to_reg_flt(regnr,v,tempnr) \
-    if ((v)->flags & INMEMORY) { \
-        COUNT_SPILLS; \
-        if ((v)->type == TYPE_FLT) { \
-            x86_64_movlps_membase_reg(cd, REG_SP, (v)->regoff * 8, tempnr); \
-        } else { \
-            x86_64_movlpd_membase_reg(cd, REG_SP, (v)->regoff * 8, tempnr); \
-        } \
-/*        x86_64_movq_membase_reg(REG_SP, (v)->regoff * 8, tempnr);*/ \
-        regnr = tempnr; \
-    } else { \
-        regnr = (v)->regoff; \
-    }
-
-
-/* store_reg_to_var_xxx:
-    This function generates the code to store the result of an operation
-    back into a spilled pseudo-variable.
-    If the pseudo-variable has not been spilled in the first place, this 
-    function will generate nothing.
-    
-    v ............ Pseudovariable
-    tempregnum ... Number of the temporary registers as returned by
-                   reg_of_var.
-*/     
-
-#define store_reg_to_var_int(sptr, tempregnum) \
-    if ((sptr)->flags & INMEMORY) { \
-        COUNT_SPILLS; \
-        x86_64_mov_reg_membase(cd, tempregnum, REG_SP, (sptr)->regoff * 8); \
-    }
-
-
-#define store_reg_to_var_flt(sptr, tempregnum) \
-    if ((sptr)->flags & INMEMORY) { \
-         COUNT_SPILLS; \
-         x86_64_movq_reg_membase(cd, tempregnum, REG_SP, (sptr)->regoff * 8); \
-    }
-
-
-#define M_COPY(from,to) \
-    d = reg_of_var(rd, to, REG_ITMP1); \
-       if ((from->regoff != to->regoff) || \
-           ((from->flags ^ to->flags) & INMEMORY)) { \
-               if (IS_FLT_DBL_TYPE(from->type)) { \
-                       var_to_reg_flt(s1, from, d); \
-                       M_FLTMOVE(s1, d); \
-                       store_reg_to_var_flt(to, d); \
-               } else { \
-                       var_to_reg_int(s1, from, d); \
-                       M_INTMOVE(s1, d); \
-                       store_reg_to_var_int(to, d); \
-               } \
-       }
-
-
-/* macros to create code ******************************************************/
+#define M_IST(a,b,disp)         emit_movl_reg_membase(cd, (a), (b), (disp))
+#define M_LST(a,b,disp)         emit_mov_reg_membase(cd, (a), (b), (disp))
 
-#define M_MOV(a,b)              x86_64_mov_reg_reg(cd, (a), (b))
-#define M_MOV_IMM(a,b)          x86_64_mov_imm_reg(cd, (u8) (a), (b))
+#define M_IST_IMM(a,b,disp)     emit_movl_imm_membase(cd, (a), (b), (disp))
+#define M_LST_IMM32(a,b,disp)   emit_mov_imm_membase(cd, (a), (b), (disp))
 
-#define M_FMOV(a,b)             x86_64_movq_reg_reg(cd, (a), (b))
+#define M_IST32(a,b,disp)       emit_movl_reg_membase32(cd, (a), (b), (disp))
+#define M_LST32(a,b,disp)       emit_mov_reg_membase32(cd, (a), (b), (disp))
 
-#define M_IMOV_IMM(a,b)         x86_64_movl_imm_reg(cd, (u4) (a), (b))
+#define M_IST32_IMM(a,b,disp)   emit_movl_imm_membase32(cd, (a), (b), (disp))
+#define M_LST32_IMM32(a,b,disp) emit_mov_imm_membase32(cd, (a), (b), (disp))
 
-#define M_ILD(a,b,disp)         x86_64_movl_membase_reg(cd, (b), (disp), (a))
-#define M_LLD(a,b,disp)         x86_64_mov_membase_reg(cd, (b), (disp), (a))
-#define M_DLD(a,b,disp)         x86_64_movq_membase_reg(cd, (b), (disp), (a))
+#define M_IADD(a,b)             emit_alul_reg_reg(cd, ALU_ADD, (a), (b))
+#define M_ISUB(a,b)             emit_alul_reg_reg(cd, ALU_SUB, (a), (b))
+#define M_IMUL(a,b)             emit_imull_reg_reg(cd, (a), (b))
 
-#define M_ILD32(a,b,disp)       x86_64_movl_membase32_reg(cd, (b), (disp), (a))
-#define M_LLD32(a,b,disp)       x86_64_mov_membase32_reg(cd, (b), (disp), (a))
+#define M_IADD_IMM(a,b)         emit_alul_imm_reg(cd, ALU_ADD, (a), (b))
+#define M_ISUB_IMM(a,b)         emit_alul_imm_reg(cd, ALU_SUB, (a), (b))
+#define M_IMUL_IMM(a,b,c)       emit_imull_imm_reg_reg(cd, (b), (a), (c))
 
-#define M_IST(a,b,disp)         x86_64_movl_reg_membase(cd, (a), (b), (disp))
-#define M_LST(a,b,disp)         x86_64_mov_reg_membase(cd, (a), (b), (disp))
-#define M_DST(a,b,disp)         x86_64_movq_reg_membase(cd, (a), (b), (disp))
+#define M_LADD(a,b)             emit_alu_reg_reg(cd, ALU_ADD, (a), (b))
+#define M_LSUB(a,b)             emit_alu_reg_reg(cd, ALU_SUB, (a), (b))
+#define M_LMUL(a,b)             emit_imul_reg_reg(cd, (a), (b))
 
-#define M_IST_IMM(a,b,disp)     x86_64_movl_imm_membase(cd, (a), (b), (disp))
-#define M_LST_IMM32(a,b,disp)   x86_64_mov_imm_membase(cd, (a), (b), (disp))
+#define M_LADD_IMM(a,b)         emit_alu_imm_reg(cd, ALU_ADD, (a), (b))
+#define M_LSUB_IMM(a,b)         emit_alu_imm_reg(cd, ALU_SUB, (a), (b))
+#define M_LMUL_IMM(a,b,c)       emit_imul_imm_reg_reg(cd, (b), (a), (c))
 
-#define M_IST32(a,b,disp)       x86_64_movl_reg_membase32(cd, (a), (b), (disp))
-#define M_LST32(a,b,disp)       x86_64_mov_reg_membase32(cd, (a), (b), (disp))
+#define M_IINC(a)               emit_incl_reg(cd, (a))
+#define M_LINC(a)               emit_incq_reg(cd, (a))
+#define M_IDEC(a)               emit_decl_reg(cd, (a))
 
-#define M_IST32_IMM(a,b,disp)   x86_64_movl_imm_membase32(cd, (a), (b), (disp))
-#define M_LST32_IMM32(a,b,disp) x86_64_mov_imm_membase32(cd, (a), (b), (disp))
+#define M_ALD(a,b,disp) \
+    do { \
+        if (b == RIP) \
+            M_LLD(a, b, disp + -((cd->mcodeptr + 7) - cd->mcodebase)); \
+        else \
+            M_LLD(a, b, disp); \
+    } while (0)
 
-#define M_LADD(a,b)             x86_64_alu_reg_reg(cd, X86_64_ADD, (a), (b))
-#define M_LADD_IMM(a,b)         x86_64_alu_imm_reg(cd, X86_64_ADD, (a), (b))
-#define M_LSUB(a,b)             x86_64_alu_reg_reg(cd, X86_64_SUB, (a), (b))
-#define M_LSUB_IMM(a,b)         x86_64_alu_imm_reg(cd, X86_64_SUB, (a), (b))
+#define M_ALD32(a,b,disp)       M_LLD32(a,b,disp)
 
-#define M_IINC_MEMBASE(a,b)     x86_64_incl_membase(cd, (a), (b))
+#define M_ALD_MEM(a,disp)       emit_mov_mem_reg(cd, (disp), (a))
 
-#define M_IADD_MEMBASE(a,b,c)   x86_64_alul_reg_membase(cd, X86_64_ADD, (a), (b), (c))
-#define M_IADC_MEMBASE(a,b,c)   x86_64_alul_reg_membase(cd, X86_64_ADC, (a), (b), (c))
-#define M_ISUB_MEMBASE(a,b,c)   x86_64_alul_reg_membase(cd, X86_64_SUB, (a), (b), (c))
-#define M_ISBB_MEMBASE(a,b,c)   x86_64_alul_reg_membase(cd, X86_64_SBB, (a), (b), (c))
+#define M_ALD_MEM_GET_OPC(p)     (  *(        (p) + 1))
+#define M_ALD_MEM_GET_MOD(p)     (((*(        (p) + 2)) >> 6) & 0x03)
+#define M_ALD_MEM_GET_REG(p)    ((((*(        (p) + 2)) >> 3) & 0x07) + (((*(p) >> 2) & 0x01) << 3))
+#define M_ALD_MEM_GET_RM(p)      (((*(        (p) + 2))     ) & 0x07)
+#define M_ALD_MEM_GET_DISP(p)    (  *((u4 *) ((p) + 4)))
 
-#define M_ALD(a,b,c)            M_LLD(a,b,c)
 #define M_AST(a,b,c)            M_LST(a,b,c)
 #define M_AST_IMM32(a,b,c)      M_LST_IMM32(a,b,c)
+
 #define M_AADD(a,b)             M_LADD(a,b)
 #define M_AADD_IMM(a,b)         M_LADD_IMM(a,b)
 #define M_ASUB_IMM(a,b)         M_LSUB_IMM(a,b)
 
-#define M_LADD_IMM32(a,b)       x86_64_alu_imm32_reg(cd, X86_64_ADD, (a), (b))
+#define M_ISUB_IMM32(a,b)       emit_alul_imm32_reg(cd, ALU_SUB, (a), (b))
+
+#define M_LADD_IMM32(a,b)       emit_alu_imm32_reg(cd, ALU_ADD, (a), (b))
+#define M_LSUB_IMM32(a,b)       emit_alu_imm32_reg(cd, ALU_SUB, (a), (b))
+
 #define M_AADD_IMM32(a,b)       M_LADD_IMM32(a,b)
-#define M_LSUB_IMM32(a,b)       x86_64_alu_imm32_reg(cd, X86_64_SUB, (a), (b))
 
-#define M_ILEA(a,b,c)           x86_64_leal_membase_reg(cd, (a), (b), (c))
-#define M_LLEA(a,b,c)           x86_64_lea_membase_reg(cd, (a), (b), (c))
+#define M_ILEA(a,b,c)           emit_leal_membase_reg(cd, (a), (b), (c))
+#define M_LLEA(a,b,c)           emit_lea_membase_reg(cd, (a), (b), (c))
 #define M_ALEA(a,b,c)           M_LLEA(a,b,c)
 
-#define M_AND(a,b)              x86_64_alu_reg_reg(cd, X86_64_AND, (a), (b))
-#define M_XOR(a,b)              x86_64_alu_reg_reg(cd, X86_64_XOR, (a), (b))
+#define M_INEG(a)               emit_negl_reg(cd, (a))
+#define M_LNEG(a)               emit_neg_reg(cd, (a))
+
+#define M_IAND(a,b)             emit_alul_reg_reg(cd, ALU_AND, (a), (b))
+#define M_IOR(a,b)              emit_alul_reg_reg(cd, ALU_OR, (a), (b))
+#define M_IXOR(a,b)             emit_alul_reg_reg(cd, ALU_XOR, (a), (b))
+
+#define M_IAND_IMM(a,b)         emit_alul_imm_reg(cd, ALU_AND, (a), (b))
+#define M_IOR_IMM(a,b)          emit_alul_imm_reg(cd, ALU_OR, (a), (b))
+#define M_IXOR_IMM(a,b)         emit_alul_imm_reg(cd, ALU_XOR, (a), (b))
+
+#define M_LAND(a,b)             emit_alu_reg_reg(cd, ALU_AND, (a), (b))
+#define M_LOR(a,b)              emit_alu_reg_reg(cd, ALU_OR, (a), (b))
+#define M_LXOR(a,b)             emit_alu_reg_reg(cd, ALU_XOR, (a), (b))
+
+#define M_LAND_IMM(a,b)         emit_alu_imm_reg(cd, ALU_AND, (a), (b))
+#define M_LOR_IMM(a,b)          emit_alu_imm_reg(cd, ALU_OR, (a), (b))
+#define M_LXOR_IMM(a,b)         emit_alu_imm_reg(cd, ALU_XOR, (a), (b))
+
+#define M_BSEXT(a,b)            emit_movsbq_reg_reg(cd, (a), (b))
+#define M_SSEXT(a,b)            emit_movswq_reg_reg(cd, (a), (b))
+#define M_ISEXT(a,b)            emit_movslq_reg_reg(cd, (a), (b))
+
+#define M_BZEXT(a,b)            emit_movzbq_reg_reg(cd, (a), (b))
+#define M_CZEXT(a,b)            emit_movzwq_reg_reg(cd, (a), (b))
 
-#define M_IAND(a,b)             x86_64_alul_reg_reg(cd, X86_64_AND, (a), (b))
-#define M_IAND_IMM(a,b)         x86_64_alul_imm_reg(cd, X86_64_AND, (a), (b))
-#define M_IXOR(a,b)             x86_64_alul_reg_reg(cd, X86_64_XOR, (a), (b))
+#define M_ISLL_IMM(a,b)         emit_shiftl_imm_reg(cd, SHIFT_SHL, (a), (b))
+#define M_ISRA_IMM(a,b)         emit_shiftl_imm_reg(cd, SHIFT_SAR, (a), (b))
+#define M_ISRL_IMM(a,b)         emit_shiftl_imm_reg(cd, SHIFT_SHR, (a), (b))
 
-#define M_TEST(a)               x86_64_test_reg_reg(cd, (a), (a))
-#define M_ITEST(a)              x86_64_testl_reg_reg(cd, (a), (a))
+#define M_LSLL_IMM(a,b)         emit_shift_imm_reg(cd, SHIFT_SHL, (a), (b))
+#define M_LSRA_IMM(a,b)         emit_shift_imm_reg(cd, SHIFT_SAR, (a), (b))
+#define M_LSRL_IMM(a,b)         emit_shift_imm_reg(cd, SHIFT_SHR, (a), (b))
 
-#define M_CMP(a,b)              x86_64_alu_reg_reg(cd, X86_64_CMP, (a), (b))
-#define M_CMP_IMM(a,b)          x86_64_alu_imm_reg(cd, X86_64_CMP, (a), (b))
-#define M_CMP_IMM_MEMBASE(a,b,c) x86_64_alu_imm_membase(cd, X86_64_CMP, (a), (b), (c))
-#define M_CMP_MEMBASE(a,b,c)    x86_64_alu_membase_reg(cd, X86_64_CMP, (a), (b), (c))
+#define M_TEST(a)               emit_test_reg_reg(cd, (a), (a))
+#define M_ITEST(a)              emit_testl_reg_reg(cd, (a), (a))
 
-#define M_ICMP(a,b)             x86_64_alul_reg_reg(cd, X86_64_CMP, (a), (b))
-#define M_ICMP_IMM(a,b)         x86_64_alul_imm_reg(cd, X86_64_CMP, (a), (b))
-#define M_ICMP_IMM_MEMBASE(a,b,c) x86_64_alul_imm_membase(cd, X86_64_CMP, (a), (b), (c))
+#define M_LCMP(a,b)             emit_alu_reg_reg(cd, ALU_CMP, (a), (b))
+#define M_LCMP_IMM(a,b)         emit_alu_imm_reg(cd, ALU_CMP, (a), (b))
+#define M_LCMP_IMM_MEMBASE(a,b,c) emit_alu_imm_membase(cd, ALU_CMP, (a), (b), (c))
+#define M_LCMP_MEMBASE(a,b,c)   emit_alu_membase_reg(cd, ALU_CMP, (a), (b), (c))
 
-#define M_BEQ(disp)             x86_64_jcc(cd, X86_64_CC_E, (disp))
-#define M_BNE(disp)             x86_64_jcc(cd, X86_64_CC_NE, (disp))
-#define M_BLE(disp)             x86_64_jcc(cd, X86_64_CC_LE, (disp))
-#define M_BAE(disp)             x86_64_jcc(cd, X86_64_CC_AE, (disp))
-#define M_BA(disp)              x86_64_jcc(cd, X86_64_CC_A, (disp))
+#define M_ICMP(a,b)             emit_alul_reg_reg(cd, ALU_CMP, (a), (b))
+#define M_ICMP_IMM(a,b)         emit_alul_imm_reg(cd, ALU_CMP, (a), (b))
+#define M_ICMP_IMM32(a,b)       emit_alul_imm32_reg(cd, ALU_CMP, (a), (b))
+#define M_ICMP_IMM_MEMBASE(a,b,c) emit_alul_imm_membase(cd, ALU_CMP, (a), (b), (c))
+#define M_ICMP_MEMBASE(a,b,c)   emit_alul_membase_reg(cd, ALU_CMP, (a), (b), (c))
 
-#define M_CMOVEQ(a,b)           x86_64_cmovcc_reg_reg(cd, X86_64_CC_E, (a), (b))
-#define M_CMOVNE(a,b)           x86_64_cmovcc_reg_reg(cd, X86_64_CC_NE, (a), (b))
-#define M_CMOVLT(a,b)           x86_64_cmovcc_reg_reg(cd, X86_64_CC_L, (a), (b))
-#define M_CMOVLE(a,b)           x86_64_cmovcc_reg_reg(cd, X86_64_CC_LE, (a), (b))
-#define M_CMOVGE(a,b)           x86_64_cmovcc_reg_reg(cd, X86_64_CC_GE, (a), (b))
-#define M_CMOVGT(a,b)           x86_64_cmovcc_reg_reg(cd, X86_64_CC_G, (a), (b))
+#define M_BEQ(disp)             emit_jcc(cd, CC_E, (disp))
+#define M_BNE(disp)             emit_jcc(cd, CC_NE, (disp))
+#define M_BLT(disp)             emit_jcc(cd, CC_L, (disp))
+#define M_BLE(disp)             emit_jcc(cd, CC_LE, (disp))
+#define M_BGE(disp)             emit_jcc(cd, CC_GE, (disp))
+#define M_BGT(disp)             emit_jcc(cd, CC_G, (disp))
 
-#define M_CMOVB(a,b)            x86_64_cmovcc_reg_reg(cd, X86_64_CC_B, (a), (b))
-#define M_CMOVA(a,b)            x86_64_cmovcc_reg_reg(cd, X86_64_CC_A, (a), (b))
-#define M_CMOVP(a,b)            x86_64_cmovcc_reg_reg(cd, X86_64_CC_P, (a), (b))
+#define M_BULT(disp)            emit_jcc(cd, CC_B, (disp))
+#define M_BULE(disp)            emit_jcc(cd, CC_BE, (disp))
+#define M_BUGE(disp)            emit_jcc(cd, CC_AE, (disp))
+#define M_BUGT(disp)            emit_jcc(cd, CC_A, (disp))
 
-#define M_PUSH(a)               x86_64_push_reg(cd, (a))
-#define M_PUSH_IMM(a)           x86_64_push_imm(cd, (a))
-#define M_POP(a)                x86_64_pop_reg(cd, (a))
+#define M_SETE(a)               emit_setcc_reg(cd, CC_E, (a))
+#define M_SETNE(a)              emit_setcc_reg(cd, CC_NE, (a))
+#define M_SETULE(a)             emit_setcc_reg(cd, CC_BE, (a))
 
-#define M_JMP(a)                x86_64_jmp_reg(cd, (a))
-#define M_JMP_IMM(a)            x86_64_jmp_imm(cd, (a))
-#define M_CALL(a)               x86_64_call_reg(cd, (a))
-#define M_CALL_IMM(a)           x86_64_call_imm(cd, (a))
-#define M_RET                   x86_64_ret(cd)
+#define M_CMOVEQ(a,b)           emit_cmovcc_reg_reg(cd, CC_E, (a), (b))
+#define M_CMOVNE(a,b)           emit_cmovcc_reg_reg(cd, CC_NE, (a), (b))
+#define M_CMOVLT(a,b)           emit_cmovcc_reg_reg(cd, CC_L, (a), (b))
+#define M_CMOVLE(a,b)           emit_cmovcc_reg_reg(cd, CC_LE, (a), (b))
+#define M_CMOVGE(a,b)           emit_cmovcc_reg_reg(cd, CC_GE, (a), (b))
+#define M_CMOVGT(a,b)           emit_cmovcc_reg_reg(cd, CC_G, (a), (b))
 
-#define M_NOP                   x86_64_nop(cd)
+#define M_CMOVULT(a,b)          emit_cmovcc_reg_reg(cd, CC_B, (a), (b))
+#define M_CMOVUGT(a,b)          emit_cmovcc_reg_reg(cd, CC_A, (a), (b))
+#define M_CMOVP(a,b)            emit_cmovcc_reg_reg(cd, CC_P, (a), (b))
 
-#define M_CLR(a)                M_XOR(a,a)
+#define M_PUSH(a)               emit_push_reg(cd, (a))
+#define M_PUSH_IMM(a)           emit_push_imm(cd, (a))
+#define M_POP(a)                emit_pop_reg(cd, (a))
+
+#define M_JMP(a)                emit_jmp_reg(cd, (a))
+#define M_JMP_IMM(a)            emit_jmp_imm(cd, (a))
+#define M_JMP_IMM2(a)           emit_jmp_imm2(cd, (a))
+#define M_CALL(a)               emit_call_reg(cd, (a))
+#define M_CALL_IMM(a)           emit_call_imm(cd, (a))
+#define M_RET                   M_BYTE1(0xc3)
+
+#define M_NOP                   M_BYTE1(0x90)
+#define M_UD2                   M_BYTE2(0x0f, 0x0b)
+
+#define M_CLR(a)                M_LXOR(a,a)
+
+
+#define M_FLD(a,b,disp)         emit_movss_membase_reg(cd, (b), (disp), (a))
+#define M_DLD(a,b,disp)         emit_movsd_membase_reg(cd, (b), (disp), (a))
+
+#define M_FLD32(a,b,disp)       emit_movss_membase32_reg(cd, (b), (disp), (a))
+#define M_DLD32(a,b,disp)       emit_movsd_membase32_reg(cd, (b), (disp), (a))
+
+#define M_FST(a,b,disp)         emit_movss_reg_membase(cd, (a), (b), (disp))
+#define M_DST(a,b,disp)         emit_movsd_reg_membase(cd, (a), (b), (disp))
+
+#define M_FST32(a,b,disp)       emit_movss_reg_membase32(cd, (a), (b), (disp))
+#define M_DST32(a,b,disp)       emit_movsd_reg_membase32(cd, (a), (b), (disp))
+
+#define M_FADD(a,b)             emit_addss_reg_reg(cd, (a), (b))
+#define M_DADD(a,b)             emit_addsd_reg_reg(cd, (a), (b))
+#define M_FSUB(a,b)             emit_subss_reg_reg(cd, (a), (b))
+#define M_DSUB(a,b)             emit_subsd_reg_reg(cd, (a), (b))
+#define M_FMUL(a,b)             emit_mulss_reg_reg(cd, (a), (b))
+#define M_DMUL(a,b)             emit_mulsd_reg_reg(cd, (a), (b))
+#define M_FDIV(a,b)             emit_divss_reg_reg(cd, (a), (b))
+#define M_DDIV(a,b)             emit_divsd_reg_reg(cd, (a), (b))
+
+#define M_CVTIF(a,b)            emit_cvtsi2ss_reg_reg(cd, (a), (b))
+#define M_CVTID(a,b)            emit_cvtsi2sd_reg_reg(cd, (a), (b))
+#define M_CVTLF(a,b)            emit_cvtsi2ssq_reg_reg(cd, (a), (b))
+#define M_CVTLD(a,b)            emit_cvtsi2sdq_reg_reg(cd, (a), (b))
+#define M_CVTFI(a,b)            emit_cvttss2si_reg_reg(cd, (a), (b))
+#define M_CVTDI(a,b)            emit_cvttsd2si_reg_reg(cd, (a), (b))
+#define M_CVTFL(a,b)            emit_cvttss2siq_reg_reg(cd, (a), (b))
+#define M_CVTDL(a,b)            emit_cvttsd2siq_reg_reg(cd, (a), (b))
+
+#define M_CVTFD(a,b)            emit_cvtss2sd_reg_reg(cd, (a), (b))
+#define M_CVTDF(a,b)            emit_cvtsd2ss_reg_reg(cd, (a), (b))
 
 
 /* system instructions ********************************************************/
 
 #define M_RDTSC                 emit_rdtsc(cd)
 
+#define M_IINC_MEMBASE(a,b)     emit_incl_membase(cd, (a), (b))
+#define M_LINC_MEMBASE(a,b)     emit_incq_membase(cd, (a), (b))
+
+#define M_IADD_MEMBASE(a,b,c)   emit_alul_reg_membase(cd, ALU_ADD, (a), (b), (c))
+#define M_IADC_MEMBASE(a,b,c)   emit_alul_reg_membase(cd, ALU_ADC, (a), (b), (c))
+#define M_ISUB_MEMBASE(a,b,c)   emit_alul_reg_membase(cd, ALU_SUB, (a), (b), (c))
+#define M_ISBB_MEMBASE(a,b,c)   emit_alul_reg_membase(cd, ALU_SBB, (a), (b), (c))
+
+
+#if defined(ENABLE_PROFILING)
+
 #define PROFILE_CYCLE_START \
     do { \
-        if (opt_prof) { \
+        if (JITDATA_HAS_FLAG_INSTRUMENT(jd)) { \
             M_PUSH(RAX); \
             M_PUSH(RDX); \
             \
-            M_MOV_IMM((ptrint) m, REG_ITMP3); \
+            M_MOV_IMM(code, REG_ITMP3); \
             M_RDTSC; \
-            M_ISUB_MEMBASE(RAX, REG_ITMP3, OFFSET(methodinfo, cycles)); \
-            M_ISBB_MEMBASE(RDX, REG_ITMP3, OFFSET(methodinfo, cycles) + 4); \
+            M_ISUB_MEMBASE(RAX, REG_ITMP3, OFFSET(codeinfo, cycles)); \
+            M_ISBB_MEMBASE(RDX, REG_ITMP3, OFFSET(codeinfo, cycles) + 4); \
             \
             M_POP(RDX); \
             M_POP(RAX); \
@@ -552,33 +393,26 @@ typedef enum {
 
 #define PROFILE_CYCLE_STOP \
     do { \
-        if (opt_prof) { \
+        if (JITDATA_HAS_FLAG_INSTRUMENT(jd)) { \
             M_PUSH(RAX); \
             M_PUSH(RDX); \
             \
-            M_MOV_IMM((ptrint) m, REG_ITMP3); \
+            M_MOV_IMM(code, REG_ITMP3); \
             M_RDTSC; \
-            M_IADD_MEMBASE(RAX, REG_ITMP3, OFFSET(methodinfo, cycles)); \
-            M_IADC_MEMBASE(RDX, REG_ITMP3, OFFSET(methodinfo, cycles) + 4); \
+            M_IADD_MEMBASE(RAX, REG_ITMP3, OFFSET(codeinfo, cycles)); \
+            M_IADC_MEMBASE(RDX, REG_ITMP3, OFFSET(codeinfo, cycles) + 4); \
             \
             M_POP(RDX); \
             M_POP(RAX); \
         } \
     } while (0)
 
+#else
 
-/* function gen_resolvebranch **************************************************
-
-    backpatches a branch instruction
-
-    parameters: ip ... pointer to instruction after branch (void*)
-                so ... offset of instruction after branch  (s8)
-                to ... offset of branch target             (s8)
-
-*******************************************************************************/
+#define PROFILE_CYCLE_START
+#define PROFILE_CYCLE_STOP
 
-#define gen_resolvebranch(ip,so,to) \
-    *((s4*) ((ip) - 4)) = (s4) ((to) - (so));
+#endif
 
 #endif /* _CODEGEN_H */