* Removed all Id tags.
[cacao.git] / src / vm / jit / x86_64 / emit.c
index 47d1a3db3905d293d80b6133a92e16c641f2f0c9..44f3742a704166127f9e5f0a97401c5cfbe85e59 100644 (file)
@@ -1,6 +1,6 @@
 /* src/vm/jit/x86_64/emit.c - x86_64 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 6047 2006-11-22 21:19:38Z twisti $
-
 */
 
 #include "config.h"
 
+#include <assert.h>
+
 #include "vm/types.h"
 
 #include "md-abi.h"
 #include "vm/jit/x86_64/codegen.h"
 #include "vm/jit/x86_64/emit.h"
 
-#if defined(ENABLE_THREADS)
-# include "threads/native/lock.h"
-#endif
+#include "mm/memory.h"
+
+#include "threads/lock-common.h"
 
 #include "vm/builtin.h"
+#include "vm/exceptions.h"
+
+#include "vm/jit/abi.h"
 #include "vm/jit/abi-asm.h"
 #include "vm/jit/asmpart.h"
 #include "vm/jit/codegen-common.h"
@@ -51,6 +50,8 @@
 #include "vm/jit/jit.h"
 #include "vm/jit/replace.h"
 
+#include "vmcore/options.h"
+
 
 /* emit_load *******************************************************************
 
@@ -71,19 +72,24 @@ s4 emit_load(jitdata *jd, instruction *iptr, varinfo *src, s4 tempreg)
        if (IS_INMEMORY(src->flags)) {
                COUNT_SPILLS;
 
-               disp = src->vv.regoff * 8;
-
-               if (IS_FLT_DBL_TYPE(src->type)) {
-                       if (IS_2_WORD_TYPE(src->type))
-                               M_DLD(tempreg, REG_SP, disp);
-                       else
-                               M_FLD(tempreg, REG_SP, disp);
-               }
-               else {
-                       if (IS_INT_TYPE(src->type))
-                               M_ILD(tempreg, REG_SP, disp);
-                       else
-                               M_LLD(tempreg, REG_SP, disp);
+               disp = src->vv.regoff;
+
+               switch (src->type) {
+               case TYPE_INT:
+                       M_ILD(tempreg, REG_SP, disp);
+                       break;
+               case TYPE_LNG:
+               case TYPE_ADR:
+                       M_LLD(tempreg, REG_SP, disp);
+                       break;
+               case TYPE_FLT:
+                       M_FLD(tempreg, REG_SP, disp);
+                       break;
+               case TYPE_DBL:
+                       M_DLD(tempreg, REG_SP, disp);
+                       break;
+               default:
+                       vm_abort("emit_load: unknown type %d", src->type);
                }
 
                reg = tempreg;
@@ -143,16 +149,23 @@ inline void emit_store(jitdata *jd, instruction *iptr, varinfo *dst, s4 d)
        if (IS_INMEMORY(dst->flags)) {
                COUNT_SPILLS;
 
-               disp = dst->vv.regoff * 8;
+               disp = dst->vv.regoff;
 
-               if (IS_FLT_DBL_TYPE(dst->type)) {
-                       if (IS_2_WORD_TYPE(dst->type))
-                               M_DST(d, REG_SP, disp);
-                       else
-                               M_FST(d, REG_SP, disp);
-               }
-               else
+               switch (dst->type) {
+               case TYPE_INT:
+               case TYPE_LNG:
+               case TYPE_ADR:
                        M_LST(d, REG_SP, disp);
+                       break;
+               case TYPE_FLT:
+                       M_FST(d, REG_SP, disp);
+                       break;
+               case TYPE_DBL:
+                       M_DST(d, REG_SP, disp);
+                       break;
+               default:
+                       vm_abort("emit_store: unknown type %d", dst->type);
+               }
        }
 }
 
@@ -163,36 +176,57 @@ inline void emit_store(jitdata *jd, instruction *iptr, varinfo *dst, s4 d)
 
 *******************************************************************************/
 
