* Removed all Id tags.
[cacao.git] / src / vm / jit / s390 / emit.c
index a93fab1d3b4f4b87aa5bdd00c8adbd7e65a32b60..bd66f89796faafa0f34e30fb1e2f9e9d1b6e3fe1 100644 (file)
@@ -1,6 +1,6 @@
-/* src/vm/jit/x86_64/emit.c - x86_64 code emitter functions
+/* src/vm/jit/s390/emit.c - s390 code emitter functions
 
-   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: Christian Thalinger
-
-   $Id: emit.c 7300 2007-02-07 22:06:53Z pm $
-
 */
 
-#include <assert.h>
-
 #include "config.h"
 
-#include "vm/types.h"
-
-#include "md-abi.h"
-
-#include "vm/jit/s390/codegen.h"
-#include "vm/jit/s390/emit.h"
+#include <assert.h>
+#include <stdint.h>
 
+#include "mm/memory.h"
 #if defined(ENABLE_THREADS)
 # include "threads/native/lock.h"
 #endif
-
 #include "vm/builtin.h"
+#include "vm/exceptions.h"
+#include "vm/global.h"
+#include "vm/jit/abi.h"
 #include "vm/jit/abi-asm.h"
 #include "vm/jit/asmpart.h"
 #include "vm/jit/codegen-common.h"
 #include "vm/jit/emit-common.h"
 #include "vm/jit/jit.h"
+#include "vm/jit/patcher-common.h"
 #include "vm/jit/replace.h"
-
-#define __PORTED__
+#include "vm/jit/s390/codegen.h"
+#include "vm/jit/s390/emit.h"
+#include "vm/jit/s390/md-abi.h"
+#include "vm/types.h"
+#include "vmcore/options.h"
 
 /* emit_load *******************************************************************
 
@@ -61,7 +56,7 @@
 
 *******************************************************************************/
 