-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 ((src->type == TYPE_RET) || (dst->type == TYPE_RET)) {
+                       /* emit nothing, as the value won't be used anyway */
+                       return;
+               }
+
                /* 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);
+                       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);
+                       d  = codegen_reg_of_var(iptr->opc, dst, s1);
                }
 
                if (s1 != d) {
-                       if (IS_FLT_DBL_TYPE(src->type))
-                               M_FMOV(s1, d);
-                       else
+                       switch (src->type) {
+                       case TYPE_INT:
+                       case TYPE_LNG:
+                       case TYPE_ADR:
                                M_MOV(s1, d);
+                               break;
+                       case TYPE_FLT:
+                       case TYPE_DBL:
+                               M_FMOV(s1, d);
+                               break;
+                       default:
+                               vm_abort("emit_copy: unknown type %d", src->type);
+                       }
                }
 
                emit_store(jd, iptr, dst, d);
@@ -227,79 +261,159 @@ void emit_cmovxx(codegendata *cd, instruction *iptr, s4 s, s4 d)
 }
 
 
-/* emit_exception_stubs ********************************************************
+/* emit_branch *****************************************************************
 
-   Generates the code for the exception stubs.
+   Emits the code for conditional and unconditional branchs.
 
 *******************************************************************************/
 
-void emit_exception_stubs(jitdata *jd)
+void emit_branch(codegendata *cd, s4 disp, s4 condition, s4 reg, u4 options)
 {
-       codegendata  *cd;
-       registerdata *rd;
-       exceptionref *er;
-       s4            branchmpc;
-       s4            targetmpc;
-       s4            targetdisp;
+       s4 branchdisp;
 
-       /* get required compiler data */
+       /* NOTE: A displacement overflow cannot happen. */
 
-       cd = jd->cd;
-       rd = jd->rd;
+       /* check which branch to generate */
 
-       /* generate exception stubs */
+       if (condition == BRANCH_UNCONDITIONAL) {
 
-       targetdisp = 0;
+               /* calculate the different displacements */
 
-       for (er = cd->exceptionrefs; er != NULL; er = er->next) {
-               /* back-patch the branch to this exception code */
+               branchdisp = disp - BRANCH_UNCONDITIONAL_SIZE;
 
-               branchmpc = er->branchpos;
-               targetmpc = cd->mcodeptr - cd->mcodebase;
+               M_JMP_IMM(branchdisp);
+       }
+       else {
+               /* calculate the different displacements */
+
+               branchdisp = disp - BRANCH_CONDITIONAL_SIZE;
+
+               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_ULT:
+                       M_BULT(branchdisp);
+                       break;
+               case BRANCH_ULE:
+                       M_BULE(branchdisp);
+                       break;
+               case BRANCH_UGE:
+                       M_BUGE(branchdisp);
+                       break;
+               case BRANCH_UGT:
+                       M_BUGT(branchdisp);
+                       break;
+               default:
+                       vm_abort("emit_branch: unknown condition %d", condition);
+               }
+       }
+}
 
-               md_codegen_patch_branch(cd, branchmpc, targetmpc);
 
-               MCODECHECK(512);
+/* emit_arithmetic_check *******************************************************
 
-               /* Check if the exception is an
-                  ArrayIndexOutOfBoundsException.  If so, move index register
-                  into a4. */
+   Emit an ArithmeticException check.
 
-               if (er->reg != -1)
-                       M_MOV(er->reg, rd->argintregs[4]);
+*******************************************************************************/
 
-               /* calcuate exception address */
+void emit_arithmetic_check(codegendata *cd, instruction *iptr, s4 reg)
+{
+       if (INSTRUCTION_MUST_CHECK(iptr)) {
+               M_TEST(reg);
+               M_BNE(8);
+               M_ALD_MEM(reg, EXCEPTION_HARDWARE_ARITHMETIC);
+       }
+}
 
-               M_MOV_IMM(0, rd->argintregs[3]);
-               dseg_adddata(cd);
-               M_AADD_IMM32(er->branchpos - 6, rd->argintregs[3]);
 
-               /* move function to call into REG_ITMP3 */
+/* emit_arrayindexoutofbounds_check ********************************************
 
-               M_MOV_IMM(er->function, REG_ITMP3);
+   Emit a ArrayIndexOutOfBoundsException check.
 
-               if (targetdisp == 0) {
-                       targetdisp = cd->mcodeptr - cd->mcodebase;
+*******************************************************************************/
 
-                       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);
+void emit_arrayindexoutofbounds_check(codegendata *cd, instruction *iptr, s4 s1, s4 s2)
+{
+       if (INSTRUCTION_MUST_CHECK(iptr)) {
+        M_ILD(REG_ITMP3, s1, OFFSET(java_array_t, size));
+        M_ICMP(REG_ITMP3, s2);
+               M_BULT(8);
+               M_ALD_MEM(s2, EXCEPTION_HARDWARE_ARRAYINDEXOUTOFBOUNDS);
+       }
+}
 
-                       M_ASUB_IMM(2 * 8, REG_SP);
-                       M_AST(rd->argintregs[3], REG_SP, 0 * 8);             /* store XPC */
 
-                       M_CALL(REG_ITMP3);
+/* emit_classcast_check ********************************************************
 
-                       M_ALD(REG_ITMP2_XPC, REG_SP, 0 * 8);
-                       M_AADD_IMM(2 * 8, REG_SP);
+   Emit a ClassCastException check.
 
-                       M_MOV_IMM(asm_handle_exception, REG_ITMP3);
-                       M_JMP(REG_ITMP3);
-               }
-               else {
-                       M_JMP_IMM((cd->mcodebase + targetdisp) -
-                                         (cd->mcodeptr + PATCHER_CALL_SIZE));
+*******************************************************************************/
+
+void emit_classcast_check(codegendata *cd, instruction *iptr, s4 condition, s4 reg, s4 s1)
+{
+       if (INSTRUCTION_MUST_CHECK(iptr)) {
+               switch (condition) {
+               case BRANCH_LE:
+                       M_BGT(8);
+                       break;
+               case BRANCH_EQ:
+                       M_BNE(8);
+                       break;
+               case BRANCH_UGT:
+                       M_BULE(8);
+                       break;
+               default:
+                       vm_abort("emit_classcast_check: unknown condition %d", condition);
                }
+               M_ALD_MEM(s1, EXCEPTION_HARDWARE_CLASSCAST);
+       }
+}
+
+
+/* emit_nullpointer_check ******************************************************
+
+   Emit a NullPointerException check.
+
+*******************************************************************************/
+
+void emit_nullpointer_check(codegendata *cd, instruction *iptr, s4 reg)
+{
+       if (INSTRUCTION_MUST_CHECK(iptr)) {
+               M_TEST(reg);
+               M_BNE(8);
+               M_ALD_MEM(reg, EXCEPTION_HARDWARE_NULLPOINTER);
+       }
+}
+
+
+/* emit_exception_check ********************************************************
+
+   Emit an Exception check.
+
+*******************************************************************************/
+
+void emit_exception_check(codegendata *cd, instruction *iptr)
+{
+       if (INSTRUCTION_MUST_CHECK(iptr)) {
+               M_TEST(REG_RESULT);
+               M_BNE(8);
+               M_ALD_MEM(REG_RESULT, EXCEPTION_HARDWARE_EXCEPTION);
        }
 }
 
@@ -391,54 +505,26 @@ void emit_patcher_stubs(jitdata *jd)
 }
 
 
-/* emit_replacement_stubs ******************************************************
+/* emit_trap *******************************************************************
 
-   Generates the code for the replacement stubs.
+   Emit a trap instruction and return the original machine code.
 
 *******************************************************************************/
 
-void emit_replacement_stubs(jitdata *jd)
+uint32_t emit_trap(codegendata *cd)
 {
-       codegendata *cd;
-       codeinfo    *code;
-       rplpoint    *rplp;
-       s4           disp;
-       s4           i;
-
-       /* get required compiler data */
-
-       cd   = jd->cd;
-       code = jd->code;
-
-       rplp = code->rplpoints;
-
-       for (i = 0; i < code->rplpointcount; ++i, ++rplp) {
-               /* check code segment size */
-
-               MCODECHECK(512);
-
-               /* note start of stub code */
-
-               rplp->outcode = (u1 *) (ptrint) (cd->mcodeptr - cd->mcodebase);
+       uint32_t mcode;
 
-               /* make machine code for patching */
+       /* Get machine code which is patched back in later. The
+          trap is 1 instruction word long. */
 
-               disp = (ptrint) (rplp->outcode - rplp->pc) - 5;
+       mcode = *((uint32_t *) cd->mcodeptr);
 
-               rplp->mcode = 0xe9 | ((u8) disp << 8);
-
-               /* push address of `rplpoint` struct */
-                       
-               M_MOV_IMM(rplp, REG_ITMP3);
-               M_PUSH(REG_ITMP3);
-
-               /* jump to replacement function */
+       M_NOP;
 
-               M_MOV_IMM(asm_replacement_out, REG_ITMP3);
-               M_JMP(REG_ITMP3);
-       }
+       return mcode;
 }
-       
+
 
 /* emit_verbosecall_enter ******************************************************
 
@@ -474,10 +560,10 @@ void emit_verbosecall_enter(jitdata *jd)
        /* save argument registers */
 
        for (i = 0; i < INT_ARG_CNT; i++)