-__PORTED__ s4 emit_load(jitdata *jd, instruction *iptr, varinfo *src, s4 tempreg)
+s4 emit_load(jitdata *jd, instruction *iptr, varinfo *src, s4 tempreg)
 {
        codegendata *cd;
        s4           disp;
@@ -74,7 +69,7 @@ __PORTED__ s4 emit_load(jitdata *jd, instruction *iptr, varinfo *src, s4 tempreg
        if (IS_INMEMORY(src->flags)) {
                COUNT_SPILLS;
 
-               disp = src->vv.regoff * 4;
+               disp = src->vv.regoff;
 
                if (IS_FLT_DBL_TYPE(src->type)) {
                        if (IS_2_WORD_TYPE(src->type))
@@ -107,7 +102,7 @@ __PORTED__ s4 emit_load(jitdata *jd, instruction *iptr, varinfo *src, s4 tempreg
     
 *******************************************************************************/
 
-__PORTED__ inline void emit_store(jitdata *jd, instruction *iptr, varinfo *dst, s4 d)
+void emit_store(jitdata *jd, instruction *iptr, varinfo *dst, s4 d)
 {
        codegendata *cd;
 
@@ -120,15 +115,15 @@ __PORTED__ inline void emit_store(jitdata *jd, instruction *iptr, varinfo *dst,
 
                if (IS_FLT_DBL_TYPE(dst->type)) {
                        if (IS_2_WORD_TYPE(dst->type))
-                               M_DST(d, REG_SP, dst->vv.regoff * 4);
+                               M_DST(d, REG_SP, dst->vv.regoff);
                        else
-                               M_FST(d, REG_SP, dst->vv.regoff * 4);
+                               M_FST(d, REG_SP, dst->vv.regoff);
                }
                else {
                        if (IS_2_WORD_TYPE(dst->type))
-                               M_LST(d, REG_SP, dst->vv.regoff * 4);
+                               M_LST(d, REG_SP, dst->vv.regoff);
                        else
-                               M_IST(d, REG_SP, dst->vv.regoff * 4);
+                               M_IST(d, REG_SP, dst->vv.regoff);
                }
        }
 }
@@ -140,420 +135,455 @@ __PORTED__ inline void emit_store(jitdata *jd, instruction *iptr, varinfo *dst,
 
 *******************************************************************************/
 
-__PORTED__ void emit_copy(jitdata *jd, instruction *iptr, varinfo *src, varinfo *dst)
+void emit_copy(jitdata *jd, instruction *iptr)
 {
-       codegendata  *cd;
-       s4            s1, d;
+       codegendata *cd;
+       varinfo     *src;
+       varinfo     *dst;
+       s4           s1, d;
 
        /* get required compiler data */
 
        cd = jd->cd;
 
+       /* get source and destination variables */
+
+       src = VAROP(iptr->s1);
+       dst = VAROP(iptr->dst);
+
        if ((src->vv.regoff != dst->vv.regoff) ||
                ((src->flags ^ dst->flags) & INMEMORY)) {
 
-               /* If one of the variables resides in memory, we can eliminate
-                  the register move from/to the temporary register with the
-                  order of getting the destination register and the load. */
-
-               if (IS_INMEMORY(src->flags)) {
-                       d = codegen_reg_of_var(iptr->opc, dst, REG_IFTMP);
-                       s1 = emit_load(jd, iptr, src, d);
-               }
-               else {
-                       s1 = emit_load(jd, iptr, src, REG_IFTMP);
-                       d = codegen_reg_of_var(iptr->opc, dst, s1);
+               if ((src->type == TYPE_RET) || (dst->type == TYPE_RET)) {
+                       /* emit nothing, as the value won't be used anyway */
+                       return;
                }
 
-               if (s1 != d) {
-                       if (IS_FLT_DBL_TYPE(src->type))
-                               M_FMOV(s1, d);
-                       else
-                               M_MOV(s1, d);
-               }
+               if (IS_INMEMORY(src->flags) && IS_INMEMORY(dst->flags)) {
+                       if (IS_2_WORD_TYPE(src->type)) {
+                               N_MVC(dst->vv.regoff, 8, REG_SP, src->vv.regoff, REG_SP);
+                       } else {
+                               N_MVC(dst->vv.regoff, 4, REG_SP, src->vv.regoff, REG_SP);
+                       }
+               } else {
 
-               emit_store(jd, iptr, dst, d);
-       }
-}
+                       /* If one of the variables resides in memory, we can eliminate
+                          the register move from/to the temporary register with the
+                          order of getting the destination register and the load. */
+
+                       if (IS_INMEMORY(src->flags)) {
+                               if (IS_FLT_DBL_TYPE(dst->type)) {
+                                       d = codegen_reg_of_var(iptr->opc, dst, REG_FTMP1);
+                               } else {
+                                       if (IS_2_WORD_TYPE(dst->type)) {
+                                               d = codegen_reg_of_var(iptr->opc, dst, REG_ITMP12_PACKED);
+                                       } else {
+                                               d = codegen_reg_of_var(iptr->opc, dst, REG_ITMP1);
+                                       }
+                               }
+                               s1 = emit_load(jd, iptr, src, d);
+                       }
+                       else {
+                               if (IS_FLT_DBL_TYPE(src->type)) {
+                                       s1 = emit_load(jd, iptr, src, REG_FTMP1);
+                               } else {
+                                       if (IS_2_WORD_TYPE(src->type)) {
+                                               s1 = emit_load(jd, iptr, src, REG_ITMP12_PACKED);
+                                       } else {
+                                               s1 = emit_load(jd, iptr, src, REG_ITMP1);
+                                       }
+                               }
+                               d = codegen_reg_of_var(iptr->opc, dst, s1);
+                       }
 
+                       if (s1 != d) {
+                               if (IS_FLT_DBL_TYPE(src->type)) {
+                                       M_FMOV(s1, d);
+                               } else {
+                                       if (IS_2_WORD_TYPE(src->type)) {
+                                               M_LNGMOVE(s1, d);
+                                       } else {
+                                               M_MOV(s1, d);
+                                       }
+                               }
+                       }
 
-void emit_cmovxx(codegendata *cd, instruction *iptr, s4 s, s4 d)
-{
-#if 0
-       switch (iptr->flags.fields.condition) {
-       case ICMD_IFEQ:
-               M_CMOVEQ(s, d);
-               break;
-       case ICMD_IFNE:
-               M_CMOVNE(s, d);
-               break;
-       case ICMD_IFLT:
-               M_CMOVLT(s, d);
-               break;
-       case ICMD_IFGE:
-               M_CMOVGE(s, d);
-               break;
-       case ICMD_IFGT:
-               M_CMOVGT(s, d);
-               break;
-       case ICMD_IFLE:
-               M_CMOVLE(s, d);
-               break;
+                       emit_store(jd, iptr, dst, d);
+               }
        }
-#endif
 }
 
+/* emit_trap****************************************************************
 
-/* emit_exception_stubs ********************************************************
-
-   Generates the code for the exception stubs.
+   Emit a trap instruction and return the original machine code.
 
 *******************************************************************************/
 
-void emit_exception_stubs(jitdata *jd)
+uint32_t emit_trap(codegendata *cd)
 {
-#if 0
-       codegendata  *cd;
-       registerdata *rd;
-       exceptionref *er;
-       s4            branchmpc;
-       s4            targetmpc;
-       s4            targetdisp;
-
-       /* get required compiler data */
+       uint32_t mcode;
 
-       cd = jd->cd;
-       rd = jd->rd;
+       /* Get machine code which is patched back in later. The
+          trap is 2 bytes long. */
 
-       /* generate exception stubs */
+       mcode = *((u2 *) cd->mcodeptr);
 
-       targetdisp = 0;
+       M_ILL(EXCEPTION_HARDWARE_PATCHER);
 
-       for (er = cd->exceptionrefs; er != NULL; er = er->next) {
-               /* back-patch the branch to this exception code */
+       return mcode;
+}
 
-               branchmpc = er->branchpos;
-               targetmpc = cd->mcodeptr - cd->mcodebase;
 
-               md_codegen_patch_branch(cd, branchmpc, targetmpc);
+/* emit_verbosecall_enter ******************************************************
 
-               MCODECHECK(512);
+   Generates the code for the call trace.
 
-               /* Check if the exception is an
-                  ArrayIndexOutOfBoundsException.  If so, move index register
-                  into a4. */
+*******************************************************************************/
 
-               if (er->reg != -1)
-                       M_MOV(er->reg, rd->argintregs[4]);
+#if !defined(NDEBUG)
+#include "vm/jit/trace.h"
+void emit_verbosecall_enter(jitdata *jd)
+{
+#if 1
+       methodinfo   *m;
+       codegendata  *cd;
+       s4            stackframesize;
+       s4            i, off, disp;
 
-               /* calcuate exception address */
+       m  = jd->m;
+       cd = jd->cd;
 
-               M_MOV_IMM(0, rd->argintregs[3]);
-               dseg_adddata(cd);
-               M_AADD_IMM32(er->branchpos - 6, rd->argintregs[3]);
+       /* mark trace code */
 
-               /* move function to call into REG_ITMP3 */
+       M_NOP;
 
-               M_MOV_IMM(er->function, REG_ITMP3);
+       /* allocate stack frame */
 
-               if (targetdisp == 0) {
-                       targetdisp = cd->mcodeptr - cd->mcodebase;
+       stackframesize = 96 + (ARG_CNT * 8) + (TMP_CNT * 8);
+       M_ASUB_IMM(stackframesize, REG_SP);
 
-                       emit_lea_membase_reg(cd, RIP, -((cd->mcodeptr + 7) - cd->mcodebase), rd->argintregs[0]);
-                       M_MOV(REG_SP, rd->argintregs[1]);
-                       M_ALD(rd->argintregs[2], REG_SP, cd->stackframesize * 8);
+       /* store argument registers in array */
 
-                       M_ASUB_IMM(2 * 8, REG_SP);
-                       M_AST(rd->argintregs[3], REG_SP, 0 * 8);             /* store XPC */
+       off = 96;
 
-                       M_CALL(REG_ITMP3);
+       for (i = 0; i < INT_ARG_CNT; ++i, off += 8) {
+               M_IST(abi_registers_integer_argument[i], REG_SP, off + 4);
+               /* high bytes are sign extension */
+               M_SRA_IMM(31, abi_registers_integer_argument[i]);
+               M_IST(abi_registers_integer_argument[i], REG_SP, off);
+       }
 
-                       M_ALD(REG_ITMP2_XPC, REG_SP, 0 * 8);
-                       M_AADD_IMM(2 * 8, REG_SP);
+       for (i = 0; i < FLT_ARG_CNT; ++i, off += 8) {
+               M_DST(abi_registers_float_argument[i], REG_SP, off);
+       }
+       
+       /* save temporary registers for leaf methods */
 
-                       M_MOV_IMM(asm_handle_exception, REG_ITMP3);
-                       M_JMP(REG_ITMP3);
+       if (jd->isleafmethod) {
+               for (i = 0; i < INT_TMP_CNT; ++i, off += 8) {
+                       M_IST(abi_registers_integer_temporary[i], REG_SP, off);
                }
-               else {
-                       M_JMP_IMM((cd->mcodebase + targetdisp) -
-                                         (cd->mcodeptr + PATCHER_CALL_SIZE));
+
+               for (i = 0; i < FLT_TMP_CNT; ++i, off += 8) {
+                       M_DST(abi_registers_float_temporary[i], REG_SP, off);
                }
        }
-#endif
-}
 
+       /* load arguments for trace_java_call_enter */
 
-/* emit_patcher_stubs **********************************************************
-
-   Generates the code for the patcher stubs.
-
-*******************************************************************************/
-
-__PORTED__ void emit_patcher_stubs(jitdata *jd)
-{
-       
-       codegendata *cd;
-       patchref    *pref;
-       u4           mcode;
-       u1          *savedmcodeptr;
-       u1          *tmpmcodeptr;
-       s4           targetdisp;
-       s4           disp;
+       /* methodinfo */
+       disp = dseg_add_address(cd, m);
+       M_ALD_DSEG(REG_A0, disp);       
+       /* pointer to argument registers array */
+       M_LDA(REG_A1, REG_SP, 96);
+       /* pointer to on stack arguments */
+       M_LDA(REG_A2, REG_SP, stackframesize + (cd->stackframesize * 8));
 
-       /* get required compiler data */
+       /* call trace_java_call_enter */
 
-       cd = jd->cd;
+       disp = dseg_add_functionptr(cd, trace_java_call_enter);
+       M_ALD_DSEG(REG_ITMP3, disp);
+       M_CALL(REG_ITMP3);
 
-       /* generate code patching stub call code */
+       /* restore argument registers */
 
-       targetdisp = 0;
+       off = 96;
 
-       for (pref = cd->patchrefs; pref != NULL; pref = pref->next) {
-               /* check code segment size */
+       for (i = 0; i < INT_ARG_CNT; ++i, off += 8) {
+               M_ILD(abi_registers_integer_argument[i], REG_SP, off + 4);
+       }
 
-               MCODECHECK(100);
+       for (i = 0; i < FLT_ARG_CNT; ++i, off += 8) {
+               M_DLD(abi_registers_float_argument[i], REG_SP, off);
+       }
 
-               /* Get machine code which is patched back in later. The
-                  call is 1 instruction word long. */
+       /* restore temporary registers for leaf methods */
 
-               tmpmcodeptr = (u1 *) (cd->mcodebase + pref->branchpos);
+       if (jd->isleafmethod) {
+               for (i = 0; i < INT_TMP_CNT; ++i, off += 8) {
+                       M_ILD(abi_registers_integer_temporary[i], REG_SP, off);
+               }
 
-               mcode = *((u4 *) tmpmcodeptr);
+               for (i = 0; i < FLT_TMP_CNT; ++i, off += 8) {
+                       M_DLD(abi_registers_float_temporary[i], REG_SP, off);
+               }
+       }
 
-               /* Patch in the call to call the following code (done at
-                  compile time). */
+       /* remove stack frame */
 
-               savedmcodeptr = cd->mcodeptr;   /* save current mcodeptr              */
-               cd->mcodeptr  = tmpmcodeptr;    /* set mcodeptr to patch position     */
+       M_AADD_IMM(stackframesize, REG_SP);
 
-               disp = (savedmcodeptr) - (tmpmcodeptr);
-               M_BSR(REG_ITMP3, disp);
+       /* mark trace code */
 
-               cd->mcodeptr = savedmcodeptr;   /* restore the current mcodeptr       */
+       M_NOP;
 
-               /* create stack frame */
+#else
+       methodinfo   *m;
+       codegendata  *cd;
+       methoddesc   *md;
+       s4            i, j, k;
+       s4            stackframesize, off, foff, aoff, doff, t, iargctr, fargctr, disp;
 
-               M_ASUB_IMM(6 * 4, REG_SP);
+       /* get required compiler data */
 
-               /* move return address onto stack */
+       m  = jd->m;
+       cd = jd->cd;
 
-               M_AST(REG_ITMP3, REG_SP, 5 * 4);
+       md = m->parseddesc;
 
-               /* move pointer to java_objectheader onto stack */
+       /* mark trace code */
 
-#if defined(ENABLE_THREADS)
-               /* create a virtual java_objectheader */
+       M_NOP;
 
-               (void) dseg_add_unique_address(cd, NULL);                  /* flcword */
-               (void) dseg_add_unique_address(cd, lock_get_initial_lock_word());
-               disp = dseg_add_unique_address(cd, NULL);                  /* vftbl   */
+       stackframesize = 
+               (6 * 8) + /* s8 on stack parameters x 6 */
+               (1 * 4) + /* methodinfo on stack parameter */
+               (ARG_CNT * 8) +
+               (TMP_CNT * 8) 
+               ;
 
-               M_LDA(REG_ITMP3, REG_PV, disp);
-               M_AST(REG_ITMP3, REG_SP, 4 * 4);
-#else
-               /* nothing to do */
-#endif
+       M_ASUB_IMM(stackframesize, REG_SP); /* allocate stackframe */
 
-               /* move machine code onto stack */
+       /* save argument registers */
 
-               disp = dseg_add_s4(cd, mcode);
-               M_ILD(REG_ITMP3, REG_PV, disp);
-               M_IST(REG_ITMP3, REG_SP, 3 * 4);
+       off = (6 * 8) + (1 * 4);
 
-               /* move class/method/field reference onto stack */
+       for (i = 0; i < INT_ARG_CNT; i++, off += 8)
+               M_IST(abi_registers_integer_argument[i], REG_SP, off);
 
-               disp = dseg_add_address(cd, pref->ref);
-               M_ALD(REG_ITMP3, REG_PV, disp);
-               M_AST(REG_ITMP3, REG_SP, 2 * 4);
+       for (i = 0; i < FLT_ARG_CNT; i++, off += 8)
+               M_DST(abi_registers_float_argument[i], REG_SP, off);
 
-               /* move data segment displacement onto stack */
+       /* save temporary registers for leaf methods */
 
-               disp = dseg_add_s4(cd, pref->disp);
-               M_ILD(REG_ITMP3, REG_PV, disp);
-               M_IST(REG_ITMP3, REG_SP, 1 * 4);
+       if (jd->isleafmethod) {
+               for (i = 0; i < INT_TMP_CNT; i++, off += 8)
+                       M_LST(abi_registers_integer_temporary[i], REG_SP, off);
 
-               /* move patcher function pointer onto stack */
+               for (i = 0; i < FLT_TMP_CNT; i++, off += 8)
+                       M_DST(abi_registers_float_temporary[i], REG_SP, off);
+       }
 
-               disp = dseg_add_functionptr(cd, pref->patcher);
-               M_ALD(REG_ITMP3, REG_PV, disp);
-               M_AST(REG_ITMP3, REG_SP, 0 * 4);
+       /* Load arguments to new locations */
 
-               if (targetdisp == 0) {
-                       targetdisp = (cd->mcodeptr) - (cd->mcodebase);
+       /* First move all arguments to stack
+        *
+        * (s8) a7
+        * (s8) a2
+        *   ...
+        * (s8) a1 \ Auxilliary stack frame
+        * (s8) a0 /
+        * ------- <---- SP
+        */
 
-                       disp = dseg_add_functionptr(cd, asm_patcher_wrapper);
-                       M_ALD(REG_ITMP3, REG_PV, disp);
-                       M_JMP(RN, REG_ITMP3);
+       M_ASUB_IMM(2 * 8, REG_SP);
+       
+       /* offset to where first integer arg is saved on stack */
+       off = (2 * 8) + (6 * 8) + (1 * 4); 
+       /* offset to where first float arg is saved on stack */
+       foff = off + (INT_ARG_CNT * 8); 
+       /* offset to where first argument is passed on stack */
+       aoff = (2 * 8) + stackframesize + (cd->stackframesize * 8);
+       /* offset to destination on stack */
+       doff = 0; 
+
+       iargctr = fargctr = 0;
+
+       ICONST(REG_ITMP1, 0);
+
+       for (i = 0; i < md->paramcount && i < 8; i++) {
+               t = md->paramtypes[i].type;
+
+               M_IST(REG_ITMP1, REG_SP, doff);
+               M_IST(REG_ITMP1, REG_SP, doff + 4);
+
+               if (IS_FLT_DBL_TYPE(t)) {
+                       if (fargctr < 2) { /* passed in register */
+                               N_STD(abi_registers_float_argument[fargctr], doff, RN, REG_SP);
+                               fargctr += 1;
+                       } else { /* passed on stack */
+                               /*
+                               if (IS_2_WORD_TYPE(t)) {
+                                       N_MVC(doff, 8, REG_SP, aoff, REG_SP);
+                               } else {
+                                       N_MVC(doff + 4, 4, REG_SP, aoff, REG_SP);
+                               }
+                               */
+                               N_MVC(doff, 8, REG_SP, aoff, REG_SP);
+                               aoff += 8;
+                       }
+               } else {
+                       if (IS_2_WORD_TYPE(t)) {
+                               if (iargctr < 4) { /* passed in 2 registers */
+                                       N_STM(REG_A0 + iargctr, REG_A0 + iargctr + 1, doff, REG_SP);
+                                       iargctr += 2;
+                               } else { /* passed on stack */
+                                       N_MVC(doff, 8, REG_SP, aoff, REG_SP);
+                                       aoff += 8;
+                               }
+                       } else {
+                               if (iargctr < 5) { /* passed in register */
+                                       N_ST(REG_A0 + iargctr, doff + 4, RN, REG_SP);
+                                       iargctr += 1;
+                               } else { /* passed on stack */
+                                       N_MVC(doff + 4, 4, REG_SP, aoff, REG_SP);
+                                       aoff += 8;
+                               }
+                       }
                }
-               else {
-                       disp = ((cd->mcodebase) + targetdisp) -
-                               (( cd->mcodeptr) );
 
-                       M_BR(disp);
-               }
+               doff += 8;
        }
-}
 
+       /* Now move a0 and a1 to registers
+        *
+        * (s8) a7
+        *   ...
+        * (s8) a2
+        * ------- <- SP
+        * (s8) a0 ==> a0, a1
+        * (s8) a1 ==> a2, a3
+        */
 
-/* emit_replacement_stubs ******************************************************
+       N_LM(REG_A0, REG_A1, 0, REG_SP);
+       N_LM(REG_A2, REG_A3, 8, REG_SP);
 
-   Generates the code for the replacement stubs.
+       M_AADD_IMM(2 * 8, REG_SP);
 
-*******************************************************************************/
+       /* Finally load methodinfo argument */
 
-void emit_replacement_stubs(jitdata *jd)
-{
-#if 0
-       codegendata *cd;
-       codeinfo    *code;
-       rplpoint    *rplp;
-       s4           disp;
-       s4           i;
+       disp = dseg_add_address(cd, m);
+       M_ALD_DSEG(REG_ITMP2, disp);    
+       M_AST(REG_ITMP2, REG_SP, 6 * 8);
 
-       /* get required compiler data */
+       /* Call builtin_verbosecall_enter */
 
-       cd   = jd->cd;
-       code = jd->code;
+       disp = dseg_add_address(cd, builtin_verbosecall_enter);
+       M_ALD_DSEG(REG_ITMP2, disp);
+       M_ASUB_IMM(96, REG_SP);
+       M_CALL(REG_ITMP2);
+       M_AADD_IMM(96, REG_SP);
 
-       rplp = code->rplpoints;
+       /* restore argument registers */
 
-       for (i = 0; i < code->rplpointcount; ++i, ++rplp) {
-               /* check code segment size */
+       off = (6 * 8) + (1 * 4);
 
-               MCODECHECK(512);
+       for (i = 0; i < INT_ARG_CNT; i++, off += 8)
+               M_ILD(abi_registers_integer_argument[i], REG_SP, off);
 
-               /* note start of stub code */
+       for (i = 0; i < FLT_ARG_CNT; i++, off += 8)
+               M_DLD(abi_registers_float_argument[i], REG_SP, off);
 
-               rplp->outcode = (u1 *) (ptrint) (cd->mcodeptr - cd->mcodebase);
+       /* restore temporary registers for leaf methods */
 
-               /* make machine code for patching */
+       if (jd->isleafmethod) {
+               for (i = 0; i < INT_TMP_CNT; i++, off += 8)
+                       M_ILD(abi_registers_integer_temporary[i], REG_SP, off);
 
-               disp = (ptrint) (rplp->outcode - rplp->pc) - 5;
+               for (i = 0; i < FLT_TMP_CNT; i++, off += 8)
+                       M_DLD(abi_registers_float_temporary[i], REG_SP, off);
+       }
 
-               rplp->mcode = 0xe9 | ((u8) disp << 8);
+       /* remove stackframe */
 
-               /* push address of `rplpoint` struct */
-                       
-               M_MOV_IMM(rplp, REG_ITMP3);
-               M_PUSH(REG_ITMP3);
+       M_AADD_IMM(stackframesize, REG_SP);
 
-               /* jump to replacement function */
+       /* mark trace code */
 
-               M_MOV_IMM(asm_replacement_out, REG_ITMP3);
-               M_JMP(REG_ITMP3);
-       }
+       M_NOP;
 #endif
 }
-       
+#endif /* !defined(NDEBUG) */
 
-/* emit_verbosecall_enter ******************************************************
+
+/* emit_verbosecall_exit *******************************************************
 
    Generates the code for the call trace.
 
 *******************************************************************************/
 
 #if !defined(NDEBUG)
-void emit_verbosecall_enter(jitdata *jd)
+void emit_verbosecall_exit(jitdata *jd)
 {
+#if 1
        methodinfo   *m;
        codegendata  *cd;
-       registerdata *rd;
-       methoddesc   *md;
-       s4            i, j, k;
-
-       /* get required compiler data */
+       s4            disp;
+       s4            stackframesize;
 
        m  = jd->m;
        cd = jd->cd;
-       rd = jd->rd;
-
-       md = m->parseddesc;
 
        /* mark trace code */
 
        M_NOP;
 
-       /* additional +1 is for 16-byte stack alignment */
-
-       M_LSUB_IMM((ARG_CNT + TMP_CNT + 1 + 1) * 8, REG_SP);
-
-       /* save argument registers */
-
-       for (i = 0; i < INT_ARG_CNT; i++)
-               M_LST(rd->argintregs[i], REG_SP, (1 + i) * 8);
-
-       for (i = 0; i < FLT_ARG_CNT; i++)
-               M_DST(rd->argfltregs[i], REG_SP, (1 + INT_ARG_CNT + i) * 8);
-
-       /* save temporary registers for leaf methods */
-
-       if (jd->isleafmethod) {
-               for (i = 0; i < INT_TMP_CNT; i++)
-                       M_LST(rd->tmpintregs[i], REG_SP, (1 + ARG_CNT + i) * 8);
-
-               for (i = 0; i < FLT_TMP_CNT; i++)
-                       M_DST(rd->tmpfltregs[i], REG_SP, (1 + ARG_CNT + INT_TMP_CNT + i) * 8);
-       }
+       /* allocate stackframe */
 
-       /* show integer hex code for float arguments */
+       stackframesize = 96 + (3 * 8);
+       M_ASUB_IMM(stackframesize, REG_SP);
 
-       for (i = 0, j = 0; i < md->paramcount && i < INT_ARG_CNT; i++) {
-               /* If the paramtype is a float, we have to right shift all
-                  following integer registers. */
-       
-               if (IS_FLT_DBL_TYPE(md->paramtypes[i].type)) {
-                       for (k = INT_ARG_CNT - 2; k >= i; k--)
-                               M_MOV(rd->argintregs[k], rd->argintregs[k + 1]);
+       /* store return values in array and sign extend them */
 
-                       emit_movd_freg_reg(cd, rd->argfltregs[j], rd->argintregs[i]);
-                       j++;
-               }
-       }
+       M_IST(REG_RESULT, REG_SP, 96 + (0 * 8) + 4);
+       M_SRA_IMM(31, REG_RESULT);
+       M_IST(REG_RESULT, REG_SP, 96 + (0 * 8));
 
-       M_MOV_IMM(m, REG_ITMP2);
-       M_AST(REG_ITMP2, REG_SP, 0 * 8);
-       M_MOV_IMM(builtin_trace_args, REG_ITMP1);
-       M_CALL(REG_ITMP1);
+       M_IST(REG_RESULT2, REG_SP, 96 + (1 * 8) + 4);
+       M_SRA_IMM(31, REG_RESULT2);
+       M_IST(REG_RESULT2, REG_SP, 96 + (1 * 8));
 
-       /* restore argument registers */
+       M_DST(REG_FRESULT, REG_SP, 96 + (2 * 8));
 
-       for (i = 0; i < INT_ARG_CNT; i++)
-               M_LLD(rd->argintregs[i], REG_SP, (1 + i) * 8);
+       /* call trace_java_call_exit */
 
-       for (i = 0; i < FLT_ARG_CNT; i++)
-               M_DLD(rd->argfltregs[i], REG_SP, (1 + INT_ARG_CNT + i) * 8);
+       disp = dseg_add_address(cd, m);
+       M_ALD_DSEG(REG_A0, disp);
+       M_LDA(REG_A1, REG_SP, 96);
+       disp = dseg_add_functionptr(cd, trace_java_call_exit);
+       M_ALD_DSEG(REG_ITMP3, disp);
+       M_CALL(REG_ITMP3);
 
-       /* restore temporary registers for leaf methods */
+       /* restore return values */
 
-       if (jd->isleafmethod) {
-               for (i = 0; i < INT_TMP_CNT; i++)
-                       M_LLD(rd->tmpintregs[i], REG_SP, (1 + ARG_CNT + i) * 8);
+       M_ILD(REG_RESULT, REG_SP, 96 + (0 * 8) + 4);
+       M_ILD(REG_RESULT2, REG_SP, 96 + (1 * 8) + 4);
+       M_DLD(REG_FRESULT, REG_SP, 96 + (2 * 8));
 
-               for (i = 0; i < FLT_TMP_CNT; i++)
-                       M_DLD(rd->tmpfltregs[i], REG_SP, (1 + ARG_CNT + INT_TMP_CNT + i) * 8);
-       }
+       /* remove stackframe */
 
-       M_LADD_IMM((ARG_CNT + TMP_CNT + 1 + 1) * 8, REG_SP);
+       M_AADD_IMM(stackframesize, REG_SP);
 
        /* mark trace code */
 
        M_NOP;
-}
-#endif /* !defined(NDEBUG) */
-
-
-/* emit_verbosecall_exit *******************************************************
 
-   Generates the code for the call trace.
-
-*******************************************************************************/
+#else
 
-#if !defined(NDEBUG)
-void emit_verbosecall_exit(jitdata *jd)
-{
        methodinfo   *m;
        codegendata  *cd;
        registerdata *rd;
+       s4            disp;
 
        /* get required compiler data */
 
@@ -567,18 +597,29 @@ void emit_verbosecall_exit(jitdata *jd)
 
        M_ASUB_IMM(2 * 8, REG_SP);
 
-       M_LST(REG_RESULT, REG_SP, 0 * 8);
+       N_STM(REG_RESULT, REG_RESULT2, 0 * 8, REG_SP);
        M_DST(REG_FRESULT, REG_SP, 1 * 8);
 
-       M_MOV_IMM(m, rd->argintregs[0]);
-       M_MOV(REG_RESULT, rd->argintregs[1]);
-       M_FLTMOVE(REG_FRESULT, rd->argfltregs[0]);
-       M_FLTMOVE(REG_FRESULT, rd->argfltregs[1]);
+       if (IS_2_WORD_TYPE(m->parseddesc->returntype.type)) {
+               /* (REG_A0, REG_A1) == (REG_RESULT, REG_RESULT2), se no need to move */
+       } else {
+               M_INTMOVE(REG_RESULT, REG_A1);
+               ICONST(REG_A0, 0);
+       }
+
+       disp = dseg_add_address(cd, m);
+       M_ALD_DSEG(REG_A2, disp);
+
+       /* REG_FRESULT is REG_FA0, so no need to move */
+       M_FLTMOVE(REG_FRESULT, REG_FA1);
 
-       M_MOV_IMM(builtin_displaymethodstop, REG_ITMP1);
+       disp = dseg_add_address(cd, builtin_verbosecall_exit);
+       M_ALD_DSEG(REG_ITMP1, disp);
+       M_ASUB_IMM(96, REG_SP);
        M_CALL(REG_ITMP1);
+       M_AADD_IMM(96, REG_SP);
 
-       M_LLD(REG_RESULT, REG_SP, 0 * 8);
+       N_LM(REG_RESULT, REG_RESULT2, 0 * 8, REG_SP);
        M_DLD(REG_FRESULT, REG_SP, 1 * 8);
 
        M_AADD_IMM(2 * 8, REG_SP);
@@ -586,1747 +627,438 @@ void emit_verbosecall_exit(jitdata *jd)
        /* mark trace code */
 
        M_NOP;
+#endif
 }
 #endif /* !defined(NDEBUG) */
 
 
-/* code generation functions **************************************************/
+/* emit_load_high **************************************************************
 
-static void emit_membase(codegendata *cd, s4 basereg, s4 disp, s4 dreg)
-{
-       if ((basereg == REG_SP) || (basereg == R12)) {
-               if (disp == 0) {
-                       emit_address_byte(0, dreg, REG_SP);
-                       emit_address_byte(0, REG_SP, REG_SP);
+   Emits a possible load of the high 32-bits of an operand.
 
-               } else if (IS_IMM8(disp)) {
-                       emit_address_byte(1, dreg, REG_SP);
-                       emit_address_byte(0, REG_SP, REG_SP);
-                       emit_imm8(disp);
+*******************************************************************************/
 
-               } else {
-                       emit_address_byte(2, dreg, REG_SP);
-                       emit_address_byte(0, REG_SP, REG_SP);
-                       emit_imm32(disp);
-               }
+s4 emit_load_high(jitdata *jd, instruction *iptr, varinfo *src, s4 tempreg)
+{
+       codegendata  *cd;
+       s4            disp;
+       s4            reg;
 
-       } else if ((disp) == 0 && (basereg) != RBP && (basereg) != R13) {
-               emit_address_byte(0,(dreg),(basereg));
+       assert(src->type == TYPE_LNG);
 
-       } else if ((basereg) == RIP) {
-               emit_address_byte(0, dreg, RBP);
-               emit_imm32(disp);
+       /* get required compiler data */
 
-       } else {
-               if (IS_IMM8(disp)) {
-                       emit_address_byte(1, dreg, basereg);
-                       emit_imm8(disp);
+       cd = jd->cd;
 
-               } else {
-                       emit_address_byte(2, dreg, basereg);
-                       emit_imm32(disp);
-               }
-       }
-}
+       if (IS_INMEMORY(src->flags)) {
+               COUNT_SPILLS;
 
+               disp = src->vv.regoff;
 
-static void emit_membase32(codegendata *cd, s4 basereg, s4 disp, s4 dreg)
-{
-       if ((basereg == REG_SP) || (basereg == R12)) {
-               emit_address_byte(2, dreg, REG_SP);
-               emit_address_byte(0, REG_SP, REG_SP);
-               emit_imm32(disp);
-       }
-       else {
-               emit_address_byte(2, dreg, basereg);
-               emit_imm32(disp);
+               M_ILD(tempreg, REG_SP, disp);
+
+               reg = tempreg;
        }
+       else
+               reg = GET_HIGH_REG(src->vv.regoff);
+
+       return reg;
 }
 
+/* emit_load_low ***************************************************************
 
-static void emit_memindex(codegendata *cd, s4 reg, s4 disp, s4 basereg, s4 indexreg, s4 scale)
-{
-       if (basereg == -1) {
-               emit_address_byte(0, reg, 4);
-               emit_address_byte(scale, indexreg, 5);
-               emit_imm32(disp);
-       }
-       else if ((disp == 0) && (basereg != RBP) && (basereg != R13)) {
-               emit_address_byte(0, reg, 4);
-               emit_address_byte(scale, indexreg, basereg);
-       }
-       else if (IS_IMM8(disp)) {
-               emit_address_byte(1, reg, 4);
-               emit_address_byte(scale, indexreg, basereg);
-               emit_imm8(disp);
-       }
-       else {
-               emit_address_byte(2, reg, 4);
-               emit_address_byte(scale, indexreg, basereg);
-               emit_imm32(disp);
-       }
-}
+   Emits a possible load of the low 32-bits of an operand.
 
+*******************************************************************************/
 
-void emit_ishift(jitdata *jd, s4 shift_op, instruction *iptr)
+s4 emit_load_low(jitdata *jd, instruction *iptr, varinfo *src, s4 tempreg)
 {
-       s4 s1, s2, d, d_old;
-       varinfo *v_s1,*v_s2,*v_dst;
-       codegendata *cd;
+       codegendata  *cd;
+       s4            disp;
+       s4            reg;
+
+       assert(src->type == TYPE_LNG);
 
        /* get required compiler data */
 
        cd = jd->cd;
 
-       v_s1  = VAROP(iptr->s1);
-       v_s2  = VAROP(iptr->sx.s23.s2);
-       v_dst = VAROP(iptr->dst);
+       if (IS_INMEMORY(src->flags)) {
+               COUNT_SPILLS;
 
-       s1 = v_s1->vv.regoff;
-       s2 = v_s2->vv.regoff;
-       d  = v_dst->vv.regoff;
+               disp = src->vv.regoff;
 
-       M_INTMOVE(RCX, REG_ITMP1);                                    /* save RCX */
+               M_ILD(tempreg, REG_SP, disp + 4);
 
-       if (IS_INMEMORY(v_dst->flags)) {
-               if (IS_INMEMORY(v_s2->flags) && IS_INMEMORY(v_s1->flags)) {
-                       if (s1 == d) {
-                               M_ILD(RCX, REG_SP, s2 * 8);
-                               emit_shiftl_membase(cd, shift_op, REG_SP, d * 8);
+               reg = tempreg;
+       }
+       else
+               reg = GET_LOW_REG(src->vv.regoff);
 
-                       } else {
-                               M_ILD(RCX, REG_SP, s2 * 8);
-                               M_ILD(REG_ITMP2, REG_SP, s1 * 8);
-                               emit_shiftl_reg(cd, shift_op, REG_ITMP2);
-                               M_IST(REG_ITMP2, REG_SP, d * 8);
-                       }
+       return reg;
+}
 
-               } else if (IS_INMEMORY(v_s2->flags) && !IS_INMEMORY(v_s1->flags)) {
-                       /* s1 may be equal to RCX */
-                       if (s1 == RCX) {
-                               if (s2 == d) {
-                                       M_ILD(REG_ITMP1, REG_SP, s2 * 8);
-                                       M_IST(s1, REG_SP, d * 8);
-                                       M_INTMOVE(REG_ITMP1, RCX);
+s4 emit_load_s1_notzero(jitdata *jd, instruction *iptr, s4 tempreg) {
+       codegendata *cd = jd->cd;
+       s4 reg = emit_load_s1(jd, iptr, tempreg);
+       if (reg == 0) {
+               M_MOV(reg, tempreg);
+               return tempreg;
+       } else {
+               return reg;
+       }
+}
 
-                               } else {
-                                       M_IST(s1, REG_SP, d * 8);
-                                       M_ILD(RCX, REG_SP, s2 * 8);
-                               }
-
-                       } else {
-                               M_ILD(RCX, REG_SP, s2 * 8);
-                               M_IST(s1, REG_SP, d * 8);
-                       }
-
-                       emit_shiftl_membase(cd, shift_op, REG_SP, d * 8);
-
-               } else if (!IS_INMEMORY(v_s2->flags) && IS_INMEMORY(v_s1->flags)) {
-                       if (s1 == d) {
-                               M_INTMOVE(s2, RCX);
-                               emit_shiftl_membase(cd, shift_op, REG_SP, d * 8);
-
-                       } else {
-                               M_INTMOVE(s2, RCX);
-                               M_ILD(REG_ITMP2, REG_SP, s1 * 8);
-                               emit_shiftl_reg(cd, shift_op, REG_ITMP2);
-                               M_IST(REG_ITMP2, REG_SP, d * 8);
-                       }
+s4 emit_load_s2_notzero(jitdata *jd, instruction *iptr, s4 tempreg) {
+       codegendata *cd = jd->cd;
+       s4 reg = emit_load_s2(jd, iptr, tempreg);
+       if (reg == 0) {
+               if (IS_FLT_DBL_TYPE(VAROP(iptr->sx.s23.s2)->type)) {
+                       M_FMOV(reg, tempreg);
+               } else {
+                       M_MOV(reg, tempreg);
+               }
+               return tempreg;
+       } else {
+               return reg;
+       }
+}
 
+s4 emit_load_s1_but(jitdata *jd, instruction *iptr, s4 tempreg, s4 notreg) {
+       codegendata *cd = jd->cd;
+       s4 reg = emit_load_s1(jd, iptr, tempreg);
+       if (reg == notreg) {
+               if (IS_FLT_DBL_TYPE(VAROP(iptr->s1)->type)) {
+                       M_FMOV(reg, tempreg);
                } else {
-                       /* s1 may be equal to RCX */
-                       M_IST(s1, REG_SP, d * 8);
-                       M_INTMOVE(s2, RCX);
-                       emit_shiftl_membase(cd, shift_op, REG_SP, d * 8);
+                       M_MOV(reg, tempreg);
                }
-
-               M_INTMOVE(REG_ITMP1, RCX);                             /* restore RCX */
-
+               return tempreg;
        } else {
-               d_old = d;
-               if (d == RCX) {
-                       d = REG_ITMP3;
-               }
-                                       
-               if (IS_INMEMORY(v_s2->flags) && IS_INMEMORY(v_s1->flags)) {
-                       M_ILD(RCX, REG_SP, s2 * 8);
-                       M_ILD(d, REG_SP, s1 * 8);
-                       emit_shiftl_reg(cd, shift_op, d);
-
-               } else if (IS_INMEMORY(v_s2->flags) && !IS_INMEMORY(v_s1->flags)) {
-                       /* s1 may be equal to RCX */
-                       M_INTMOVE(s1, d);
-                       M_ILD(RCX, REG_SP, s2 * 8);
-                       emit_shiftl_reg(cd, shift_op, d);
-
-               } else if (!IS_INMEMORY(v_s2->flags) && IS_INMEMORY(v_s1->flags)) {
-                       M_INTMOVE(s2, RCX);
-                       M_ILD(d, REG_SP, s1 * 8);
-                       emit_shiftl_reg(cd, shift_op, d);
+               return reg;
+       }
+}
 
+s4 emit_load_s2_but(jitdata *jd, instruction *iptr, s4 tempreg, s4 notreg) {
+       codegendata *cd = jd->cd;
+       s4 reg = emit_load_s2(jd, iptr, tempreg);
+       if (reg == notreg) {
+               if (IS_FLT_DBL_TYPE(VAROP(iptr->sx.s23.s2)->type)) {
+                       M_FMOV(reg, tempreg);
                } else {
-                       /* s1 may be equal to RCX */
-                       if (s1 == RCX) {
-                               if (s2 == d) {
-                                       /* d cannot be used to backup s1 since this would
-                                          overwrite s2. */
-                                       M_INTMOVE(s1, REG_ITMP3);
-                                       M_INTMOVE(s2, RCX);
-                                       M_INTMOVE(REG_ITMP3, d);
-
-                               } else {
-                                       M_INTMOVE(s1, d);
-                                       M_INTMOVE(s2, RCX);
-                               }
-
-                       } else {
-                               /* d may be equal to s2 */
-                               M_INTMOVE(s2, RCX);
-                               M_INTMOVE(s1, d);
-                       }
-                       emit_shiftl_reg(cd, shift_op, d);
+                       M_MOV(reg, tempreg);
                }
-
-               if (d_old == RCX)
-                       M_INTMOVE(REG_ITMP3, RCX);
-               else
-                       M_INTMOVE(REG_ITMP1, RCX);                         /* restore RCX */
+               return tempreg;
+       } else {
+               return reg;
        }
 }
 
-
-void emit_lshift(jitdata *jd, s4 shift_op, instruction *iptr)
-{
-       s4 s1, s2, d, d_old;
-       varinfo *v_s1,*v_s2,*v_dst;
+s4 emit_alloc_dst_even_odd(jitdata *jd, instruction *iptr, s4 htmpreg, s4 ltmpreg, s4 breg) {
        codegendata *cd;
-
-       /* get required compiler data */
+       s4           hr, lr;
+       varinfo     *dst;
+
+       /* (r0, r1)    
+        * (r2, r3)
+        * (r4, r5)
+        * (r6, r7)
+        * (r8, r9)
+        * (r10, r11)
+        * (r12, r13) Illegal, because r13 is PV
+        * (r14, r15) Illegal, because r15 is SP
+        */
 
        cd = jd->cd;
+       dst = VAROP(iptr->dst);
 
-       v_s1  = VAROP(iptr->s1);
-       v_s2  = VAROP(iptr->sx.s23.s2);
-       v_dst = VAROP(iptr->dst);
-
-       s1 = v_s1->vv.regoff;
-       s2 = v_s2->vv.regoff;
-       d  = v_dst->vv.regoff;
-       
-       M_INTMOVE(RCX, REG_ITMP1);                                    /* save RCX */
-
-       if (IS_INMEMORY(v_dst->flags)) {
-               if (IS_INMEMORY(v_s2->flags) && IS_INMEMORY(v_s1->flags)) {
-                       if (s1 == d) {
-                               M_ILD(RCX, REG_SP, s2 * 8);
-                               emit_shift_membase(cd, shift_op, REG_SP, d * 8);
-
-                       } else {
-                               M_ILD(RCX, REG_SP, s2 * 8);
-                               M_LLD(REG_ITMP2, REG_SP, s1 * 8);
-                               emit_shift_reg(cd, shift_op, REG_ITMP2);
-                               M_LST(REG_ITMP2, REG_SP, d * 8);
+       if (IS_INMEMORY(dst->flags)) {
+               if (! IS_REG_ITMP(ltmpreg)) {
+                       M_INTMOVE(ltmpreg, breg);
+               }
+               if (! IS_REG_ITMP(htmpreg)) {
+                       M_INTMOVE(htmpreg, breg);
+               }
+               return PACK_REGS(ltmpreg, htmpreg);
+       } else {
+               hr = GET_HIGH_REG(dst->vv.regoff);
+               lr = GET_LOW_REG(dst->vv.regoff);
+               if (((hr % 2) == 0) && lr == (hr + 1)) {
+                       /* the result is already in a even-odd pair */
+                       return dst->vv.regoff;                  
+               } else if (((hr % 2) == 0) && (hr < R12)) {
+                       /* the high register is at a even position */
+                       M_INTMOVE(hr + 1, breg);
+                       return PACK_REGS(hr + 1, hr);
+               } else if (((lr % 2) == 1) && (lr < R12)) {
+                       /* the low register is at a odd position */
+                       M_INTMOVE(lr - 1, breg);
+                       return PACK_REGS(lr, lr - 1);
+               } else {
+                       /* no way to create an even-odd pair by 1 copy operation,
+                        * Use the temporary register pair.
+                        */
+                       if (! IS_REG_ITMP(ltmpreg)) {
+                               M_INTMOVE(ltmpreg, breg);
                        }
-
-               } else if (IS_INMEMORY(v_s2->flags) && !IS_INMEMORY(v_s1->flags)) {
-                       /* s1 may be equal to RCX */
-                       if (s1 == RCX) {
-                               if (s2 == d) {
-                                       M_ILD(REG_ITMP1, REG_SP, s2 * 8);
-                                       M_LST(s1, REG_SP, d * 8);
-                                       M_INTMOVE(REG_ITMP1, RCX);
-
-                               } else {
-                                       M_LST(s1, REG_SP, d * 8);
-                                       M_ILD(RCX, REG_SP, s2 * 8);
-                               }
-
-                       } else {
-                               M_ILD(RCX, REG_SP, s2 * 8);
-                               M_LST(s1, REG_SP, d * 8);
+                       if (! IS_REG_ITMP(htmpreg)) {
+                               M_INTMOVE(htmpreg, breg);
                        }
+                       return PACK_REGS(ltmpreg, htmpreg);
+               }
+       }
+}
 
-                       emit_shift_membase(cd, shift_op, REG_SP, d * 8);
-
-               } else if (!IS_INMEMORY(v_s2->flags) && IS_INMEMORY(v_s1->flags)) {
-                       if (s1 == d) {
-                               M_INTMOVE(s2, RCX);
-                               emit_shift_membase(cd, shift_op, REG_SP, d * 8);
+void emit_restore_dst_even_odd(jitdata *jd, instruction *iptr, s4 htmpreg, s4 ltmpreg, s4 breg) {
+       codegendata *cd;
+       s4           hr, lr;
+       varinfo     *dst;
 
-                       } else {
-                               M_INTMOVE(s2, RCX);
-                               M_LLD(REG_ITMP2, REG_SP, s1 * 8);
-                               emit_shift_reg(cd, shift_op, REG_ITMP2);
-                               M_LST(REG_ITMP2, REG_SP, d * 8);
-                       }
+       cd = jd->cd;
+       dst = VAROP(iptr->dst);
 
-               } else {
-                       /* s1 may be equal to RCX */
-                       M_LST(s1, REG_SP, d * 8);
-                       M_INTMOVE(s2, RCX);
-                       emit_shift_membase(cd, shift_op, REG_SP, d * 8);
+       if (IS_INMEMORY(dst->flags)) {
+               if (! IS_REG_ITMP(ltmpreg)) {
+                       M_INTMOVE(breg, ltmpreg);
                }
-
-               M_INTMOVE(REG_ITMP1, RCX);                             /* restore RCX */
-
-       } else {
-               d_old = d;
-               if (d == RCX) {
-                       d = REG_ITMP3;
+               if (! IS_REG_ITMP(htmpreg)) {
+                       M_INTMOVE(breg, htmpreg);
                }
-
-               if (IS_INMEMORY(v_s2->flags) && IS_INMEMORY(v_s1->flags)) {
-                       M_ILD(RCX, REG_SP, s2 * 8);
-                       M_LLD(d, REG_SP, s1 * 8);
-                       emit_shift_reg(cd, shift_op, d);
-
-               } else if (IS_INMEMORY(v_s2->flags) && !IS_INMEMORY(v_s1->flags)) {
-                       /* s1 may be equal to RCX */
-                       M_INTMOVE(s1, d);
-                       M_ILD(RCX, REG_SP, s2 * 8);
-                       emit_shift_reg(cd, shift_op, d);
-
-               } else if (!IS_INMEMORY(v_s2->flags) && IS_INMEMORY(v_s1->flags)) {
-                       M_INTMOVE(s2, RCX);
-                       M_LLD(d, REG_SP, s1 * 8);
-                       emit_shift_reg(cd, shift_op, d);
-
+       } else {
+               hr = GET_HIGH_REG(dst->vv.regoff);
+               lr = GET_LOW_REG(dst->vv.regoff);
+               if (((hr % 2) == 0) && lr == (hr + 1)) {
+                       return;
+               } else if (((hr % 2) == 0) && (hr < R12)) {
+                       M_INTMOVE(breg, hr + 1);
+               } else if (((lr % 2) == 1) && (lr < R12)) {
+                       M_INTMOVE(breg, lr - 1);
                } else {
-                       /* s1 may be equal to RCX */
-                       if (s1 == RCX) {
-                               if (s2 == d) {
-                                       /* d cannot be used to backup s1 since this would
-                                          overwrite s2. */
-                                       M_INTMOVE(s1, REG_ITMP3);
-                                       M_INTMOVE(s2, RCX);
-                                       M_INTMOVE(REG_ITMP3, d);
-
-                               } else {
-                                       M_INTMOVE(s1, d);
-                                       M_INTMOVE(s2, RCX);
-                               }
-
-                       } else {
-                               /* d may be equal to s2 */
-                               M_INTMOVE(s2, RCX);
-                               M_INTMOVE(s1, d);
+                       if (! IS_REG_ITMP(ltmpreg)) {
+                               M_INTMOVE(breg, ltmpreg);
+                       }
+                       if (! IS_REG_ITMP(htmpreg)) {
+                               M_INTMOVE(breg, htmpreg);
                        }
-                       emit_shift_reg(cd, shift_op, d);
                }
-
-               if (d_old == RCX)
-                       M_INTMOVE(REG_ITMP3, RCX);
-               else
-                       M_INTMOVE(REG_ITMP1, RCX);                         /* restore RCX */
        }
 }
 
-
-/* low-level code emitter functions *******************************************/
-
-void emit_mov_reg_reg(codegendata *cd, s8 reg, s8 dreg)
-{
-       emit_rex(1,(reg),0,(dreg));
-       *(cd->mcodeptr++) = 0x89;
-       emit_reg((reg),(dreg));
-}
-
-
-void emit_mov_imm_reg(codegendata *cd, s8 imm, s8 reg)
-{
-       emit_rex(1,0,0,(reg));
-       *(cd->mcodeptr++) = 0xb8 + ((reg) & 0x07);
-       emit_imm64((imm));
-}
-
-
-void emit_movl_reg_reg(codegendata *cd, s8 reg, s8 dreg)
-{
-       emit_rex(0,(reg),0,(dreg));
-       *(cd->mcodeptr++) = 0x89;
-       emit_reg((reg),(dreg));
-}
-
-
-void emit_movl_imm_reg(codegendata *cd, s8 imm, s8 reg) {
-       emit_rex(0,0,0,(reg));
-       *(cd->mcodeptr++) = 0xb8 + ((reg) & 0x07);
-       emit_imm32((imm));
-}
-
-
-void emit_mov_membase_reg(codegendata *cd, s8 basereg, s8 disp, s8 reg) {
-       emit_rex(1,(reg),0,(basereg));
-       *(cd->mcodeptr++) = 0x8b;
-       emit_membase(cd, (basereg),(disp),(reg));
-}
-
-
-/*
- * this one is for INVOKEVIRTUAL/INVOKEINTERFACE to have a
- * constant membase immediate length of 32bit
- */
-void emit_mov_membase32_reg(codegendata *cd, s8 basereg, s8 disp, s8 reg) {
-       emit_rex(1,(reg),0,(basereg));
-       *(cd->mcodeptr++) = 0x8b;
-       emit_membase32(cd, (basereg),(disp),(reg));
-}
-
-
-void emit_movl_membase_reg(codegendata *cd, s8 basereg, s8 disp, s8 reg)
-{
-       emit_rex(0,(reg),0,(basereg));
-       *(cd->mcodeptr++) = 0x8b;
-       emit_membase(cd, (basereg),(disp),(reg));
-}
-
-
-/* ATTENTION: Always emit a REX byte, because the instruction size can
-   be smaller when all register indexes are smaller than 7. */
-void emit_movl_membase32_reg(codegendata *cd, s8 basereg, s8 disp, s8 reg)
-{
-       emit_byte_rex((reg),0,(basereg));
-       *(cd->mcodeptr++) = 0x8b;
-       emit_membase32(cd, (basereg),(disp),(reg));
-}
-
-
-void emit_mov_reg_membase(codegendata *cd, s8 reg, s8 basereg, s8 disp) {
-       emit_rex(1,(reg),0,(basereg));
-       *(cd->mcodeptr++) = 0x89;
-       emit_membase(cd, (basereg),(disp),(reg));
-}
-
-
-void emit_mov_reg_membase32(codegendata *cd, s8 reg, s8 basereg, s8 disp) {
-       emit_rex(1,(reg),0,(basereg));
-       *(cd->mcodeptr++) = 0x89;
-       emit_membase32(cd, (basereg),(disp),(reg));
-}
-
-
-void emit_movl_reg_membase(codegendata *cd, s8 reg, s8 basereg, s8 disp) {
-       emit_rex(0,(reg),0,(basereg));
-       *(cd->mcodeptr++) = 0x89;
-       emit_membase(cd, (basereg),(disp),(reg));
-}
-
-
-/* Always emit a REX byte, because the instruction size can be smaller when   */
-/* all register indexes are smaller than 7.                                   */
-void emit_movl_reg_membase32(codegendata *cd, s8 reg, s8 basereg, s8 disp) {
-       emit_byte_rex((reg),0,(basereg));
-       *(cd->mcodeptr++) = 0x89;
-       emit_membase32(cd, (basereg),(disp),(reg));
-}
-
-
-void emit_mov_memindex_reg(codegendata *cd, s8 disp, s8 basereg, s8 indexreg, s8 scale, s8 reg) {
-       emit_rex(1,(reg),(indexreg),(basereg));
-       *(cd->mcodeptr++) = 0x8b;
-       emit_memindex(cd, (reg),(disp),(basereg),(indexreg),(scale));
-}
-
-
-void emit_movl_memindex_reg(codegendata *cd, s8 disp, s8 basereg, s8 indexreg, s8 scale, s8 reg) {
-       emit_rex(0,(reg),(indexreg),(basereg));
-       *(cd->mcodeptr++) = 0x8b;
-       emit_memindex(cd, (reg),(disp),(basereg),(indexreg),(scale));
-}
-
-
-void emit_mov_reg_memindex(codegendata *cd, s8 reg, s8 disp, s8 basereg, s8 indexreg, s8 scale) {
-       emit_rex(1,(reg),(indexreg),(basereg));
-       *(cd->mcodeptr++) = 0x89;
-       emit_memindex(cd, (reg),(disp),(basereg),(indexreg),(scale));
-}
-
-
-void emit_movl_reg_memindex(codegendata *cd, s8 reg, s8 disp, s8 basereg, s8 indexreg, s8 scale) {
-       emit_rex(0,(reg),(indexreg),(basereg));
-       *(cd->mcodeptr++) = 0x89;
-       emit_memindex(cd, (reg),(disp),(basereg),(indexreg),(scale));
-}
-
-
-void emit_movw_reg_memindex(codegendata *cd, s8 reg, s8 disp, s8 basereg, s8 indexreg, s8 scale) {
-       *(cd->mcodeptr++) = 0x66;
-       emit_rex(0,(reg),(indexreg),(basereg));
-       *(cd->mcodeptr++) = 0x89;
-       emit_memindex(cd, (reg),(disp),(basereg),(indexreg),(scale));
-}
-
-
-void emit_movb_reg_memindex(codegendata *cd, s8 reg, s8 disp, s8 basereg, s8 indexreg, s8 scale) {
-       emit_byte_rex((reg),(indexreg),(basereg));
-       *(cd->mcodeptr++) = 0x88;
-       emit_memindex(cd, (reg),(disp),(basereg),(indexreg),(scale));
-}
-
-
-void emit_mov_imm_membase(codegendata *cd, s8 imm, s8 basereg, s8 disp) {
-       emit_rex(1,0,0,(basereg));
-       *(cd->mcodeptr++) = 0xc7;
-       emit_membase(cd, (basereg),(disp),0);
-       emit_imm32((imm));
-}
-
-
-void emit_mov_imm_membase32(codegendata *cd, s8 imm, s8 basereg, s8 disp) {
-       emit_rex(1,0,0,(basereg));
-       *(cd->mcodeptr++) = 0xc7;
-       emit_membase32(cd, (basereg),(disp),0);
-       emit_imm32((imm));
-}
-
-
-void emit_movl_imm_membase(codegendata *cd, s8 imm, s8 basereg, s8 disp) {
-       emit_rex(0,0,0,(basereg));
-       *(cd->mcodeptr++) = 0xc7;
-       emit_membase(cd, (basereg),(disp),0);
-       emit_imm32((imm));
-}
-
-
-/* Always emit a REX byte, because the instruction size can be smaller when   */
-/* all register indexes are smaller than 7.                                   */
-void emit_movl_imm_membase32(codegendata *cd, s8 imm, s8 basereg, s8 disp) {
-       emit_byte_rex(0,0,(basereg));
-       *(cd->mcodeptr++) = 0xc7;
-       emit_membase32(cd, (basereg),(disp),0);
-       emit_imm32((imm));
-}
-
-
-void emit_movsbq_reg_reg(codegendata *cd, s8 reg, s8 dreg)
-{
-       emit_rex(1,(dreg),0,(reg));
-       *(cd->mcodeptr++) = 0x0f;
-       *(cd->mcodeptr++) = 0xbe;
-       /* XXX: why do reg and dreg have to be exchanged */
-       emit_reg((dreg),(reg));
-}
-
-
-void emit_movswq_reg_reg(codegendata *cd, s8 reg, s8 dreg)
-{
-       emit_rex(1,(dreg),0,(reg));
-       *(cd->mcodeptr++) = 0x0f;
-       *(cd->mcodeptr++) = 0xbf;
-       /* XXX: why do reg and dreg have to be exchanged */
-       emit_reg((dreg),(reg));
-}
-
-
-void emit_movslq_reg_reg(codegendata *cd, s8 reg, s8 dreg)
-{
-       emit_rex(1,(dreg),0,(reg));
-       *(cd->mcodeptr++) = 0x63;
-       /* XXX: why do reg and dreg have to be exchanged */
-       emit_reg((dreg),(reg));
-}
-
-
-void emit_movzwq_reg_reg(codegendata *cd, s8 reg, s8 dreg)
-{
-       emit_rex(1,(dreg),0,(reg));
-       *(cd->mcodeptr++) = 0x0f;
-       *(cd->mcodeptr++) = 0xb7;
-       /* XXX: why do reg and dreg have to be exchanged */
-       emit_reg((dreg),(reg));
-}
-
-
-void emit_movswq_memindex_reg(codegendata *cd, s8 disp, s8 basereg, s8 indexreg, s8 scale, s8 reg) {
-       emit_rex(1,(reg),(indexreg),(basereg));
-       *(cd->mcodeptr++) = 0x0f;
-       *(cd->mcodeptr++) = 0xbf;
-       emit_memindex(cd, (reg),(disp),(basereg),(indexreg),(scale));
-}
-
-
-void emit_movsbq_memindex_reg(codegendata *cd, s8 disp, s8 basereg, s8 indexreg, s8 scale, s8 reg) {
-       emit_rex(1,(reg),(indexreg),(basereg));
-       *(cd->mcodeptr++) = 0x0f;
-       *(cd->mcodeptr++) = 0xbe;
-       emit_memindex(cd, (reg),(disp),(basereg),(indexreg),(scale));
-}
-
-
-void emit_movzwq_memindex_reg(codegendata *cd, s8 disp, s8 basereg, s8 indexreg, s8 scale, s8 reg) {
-       emit_rex(1,(reg),(indexreg),(basereg));
-       *(cd->mcodeptr++) = 0x0f;
-       *(cd->mcodeptr++) = 0xb7;
-       emit_memindex(cd, (reg),(disp),(basereg),(indexreg),(scale));
-}
-
-
-void emit_mov_imm_memindex(codegendata *cd, s4 imm, s4 disp, s4 basereg, s4 indexreg, s4 scale)
-{
-       emit_rex(1,0,(indexreg),(basereg));
-       *(cd->mcodeptr++) = 0xc7;
-       emit_memindex(cd, 0,(disp),(basereg),(indexreg),(scale));
-       emit_imm32((imm));
-}
-
-
-void emit_movl_imm_memindex(codegendata *cd, s4 imm, s4 disp, s4 basereg, s4 indexreg, s4 scale)
-{
-       emit_rex(0,0,(indexreg),(basereg));
-       *(cd->mcodeptr++) = 0xc7;
-       emit_memindex(cd, 0,(disp),(basereg),(indexreg),(scale));
-       emit_imm32((imm));
+void emit_copy_dst(jitdata *jd, instruction *iptr, s4 dtmpreg) {
+       codegendata *cd;
+       varinfo *dst;
+       cd = jd->cd;
+       dst = VAROP(iptr->dst);
+       if (! IS_INMEMORY(dst->flags)) {
+               if (dst->vv.regoff != dtmpreg) {
+                       if (IS_FLT_DBL_TYPE(dst->type)) {
+                               M_FLTMOVE(dtmpreg, dst->vv.regoff);
+                       } else if (IS_2_WORD_TYPE(dst->type)) {
+                               M_LNGMOVE(dtmpreg, dst->vv.regoff);
+                       } else {
+                               M_INTMOVE(dtmpreg, dst->vv.regoff);
+                       }
+               }
+       }
 }
 
+void emit_branch(codegendata *cd, s4 disp, s4 condition, s4 reg, u4 opt) {
+
+       s4 branchdisp = disp;
+       s4 branchmpc;
+       u1 *ref;
+
+       if (N_VALID_BRANCH(branchdisp)) {
+
+               /* valid displacement */
+
+               switch (condition) {
+                       case BRANCH_EQ:
+                               M_BEQ(branchdisp);
+                               break;
+                       case BRANCH_NE:
+                               M_BNE(branchdisp);
+                               break;
+                       case BRANCH_LT:
+                               M_BLT(branchdisp);
+                               break;
+                       case BRANCH_GE:
+                               M_BGE(branchdisp);
+                               break;
+                       case BRANCH_GT:
+                               M_BGT(branchdisp);
+                               break;
+                       case BRANCH_LE:
+                               M_BLE(branchdisp);
+                               break;
+                       case BRANCH_UNCONDITIONAL:
+                               M_BR(branchdisp);
+                               break;
+                       default:
+                               vm_abort("emit_branch: unknown condition %d", condition);
+               }
+       } else {
 
-void emit_movw_imm_memindex(codegendata *cd, s4 imm, s4 disp, s4 basereg, s4 indexreg, s4 scale)
-{
-       *(cd->mcodeptr++) = 0x66;
-       emit_rex(0,0,(indexreg),(basereg));
-       *(cd->mcodeptr++) = 0xc7;
-       emit_memindex(cd, 0,(disp),(basereg),(indexreg),(scale));
-       emit_imm16((imm));
-}
+               /* If LONGBRANCHES is not set, the flag and the error flag */
 
+               if (!CODEGENDATA_HAS_FLAG_LONGBRANCHES(cd)) {
+                       cd->flags |= (CODEGENDATA_FLAG_ERROR |
+                               CODEGENDATA_FLAG_LONGBRANCHES);
+               }
 
-void emit_movb_imm_memindex(codegendata *cd, s4 imm, s4 disp, s4 basereg, s4 indexreg, s4 scale)
-{
-       emit_rex(0,0,(indexreg),(basereg));
-       *(cd->mcodeptr++) = 0xc6;
-       emit_memindex(cd, 0,(disp),(basereg),(indexreg),(scale));
-       emit_imm8((imm));
-}
+               /* If error flag is set, do nothing. The method has to be recompiled. */
 
+               if (CODEGENDATA_HAS_FLAG_LONGBRANCHES(cd) && CODEGENDATA_HAS_FLAG_ERROR(cd)) {
+                       return;
+               }
 
-/*
- * alu operations
- */
-void emit_alu_reg_reg(codegendata *cd, s8 opc, s8 reg, s8 dreg)
-{
-       emit_rex(1,(reg),0,(dreg));
-       *(cd->mcodeptr++) = (((opc)) << 3) + 1;
-       emit_reg((reg),(dreg));
-}
+               /* Patch the displacement to branch over the actual branch manually
+                * to not get yet more nops.
+                */
+
+               branchmpc = cd->mcodeptr - cd->mcodebase;
+               ref = cd->mcodeptr;
+
+               switch (condition) {
+                       case BRANCH_EQ:
+                               M_BNE(0);
+                               break;
+                       case BRANCH_NE:
+                               M_BEQ(0);
+                               break;
+                       case BRANCH_LT:
+                               M_BGE(0);
+                               break;
+                       case BRANCH_GE:
+                               M_BLT(0);
+                               break;
+                       case BRANCH_GT:
+                               M_BLE(0);
+                               break;
+                       case BRANCH_LE:
+                               M_BGT(0);
+                               break;
+                       case BRANCH_UNCONDITIONAL:
+                               /* fall through, no displacement to patch */
+                               ref = NULL;
+                               break;
+                       default:
+                               vm_abort("emit_branch: unknown condition %d", condition);
+               }
 
+               /* The actual long branch */
 
-void emit_alul_reg_reg(codegendata *cd, s8 opc, s8 reg, s8 dreg)
-{
-       emit_rex(0,(reg),0,(dreg));
-       *(cd->mcodeptr++) = (((opc)) << 3) + 1;
-       emit_reg((reg),(dreg));
-}
+               disp = dseg_add_s4(cd, branchmpc + disp - N_PV_OFFSET);
+               M_ILD_DSEG(REG_ITMP3, disp);
+               M_AADD(REG_PV, REG_ITMP3);
+               M_JMP(RN, REG_ITMP3);
 
+               /* Patch back the displacement */
 
-void emit_alu_reg_membase(codegendata *cd, s8 opc, s8 reg, s8 basereg, s8 disp)
-{
-       emit_rex(1,(reg),0,(basereg));
-       *(cd->mcodeptr++) = (((opc)) << 3) + 1;
-       emit_membase(cd, (basereg),(disp),(reg));
+               if (ref != NULL) {
+                       *(u4 *)ref |= (u4)((cd->mcodeptr - ref) / 2);
+               }
+       }
 }
 
-
-void emit_alul_reg_membase(codegendata *cd, s8 opc, s8 reg, s8 basereg, s8 disp)
-{
-       emit_rex(0,(reg),0,(basereg));
-       *(cd->mcodeptr++) = (((opc)) << 3) + 1;
-       emit_membase(cd, (basereg),(disp),(reg));
+void emit_arithmetic_check(codegendata *cd, instruction *iptr, s4 reg) {
+       if (INSTRUCTION_MUST_CHECK(iptr)) {
+               M_TEST(reg);
+               M_BNE(SZ_BRC + SZ_ILL);
+               M_ILL(EXCEPTION_HARDWARE_ARITHMETIC);
+       }
 }
 
+/* emit_arrayindexoutofbounds_check ********************************************
 
-void emit_alu_membase_reg(codegendata *cd, s8 opc, s8 basereg, s8 disp, s8 reg)
-{
-       emit_rex(1,(reg),0,(basereg));
-       *(cd->mcodeptr++) = (((opc)) << 3) + 3;
-       emit_membase(cd, (basereg),(disp),(reg));
-}
+   Emit a ArrayIndexOutOfBoundsException check.
 
+*******************************************************************************/
 
-void emit_alul_membase_reg(codegendata *cd, s8 opc, s8 basereg, s8 disp, s8 reg)
+void emit_arrayindexoutofbounds_check(codegendata *cd, instruction *iptr, s4 s1, s4 s2)
 {
-       emit_rex(0,(reg),0,(basereg));
-       *(cd->mcodeptr++) = (((opc)) << 3) + 3;
-       emit_membase(cd, (basereg),(disp),(reg));
-}
-
-
-void emit_alu_imm_reg(codegendata *cd, s8 opc, s8 imm, s8 dreg) {
-       if (IS_IMM8(imm)) {
-               emit_rex(1,0,0,(dreg));
-               *(cd->mcodeptr++) = 0x83;
-               emit_reg((opc),(dreg));
-               emit_imm8((imm));
-       } else {
-               emit_rex(1,0,0,(dreg));
-               *(cd->mcodeptr++) = 0x81;
-               emit_reg((opc),(dreg));
-               emit_imm32((imm));
+       if (INSTRUCTION_MUST_CHECK(iptr)) {
+               /* Size is s4, >= 0
+                * Do unsigned comparison to catch negative indexes.
+                */
+               N_CL(s2, OFFSET(java_array_t, size), RN, s1);
+        M_BLT(SZ_BRC + SZ_ILL);
+               M_ILL2(s2, EXCEPTION_HARDWARE_ARRAYINDEXOUTOFBOUNDS);
        }
 }
 
-
-void emit_alu_imm32_reg(codegendata *cd, s8 opc, s8 imm, s8 dreg) {
-       emit_rex(1,0,0,(dreg));
-       *(cd->mcodeptr++) = 0x81;
-       emit_reg((opc),(dreg));
-       emit_imm32((imm));
-}
-
-
-void emit_alul_imm_reg(codegendata *cd, s8 opc, s8 imm, s8 dreg) {
-       if (IS_IMM8(imm)) {
-               emit_rex(0,0,0,(dreg));
-               *(cd->mcodeptr++) = 0x83;
-               emit_reg((opc),(dreg));
-               emit_imm8((imm));
-       } else {
-               emit_rex(0,0,0,(dreg));
-               *(cd->mcodeptr++) = 0x81;
-               emit_reg((opc),(dreg));
-               emit_imm32((imm));
+void emit_classcast_check(codegendata *cd, instruction *iptr, s4 condition, s4 reg, s4 s1) {
+       if (INSTRUCTION_MUST_CHECK(iptr)) {
+               if (reg != RN) {
+                       M_TEST(reg);
+               }
+               switch (condition) {
+                       case BRANCH_LE:
+                               M_BGT(SZ_BRC + SZ_ILL);
+                               break;
+                       case BRANCH_EQ:
+                               M_BNE(SZ_BRC + SZ_ILL);
+                               break;
+                       case BRANCH_GT:
+                               M_BLE(SZ_BRC + SZ_ILL);
+                               break;
+                       default:
+                               vm_abort("emit_classcast_check: unknown condition %d", condition);
+               }
+               M_ILL2(s1, EXCEPTION_HARDWARE_CLASSCAST);
        }
 }
 
-
-void emit_alu_imm_membase(codegendata *cd, s8 opc, s8 imm, s8 basereg, s8 disp) {
-       if (IS_IMM8(imm)) {
-               emit_rex(1,(basereg),0,0);
-               *(cd->mcodeptr++) = 0x83;
-               emit_membase(cd, (basereg),(disp),(opc));
-               emit_imm8((imm));
-       } else {
-               emit_rex(1,(basereg),0,0);
-               *(cd->mcodeptr++) = 0x81;
-               emit_membase(cd, (basereg),(disp),(opc));
-               emit_imm32((imm));
+void emit_nullpointer_check(codegendata *cd, instruction *iptr, s4 reg) {
+       if (INSTRUCTION_MUST_CHECK(iptr)) {
+               M_TEST(reg);
+               M_BNE(SZ_BRC + SZ_ILL);
+               M_ILL(EXCEPTION_HARDWARE_NULLPOINTER);
        }
 }
 
-
-void emit_alul_imm_membase(codegendata *cd, s8 opc, s8 imm, s8 basereg, s8 disp) {
-       if (IS_IMM8(imm)) {
-               emit_rex(0,(basereg),0,0);
-               *(cd->mcodeptr++) = 0x83;
-               emit_membase(cd, (basereg),(disp),(opc));
-               emit_imm8((imm));
-       } else {
-               emit_rex(0,(basereg),0,0);
-               *(cd->mcodeptr++) = 0x81;
-               emit_membase(cd, (basereg),(disp),(opc));
-               emit_imm32((imm));
+void emit_exception_check(codegendata *cd, instruction *iptr) {
+       if (INSTRUCTION_MUST_CHECK(iptr)) {
+               M_TEST(REG_RESULT);
+               M_BNE(SZ_BRC + SZ_ILL);
+               M_ILL(EXCEPTION_HARDWARE_EXCEPTION);
        }
 }
 
+void emit_restore_pv(codegendata *cd) {
+       s4 offset, offset_imm;
 
-void emit_test_reg_reg(codegendata *cd, s8 reg, s8 dreg) {
-       emit_rex(1,(reg),0,(dreg));
-       *(cd->mcodeptr++) = 0x85;
-       emit_reg((reg),(dreg));
-}
-
-
-void emit_testl_reg_reg(codegendata *cd, s8 reg, s8 dreg) {
-       emit_rex(0,(reg),0,(dreg));
-       *(cd->mcodeptr++) = 0x85;
-       emit_reg((reg),(dreg));
-}
-
-
-void emit_test_imm_reg(codegendata *cd, s8 imm, s8 reg) {
-       *(cd->mcodeptr++) = 0xf7;
-       emit_reg(0,(reg));
-       emit_imm32((imm));
-}
-
-
-void emit_testw_imm_reg(codegendata *cd, s8 imm, s8 reg) {
-       *(cd->mcodeptr++) = 0x66;
-       *(cd->mcodeptr++) = 0xf7;
-       emit_reg(0,(reg));
-       emit_imm16((imm));
-}
-
-
-void emit_testb_imm_reg(codegendata *cd, s8 imm, s8 reg) {
-       *(cd->mcodeptr++) = 0xf6;
-       emit_reg(0,(reg));
-       emit_imm8((imm));
-}
-
-
-void emit_lea_membase_reg(codegendata *cd, s8 basereg, s8 disp, s8 reg) {
-       emit_rex(1,(reg),0,(basereg));
-       *(cd->mcodeptr++) = 0x8d;
-       emit_membase(cd, (basereg),(disp),(reg));
-}
-
-
-void emit_leal_membase_reg(codegendata *cd, s8 basereg, s8 disp, s8 reg) {
-       emit_rex(0,(reg),0,(basereg));
-       *(cd->mcodeptr++) = 0x8d;
-       emit_membase(cd, (basereg),(disp),(reg));
-}
-
-
-
-void emit_incl_membase(codegendata *cd, s8 basereg, s8 disp)
-{
-       emit_rex(0,0,0,(basereg));
-       *(cd->mcodeptr++) = 0xff;
-       emit_membase(cd, (basereg),(disp),0);
-}
+       /*
+       N_BASR(REG_PV, RN);
+       disp = (s4) (cd->mcodeptr - cd->mcodebase);
+       M_ASUB_IMM32(disp, REG_ITMP1, REG_PV);
+       */
 
+       /* If the offset from the method start does not fit into an immediate
+        * value, we can't put it into the data segment!
+        */
 
+       /* Displacement from start of method to here */
 
-void emit_cltd(codegendata *cd) {
-    *(cd->mcodeptr++) = 0x99;
-}
-
+       offset = (s4) (cd->mcodeptr - cd->mcodebase);
+       offset_imm = -offset - SZ_BASR + N_PV_OFFSET;
 
-void emit_cqto(codegendata *cd) {
-       emit_rex(1,0,0,0);
-       *(cd->mcodeptr++) = 0x99;
+       if (N_VALID_IMM(offset_imm)) {
+               /* Get program counter */
+               N_BASR(REG_PV, RN);
+               /* Substract displacement */
+               M_AADD_IMM(offset_imm, REG_PV);
+       } else {
+               /* Save program counter and jump over displacement in instruction flow */
+               N_BRAS(REG_PV, SZ_BRAS + SZ_LONG);
+               /* Place displacement here */
+               /* REG_PV points now exactly to this position */
+               N_LONG(-offset - SZ_BRAS + N_PV_OFFSET);
+               /* Substract *(REG_PV) from REG_PV */
+               N_A(REG_PV, 0, RN, REG_PV);
+       }
 }
 
-
-
-void emit_imul_reg_reg(codegendata *cd, s8 reg, s8 dreg) {
-       emit_rex(1,(dreg),0,(reg));
-       *(cd->mcodeptr++) = 0x0f;
-       *(cd->mcodeptr++) = 0xaf;
-       emit_reg((dreg),(reg));
-}
-
-
-void emit_imull_reg_reg(codegendata *cd, s8 reg, s8 dreg) {
-       emit_rex(0,(dreg),0,(reg));
-       *(cd->mcodeptr++) = 0x0f;
-       *(cd->mcodeptr++) = 0xaf;
-       emit_reg((dreg),(reg));
-}
-
-
-void emit_imul_membase_reg(codegendata *cd, s8 basereg, s8 disp, s8 dreg) {
-       emit_rex(1,(dreg),0,(basereg));
-       *(cd->mcodeptr++) = 0x0f;
-       *(cd->mcodeptr++) = 0xaf;
-       emit_membase(cd, (basereg),(disp),(dreg));
-}
-
-
-void emit_imull_membase_reg(codegendata *cd, s8 basereg, s8 disp, s8 dreg) {
-       emit_rex(0,(dreg),0,(basereg));
-       *(cd->mcodeptr++) = 0x0f;
-       *(cd->mcodeptr++) = 0xaf;
-       emit_membase(cd, (basereg),(disp),(dreg));
-}
-
-
-void emit_imul_imm_reg(codegendata *cd, s8 imm, s8 dreg) {
-       if (IS_IMM8((imm))) {
-               emit_rex(1,0,0,(dreg));
-               *(cd->mcodeptr++) = 0x6b;
-               emit_reg(0,(dreg));
-               emit_imm8((imm));
-       } else {
-               emit_rex(1,0,0,(dreg));
-               *(cd->mcodeptr++) = 0x69;
-               emit_reg(0,(dreg));
-               emit_imm32((imm));
-       }
-}
-
-
-void emit_imul_imm_reg_reg(codegendata *cd, s8 imm, s8 reg, s8 dreg) {
-       if (IS_IMM8((imm))) {
-               emit_rex(1,(dreg),0,(reg));
-               *(cd->mcodeptr++) = 0x6b;
-               emit_reg((dreg),(reg));
-               emit_imm8((imm));
-       } else {
-               emit_rex(1,(dreg),0,(reg));
-               *(cd->mcodeptr++) = 0x69;
-               emit_reg((dreg),(reg));
-               emit_imm32((imm));
-       }
-}
-
-
-void emit_imull_imm_reg_reg(codegendata *cd, s8 imm, s8 reg, s8 dreg) {
-       if (IS_IMM8((imm))) {
-               emit_rex(0,(dreg),0,(reg));
-               *(cd->mcodeptr++) = 0x6b;
-               emit_reg((dreg),(reg));
-               emit_imm8((imm));
-       } else {
-               emit_rex(0,(dreg),0,(reg));
-               *(cd->mcodeptr++) = 0x69;
-               emit_reg((dreg),(reg));
-               emit_imm32((imm));
-       }
-}
-
-
-void emit_imul_imm_membase_reg(codegendata *cd, s8 imm, s8 basereg, s8 disp, s8 dreg) {
-       if (IS_IMM8((imm))) {
-               emit_rex(1,(dreg),0,(basereg));
-               *(cd->mcodeptr++) = 0x6b;
-               emit_membase(cd, (basereg),(disp),(dreg));
-               emit_imm8((imm));
-       } else {
-               emit_rex(1,(dreg),0,(basereg));
-               *(cd->mcodeptr++) = 0x69;
-               emit_membase(cd, (basereg),(disp),(dreg));
-               emit_imm32((imm));
-       }
-}
-
-
-void emit_imull_imm_membase_reg(codegendata *cd, s8 imm, s8 basereg, s8 disp, s8 dreg) {
-       if (IS_IMM8((imm))) {
-               emit_rex(0,(dreg),0,(basereg));
-               *(cd->mcodeptr++) = 0x6b;
-               emit_membase(cd, (basereg),(disp),(dreg));
-               emit_imm8((imm));
-       } else {
-               emit_rex(0,(dreg),0,(basereg));
-               *(cd->mcodeptr++) = 0x69;
-               emit_membase(cd, (basereg),(disp),(dreg));
-               emit_imm32((imm));
-       }
-}
-
-
-void emit_idiv_reg(codegendata *cd, s8 reg) {
-       emit_rex(1,0,0,(reg));
-       *(cd->mcodeptr++) = 0xf7;
-       emit_reg(7,(reg));
-}
-
-
-void emit_idivl_reg(codegendata *cd, s8 reg) {
-       emit_rex(0,0,0,(reg));
-       *(cd->mcodeptr++) = 0xf7;
-       emit_reg(7,(reg));
-}
-
-
-
-void emit_ret(codegendata *cd) {
-    *(cd->mcodeptr++) = 0xc3;
-}
-
-
-
-/*
- * shift ops
- */
-void emit_shift_reg(codegendata *cd, s8 opc, s8 reg) {
-       emit_rex(1,0,0,(reg));
-       *(cd->mcodeptr++) = 0xd3;
-       emit_reg((opc),(reg));
-}
-
-
-void emit_shiftl_reg(codegendata *cd, s8 opc, s8 reg) {
-       emit_rex(0,0,0,(reg));
-       *(cd->mcodeptr++) = 0xd3;
-       emit_reg((opc),(reg));
-}
-
-
-void emit_shift_membase(codegendata *cd, s8 opc, s8 basereg, s8 disp) {
-       emit_rex(1,0,0,(basereg));
-       *(cd->mcodeptr++) = 0xd3;
-       emit_membase(cd, (basereg),(disp),(opc));
-}
-
-
-void emit_shiftl_membase(codegendata *cd, s8 opc, s8 basereg, s8 disp) {
-       emit_rex(0,0,0,(basereg));
-       *(cd->mcodeptr++) = 0xd3;
-       emit_membase(cd, (basereg),(disp),(opc));
-}
-
-
-void emit_shift_imm_reg(codegendata *cd, s8 opc, s8 imm, s8 dreg) {
-       if ((imm) == 1) {
-               emit_rex(1,0,0,(dreg));
-               *(cd->mcodeptr++) = 0xd1;
-               emit_reg((opc),(dreg));
-       } else {
-               emit_rex(1,0,0,(dreg));
-               *(cd->mcodeptr++) = 0xc1;
-               emit_reg((opc),(dreg));
-               emit_imm8((imm));
-       }
-}
-
-
-void emit_shiftl_imm_reg(codegendata *cd, s8 opc, s8 imm, s8 dreg) {
-       if ((imm) == 1) {
-               emit_rex(0,0,0,(dreg));
-               *(cd->mcodeptr++) = 0xd1;
-               emit_reg((opc),(dreg));
-       } else {
-               emit_rex(0,0,0,(dreg));
-               *(cd->mcodeptr++) = 0xc1;
-               emit_reg((opc),(dreg));
-               emit_imm8((imm));
-       }
-}
-
-
-void emit_shift_imm_membase(codegendata *cd, s8 opc, s8 imm, s8 basereg, s8 disp) {
-       if ((imm) == 1) {
-               emit_rex(1,0,0,(basereg));
-               *(cd->mcodeptr++) = 0xd1;
-               emit_membase(cd, (basereg),(disp),(opc));
-       } else {
-               emit_rex(1,0,0,(basereg));
-               *(cd->mcodeptr++) = 0xc1;
-               emit_membase(cd, (basereg),(disp),(opc));
-               emit_imm8((imm));
-       }
-}
-
-
-void emit_shiftl_imm_membase(codegendata *cd, s8 opc, s8 imm, s8 basereg, s8 disp) {
-       if ((imm) == 1) {
-               emit_rex(0,0,0,(basereg));
-               *(cd->mcodeptr++) = 0xd1;
-               emit_membase(cd, (basereg),(disp),(opc));
-       } else {
-               emit_rex(0,0,0,(basereg));
-               *(cd->mcodeptr++) = 0xc1;
-               emit_membase(cd, (basereg),(disp),(opc));
-               emit_imm8((imm));
-       }
-}
-
-
-
-/*
- * jump operations
- */
-void emit_jmp_imm(codegendata *cd, s8 imm) {
-       *(cd->mcodeptr++) = 0xe9;
-       emit_imm32((imm));
-}
-
-
-void emit_jmp_reg(codegendata *cd, s8 reg) {
-       emit_rex(0,0,0,(reg));
-       *(cd->mcodeptr++) = 0xff;
-       emit_reg(4,(reg));
-}
-
-
-void emit_jcc(codegendata *cd, s8 opc, s8 imm) {
-       *(cd->mcodeptr++) = 0x0f;
-       *(cd->mcodeptr++) = (0x80 + (opc));
-       emit_imm32((imm));
-}
-
-
-
-/*
- * conditional set and move operations
- */
-
-/* we need the rex byte to get all low bytes */
-void emit_setcc_reg(codegendata *cd, s8 opc, s8 reg) {
-       *(cd->mcodeptr++) = (0x40 | (((reg) >> 3) & 0x01));
-       *(cd->mcodeptr++) = 0x0f;
-       *(cd->mcodeptr++) = (0x90 + (opc));
-       emit_reg(0,(reg));
-}
-
-
-/* we need the rex byte to get all low bytes */
-void emit_setcc_membase(codegendata *cd, s8 opc, s8 basereg, s8 disp) {
-       *(cd->mcodeptr++) = (0x40 | (((basereg) >> 3) & 0x01));
-       *(cd->mcodeptr++) = 0x0f;
-       *(cd->mcodeptr++) = (0x90 + (opc));
-       emit_membase(cd, (basereg),(disp),0);
-}
-
-
-void emit_cmovcc_reg_reg(codegendata *cd, s8 opc, s8 reg, s8 dreg)
-{
-       emit_rex(1,(dreg),0,(reg));
-       *(cd->mcodeptr++) = 0x0f;
-       *(cd->mcodeptr++) = (0x40 + (opc));
-       emit_reg((dreg),(reg));
-}
-
-
-void emit_cmovccl_reg_reg(codegendata *cd, s8 opc, s8 reg, s8 dreg)
-{
-       emit_rex(0,(dreg),0,(reg));
-       *(cd->mcodeptr++) = 0x0f;
-       *(cd->mcodeptr++) = (0x40 + (opc));
-       emit_reg((dreg),(reg));
-}
-
-
-
-void emit_neg_reg(codegendata *cd, s8 reg)
-{
-       emit_rex(1,0,0,(reg));
-       *(cd->mcodeptr++) = 0xf7;
-       emit_reg(3,(reg));
-}
-
-
-void emit_negl_reg(codegendata *cd, s8 reg)
-{
-       emit_rex(0,0,0,(reg));
-       *(cd->mcodeptr++) = 0xf7;
-       emit_reg(3,(reg));
-}
-
-
-void emit_push_reg(codegendata *cd, s8 reg) {
-       emit_rex(0,0,0,(reg));
-       *(cd->mcodeptr++) = 0x50 + (0x07 & (reg));
-}
-
-
-void emit_push_imm(codegendata *cd, s8 imm) {
-       *(cd->mcodeptr++) = 0x68;
-       emit_imm32((imm));
-}
-
-
-void emit_pop_reg(codegendata *cd, s8 reg) {
-       emit_rex(0,0,0,(reg));
-       *(cd->mcodeptr++) = 0x58 + (0x07 & (reg));
-}
-
-
-void emit_xchg_reg_reg(codegendata *cd, s8 reg, s8 dreg) {
-       emit_rex(1,(reg),0,(dreg));
-       *(cd->mcodeptr++) = 0x87;
-       emit_reg((reg),(dreg));
-}
-
-
-void emit_nop(codegendata *cd) {
-    *(cd->mcodeptr++) = 0x90;
-}
-
-
-
-/*
- * call instructions
- */
-void emit_call_reg(codegendata *cd, s8 reg) {
-       emit_rex(1,0,0,(reg));
-       *(cd->mcodeptr++) = 0xff;
-       emit_reg(2,(reg));
-}
-
-
-void emit_call_imm(codegendata *cd, s8 imm) {
-       *(cd->mcodeptr++) = 0xe8;
-       emit_imm32((imm));
-}
-
-
-void emit_call_mem(codegendata *cd, ptrint mem)
-{
-       *(cd->mcodeptr++) = 0xff;
-       emit_mem(2,(mem));
-}
-
-
-
-/*
- * floating point instructions (SSE2)
- */
-void emit_addsd_reg_reg(codegendata *cd, s8 reg, s8 dreg) {
-       *(cd->mcodeptr++) = 0xf2;
-       emit_rex(0,(dreg),0,(reg));
-       *(cd->mcodeptr++) = 0x0f;
-       *(cd->mcodeptr++) = 0x58;
-       emit_reg((dreg),(reg));
-}
-
-
-void emit_addss_reg_reg(codegendata *cd, s8 reg, s8 dreg) {
-       *(cd->mcodeptr++) = 0xf3;
-       emit_rex(0,(dreg),0,(reg));
-       *(cd->mcodeptr++) = 0x0f;
-       *(cd->mcodeptr++) = 0x58;
-       emit_reg((dreg),(reg));
-}
-
-
-void emit_cvtsi2ssq_reg_reg(codegendata *cd, s8 reg, s8 dreg) {
-       *(cd->mcodeptr++) = 0xf3;
-       emit_rex(1,(dreg),0,(reg));
-       *(cd->mcodeptr++) = 0x0f;
-       *(cd->mcodeptr++) = 0x2a;
-       emit_reg((dreg),(reg));
-}
-
-
-void emit_cvtsi2ss_reg_reg(codegendata *cd, s8 reg, s8 dreg) {
-       *(cd->mcodeptr++) = 0xf3;
-       emit_rex(0,(dreg),0,(reg));
-       *(cd->mcodeptr++) = 0x0f;
-       *(cd->mcodeptr++) = 0x2a;
-       emit_reg((dreg),(reg));
-}
-
-
-void emit_cvtsi2sdq_reg_reg(codegendata *cd, s8 reg, s8 dreg) {
-       *(cd->mcodeptr++) = 0xf2;
-       emit_rex(1,(dreg),0,(reg));
-       *(cd->mcodeptr++) = 0x0f;
-       *(cd->mcodeptr++) = 0x2a;
-       emit_reg((dreg),(reg));
-}
-
-
-void emit_cvtsi2sd_reg_reg(codegendata *cd, s8 reg, s8 dreg) {
-       *(cd->mcodeptr++) = 0xf2;
-       emit_rex(0,(dreg),0,(reg));
-       *(cd->mcodeptr++) = 0x0f;
-       *(cd->mcodeptr++) = 0x2a;
-       emit_reg((dreg),(reg));
-}
-
-
-void emit_cvtss2sd_reg_reg(codegendata *cd, s8 reg, s8 dreg) {
-       *(cd->mcodeptr++) = 0xf3;
-       emit_rex(0,(dreg),0,(reg));
-       *(cd->mcodeptr++) = 0x0f;
-       *(cd->mcodeptr++) = 0x5a;
-       emit_reg((dreg),(reg));
-}
-
-
-void emit_cvtsd2ss_reg_reg(codegendata *cd, s8 reg, s8 dreg) {
-       *(cd->mcodeptr++) = 0xf2;
-       emit_rex(0,(dreg),0,(reg));
-       *(cd->mcodeptr++) = 0x0f;
-       *(cd->mcodeptr++) = 0x5a;
-       emit_reg((dreg),(reg));
-}
-
-
-void emit_cvttss2siq_reg_reg(codegendata *cd, s8 reg, s8 dreg) {
-       *(cd->mcodeptr++) = 0xf3;
-       emit_rex(1,(dreg),0,(reg));
-       *(cd->mcodeptr++) = 0x0f;
-       *(cd->mcodeptr++) = 0x2c;
-       emit_reg((dreg),(reg));
-}
-
-
-void emit_cvttss2si_reg_reg(codegendata *cd, s8 reg, s8 dreg) {
-       *(cd->mcodeptr++) = 0xf3;
-       emit_rex(0,(dreg),0,(reg));
-       *(cd->mcodeptr++) = 0x0f;
-       *(cd->mcodeptr++) = 0x2c;
-       emit_reg((dreg),(reg));
-}
-
-
-void emit_cvttsd2siq_reg_reg(codegendata *cd, s8 reg, s8 dreg) {
-       *(cd->mcodeptr++) = 0xf2;
-       emit_rex(1,(dreg),0,(reg));
-       *(cd->mcodeptr++) = 0x0f;
-       *(cd->mcodeptr++) = 0x2c;
-       emit_reg((dreg),(reg));
-}
-
-
-void emit_cvttsd2si_reg_reg(codegendata *cd, s8 reg, s8 dreg) {
-       *(cd->mcodeptr++) = 0xf2;
-       emit_rex(0,(dreg),0,(reg));
-       *(cd->mcodeptr++) = 0x0f;
-       *(cd->mcodeptr++) = 0x2c;
-       emit_reg((dreg),(reg));
-}
-
-
-void emit_divss_reg_reg(codegendata *cd, s8 reg, s8 dreg) {
-       *(cd->mcodeptr++) = 0xf3;
-       emit_rex(0,(dreg),0,(reg));
-       *(cd->mcodeptr++) = 0x0f;
-       *(cd->mcodeptr++) = 0x5e;
-       emit_reg((dreg),(reg));
-}
-
-
-void emit_divsd_reg_reg(codegendata *cd, s8 reg, s8 dreg) {
-       *(cd->mcodeptr++) = 0xf2;
-       emit_rex(0,(dreg),0,(reg));
-       *(cd->mcodeptr++) = 0x0f;
-       *(cd->mcodeptr++) = 0x5e;
-       emit_reg((dreg),(reg));
-}
-
-
-void emit_movd_reg_freg(codegendata *cd, s8 reg, s8 freg) {
-       *(cd->mcodeptr++) = 0x66;
-       emit_rex(1,(freg),0,(reg));
-       *(cd->mcodeptr++) = 0x0f;
-       *(cd->mcodeptr++) = 0x6e;
-       emit_reg((freg),(reg));
-}
-
-
-void emit_movd_freg_reg(codegendata *cd, s8 freg, s8 reg) {
-       *(cd->mcodeptr++) = 0x66;
-       emit_rex(1,(freg),0,(reg));
-       *(cd->mcodeptr++) = 0x0f;
-       *(cd->mcodeptr++) = 0x7e;
-       emit_reg((freg),(reg));
-}
-
-
-void emit_movd_reg_membase(codegendata *cd, s8 reg, s8 basereg, s8 disp) {
-       *(cd->mcodeptr++) = 0x66;
-       emit_rex(0,(reg),0,(basereg));
-       *(cd->mcodeptr++) = 0x0f;
-       *(cd->mcodeptr++) = 0x7e;
-       emit_membase(cd, (basereg),(disp),(reg));
-}
-
-
-void emit_movd_reg_memindex(codegendata *cd, s8 reg, s8 disp, s8 basereg, s8 indexreg, s8 scale) {
-       *(cd->mcodeptr++) = 0x66;
-       emit_rex(0,(reg),(indexreg),(basereg));
-       *(cd->mcodeptr++) = 0x0f;
-       *(cd->mcodeptr++) = 0x7e;
-       emit_memindex(cd, (reg),(disp),(basereg),(indexreg),(scale));
-}
-
-
-void emit_movd_membase_reg(codegendata *cd, s8 basereg, s8 disp, s8 dreg) {
-       *(cd->mcodeptr++) = 0x66;
-       emit_rex(1,(dreg),0,(basereg));
-       *(cd->mcodeptr++) = 0x0f;
-       *(cd->mcodeptr++) = 0x6e;
-       emit_membase(cd, (basereg),(disp),(dreg));
-}
-
-
-void emit_movdl_membase_reg(codegendata *cd, s8 basereg, s8 disp, s8 dreg) {
-       *(cd->mcodeptr++) = 0x66;
-       emit_rex(0,(dreg),0,(basereg));
-       *(cd->mcodeptr++) = 0x0f;
-       *(cd->mcodeptr++) = 0x6e;
-       emit_membase(cd, (basereg),(disp),(dreg));
-}
-
-
-void emit_movd_memindex_reg(codegendata *cd, s8 disp, s8 basereg, s8 indexreg, s8 scale, s8 dreg) {
-       *(cd->mcodeptr++) = 0x66;
-       emit_rex(0,(dreg),(indexreg),(basereg));
-       *(cd->mcodeptr++) = 0x0f;
-       *(cd->mcodeptr++) = 0x6e;
-       emit_memindex(cd, (dreg),(disp),(basereg),(indexreg),(scale));
-}
-
-
-void emit_movq_reg_reg(codegendata *cd, s8 reg, s8 dreg) {
-       *(cd->mcodeptr++) = 0xf3;
-       emit_rex(0,(dreg),0,(reg));
-       *(cd->mcodeptr++) = 0x0f;
-       *(cd->mcodeptr++) = 0x7e;
-       emit_reg((dreg),(reg));
-}
-
-
-void emit_movq_reg_membase(codegendata *cd, s8 reg, s8 basereg, s8 disp) {
-       *(cd->mcodeptr++) = 0x66;
-       emit_rex(0,(reg),0,(basereg));
-       *(cd->mcodeptr++) = 0x0f;
-       *(cd->mcodeptr++) = 0xd6;
-       emit_membase(cd, (basereg),(disp),(reg));
-}
-
-
-void emit_movq_membase_reg(codegendata *cd, s8 basereg, s8 disp, s8 dreg) {
-       *(cd->mcodeptr++) = 0xf3;
-       emit_rex(0,(dreg),0,(basereg));
-       *(cd->mcodeptr++) = 0x0f;
-       *(cd->mcodeptr++) = 0x7e;
-       emit_membase(cd, (basereg),(disp),(dreg));
-}
-
-
-void emit_movss_reg_reg(codegendata *cd, s8 reg, s8 dreg) {
-       *(cd->mcodeptr++) = 0xf3;
-       emit_rex(0,(reg),0,(dreg));
-       *(cd->mcodeptr++) = 0x0f;
-       *(cd->mcodeptr++) = 0x10;
-       emit_reg((reg),(dreg));
-}
-
-
-void emit_movsd_reg_reg(codegendata *cd, s8 reg, s8 dreg) {
-       *(cd->mcodeptr++) = 0xf2;
-       emit_rex(0,(reg),0,(dreg));
-       *(cd->mcodeptr++) = 0x0f;
-       *(cd->mcodeptr++) = 0x10;
-       emit_reg((reg),(dreg));
-}
-
-
-void emit_movss_reg_membase(codegendata *cd, s8 reg, s8 basereg, s8 disp) {
-       *(cd->mcodeptr++) = 0xf3;
-       emit_rex(0,(reg),0,(basereg));
-       *(cd->mcodeptr++) = 0x0f;
-       *(cd->mcodeptr++) = 0x11;
-       emit_membase(cd, (basereg),(disp),(reg));
-}
-
-
-/* Always emit a REX byte, because the instruction size can be smaller when   */
-/* all register indexes are smaller than 7.                                   */
-void emit_movss_reg_membase32(codegendata *cd, s8 reg, s8 basereg, s8 disp) {
-       *(cd->mcodeptr++) = 0xf3;
-       emit_byte_rex((reg),0,(basereg));
-       *(cd->mcodeptr++) = 0x0f;
-       *(cd->mcodeptr++) = 0x11;
-       emit_membase32(cd, (basereg),(disp),(reg));
-}
-
-
-void emit_movsd_reg_membase(codegendata *cd, s8 reg, s8 basereg, s8 disp) {
-       *(cd->mcodeptr++) = 0xf2;
-       emit_rex(0,(reg),0,(basereg));
-       *(cd->mcodeptr++) = 0x0f;
-       *(cd->mcodeptr++) = 0x11;
-       emit_membase(cd, (basereg),(disp),(reg));
-}
-
-
-/* Always emit a REX byte, because the instruction size can be smaller when   */
-/* all register indexes are smaller than 7.                                   */
-void emit_movsd_reg_membase32(codegendata *cd, s8 reg, s8 basereg, s8 disp) {
-       *(cd->mcodeptr++) = 0xf2;
-       emit_byte_rex((reg),0,(basereg));
-       *(cd->mcodeptr++) = 0x0f;
-       *(cd->mcodeptr++) = 0x11;
-       emit_membase32(cd, (basereg),(disp),(reg));
-}
-
-
-void emit_movss_membase_reg(codegendata *cd, s8 basereg, s8 disp, s8 dreg) {
-       *(cd->mcodeptr++) = 0xf3;
-       emit_rex(0,(dreg),0,(basereg));
-       *(cd->mcodeptr++) = 0x0f;
-       *(cd->mcodeptr++) = 0x10;
-       emit_membase(cd, (basereg),(disp),(dreg));
-}
-
-
-/* Always emit a REX byte, because the instruction size can be smaller when   */
-/* all register indexes are smaller than 7.                                   */
-void emit_movss_membase32_reg(codegendata *cd, s8 basereg, s8 disp, s8 dreg) {
-       *(cd->mcodeptr++) = 0xf3;
-       emit_byte_rex((dreg),0,(basereg));
-       *(cd->mcodeptr++) = 0x0f;
-       *(cd->mcodeptr++) = 0x10;
-       emit_membase32(cd, (basereg),(disp),(dreg));
-}
-
-
-void emit_movlps_membase_reg(codegendata *cd, s8 basereg, s8 disp, s8 dreg)
-{
-       emit_rex(0,(dreg),0,(basereg));
-       *(cd->mcodeptr++) = 0x0f;
-       *(cd->mcodeptr++) = 0x12;
-       emit_membase(cd, (basereg),(disp),(dreg));
-}
-
-
-void emit_movlps_reg_membase(codegendata *cd, s8 reg, s8 basereg, s8 disp)
-{
-       emit_rex(0,(reg),0,(basereg));
-       *(cd->mcodeptr++) = 0x0f;
-       *(cd->mcodeptr++) = 0x13;
-       emit_membase(cd, (basereg),(disp),(reg));
-}
-
-
-void emit_movsd_membase_reg(codegendata *cd, s8 basereg, s8 disp, s8 dreg) {
-       *(cd->mcodeptr++) = 0xf2;
-       emit_rex(0,(dreg),0,(basereg));
-       *(cd->mcodeptr++) = 0x0f;
-       *(cd->mcodeptr++) = 0x10;
-       emit_membase(cd, (basereg),(disp),(dreg));
-}
-
-
-/* Always emit a REX byte, because the instruction size can be smaller when   */
-/* all register indexes are smaller than 7.                                   */
-void emit_movsd_membase32_reg(codegendata *cd, s8 basereg, s8 disp, s8 dreg) {
-       *(cd->mcodeptr++) = 0xf2;
-       emit_byte_rex((dreg),0,(basereg));
-       *(cd->mcodeptr++) = 0x0f;
-       *(cd->mcodeptr++) = 0x10;
-       emit_membase32(cd, (basereg),(disp),(dreg));
-}
-
-
-void emit_movlpd_membase_reg(codegendata *cd, s8 basereg, s8 disp, s8 dreg)
-{
-       *(cd->mcodeptr++) = 0x66;
-       emit_rex(0,(dreg),0,(basereg));
-       *(cd->mcodeptr++) = 0x0f;
-       *(cd->mcodeptr++) = 0x12;
-       emit_membase(cd, (basereg),(disp),(dreg));
-}
-
-
-void emit_movlpd_reg_membase(codegendata *cd, s8 reg, s8 basereg, s8 disp)
-{
-       *(cd->mcodeptr++) = 0x66;
-       emit_rex(0,(reg),0,(basereg));
-       *(cd->mcodeptr++) = 0x0f;
-       *(cd->mcodeptr++) = 0x13;
-       emit_membase(cd, (basereg),(disp),(reg));
-}
-
-
-void emit_movss_reg_memindex(codegendata *cd, s8 reg, s8 disp, s8 basereg, s8 indexreg, s8 scale) {
-       *(cd->mcodeptr++) = 0xf3;
-       emit_rex(0,(reg),(indexreg),(basereg));
-       *(cd->mcodeptr++) = 0x0f;
-       *(cd->mcodeptr++) = 0x11;
-       emit_memindex(cd, (reg),(disp),(basereg),(indexreg),(scale));
-}
-
-
-void emit_movsd_reg_memindex(codegendata *cd, s8 reg, s8 disp, s8 basereg, s8 indexreg, s8 scale) {
-       *(cd->mcodeptr++) = 0xf2;
-       emit_rex(0,(reg),(indexreg),(basereg));
-       *(cd->mcodeptr++) = 0x0f;
-       *(cd->mcodeptr++) = 0x11;
-       emit_memindex(cd, (reg),(disp),(basereg),(indexreg),(scale));
-}
-
-
-void emit_movss_memindex_reg(codegendata *cd, s8 disp, s8 basereg, s8 indexreg, s8 scale, s8 dreg) {
-       *(cd->mcodeptr++) = 0xf3;
-       emit_rex(0,(dreg),(indexreg),(basereg));
-       *(cd->mcodeptr++) = 0x0f;
-       *(cd->mcodeptr++) = 0x10;
-       emit_memindex(cd, (dreg),(disp),(basereg),(indexreg),(scale));
-}
-
-
-void emit_movsd_memindex_reg(codegendata *cd, s8 disp, s8 basereg, s8 indexreg, s8 scale, s8 dreg) {
-       *(cd->mcodeptr++) = 0xf2;
-       emit_rex(0,(dreg),(indexreg),(basereg));
-       *(cd->mcodeptr++) = 0x0f;
-       *(cd->mcodeptr++) = 0x10;
-       emit_memindex(cd, (dreg),(disp),(basereg),(indexreg),(scale));
-}
-
-
-void emit_mulss_reg_reg(codegendata *cd, s8 reg, s8 dreg) {
-       *(cd->mcodeptr++) = 0xf3;
-       emit_rex(0,(dreg),0,(reg));
-       *(cd->mcodeptr++) = 0x0f;
-       *(cd->mcodeptr++) = 0x59;
-       emit_reg((dreg),(reg));
-}
-
-
-void emit_mulsd_reg_reg(codegendata *cd, s8 reg, s8 dreg) {
-       *(cd->mcodeptr++) = 0xf2;
-       emit_rex(0,(dreg),0,(reg));
-       *(cd->mcodeptr++) = 0x0f;
-       *(cd->mcodeptr++) = 0x59;
-       emit_reg((dreg),(reg));
-}
-
-
-void emit_subss_reg_reg(codegendata *cd, s8 reg, s8 dreg) {
-       *(cd->mcodeptr++) = 0xf3;
-       emit_rex(0,(dreg),0,(reg));
-       *(cd->mcodeptr++) = 0x0f;
-       *(cd->mcodeptr++) = 0x5c;
-       emit_reg((dreg),(reg));
-}
-
-
-void emit_subsd_reg_reg(codegendata *cd, s8 reg, s8 dreg) {
-       *(cd->mcodeptr++) = 0xf2;
-       emit_rex(0,(dreg),0,(reg));
-       *(cd->mcodeptr++) = 0x0f;
-       *(cd->mcodeptr++) = 0x5c;
-       emit_reg((dreg),(reg));
-}
-
-
-void emit_ucomiss_reg_reg(codegendata *cd, s8 reg, s8 dreg) {
-       emit_rex(0,(dreg),0,(reg));
-       *(cd->mcodeptr++) = 0x0f;
-       *(cd->mcodeptr++) = 0x2e;
-       emit_reg((dreg),(reg));
-}
-
-
-void emit_ucomisd_reg_reg(codegendata *cd, s8 reg, s8 dreg) {
-       *(cd->mcodeptr++) = 0x66;
-       emit_rex(0,(dreg),0,(reg));
-       *(cd->mcodeptr++) = 0x0f;
-       *(cd->mcodeptr++) = 0x2e;
-       emit_reg((dreg),(reg));
-}
-
-
-void emit_xorps_reg_reg(codegendata *cd, s8 reg, s8 dreg) {
-       emit_rex(0,(dreg),0,(reg));
-       *(cd->mcodeptr++) = 0x0f;
-       *(cd->mcodeptr++) = 0x57;
-       emit_reg((dreg),(reg));
-}
-
-
-void emit_xorps_membase_reg(codegendata *cd, s8 basereg, s8 disp, s8 dreg) {
-       emit_rex(0,(dreg),0,(basereg));
-       *(cd->mcodeptr++) = 0x0f;
-       *(cd->mcodeptr++) = 0x57;
-       emit_membase(cd, (basereg),(disp),(dreg));
-}
-
-
-void emit_xorpd_reg_reg(codegendata *cd, s8 reg, s8 dreg) {
-       *(cd->mcodeptr++) = 0x66;
-       emit_rex(0,(dreg),0,(reg));
-       *(cd->mcodeptr++) = 0x0f;
-       *(cd->mcodeptr++) = 0x57;
-       emit_reg((dreg),(reg));
-}
-
-
-void emit_xorpd_membase_reg(codegendata *cd, s8 basereg, s8 disp, s8 dreg) {
-       *(cd->mcodeptr++) = 0x66;
-       emit_rex(0,(dreg),0,(basereg));
-       *(cd->mcodeptr++) = 0x0f;
-       *(cd->mcodeptr++) = 0x57;
-       emit_membase(cd, (basereg),(disp),(dreg));
-}
-
-
-/* system instructions ********************************************************/
-
-void emit_rdtsc(codegendata *cd)
-{
-       *(cd->mcodeptr++) = 0x0f;
-       *(cd->mcodeptr++) = 0x31;
-}
-
-/* emit_load_high **************************************************************
-
-   Emits a possible load of the high 32-bits of an operand.
-
-*******************************************************************************/
-
-s4 emit_load_high(jitdata *jd, instruction *iptr, varinfo *src, s4 tempreg)
-{
-       codegendata  *cd;
-       s4            disp;
-       s4            reg;
-
-       assert(src->type == TYPE_LNG);
-
-       /* get required compiler data */
-
-       cd = jd->cd;
-
-       if (IS_INMEMORY(src->flags)) {
-               COUNT_SPILLS;
-
-               disp = src->vv.regoff * 4;
-
-               M_ILD(tempreg, REG_SP, disp);
-
-               reg = tempreg;
-       }
-       else
-               reg = GET_HIGH_REG(src->vv.regoff);
-
-       return reg;
-}
-
-/* emit_load_low ***************************************************************
-
-   Emits a possible load of the low 32-bits of an operand.
-
-*******************************************************************************/
-
-s4 emit_load_low(jitdata *jd, instruction *iptr, varinfo *src, s4 tempreg)
-{
-       codegendata  *cd;
-       s4            disp;
-       s4            reg;
-
-       assert(src->type == TYPE_LNG);
-
-       /* get required compiler data */
-
-       cd = jd->cd;
-
-       if (IS_INMEMORY(src->flags)) {
-               COUNT_SPILLS;
-
-               disp = src->vv.regoff * 4;
-
-               M_ILD(tempreg, REG_SP, disp + 4);
-
-               reg = tempreg;
-       }
-       else
-               reg = GET_LOW_REG(src->vv.regoff);
-
-       return reg;
-}
-
-/* emit_nullpointer_check ******************************************************
-
-   Emit a NullPointerException check.
-
-*******************************************************************************/
-
-__PORTED__ void emit_nullpointer_check(codegendata *cd, instruction *iptr, s4 reg)
-{
-       if (INSTRUCTION_MUST_CHECK(iptr)) {
-               M_TEST(reg);
-               M_BEQ(0);
-               codegen_add_nullpointerexception_ref(cd);
-       }
-}
-
-/* emit_arrayindexoutofbounds_check ********************************************
-
-   Emit a ArrayIndexOutOfBoundsException check.
-
-*******************************************************************************/
-
-void emit_arrayindexoutofbounds_check(codegendata *cd, instruction *iptr, s4 s1, s4 s2)
-{
-#if 0
-       if (INSTRUCTION_MUST_CHECK(iptr)) {
-        M_ILD(REG_ITMP3, s1, OFFSET(java_arrayheader, size));
-        M_ICMP(REG_ITMP3, s2);
-        M_BAE(0);
-        codegen_add_arrayindexoutofboundsexception_ref(cd, s2);
-       }
-#endif
-}
-
-
 /*
  * These are local overrides for various environment variables in Emacs.
  * Please do not remove this and leave it at the end of the file, where