-               M_LST(rd->argintregs[i], REG_SP, (1 + i) * 8);
+               M_LST(abi_registers_integer_argument[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);
+               M_DST(abi_registers_float_argument[i], REG_SP, (1 + INT_ARG_CNT + i) * 8);
 
        /* save temporary registers for leaf methods */
 
@@ -497,25 +583,27 @@ void emit_verbosecall_enter(jitdata *jd)
        
                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]);
+                               M_MOV(abi_registers_integer_argument[k],
+                                         abi_registers_integer_argument[k + 1]);
 
-                       emit_movd_freg_reg(cd, rd->argfltregs[j], rd->argintregs[i]);
+                       emit_movd_freg_reg(cd, abi_registers_float_argument[j],
+                                                          abi_registers_integer_argument[i]);
                        j++;
                }
        }
 
        M_MOV_IMM(m, REG_ITMP2);
        M_AST(REG_ITMP2, REG_SP, 0 * 8);
-       M_MOV_IMM(builtin_trace_args, REG_ITMP1);
+       M_MOV_IMM(builtin_verbosecall_enter, REG_ITMP1);
        M_CALL(REG_ITMP1);
 
        /* restore argument registers */
 
        for (i = 0; i < INT_ARG_CNT; i++)
-               M_LLD(rd->argintregs[i], REG_SP, (1 + i) * 8);
+               M_LLD(abi_registers_integer_argument[i], REG_SP, (1 + i) * 8);
 
        for (i = 0; i < FLT_ARG_CNT; i++)
-               M_DLD(rd->argfltregs[i], REG_SP, (1 + INT_ARG_CNT + i) * 8);
+               M_DLD(abi_registers_float_argument[i], REG_SP, (1 + INT_ARG_CNT + i) * 8);
 
        /* restore temporary registers for leaf methods */
 
@@ -564,12 +652,12 @@ void emit_verbosecall_exit(jitdata *jd)
        M_LST(REG_RESULT, REG_SP, 0 * 8);
        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]);
+       M_INTMOVE(REG_RESULT, REG_A0);
+       M_FLTMOVE(REG_FRESULT, REG_FA0);
+       M_FLTMOVE(REG_FRESULT, REG_FA1);
+       M_MOV_IMM(m, REG_A1);
 
-       M_MOV_IMM(builtin_displaymethodstop, REG_ITMP1);
+       M_MOV_IMM(builtin_verbosecall_exit, REG_ITMP1);
        M_CALL(REG_ITMP1);
 
        M_LLD(REG_RESULT, REG_SP, 0 * 8);
@@ -685,53 +773,53 @@ void emit_ishift(jitdata *jd, s4 shift_op, instruction *iptr)
        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);
+                               M_ILD(RCX, REG_SP, s2);
+                               emit_shiftl_membase(cd, shift_op, REG_SP, d);
 
                        } else {
-                               M_ILD(RCX, REG_SP, s2 * 8);
-                               M_ILD(REG_ITMP2, REG_SP, s1 * 8);
+                               M_ILD(RCX, REG_SP, s2);
+                               M_ILD(REG_ITMP2, REG_SP, s1);
                                emit_shiftl_reg(cd, shift_op, REG_ITMP2);
-                               M_IST(REG_ITMP2, REG_SP, d * 8);
+                               M_IST(REG_ITMP2, REG_SP, d);
                        }
 
                } 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_ILD(REG_ITMP1, REG_SP, s2);
+                                       M_IST(s1, REG_SP, d);
                                        M_INTMOVE(REG_ITMP1, RCX);
 
                                } else {
-                                       M_IST(s1, REG_SP, d * 8);
-                                       M_ILD(RCX, REG_SP, s2 * 8);
+                                       M_IST(s1, REG_SP, d);
+                                       M_ILD(RCX, REG_SP, s2);
                                }
 
                        } else {
-                               M_ILD(RCX, REG_SP, s2 * 8);
-                               M_IST(s1, REG_SP, d * 8);
+                               M_ILD(RCX, REG_SP, s2);
+                               M_IST(s1, REG_SP, d);
                        }
 
-                       emit_shiftl_membase(cd, shift_op, REG_SP, d * 8);
+                       emit_shiftl_membase(cd, shift_op, REG_SP, d);
 
                } 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);
+                               emit_shiftl_membase(cd, shift_op, REG_SP, d);
 
                        } else {
                                M_INTMOVE(s2, RCX);
-                               M_ILD(REG_ITMP2, REG_SP, s1 * 8);
+                               M_ILD(REG_ITMP2, REG_SP, s1);
                                emit_shiftl_reg(cd, shift_op, REG_ITMP2);
-                               M_IST(REG_ITMP2, REG_SP, d * 8);
+                               M_IST(REG_ITMP2, REG_SP, d);
                        }
 
                } else {
                        /* s1 may be equal to RCX */
-                       M_IST(s1, REG_SP, d * 8);
+                       M_IST(s1, REG_SP, d);
                        M_INTMOVE(s2, RCX);
-                       emit_shiftl_membase(cd, shift_op, REG_SP, d * 8);
+                       emit_shiftl_membase(cd, shift_op, REG_SP, d);
                }
 
                M_INTMOVE(REG_ITMP1, RCX);                             /* restore RCX */
@@ -743,19 +831,19 @@ void emit_ishift(jitdata *jd, s4 shift_op, instruction *iptr)
                }
                                        
                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);
+                       M_ILD(RCX, REG_SP, s2);
+                       M_ILD(d, REG_SP, s1);
                        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);
+                       M_ILD(RCX, REG_SP, s2);
                        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);
+                       M_ILD(d, REG_SP, s1);
                        emit_shiftl_reg(cd, shift_op, d);
 
                } else {
@@ -812,53 +900,53 @@ void emit_lshift(jitdata *jd, s4 shift_op, instruction *iptr)
        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);
+                               M_ILD(RCX, REG_SP, s2);
+                               emit_shift_membase(cd, shift_op, REG_SP, d);
 
                        } else {
-                               M_ILD(RCX, REG_SP, s2 * 8);
-                               M_LLD(REG_ITMP2, REG_SP, s1 * 8);
+                               M_ILD(RCX, REG_SP, s2);
+                               M_LLD(REG_ITMP2, REG_SP, s1);
                                emit_shift_reg(cd, shift_op, REG_ITMP2);
-                               M_LST(REG_ITMP2, REG_SP, d * 8);
+                               M_LST(REG_ITMP2, REG_SP, d);
                        }
 
                } 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_ILD(REG_ITMP1, REG_SP, s2);
+                                       M_LST(s1, REG_SP, d);
                                        M_INTMOVE(REG_ITMP1, RCX);
 
                                } else {
-                                       M_LST(s1, REG_SP, d * 8);
-                                       M_ILD(RCX, REG_SP, s2 * 8);
+                                       M_LST(s1, REG_SP, d);
+                                       M_ILD(RCX, REG_SP, s2);
                                }
 
                        } else {
-                               M_ILD(RCX, REG_SP, s2 * 8);
-                               M_LST(s1, REG_SP, d * 8);
+                               M_ILD(RCX, REG_SP, s2);
+                               M_LST(s1, REG_SP, d);
                        }
 
-                       emit_shift_membase(cd, shift_op, REG_SP, d * 8);
+                       emit_shift_membase(cd, shift_op, REG_SP, d);
 
                } 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);
+                               emit_shift_membase(cd, shift_op, REG_SP, d);
 
                        } else {
                                M_INTMOVE(s2, RCX);
-                               M_LLD(REG_ITMP2, REG_SP, s1 * 8);
+                               M_LLD(REG_ITMP2, REG_SP, s1);
                                emit_shift_reg(cd, shift_op, REG_ITMP2);
-                               M_LST(REG_ITMP2, REG_SP, d * 8);
+                               M_LST(REG_ITMP2, REG_SP, d);
                        }
 
                } else {
                        /* s1 may be equal to RCX */
-                       M_LST(s1, REG_SP, d * 8);
+                       M_LST(s1, REG_SP, d);
                        M_INTMOVE(s2, RCX);
-                       emit_shift_membase(cd, shift_op, REG_SP, d * 8);
+                       emit_shift_membase(cd, shift_op, REG_SP, d);
                }
 
                M_INTMOVE(REG_ITMP1, RCX);                             /* restore RCX */
@@ -870,19 +958,19 @@ void emit_lshift(jitdata *jd, s4 shift_op, instruction *iptr)
                }
 
                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);
+                       M_ILD(RCX, REG_SP, s2);
+                       M_LLD(d, REG_SP, s1);
                        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);
+                       M_ILD(RCX, REG_SP, s2);
                        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);
+                       M_LLD(d, REG_SP, s1);
                        emit_shift_reg(cd, shift_op, d);
 
                } else {
@@ -1192,6 +1280,15 @@ void emit_movb_imm_memindex(codegendata *cd, s4 imm, s4 disp, s4 basereg, s4 ind
 }
 
 
+void emit_mov_mem_reg(codegendata *cd, s4 disp, s4 dreg)
+{
+       emit_rex(1, dreg, 0, 0);
+       *(cd->mcodeptr++) = 0x8b;
+       emit_address_byte(0, dreg, 4);
+       emit_mem(4, disp);
+}
+
+
 /*
  * alu operations
  */
@@ -1258,7 +1355,8 @@ void emit_alu_imm_reg(codegendata *cd, s8 opc, s8 imm, s8 dreg) {
 }
 
 
-void emit_alu_imm32_reg(codegendata *cd, s8 opc, s8 imm, s8 dreg) {
+void emit_alu_imm32_reg(codegendata *cd, s4 opc, s4 imm, s4 dreg)
+{
        emit_rex(1,0,0,(dreg));
        *(cd->mcodeptr++) = 0x81;
        emit_reg((opc),(dreg));
@@ -1266,6 +1364,15 @@ void emit_alu_imm32_reg(codegendata *cd, s8 opc, s8 imm, s8 dreg) {
 }
 
 
+void emit_alul_imm32_reg(codegendata *cd, s4 opc, s4 imm, s4 dreg)
+{
+       emit_rex(0,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));
@@ -1628,7 +1735,8 @@ void emit_jcc(codegendata *cd, s8 opc, s8 imm) {
  */
 
 /* we need the rex byte to get all low bytes */
-void emit_setcc_reg(codegendata *cd, s8 opc, s8 reg) {
+void emit_setcc_reg(codegendata *cd, s4 opc, s4 reg)
+{
        *(cd->mcodeptr++) = (0x40 | (((reg) >> 3) & 0x01));
        *(cd->mcodeptr++) = 0x0f;
        *(cd->mcodeptr++) = (0x90 + (opc));
@@ -1637,7 +1745,8 @@ void emit_setcc_reg(codegendata *cd, s8 opc, s8 reg) {
 
 
 /* we need the rex byte to get all low bytes */
-void emit_setcc_membase(codegendata *cd, s8 opc, s8 basereg, s8 disp) {
+void emit_setcc_membase(codegendata *cd, s4 opc, s4 basereg, s4 disp)
+{
        *(cd->mcodeptr++) = (0x40 | (((basereg) >> 3) & 0x01));
        *(cd->mcodeptr++) = 0x0f;
        *(cd->mcodeptr++) = (0x90 + (opc));
@@ -1645,7 +1754,7 @@ void emit_setcc_membase(codegendata *cd, s8 opc, s8 basereg, s8 disp) {
 }
 
 
-void emit_cmovcc_reg_reg(codegendata *cd, s8 opc, s8 reg, s8 dreg)
+void emit_cmovcc_reg_reg(codegendata *cd, s4 opc, s4 reg, s4 dreg)
 {
        emit_rex(1,(dreg),0,(reg));
        *(cd->mcodeptr++) = 0x0f;
@@ -1654,7 +1763,7 @@ void emit_cmovcc_reg_reg(codegendata *cd, s8 opc, s8 reg, s8 dreg)
 }
 
 
-void emit_cmovccl_reg_reg(codegendata *cd, s8 opc, s8 reg, s8 dreg)
+void emit_cmovccl_reg_reg(codegendata *cd, s4 opc, s4 reg, s4 dreg)
 {
        emit_rex(0,(dreg),0,(reg));
        *(cd->mcodeptr++) = 0x0f;
@@ -1663,7 +1772,6 @@ void emit_cmovccl_reg_reg(codegendata *cd, s8 opc, s8 reg, s8 dreg)
 }
 
 
-
 void emit_neg_reg(codegendata *cd, s8 reg)
 {
        emit_rex(1,0,0,(reg));
@@ -1714,14 +1822,16 @@ void emit_nop(codegendata *cd) {
 /*
  * call instructions
  */
-void emit_call_reg(codegendata *cd, s8 reg) {
-       emit_rex(1,0,0,(reg));
+void emit_call_reg(codegendata *cd, s8 reg)
+{
+       emit_rex(0,0,0,(reg));
        *(cd->mcodeptr++) = 0xff;
        emit_reg(2,(reg));
 }
 
 
-void emit_call_imm(codegendata *cd, s8 imm) {
+void emit_call_imm(codegendata *cd, s8 imm)
+{
        *(cd->mcodeptr++) = 0xe8;
        emit_imm32((imm));
 }