develooper Front page | perl.cvs.parrot | Postings from December 2008

[svn:parrot] r34285 - branches/jit_h_files/src/jit/i386

From:
Whiteknight
Date:
December 23, 2008 12:50
Subject:
[svn:parrot] r34285 - branches/jit_h_files/src/jit/i386
Message ID:
20081223204933.6A776CBA12@x12.develooper.com
Author: Whiteknight
Date: Tue Dec 23 12:49:30 2008
New Revision: 34285

Modified:
   branches/jit_h_files/src/jit/i386/jit_defs.c
   branches/jit_h_files/src/jit/i386/jit_emit.h

Log:
[jit_h_files] move functions from the first part of the .h file to the .c file, along with a few duplicated macros. Compiles.

Modified: branches/jit_h_files/src/jit/i386/jit_defs.c
==============================================================================
--- branches/jit_h_files/src/jit/i386/jit_defs.c	(original)
+++ branches/jit_h_files/src/jit/i386/jit_defs.c	Tue Dec 23 12:49:30 2008
@@ -1,14 +1,9 @@
-
 #include <assert.h>
 #include "parrot/parrot.h"
 #include "parrot/hash.h"
 #include "parrot/oplib/ops.h"
-#include "jit_emit.h"
-
+#include "jit.h"
 
-/*
- * helper funcs - get argument n
- */
 INTVAL
 get_nci_I(PARROT_INTERP, ARGMOD(call_state *st), int n)
 {
@@ -131,6 +126,34 @@
     }
 }
 
+/* Register codes */
+/* XXX: These should be merged with the same definition in jit_emit.h */
+#define emit_None 0
+#define emit_b00 0
+#define emit_b01 1
+#define emit_b10 2
+#define emit_b11 3
+#define emit_b000 0
+#define emit_b001 1
+#define emit_b010 2
+#define emit_b011 3
+#define emit_b100 4
+#define emit_b101 5
+#define emit_b110 6
+#define emit_b111 7
+
+/* Scale factor values */
+#define emit_Scale(scale) ((scale) << 6)
+#define emit_Scale_1 emit_Scale(0)
+#define emit_Scale_2 emit_Scale(1)
+#define emit_Scale_4 emit_Scale(2)
+#define emit_Scale_8 emit_Scale(3)
+
+/* ESIB byte */
+#define emit_reg_Index(x) (((x)-1) << 3)
+#define emit_reg_Base(x) ((x)-1)
+#define emit_Index_None ((emit_b100) << 3)
+
 void
 emit_sib(PARROT_INTERP, char *pc, int scale, int i, int base)
 {
@@ -159,6 +182,27 @@
             emit_reg_Base(base));
 }
 
+/* Mod values for Mod R/M Byte */
+/* XXX: Duplicate */
+#define emit_Mod_b00 emit_Mod(emit_b00)
+#define emit_Mod_b01 emit_Mod(emit_b01)
+#define emit_Mod_b10 emit_Mod(emit_b10)
+#define emit_reg(x) ((x) << 3)
+#define emit_Mod(Mod) ((Mod) << 6)
+#define emit_reg_rm(x) ((x)-1)
+
+#define emit_EAX 1
+#define emit_ECX 2
+#define emit_EDX 3
+#define emit_EBX 4
+#define emit_ESP 5
+#define emit_EBP 6
+#define emit_ESI 7
+#define emit_EDI 8
+
+#define emit_rm_b101 emit_b101
+#define emit_rm_b100 emit_b100
+
 char *
 emit_r_X(PARROT_INTERP, char *pc, int reg_opcode, int base, int i, int scale, long disp)
 {
@@ -213,6 +257,10 @@
     return pc;
 }
 
+#define emit_alu_X_r(X, reg) ((emit_b11 << 6) | ((X) << 3) | ((reg) - 1))
+
+#define emit_alu_r_r(reg1, reg2) emit_alu_X_r(((reg1) - 1), (reg2))
+
 char *
 emit_shift_i_r(PARROT_INTERP, char *pc, int opcode, int imm, int reg)
 {
@@ -291,2230 +339,3 @@
 
     return pc;
 }
-
-char *
-emit_pushl_m(PARROT_INTERP, char *pc, int base, int i, int scale, long disp)
-{
-    *(pc++) = (char) 0xff;
-    return emit_r_X(interp, pc, emit_reg(emit_b110), base, i, scale, disp);
-}
-
-/* POPs */
-
-char *
-emit_popl_r(char *pc, int reg)
-{
-/* XXX kwoo:  I side with valgrind.  Is it safe to remove the obsolete code? */
-#if 0
-    /* valgrind doesn't like this and the version below is smaller anyway */
-    *(pc++) = (char) 0x8f;
-    *(pc++) = (char) emit_alu_X_r(emit_b000, reg);
-#else
-    *(pc++) = (char)(0x58 | (reg - 1));
-#endif /* 0 */
-    return pc;
-}
-
-
-char *
-emit_popl_m(PARROT_INTERP, char *pc, int base, int i, int scale, long disp)
-{
-    *(pc++) = (char) 0x8f;
-    return emit_r_X(interp, pc, emit_reg(emit_b000), base, i, scale, disp);
-}
-
-/* MOVes */
-
-char *
-emit_movb_r_r(char *pc, int reg1, int reg2)
-{
-    *(pc++) = (char) 0x88;
-    *(pc++) = (char) emit_alu_r_r(reg1, reg2);
-    return pc;
-}
-
-
-char *
-emit_movb_i_r(char *pc, char imm, int reg)
-{
-    *(pc++) = (char)(0xb0 | (reg - 1));
-    *(pc++) = imm;
-    return pc;
-}
-
-char *
-emit_movb_i_m(PARROT_INTERP, char *pc, char imm, int base, int i, int scale, long disp)
-{
-    *(pc++) = (char) 0xc6;
-    pc = emit_r_X(interp, pc, emit_reg(emit_b000), base, i, scale, disp);
-    *(pc++) = imm;
-    return pc;
-}
-
-char *
-opt_mul(PARROT_INTERP, char *pc, int dest, INTVAL imm, int src)
-{
-    UINTVAL ld2 = ld((UINTVAL) imm);
-
-    if (imm == 0) {
-        jit_emit_mov_ri_i(interp, pc, dest, 0);
-    }
-    else if (imm > 0 && !(imm & (imm - 1))) {
-        /* positive power of 2 - do a shift */
-        jit_emit_mov_rr_i(pc, dest, src);
-        pc = emit_shift_i_r(interp, pc, emit_b100, ld2, dest);
-    }
-    else {
-        /* special small numbers */
-        switch (imm) {
-            case 3:
-                /* LEA dest, base, index, scale, displace
-                 * note: src may be dest, so can't be reused
-                 *
-                 * dest = src + src*2 */
-                emitm_lea_m_r(interp, pc, dest, src, src, 2, 0);
-                break;
-            case 5:      /* dest = src + src*4 */
-                emitm_lea_m_r(interp, pc, dest, src, src, 4, 0);
-                break;
-            case 6:     /* dest = src*3; dest += dest */
-                emitm_lea_m_r(interp, pc, dest, src, src, 2, 0);
-                jit_emit_add_rr_i(interp, pc, dest, dest);
-                break;
-            case 9:      /* dest = src + src*8 */
-                emitm_lea_m_r(interp, pc, dest, src, src, 8, 0);
-                break;
-            case 10:      /* dest = src + src*4 ; dest+= dest */
-                emitm_lea_m_r(interp, pc, dest, src, src, 4, 0);
-                jit_emit_add_rr_i(interp, pc, dest, dest);
-                break;
-            case 12:     /* dest= src*3; dest <<= 2 */
-                emitm_lea_m_r(interp, pc, dest, src, src, 2, 0);
-                pc = emit_shift_i_r(interp, pc, emit_b100, 2, dest);
-                break;
-            case 100:      /* dest = src + src*4 ; dest <<= 2; dest = 5*dest*/
-                emitm_lea_m_r(interp, pc, dest, src, src, 4, 0);
-                pc = emit_shift_i_r(interp, pc, emit_b100, 2, dest);
-                emitm_lea_m_r(interp, pc, dest, dest, dest, 4, 0);
-                break;
-            default:
-                emitm_alul_r_r(pc, 0x69, dest, src);
-                *(long *)(pc) = (long)imm;
-                pc += 4;
-        }
-    }
-    return pc;
-}
-
-int
-intreg_is_used(Parrot_jit_info_t *jit_info, char reg)
-{
-    int i;
-    const jit_arch_regs *reg_info;
-    Parrot_jit_register_usage_t *ru = jit_info->optimizer->cur_section->ru;
-
-    reg_info = jit_info->arch_info->regs + jit_info->code_type;
-
-    for (i = 0; i < ru[0].registers_used; ++i) {
-        if (reg_info->map_I[i] == reg) {
-            return 1;
-        }
-    }
-    return 0;
-}
-
-char *
-opt_shift_rr(PARROT_INTERP, Parrot_jit_info_t *jit_info, int dest, int count, int op)
-{
-    char *pc = jit_info->native_ptr;
-    if (count == emit_ECX) {
-        pc = emit_shift_r_r(interp, pc, op, count, dest);
-    }
-    else {
-        int saved = 0;
-        PARROT_ASSERT(count != emit_EAX);
-        if (dest == emit_EAX) {
-            if (intreg_is_used(jit_info, emit_ECX)) {
-                emitm_pushl_r(pc, emit_ECX);
-                saved = 1;
-            }
-            jit_emit_mov_rr_i(pc, emit_ECX, count);
-            pc = emit_shift_r_r(interp, pc, op, emit_ECX, dest);
-            if (saved) {
-                emitm_popl_r(pc, emit_ECX);
-            }
-
-        }
-        else if (dest == emit_ECX) {
-            jit_emit_xchg_rr_i(interp, pc, dest, count);
-            pc = emit_shift_r_r(interp, pc, op, dest, count);
-            jit_emit_xchg_rr_i(interp, pc, dest, count);
-        }
-        else {
-            jit_emit_mov_rr_i(pc, emit_EAX, emit_ECX);
-            jit_emit_mov_rr_i(pc, emit_ECX, count);
-            pc = emit_shift_r_r(interp, pc, op, emit_ECX, dest);
-            jit_emit_mov_rr_i(pc, emit_ECX, emit_EAX);
-        }
-    }
-    return pc;
-}
-
-char *
-opt_shift_rm(PARROT_INTERP, Parrot_jit_info_t *jit_info, int dest, int offs, int op)
-{
-    char *pc = jit_info->native_ptr;
-    int saved = 0;
-    /* if ECX is mapped, save it */
-    if (dest != emit_ECX && intreg_is_used(jit_info, emit_ECX)) {
-        emitm_pushl_r(pc, emit_ECX);
-        saved = 1;
-    }
-    if (dest == emit_ECX) {
-        /* jit_emit_mov_RM_i(pc, emit_EAX, count); */
-        emitm_movl_m_r(interp, pc, emit_EAX, emit_EBX, emit_None, 1, offs);
-        jit_emit_xchg_rr_i(interp, pc, dest, emit_EAX);
-        pc = emit_shift_r_r(interp, pc, op, emit_ECX, emit_EAX);
-        jit_emit_xchg_rr_i(interp, pc, dest, emit_EAX);
-    }
-    else {
-        /* jit_emit_mov_RM_i(pc, emit_ECX, count); */
-        emitm_movl_m_r(interp, pc, emit_ECX, emit_EBX, emit_None, 1, offs);
-        pc = emit_shift_r_r(interp, pc, op, emit_ECX, dest);
-    }
-    if (saved) {
-        emitm_popl_r(pc, emit_ECX);
-    }
-    return pc;
-}
-
-unsigned char *lastpc;
-
-/* ST(r1) /= ST(r2) */
-char *
-div_rr_n(PARROT_INTERP, Parrot_jit_info_t *jit_info, int r1)
-{
-    char *L1;
-    static const char div_by_zero[] = "Divide by zero";
-    char *pc = jit_info->native_ptr;
-
-    jit_emit_test_r_n(pc, (char)0);   /* TOS */
-    L1 = pc;
-    emitm_jxs(pc, emitm_jnz, 0);
-    emitm_pushl_i(pc, div_by_zero);
-    emitm_pushl_i(pc, EXCEPTION_DIV_BY_ZERO);
-    emitm_pushl_i(pc, 0);    /* NULL */
-    Parrot_jit_emit_get_INTERP(interp, pc, emit_ECX);
-    emitm_pushl_r(pc, emit_ECX);
-    jit_info->native_ptr = pc;
-    jit_emit_real_exception(jit_info);
-    pc = jit_info->native_ptr;
-    /* L1: */
-    L1[1] = (char)(pc - L1 - 2);
-    emitm_fdivp(pc, (r1+1));
-    return pc;
-}
-
-char *
-mod_rr_n(PARROT_INTERP, Parrot_jit_info_t *jit_info, int r)
-{
-    char *L1;
-    static const char div_by_zero[] = "Divide by zero";
-    char *pc = jit_info->native_ptr;
-
-    jit_emit_test_r_n(pc, (char)0);   /* TOS */
-    L1 = pc;
-    emitm_jxs(pc, emitm_jnz, 0);
-    emitm_pushl_i(pc, div_by_zero);
-    emitm_pushl_i(pc, EXCEPTION_DIV_BY_ZERO);
-    emitm_pushl_i(pc, 0);    /* NULL */
-    Parrot_jit_emit_get_INTERP(interp, pc, emit_ECX);
-    emitm_pushl_r(pc, emit_ECX);
-    jit_info->native_ptr = pc;
-    jit_emit_real_exception(jit_info);
-    pc = jit_info->native_ptr;
-    /* L1: */
-    L1[1] = (char)(pc - L1 - 2);
-    /* L2: */
-    emitm_fxch(pc, (char)1);
-    emitm_fprem(pc);
-    emitm_fstw(pc);
-    emitm_sahf(pc);
-    emitm_jxs(pc, emitm_jp, -7); /* jo L2 */
-    emitm_fstp(pc, (r+1));
-    return pc;
-}
-
-/* dest /= src
- * edx:eax /= src, quotient => eax, rem => edx
- */
-char *
-opt_div_rr(PARROT_INTERP, Parrot_jit_info_t *jit_info, int dest, int src, int is_div)
-{
-    char *pc = jit_info->native_ptr;
-    int saved = 0;
-    int div_ecx = 0;
-    char *L1, *L2, *L3;
-    static const char div_by_zero[] = "Divide by zero";
-
-    PARROT_ASSERT(src != emit_EAX);
-
-    if (dest != emit_EAX) {
-        jit_emit_mov_rr_i(pc, emit_EAX, dest);
-    }
-    if (dest == emit_EDX) {
-        /* all ok, we can globber it */
-    }
-    else {
-        /* if ECX is not mapped use it */
-        if (!intreg_is_used(jit_info, emit_ECX) && src == emit_EDX) {
-            jit_emit_mov_rr_i(pc, emit_ECX, emit_EDX);
-            div_ecx = 1;
-        }
-        else
-            /* if EDX is mapped, preserve EDX on stack */
-            if (intreg_is_used(jit_info, emit_EDX)) {
-                emitm_pushl_r(pc, emit_EDX);
-                saved = 1;
-                /* if EDX is the src, we need another temp register: ECX */
-                if (src == emit_EDX) {
-                    /* if ECX is mapped save it, but not if it's dest */
-                    if (intreg_is_used(jit_info, emit_ECX) &&
-                            dest != emit_ECX) {
-                        emitm_pushl_r(pc, emit_ECX);
-                        saved = 2;
-                    }
-                    /* else just use it */
-                    jit_emit_mov_rr_i(pc, emit_ECX, emit_EDX);
-                    div_ecx = 1;
-                }
-            }
-    }
-#if 0
-    jit_emit_cdq(pc);
-#else
-    /* this sequence allows 2 other instructions to run parallel */
-    if (dest != emit_EDX) {
-        jit_emit_mov_rr_i(pc, emit_EDX, emit_EAX);
-    }
-    pc = emit_shift_i_r(interp, pc, emit_b111, 31, emit_EDX); /* SAR 31 */
-#endif
-    if (div_ecx) {
-        jit_emit_test_r_i(pc, emit_ECX);
-        L1 = pc;
-        emitm_jxs(pc, emitm_jz, 0);
-        emitm_sdivl_r(pc, emit_ECX);
-        L3 = pc;
-        emitm_jumps(pc, 0);
-        /* L1: */
-        L1[1] = (char)(pc - L1 - 2);
-    }
-    else {
-        jit_emit_test_r_i(pc, src);
-        L2 = pc;
-        emitm_jxs(pc, emitm_jz, 0);
-        emitm_sdivl_r(pc, src);
-        L3 = pc;
-        emitm_jumps(pc, 0);
-        /* L2: */
-        L2[1] = (char)(pc - L2 - 2);
-    }
-    /* TODO Parrot_ex_throw_from_c_args */
-    emitm_pushl_i(pc, div_by_zero);
-    emitm_pushl_i(pc, EXCEPTION_DIV_BY_ZERO);
-    emitm_pushl_i(pc, 0);    /* NULL */
-    Parrot_jit_emit_get_INTERP(interp, pc, emit_ECX);
-    emitm_pushl_r(pc, emit_ECX);
-    jit_info->native_ptr = pc;
-    jit_emit_real_exception(jit_info);
-    pc = jit_info->native_ptr;
-    /* L3: */
-    L3[1] = (char)(pc - L3 - 2);
-    if (saved == 2) {
-        emitm_popl_r(pc, emit_ECX);
-    }
-    if (is_div) {
-        /* result = quotient in EAX */
-        if (saved) {
-            emitm_popl_r(pc, emit_EDX);
-        }
-        if (dest != emit_EAX) {
-            jit_emit_mov_rr_i(pc, dest, emit_EAX);
-        }
-    }
-    else {
-        /* result = remainder in EDX */
-        if (saved) {
-            emitm_popl_r(pc, emit_EAX);
-            jit_emit_mov_rr_i(pc, dest, emit_EDX);
-            jit_emit_mov_rr_i(pc, emit_EDX, emit_EAX);
-        }
-        else {
-            if (dest != emit_EDX)
-                jit_emit_mov_rr_i(pc, dest, emit_EDX);
-        }
-    }
-    if (!saved && div_ecx) {
-        /* restore EDX */
-        jit_emit_mov_rr_i(pc, emit_EDX, emit_ECX);
-    }
-    return pc;
-}
-
-char *
-opt_div_ri(PARROT_INTERP, Parrot_jit_info_t *jit_info, int dest, INTVAL imm, int is_div)
-{
-    char *pc = jit_info->native_ptr;
-
-    UINTVAL ld2 = ld((UINTVAL) imm);
-    if (is_div && imm > 1 && !(imm & (imm - 1))) {
-        /* positive power of 2 - do a shift */
-        pc = emit_shift_i_r(interp, pc, emit_b101, ld2, dest);
-    }
-    else {
-        if (dest != emit_EBX) {
-            emitm_pushl_r(pc, emit_EBX);
-            jit_emit_mov_ri_i(interp, pc, emit_EBX, imm);
-            jit_info->native_ptr = pc;
-            pc = opt_div_rr(interp, jit_info, dest, emit_EBX, is_div);
-            pc = emit_popl_r(pc, emit_EBX);
-        }
-        else {
-            emitm_pushl_r(pc, emit_EDI);
-            jit_emit_mov_ri_i(interp, pc, emit_EDI, imm);
-            jit_info->native_ptr = pc;
-            pc = opt_div_rr(interp, jit_info, dest, emit_EDI, is_div);
-            pc = emit_popl_r(pc, emit_EDI);
-        }
-    }
-    return pc;
-}
-
-char *
-opt_div_RM(PARROT_INTERP, Parrot_jit_info_t *jit_info, int dest, int offs, int is_div)
-{
-    char *pc = jit_info->native_ptr;
-    int saved = 0;
-
-    if (dest != emit_EAX) {
-        jit_emit_mov_rr_i(pc, emit_EAX, dest);
-    }
-    if (dest == emit_EDX) {
-        /* all ok, we can globber it */
-    }
-    else {
-        /* if ECX is mapped, push EDX on stack */
-        if (intreg_is_used(jit_info, emit_ECX)) {
-            emitm_pushl_r(pc, emit_EDX);
-            saved = 2;
-        }
-        /* if EDX is mapped, save it in ECX */
-        else if (intreg_is_used(jit_info, emit_EDX)) {
-            saved = 1;
-            jit_emit_mov_rr_i(pc, emit_ECX, emit_EDX);
-        }
-    }
-#if 0
-    jit_emit_cdq(pc);
-#else
-    /* this sequence allows 2 other instructions to run parallel */
-    jit_emit_mov_rr_i(pc, emit_EDX, emit_EAX);
-    pc = emit_shift_i_r(interp, pc, emit_b111, 31, emit_EDX); /* SAR 31 */
-#endif
-    emitm_sdivl_m(pc, emit_EBX, 0, 1, offs);
-
-    if (is_div) {
-        /* result = quotient in EAX */
-        if (saved == 1) {
-            jit_emit_mov_rr_i(pc, emit_EDX, emit_ECX);
-        }
-        if (dest != emit_EAX) {
-            jit_emit_mov_rr_i(pc, dest, emit_EAX);
-        }
-        if (saved == 2) {
-            emitm_popl_r(pc, emit_EDX);
-        }
-    }
-    else {
-        /* result = remainder in EDX */
-        if (dest != emit_EDX) {
-            jit_emit_mov_rr_i(pc, dest, emit_EDX);
-            if (saved == 1) {
-                jit_emit_mov_rr_i(pc, emit_EDX, emit_ECX);
-            }
-            else if (saved == 2)
-                emitm_popl_r(pc, emit_EDX);
-        }
-    }
-    return pc;
-}
-
-void
-jit_emit_jcc(Parrot_jit_info_t *jit_info, int code, opcode_t disp)
-{
-    long offset;
-    opcode_t opcode;
-
-    opcode = jit_info->op_i + disp;
-
-    if (opcode <= jit_info->op_i) {
-        offset = jit_info->arena.op_map[opcode].offset -
-                (jit_info->native_ptr - jit_info->arena.start);
-
-        /* If we are here, the current section must have a branch_target
-           section, I think. */
-        if (jit_info->optimizer->cur_section->branch_target ==
-            jit_info->optimizer->cur_section)
-                offset +=
-                    jit_info->optimizer->cur_section->branch_target->load_size;
-
-        if (emit_is8bit(offset - 2)) {
-            emitm_jxs(jit_info->native_ptr, code, offset - 2);
-        }
-        else {
-            emitm_jxl(jit_info->native_ptr, code, offset - 6);
-        }
-
-        return;
-    }
-
-    Parrot_jit_newfixup(jit_info);
-    jit_info->arena.fixups->type = JIT_X86BRANCH;
-    jit_info->arena.fixups->param.opcode = opcode;
-    /* If the branch is to the current section, skip the load instructions. */
-    if (jit_info->optimizer->cur_section->branch_target ==
-        jit_info->optimizer->cur_section)
-            jit_info->arena.fixups->skip =
-                (char)jit_info->optimizer->cur_section->branch_target->load_size;
-
-    emitm_jxl(jit_info->native_ptr, code, 0xc0def00d);
-}
-
-void
-emit_jump(Parrot_jit_info_t *jit_info, opcode_t disp)
-{
-    long offset;
-    opcode_t opcode;
-
-    opcode = jit_info->op_i + disp;
-
-    if (opcode <= jit_info->op_i) {
-        offset = jit_info->arena.op_map[opcode].offset -
-                                (jit_info->native_ptr - jit_info->arena.start);
-        if (emit_is8bit(offset - 2)) {
-            emitm_jumps(jit_info->native_ptr, (char)(offset - 2));
-        }
-        else {
-            emitm_jumpl(jit_info->native_ptr, offset - 5);
-        }
-        return;
-    }
-
-    Parrot_jit_newfixup(jit_info);
-    jit_info->arena.fixups->type = JIT_X86JUMP;
-    jit_info->arena.fixups->param.opcode = opcode;
-    /* If the branch is to the current section, skip the load instructions. */
-    if (jit_info->optimizer->cur_section->branch_target ==
-        jit_info->optimizer->cur_section)
-            jit_info->arena.fixups->skip =
-                (char)jit_info->optimizer->cur_section->branch_target->load_size;
-    emitm_jumpl(jit_info->native_ptr, 0xc0def00d);
-}
-
-void
-Parrot_emit_jump_to_eax(Parrot_jit_info_t *jit_info,
-                   PARROT_INTERP)
-{
-    /* we have to get the code pointer, which might change
-     * due too intersegment branches
-     */
-
-    /* get interpreter
-     */
-    emitm_movl_m_r(interp, jit_info->native_ptr,
-            emit_EBX, emit_EBP, emit_None, 1, INTERP_BP_OFFS);
-    if (!jit_info->objfile) {
-        /*
-         * emit interp->code->base.data
-         */
-        emitm_movl_m_r(interp, jit_info->native_ptr, emit_ECX, emit_EBX, 0, 1,
-                offsetof(Interp, code));
-        emitm_movl_m_r(interp, jit_info->native_ptr, emit_EDX, emit_ECX, 0, 1,
-                offsetof(PackFile_Segment, data));
-        /* calc code offset */
-        jit_emit_sub_rr_i(interp, jit_info->native_ptr, emit_EAX, emit_EDX);
-        /*
-         * now we have the offset of the ins in EAX
-         *
-         * interp->code->jit_info->arena->op_map
-         *
-         * TODO interleave these 2 calculations
-         */
-        emitm_movl_m_r(interp, jit_info->native_ptr, emit_EDX, emit_ECX, 0, 1,
-                offsetof(PackFile_ByteCode, jit_info));
-        emitm_lea_m_r(interp, jit_info->native_ptr, emit_EDX, emit_EDX, 0, 1,
-                offsetof(Parrot_jit_info_t, arena));
-        emitm_movl_m_r(interp, jit_info->native_ptr, emit_EDX, emit_EDX, 0, 1,
-                offsetof(Parrot_jit_arena_t, op_map));
-
-    }
-#if EXEC_CAPABLE
-    else {
-        int *reg;
-        emitm_subl_i_r(jit_info->native_ptr,
-            jit_info->objfile->bytecode_header_size, emit_EAX);
-        Parrot_exec_add_text_rellocation(jit_info->objfile,
-            jit_info->native_ptr, RTYPE_DATA, "program_code", -4);
-        reg = Parrot_exec_add_text_rellocation_reg(jit_info->objfile,
-                jit_info->native_ptr, "opcode_map", 0, 0);
-        jit_emit_mov_ri_i(interp, jit_info->native_ptr, emit_EDX, (long) reg);
-    }
-#endif
-    /* get base pointer */
-    emitm_movl_m_r(interp, jit_info->native_ptr, emit_EBX, emit_EBX, 0, 1,
-            offsetof(Interp, ctx.bp));
-
-    /* This jumps to the address in op_map[EDX + sizeof (void *) * INDEX] */
-    emitm_jumpm(jit_info->native_ptr, emit_EDX, emit_EAX,
-            sizeof (*jit_info->arena.op_map) / 4, 0);
-}
-
-void call_func(Parrot_jit_info_t *jit_info, void (*addr) (void))
-{
-    Parrot_jit_newfixup(jit_info);
-    jit_info->arena.fixups->type = JIT_X86CALL;
-    jit_info->arena.fixups->param.fptr = D2FPTR(addr);
-    emitm_calll(jit_info->native_ptr, 0xdeafc0de);
-}
-
-void jit_emit_real_exception(Parrot_jit_info_t *jit_info)
-{
-    call_func(jit_info, (void (*) (void)) & Parrot_ex_throw_from_c_args);
-}
-
-char*
-jit_set_i_p_ki(Parrot_jit_info_t *jit_info, PARROT_INTERP, size_t offset)
-{
-    char *L1, *L2, *L3, *L4;
-    /*
-     * mov $2, %edi
-     * mov (vtable)%edi, %eax
-     * mov (offset)%eax, %esi
-     * cmp Parrot_FixedIntegerArray_get_integer_keyed_int, %esi
-     * jne L1
-     */
-    jit_emit_mov_RM_i(interp, NATIVECODE, emit_EDI, JIT_ROFFS_PMC(2));
-    emitm_movl_m_r(interp, NATIVECODE, emit_EAX, emit_EDI, emit_None, 1,
-            offsetof(struct PMC, vtable));
-    emitm_movl_m_r(interp, NATIVECODE, emit_ESI, emit_EAX, emit_None, 1, offset);
-    jit_emit_cmp_ri_i(interp, NATIVECODE, emit_ESI,
-            Parrot_FixedIntegerArray_get_integer_keyed_int);
-    L1 = NATIVECODE;
-    emitm_jxs(NATIVECODE, emitm_jnz, 0);
-    /*
-     * mov $3, %ecx
-     * cmp %ecx, 0
-     * js L2
-     * mov (int_val)%edi, %eax
-     * cmp %ecx, $eax
-     * jge L3
-     *
-     */
-    if (MAP(3)) {
-        jit_emit_mov_rr_i(NATIVECODE, emit_ECX, MAP(3));
-    }
-    else {
-        jit_emit_mov_RM_i(interp, NATIVECODE, emit_ECX, JIT_ROFFS_INT(3));
-    }
-    /*  range check */
-    jit_emit_cmp_ri_i(interp, NATIVECODE, emit_ECX, 0);
-    L2 = NATIVECODE;
-    emitm_jxs(NATIVECODE, emitm_js, 0);
-    emitm_movl_m_r(interp, NATIVECODE, emit_EAX, emit_EDI, 0, 1,
-            offsetof(struct PMC, cache._i._int_val));
-    jit_emit_cmp_rr_i(NATIVECODE, emit_ECX, emit_EAX);
-    L3 = NATIVECODE;
-    emitm_jxs(NATIVECODE, emitm_jnl, 0);
-
-    /*
-     * mov (data)%edi, %eax
-     * mov (%eax, %ecx, 4), %eax
-     * jmp L4
-     */
-    emitm_movl_m_r(interp, NATIVECODE, emit_EAX, emit_EDI, 0, 1,
-            offsetof(struct PMC, data));
-    emitm_movl_m_r(interp, NATIVECODE, emit_EAX, emit_EAX, emit_ECX, 4, 0);
-
-    L4 = NATIVECODE;
-    emitm_jumps(NATIVECODE, 0);
-    /* L1: L2: L3: */
-    L1[1] = (char)(NATIVECODE - L1 - 2);
-    L2[1] = (char)(NATIVECODE - L2 - 2);
-    L3[1] = (char)(NATIVECODE - L3 - 2);
-    return L4;
-}
-
-char*
-jit_set_p_ki_i(Parrot_jit_info_t *jit_info, PARROT_INTERP, size_t offset)
-{
-    char *L1, *L2, *L3, *L4;
-    /*
-     * mov $1, %edi
-     * mov (vtable)%edi, %eax
-     * mov (offset)%eax, %esi
-     * cmp Parrot_FixedIntegerArray_set_integer_keyed_int, %esi
-     * jne L1
-     */
-    jit_emit_mov_RM_i(interp, NATIVECODE, emit_EDI, JIT_ROFFS_PMC(1));
-    emitm_movl_m_r(interp, NATIVECODE, emit_EAX, emit_EDI, emit_None, 1,
-            offsetof(struct PMC, vtable));
-    emitm_movl_m_r(interp, NATIVECODE, emit_ESI, emit_EAX, emit_None, 1, offset);
-    jit_emit_cmp_ri_i(interp, NATIVECODE, emit_ESI,
-            Parrot_FixedIntegerArray_set_integer_keyed_int);
-    L1 = NATIVECODE;
-    emitm_jxs(NATIVECODE, emitm_jnz, 0);
-    /*
-     * mov $2, %ecx
-     * cmp %ecx, 0
-     * js L2
-     * mov (int_val)%edi, %eax
-     * cmp %ecx, $eax
-     * jge L3
-     *
-     */
-    if (MAP(2)) {
-        jit_emit_mov_rr_i(NATIVECODE, emit_ECX, MAP(2));
-    }
-    else {
-        jit_emit_mov_RM_i(interp, NATIVECODE, emit_ECX, JIT_ROFFS_INT(2));
-    }
-    /*  range check */
-    jit_emit_cmp_ri_i(interp, NATIVECODE, emit_ECX, 0);
-    L2 = NATIVECODE;
-    emitm_jxs(NATIVECODE, emitm_js, 0);
-    emitm_movl_m_r(interp, NATIVECODE, emit_EAX, emit_EDI, 0, 1,
-            offsetof(struct PMC, cache._i._int_val));
-    jit_emit_cmp_rr_i(NATIVECODE, emit_ECX, emit_EAX);
-    L3 = NATIVECODE;
-    emitm_jxs(NATIVECODE, emitm_jnl, 0);
-
-    /*
-     * mov (data)%eax, %eax
-     * mov $3, %edx
-     * mov $edx, (%eax, %ecx, 4)
-     * jmp L4
-     */
-    emitm_movl_m_r(interp, NATIVECODE, emit_EAX, emit_EDI, 0, 1,
-            offsetof(struct PMC, data));
-    if (MAP(3)) {
-        jit_emit_mov_rr_i(NATIVECODE, emit_EDX, MAP(3));
-    }
-    else {
-        jit_emit_mov_RM_i(interp, NATIVECODE, emit_EDX, JIT_ROFFS_INT(3));
-    }
-    emitm_movl_r_m(interp, NATIVECODE, emit_EDX, emit_EAX, emit_ECX, 4, 0);
-
-    L4 = NATIVECODE;
-    emitm_jumps(NATIVECODE, 0);
-    /* L1: L2: L3: */
-    L1[1] = (char)(NATIVECODE - L1 - 2);
-    L2[1] = (char)(NATIVECODE - L2 - 2);
-    L3[1] = (char)(NATIVECODE - L3 - 2);
-    return L4;
-}
-
-/*
- * for vtable calls registers are already saved back
- */
-void
-Parrot_jit_vtable_n_op(Parrot_jit_info_t *jit_info,
-                PARROT_INTERP, int n, int *args)
-{
-    int        nvtable = op_jit[*jit_info->cur_op].extcall;
-    size_t     offset;
-    op_info_t *op_info = &interp->op_info_table[*jit_info->cur_op];
-    int        pi;
-    int        idx, i, op;
-    int        st      = 0;         /* stack pop correction */
-    char      *L4      = NULL;
-
-    /* get the offset of the first vtable func */
-    offset  = offsetof(VTABLE, absolute);
-    offset += nvtable * sizeof (void *);
-    op      = *jit_info->cur_op;
-
-    if (op == PARROT_OP_set_i_p_ki) {
-        L4 = jit_set_i_p_ki(jit_info, interp, offset);
-    }
-    else if (op == PARROT_OP_set_p_ki_i) {
-        L4 = jit_set_p_ki_i(jit_info, interp, offset);
-    }
-
-    /* get params $i, 0 is opcode */
-    for (idx = n; idx > 0; idx--) {
-        i  = args[idx-1];
-        pi = *(jit_info->cur_op + i);
-
-        switch (op_info->types[i - 1]) {
-            case PARROT_ARG_S:
-                emitm_movl_m_r(interp, jit_info->native_ptr,
-                        emit_EAX, emit_EBX, emit_None, 1, REG_OFFS_STR(pi));
-                emitm_pushl_r(jit_info->native_ptr, emit_EAX);
-                break;
-            case PARROT_ARG_K:
-            case PARROT_ARG_P:
-                emitm_movl_m_r(interp, jit_info->native_ptr,
-                        emit_EAX, emit_EBX, emit_None, 1, REG_OFFS_PMC(pi));
-                /* push $i, the left most Pi stays in eax, which is used
-                 * below, to call the vtable method
-                 */
-                emitm_pushl_r(jit_info->native_ptr, emit_EAX);
-                break;
-            case PARROT_ARG_KI:
-            case PARROT_ARG_I:
-                if (MAP(i))
-                    emitm_pushl_r(jit_info->native_ptr, MAP(i));
-                else {
-                    emitm_movl_m_r(interp, jit_info->native_ptr,
-                            emit_EAX, emit_EBX, emit_None, 1, REG_OFFS_INT(pi));
-                    emitm_pushl_r(jit_info->native_ptr, emit_EAX);
-                }
-                break;
-                break;
-            case PARROT_ARG_KIC:
-            case PARROT_ARG_IC:
-                /* XXX INTVAL_SIZE */
-                /* push value */
-                emitm_pushl_i(jit_info->native_ptr, pi);
-                break;
-            case PARROT_ARG_N:
-                /* push num on st(0) */
-                if (MAP(i))
-                    emitm_fld(jit_info->native_ptr, MAP(i));
-                else
-                    jit_emit_fload_mb_n(interp, jit_info->native_ptr,
-                            emit_EBX, REG_OFFS_NUM(pi));
-                goto store;
-            case PARROT_ARG_NC:
-                /*
-                 * TODO not all constants are shared between interpreters
-                 */
-#  if EXEC_CAPABLE
-                if (jit_info->objfile) {
-                    jit_emit_fload_m_n(interp, jit_info->native_ptr, JIT_CONST(i));
-                    Parrot_exec_add_text_rellocation(jit_info->objfile,
-                            jit_info->native_ptr, RTYPE_DATA, "const_table", -4);
-                }
-                else
-#  endif
-                    jit_emit_fload_m_n(interp, jit_info->native_ptr,
-                            &interp->code->const_table->
-                            constants[pi]->u.number);
-store:
-#  if NUMVAL_SIZE == 8
-                /* make room for double */
-                emitm_addb_i_r(jit_info->native_ptr, -8, emit_ESP);
-                emitm_fstpl(interp, jit_info->native_ptr, emit_ESP, emit_None, 1, 0);
-                /* additional stack adjustment */
-                st += 4;
-#  else
-                emitm_addb_i_r(jit_info->native_ptr, -12, emit_ESP);
-                emitm_fstpt(jit_info->native_ptr, emit_ESP, emit_None, 1, 0);
-                st += 8;
-#  endif
-                break;
-
-            case PARROT_ARG_SC:
-#  if EXEC_CAPABLE
-                if (jit_info->objfile) {
-                    emitm_pushl_m(jit_info->native_ptr, JIT_CONST(i));
-                    Parrot_exec_add_text_rellocation(jit_info->objfile,
-                            jit_info->native_ptr, RTYPE_DATA, "const_table", -4);
-                }
-                else
-#  endif
-                    emitm_pushl_i(jit_info->native_ptr,
-                            interp->code->const_table->
-                            constants[pi]->u.string);
-                break;
-
-            case PARROT_ARG_KC:
-            case PARROT_ARG_PC:
-#  if EXEC_CAPABLE
-                if (jit_info->objfile) {
-                    emitm_pushl_m(jit_info->native_ptr, JIT_CONST(i));
-                    Parrot_exec_add_text_rellocation(jit_info->objfile,
-                            jit_info->native_ptr, RTYPE_DATA,
-                            "const_table", -4);
-                }
-                else
-#  endif
-                    emitm_pushl_i(jit_info->native_ptr,
-                            interp->code->const_table->
-                            constants[pi]->u.key);
-                break;
-
-            default:
-                Parrot_ex_throw_from_c_args(interp, NULL, 1,
-                    "jit_vtable_n_op: unimp type %d, arg %d vtable %d",
-                    op_info->types[i - 1], i, nvtable);
-                break;
-        }
-    }
-
-    /* push interpreter */
-    Parrot_jit_emit_get_INTERP(interp, jit_info->native_ptr, emit_ECX);
-    emitm_pushl_r(jit_info->native_ptr, emit_ECX);
-
-    if (L4) {
-        emitm_callr(jit_info->native_ptr, emit_ESI);
-    }
-    else {
-        /* mov (offs)%eax, %eax i.e. $1->vtable */
-        emitm_movl_m_r(interp, jit_info->native_ptr, emit_EAX, emit_EAX, emit_None, 1,
-                offsetof(struct PMC, vtable));
-        /* call *(offset)eax */
-        emitm_callm(jit_info->native_ptr, emit_EAX, emit_None, emit_None, offset);
-    }
-
-    emitm_addb_i_r(jit_info->native_ptr,
-            st + sizeof (void *) * (n + 1), emit_ESP);
-
-    /* L4: */
-    if (L4)
-        L4[1] = (char)(jit_info->native_ptr - L4 - 2);
-}
-
-void
-Parrot_jit_store_retval(Parrot_jit_info_t *jit_info,
-                     PARROT_INTERP)
-{
-    op_info_t *op_info = &interp->op_info_table[*jit_info->cur_op];
-    int p1 = *(jit_info->cur_op + 1);
-
-    /* return result is in EAX or ST(0) */
-    switch (op_info->types[0]) {
-        case PARROT_ARG_I:
-            emitm_movl_r_m(interp, jit_info->native_ptr,
-                    emit_EAX, emit_EBX, emit_None, 1, REG_OFFS_INT(p1));
-            break;
-        case PARROT_ARG_S:
-            emitm_movl_r_m(interp, jit_info->native_ptr,
-                    emit_EAX, emit_EBX, emit_None, 1, REG_OFFS_STR(p1));
-            break;
-        case PARROT_ARG_P:
-            emitm_movl_r_m(interp, jit_info->native_ptr,
-                    emit_EAX, emit_EBX, emit_None, 1, REG_OFFS_PMC(p1));
-            break;
-        case PARROT_ARG_N:
-            jit_emit_fstore_mb_n(interp, jit_info->native_ptr, emit_EBX,
-                    REG_OFFS_NUM(p1));
-            break;
-        default:
-            Parrot_ex_throw_from_c_args(interp, NULL, 1, "jit_vtable1r: ill LHS");
-            break;
-    }
-}
-
-/* emit a call to a vtable func
- * $1->vtable(interp, $1)
- */
-void
-Parrot_jit_vtable1_op(Parrot_jit_info_t *jit_info,
-                     PARROT_INTERP)
-{
-    int a[] = { 1 };
-    Parrot_jit_vtable_n_op(jit_info, interp, 1, a);
-}
-
-/* emit a call to a vtable func
- * $1 = $2->vtable(interp, $2)
- */
-void
-Parrot_jit_vtable1r_op(Parrot_jit_info_t *jit_info,
-                     PARROT_INTERP)
-{
-    int a[] = { 2 };
-    Parrot_jit_vtable_n_op(jit_info, interp, 1, a);
-    Parrot_jit_store_retval(jit_info, interp);
-}
-
-
-/* emit a call to a vtable func
- * $1 = $2->vtable(interp, $2, $3)
- */
-void
-Parrot_jit_vtable_1r223_op(Parrot_jit_info_t *jit_info,
-                     PARROT_INTERP)
-{
-    int a[] = { 2 , 3};
-    Parrot_jit_vtable_n_op(jit_info, interp, 2, a);
-    Parrot_jit_store_retval(jit_info, interp);
-}
-
-/* emit a call to a vtable func
- * $1 = $3->vtable(interp, $3, $2)
- */
-void
-Parrot_jit_vtable_1r332_op(Parrot_jit_info_t *jit_info,
-                     PARROT_INTERP)
-{
-    int a[] = { 3 , 2};
-    Parrot_jit_vtable_n_op(jit_info, interp, 2, a);
-    Parrot_jit_store_retval(jit_info, interp);
-}
-
-/* emit a call to a vtable func
- * $1->vtable(interp, $1, $2)
- */
-void
-Parrot_jit_vtable_112_op(Parrot_jit_info_t *jit_info,
-                     PARROT_INTERP)
-{
-    int a[] = { 1, 2 };
-    Parrot_jit_vtable_n_op(jit_info, interp, 2, a);
-}
-
-/* emit a call to a vtable func
- * $1->vtable(interp, $1, $1)
- */
-void
-Parrot_jit_vtable_111_op(Parrot_jit_info_t *jit_info,
-                     PARROT_INTERP)
-{
-    int a[] = { 1, 1 };
-    Parrot_jit_vtable_n_op(jit_info, interp, 2, a);
-}
-
-/* emit a call to a vtable func
- * $2->vtable(interp, $2, $1)
- */
-void
-Parrot_jit_vtable_221_op(Parrot_jit_info_t *jit_info,
-                     PARROT_INTERP)
-{
-    int a[] = { 2, 1 };
-    Parrot_jit_vtable_n_op(jit_info, interp, 2, a);
-}
-
-/* emit a call to a vtable func
- * $2->vtable(interp, $2, $3, $1)
- */
-void
-Parrot_jit_vtable_2231_op(Parrot_jit_info_t *jit_info,
-                     PARROT_INTERP)
-{
-    int a[] = { 2, 3, 1 };
-    Parrot_jit_vtable_n_op(jit_info, interp, 3, a);
-}
-
-/* emit a call to a vtable func
- * $1->vtable(interp, $1, $2, $3)
- */
-void
-Parrot_jit_vtable_1123_op(Parrot_jit_info_t *jit_info,
-                     PARROT_INTERP)
-{
-    int a[] = { 1, 2, 3 };
-    Parrot_jit_vtable_n_op(jit_info, interp, 3, a);
-}
-
-/* emit a call to a vtable func
- * $1->vtable(interp, $1, $2, $1)
- */
-void
-Parrot_jit_vtable_1121_op(Parrot_jit_info_t *jit_info,
-                     PARROT_INTERP)
-{
-    int a[] = { 1, 2, 1 };
-    Parrot_jit_vtable_n_op(jit_info, interp, 3, a);
-}
-
-/* if_p_ic, unless_p_ic */
-void
-Parrot_jit_vtable_if_unless_op(Parrot_jit_info_t *jit_info,
-                     PARROT_INTERP, int unless)
-{
-    int ic = *(jit_info->cur_op + 2);   /* branch offset */
-
-    /* emit call  vtable function i.e. get_bool, result eax */
-    Parrot_jit_vtable1_op(jit_info, interp);
-    /* test result */
-    jit_emit_test_r_i(jit_info->native_ptr, emit_EAX);
-    jit_emit_jcc(jit_info, unless ? emitm_jz : emitm_jnz, ic);
-}
-
-/* unless_p_ic */
-void
-Parrot_jit_vtable_unlessp_op(Parrot_jit_info_t *jit_info,
-                     PARROT_INTERP)
-{
-    Parrot_jit_vtable_if_unless_op(jit_info, interp, 1);
-}
-
-/* if_p_ic */
-void
-Parrot_jit_vtable_ifp_op(Parrot_jit_info_t *jit_info,
-                     PARROT_INTERP)
-{
-    Parrot_jit_vtable_if_unless_op(jit_info, interp, 0);
-}
-
-/* new_p_ic */
-void
-Parrot_jit_vtable_newp_ic_op(Parrot_jit_info_t *jit_info,
-                     PARROT_INTERP)
-{
-    int p1, i2;
-    op_info_t *op_info = &interp->op_info_table[*jit_info->cur_op];
-    size_t offset = offsetof(VTABLE, init);
-
-    PARROT_ASSERT(op_info->types[0] == PARROT_ARG_P);
-    p1 = *(jit_info->cur_op + 1);
-    i2 = *(jit_info->cur_op + 2);
-
-    if (i2 <= 0 || i2 >= interp->n_vtable_max)
-        Parrot_ex_throw_from_c_args(interp, NULL, 1,
-            "Illegal PMC enum (%d) in new", i2);
-
-    /* get interpreter */
-    Parrot_jit_emit_get_INTERP(interp, jit_info->native_ptr, emit_ECX);
-
-    /* push pmc enum and interpreter */
-    emitm_pushl_i(jit_info->native_ptr, i2);
-    emitm_pushl_r(jit_info->native_ptr, emit_ECX);
-#  if EXEC_CAPABLE
-    if (jit_info->objfile) {
-        JIT_CALL("pmc_new_noinit");
-    }
-    else
-#  endif
-    {
-        call_func(jit_info, (void (*) (void))pmc_new_noinit);
-    }
-    /* result = eax push pmc */
-    emitm_pushl_r(jit_info->native_ptr, emit_EAX);
-    /* store in PMC too */
-    emitm_movl_r_m(interp, jit_info->native_ptr,
-            emit_EAX, emit_EBX, emit_None, 1, REG_OFFS_PMC(p1));
-    /* push interpreter */
-    Parrot_jit_emit_get_INTERP(interp, jit_info->native_ptr, emit_ECX);
-    emitm_pushl_r(jit_info->native_ptr, emit_ECX);
-    /* mov (offs)%eax, %eax i.e. $1->vtable */
-    emitm_movl_m_r(interp, jit_info->native_ptr, emit_EAX, emit_EAX, emit_None, 1,
-            offsetof(struct PMC, vtable));
-    /* call *(offset)eax */
-    emitm_callm(jit_info->native_ptr, emit_EAX, emit_None, emit_None, offset);
-    /* adjust 4 args pushed */
-    emitm_addb_i_r(jit_info->native_ptr, 16, emit_ESP);
-}
-
-void
-jit_get_params_pc(Parrot_jit_info_t *jit_info, PARROT_INTERP)
-{
-    PMC *sig_pmc;
-    INTVAL *sig_bits, i, n;
-
-    sig_pmc = CONTEXT(interp)->constants[CUR_OPCODE[1]]->u.key;
-    sig_bits = SIG_ARRAY(sig_pmc);
-    n = SIG_ELEMS(sig_pmc);
-    jit_info->n_args = n;
-    emitm_movl_m_r(interp, NATIVECODE, emit_EAX, emit_EBP, emit_None, 1, 16);
-    for (i = 0; i < n; ++i) {
-        switch (sig_bits[i] & PARROT_ARG_TYPE_MASK) {
-            case PARROT_ARG_INTVAL:
-                emitm_movl_m_r(interp, NATIVECODE, MAP(2+i), emit_EAX, emit_None,
-                        1, 4 + i*4);
-                break;
-            case PARROT_ARG_FLOATVAL:
-                emitm_movl_m_r(interp, NATIVECODE, emit_EAX, emit_EAX, emit_None,
-                        1, 4+ i*4);
-                jit_emit_fload_mb_n(interp, NATIVECODE, emit_EAX, 0);
-                emitm_fstp(NATIVECODE, (MAP(2+i) + 1));
-                if (i < n - 1)
-                    emitm_movl_m_r(interp, NATIVECODE, emit_EAX, emit_EBP,
-                            emit_None, 1, 16);
-                break;
-            default:
-                break;
-        }
-    }
-}
-
-/*
- * preserve registers
- * a) all callee saved on function entry
- */
-void
-jit_save_regs(Parrot_jit_info_t *jit_info, PARROT_INTERP)
-{
-    int i, used_i, save_i;
-    const jit_arch_regs *reg_info;
-
-    used_i = CONTEXT(interp)->n_regs_used[REGNO_INT];
-    reg_info = &jit_info->arch_info->regs[jit_info->code_type];
-    save_i = reg_info->n_preserved_I;
-    for (i = save_i; i < used_i; ++i) {
-        emitm_pushl_r(jit_info->native_ptr, reg_info->map_I[i]);
-    }
-}
-
-/* restore saved regs, see above */
-void
-jit_restore_regs(Parrot_jit_info_t *jit_info, PARROT_INTERP)
-{
-
-    int i, used_i, save_i;
-    const jit_arch_regs *reg_info;
-
-    used_i = CONTEXT(interp)->n_regs_used[REGNO_INT];
-    reg_info = &jit_info->arch_info->regs[jit_info->code_type];
-    save_i = reg_info->n_preserved_I;
-    /* note - reversed order of jit_save_regs  */
-    for (i = used_i - 1; i >= save_i; --i) {
-        emitm_popl_r(jit_info->native_ptr, reg_info->map_I[i]);
-    }
-}
-
-/*
- * preserve registers around a functioncall
- *
- * all used register around a call (skip >= 0 := return result
- *
- * TODO factor out common code
- *      use jit_emit_mov_RM_{in} functions (load/store base indexed)
- *      and a macro to retrive sp
- */
-int
-jit_save_regs_call(Parrot_jit_info_t *jit_info, PARROT_INTERP, int skip)
-{
-    int i, used_i, used_n;
-    const jit_arch_regs *reg_info;
-
-    used_i = CONTEXT(interp)->n_regs_used[REGNO_INT];
-    used_n = CONTEXT(interp)->n_regs_used[REGNO_NUM];
-    jit_emit_sub_ri_i(interp, jit_info->native_ptr, emit_ESP,
-            (used_i * sizeof (INTVAL) + used_n * sizeof (FLOATVAL)));
-    reg_info = &jit_info->arch_info->regs[jit_info->code_type];
-    for (i = 0; i < used_i; ++i) {
-        /* XXX need 2 skip vars */
-        if (reg_info->map_I[i] == skip)
-            continue;
-        emitm_movl_r_m(interp, NATIVECODE, reg_info->map_I[i], emit_ESP,
-                            emit_None, 1,
-                            (used_n * sizeof (FLOATVAL) +
-                             i      * sizeof (INTVAL)));
-    }
-    for (i = 0; i < used_n; ++i) {
-        if (reg_info->map_F[i] == skip)
-            continue;
-        emitm_fld(NATIVECODE, reg_info->map_F[i]);
-        jit_emit_fstore_mb_n(interp, NATIVECODE, emit_ESP, (i * sizeof (FLOATVAL)));
-    }
-    return used_n;
-}
-
-void
-jit_restore_regs_call(Parrot_jit_info_t *jit_info, PARROT_INTERP,
-        int skip)
-{
-
-    int i, used_i, used_n;
-    const jit_arch_regs *reg_info;
-
-    used_i = CONTEXT(interp)->n_regs_used[REGNO_INT];
-    used_n = CONTEXT(interp)->n_regs_used[REGNO_NUM];
-    reg_info = &jit_info->arch_info->regs[jit_info->code_type];
-
-    for (i = 0; i < used_i; ++i) {
-        if (reg_info->map_I[i] == skip)
-            continue;
-        emitm_movl_m_r(interp, NATIVECODE, reg_info->map_I[i], emit_ESP,
-                            emit_None, 1,
-                            (used_n * sizeof (FLOATVAL) +
-                             i      * sizeof (INTVAL)));
-    }
-    for (i = 0; i < used_n; ++i) {
-        if (reg_info->map_F[i] == skip)
-            continue;
-        jit_emit_fload_mb_n(interp, NATIVECODE, emit_ESP, (i * sizeof (FLOATVAL)));
-        emitm_fstp(NATIVECODE, (1+reg_info->map_F[i]));
-    }
-
-    jit_emit_add_ri_i(interp, jit_info->native_ptr, emit_ESP,
-            (used_i * sizeof (INTVAL) + used_n * sizeof (FLOATVAL)));
-}
-
-void
-jit_set_returns_pc(Parrot_jit_info_t *jit_info, PARROT_INTERP,
-        int recursive)
-{
-    PMC *sig_pmc;
-    INTVAL *sig_bits, sig;
-
-    sig_pmc = CONTEXT(interp)->constants[CUR_OPCODE[1]]->u.key;
-    if (!SIG_ELEMS(sig_pmc))
-        return;
-    sig_bits = SIG_ARRAY(sig_pmc);
-    sig = sig_bits[0];
-    if (!recursive) {
-        /* mov 16(%ebp), %eax - fetch args ptr */
-        emitm_movl_m_r(interp, NATIVECODE, emit_EAX, emit_EBP, emit_None, 1, 16);
-        emitm_movl_m_r(interp, NATIVECODE, emit_EAX, emit_EAX, emit_None, 1, 0);
-    }
-    /*
-     * recursive returns according to ABI */
-    switch (sig & (PARROT_ARG_TYPE_MASK|PARROT_ARG_CONSTANT)) {
-        case PARROT_ARG_INTVAL:
-            if (recursive) {
-                jit_emit_mov_rr_i(NATIVECODE, emit_EAX, MAP(2));
-            }
-            else {
-                emitm_movl_r_m(interp, NATIVECODE, MAP(2), emit_EAX, 0, 1, 0);
-            }
-            break;
-        case PARROT_ARG_INTVAL|PARROT_ARG_CONSTANT:
-            if (recursive) {
-                jit_emit_mov_ri_i(interp, NATIVECODE, emit_EAX, CUR_OPCODE[2]);
-            }
-            else {
-                emitm_movl_i_m(NATIVECODE, CUR_OPCODE[2], emit_EAX, 0, 1, 0);
-            }
-            break;
-        case PARROT_ARG_FLOATVAL:
-            if (recursive) {
-                jit_emit_mov_rr_n(NATIVECODE, FSR1, MAP(2));
-            }
-            else {
-                emitm_fld(NATIVECODE, MAP(2));
-                jit_emit_fstore_mb_n(interp, NATIVECODE, emit_EAX, 0);
-            }
-            break;
-        case PARROT_ARG_FLOATVAL|PARROT_ARG_CONSTANT:
-            if (recursive) {
-                jit_emit_mov_ri_n(interp, NATIVECODE, FSR1, &JIT_CONST(2)->u.number);
-            }
-            else {
-                jit_emit_mov_ri_n(interp, NATIVECODE, FSR1, &JIT_CONST(2)->u.number);
-                jit_emit_fstore_mb_n(interp, NATIVECODE, emit_EAX, 0);
-            }
-            break;
-        default:
-            Parrot_ex_throw_from_c_args(interp, NULL, 1,
-                "set_returns_jit - unknown typ");
-            break;
-    }
-}
-
-void
-jit_set_args_pc(Parrot_jit_info_t *jit_info, PARROT_INTERP,
-        int recursive)
-{
-    PMC *sig_args, *sig_params, *sig_result;
-    INTVAL *sig_bits, sig, i, n;
-    PackFile_Constant ** constants;
-    opcode_t *params, *result;
-    char params_map;
-    int skip, used_n;
-    char collision[16];
-    const jit_arch_regs *reg_info;
-
-    reg_info = &jit_info->arch_info->regs[jit_info->code_type];
-
-    /* create args array */
-    if (!recursive)
-        Parrot_ex_throw_from_c_args(interp, NULL, 1,
-            "set_args_jit - can't do that yet ");
-
-    constants = CONTEXT(interp)->constants;
-    sig_args  = constants[CUR_OPCODE[1]]->u.key;
-
-    if (!SIG_ELEMS(sig_args))
-        return;
-    params = jit_info->optimizer->sections->begin;
-    sig_params = constants[params[1]]->u.key;
-    ASSERT_SIG_PMC(sig_params);
-    sig_bits = SIG_ARRAY(sig_args);
-    n = SIG_ELEMS(sig_args);
-    /*
-     * preserve registers - need get_results, because we skip the
-     * return value
-     */
-    result = CUR_OPCODE + 2 + n + 3; /* set_args, set_p_pc */
-    PARROT_ASSERT(*result == PARROT_OP_get_results_pc);
-    sig_result = constants[result[1]]->u.key;
-    ASSERT_SIG_PMC(sig_result);
-
-    if (!SIG_ELEMS(sig_result))
-        skip = -1;
-    else
-        skip = MAP(2 + n + 3 + 2);
-    used_n = jit_save_regs_call(jit_info, interp, skip);
-    memset(collision, 0, 16);
-    for (i = 0; i < n; ++i) {
-        sig = sig_bits[i];
-        /* move args to params regs */
-        params_map = jit_info->optimizer->map_branch[2 + i];
-        switch (sig & (PARROT_ARG_TYPE_MASK|PARROT_ARG_CONSTANT)) {
-            case PARROT_ARG_INTVAL:
-                /* if the arg was already set,
-                 * we can't use the src again - fetch from stack
-                 *
-                 * XXX skip
-                 *
-                 * TODO write a general reg_move
-                 */
-                if (collision[(int)MAP(2+i)]) {
-                    int j;
-                    for (j = 0; j < reg_info->n_mapped_I; ++j) {
-                        if (reg_info->map_I[j] == MAP(2+i)) {
-                            emitm_movl_m_r(interp, NATIVECODE, params_map, emit_ESP,
-                                    emit_None, 1,
-                                    (used_n * sizeof (FLOATVAL) +
-                                     j  * sizeof (INTVAL)));
-                            break;
-                        }
-                    }
-                }
-                else {
-                    if (params_map != MAP(2+i)) {
-                        jit_emit_mov_rr_i(NATIVECODE, params_map, MAP(2 + i));
-                    }
-                }
-                collision[(int)params_map] = 1;
-                break;
-            case PARROT_ARG_INTVAL|PARROT_ARG_CONSTANT:
-                /* TODO move constants last */
-                jit_emit_mov_ri_i(interp, NATIVECODE, params_map, CUR_OPCODE[2 + i]);
-                break;
-            case PARROT_ARG_FLOATVAL:
-                if (collision[(int)MAP(2+i)]) {
-                    int j;
-                    for (j = 0; j < reg_info->n_mapped_F; ++j) {
-                        if (reg_info->map_F[j] == MAP(2+i)) {
-                            jit_emit_fload_mb_n(interp, NATIVECODE, emit_ESP, (j * sizeof (FLOATVAL)));
-                            emitm_fstp(NATIVECODE, (1+params_map));
-                            break;
-                        }
-                    }
-                }
-                else {
-                    jit_emit_mov_rr_n(NATIVECODE, params_map, MAP(2 + i));
-                }
-                collision[(int)params_map] = 1;
-                break;
-            case PARROT_ARG_FLOATVAL|PARROT_ARG_CONSTANT:
-                jit_emit_mov_ri_n(interp, NATIVECODE, params_map,
-                        &JIT_CONST(2 + i)->u.number);
-                break;
-            default:
-                Parrot_ex_throw_from_c_args(interp, NULL, 1,
-                    "set_args_jit - unknown type");
-                break;
-        }
-    }
-}
-
-void
-Parrot_jit_dofixup(Parrot_jit_info_t *jit_info, PARROT_INTERP)
-{
-    Parrot_jit_fixup_t *fixup, *next;
-    char *fixup_ptr;
-
-    fixup = jit_info->arena.fixups;
-
-    while (fixup) {
-        switch (fixup->type) {
-        /* This fixes-up a branch to a known opcode offset -
-           32-bit displacement only */
-            case JIT_X86BRANCH:
-                fixup_ptr = Parrot_jit_fixup_target(jit_info, fixup) + 2;
-                *(long *)(fixup_ptr) =
-                    jit_info->arena.op_map[fixup->param.opcode].offset
-                        - (fixup->native_offset + 6) + fixup->skip;
-                break;
-            case JIT_X86JUMP:
-                fixup_ptr = Parrot_jit_fixup_target(jit_info, fixup) + 1;
-                *(long *)(fixup_ptr) =
-                    jit_info->arena.op_map[fixup->param.opcode].offset
-                        - (fixup->native_offset + 5) + fixup->skip;
-                break;
-            case JIT_X86CALL:
-                fixup_ptr = jit_info->arena.start + fixup->native_offset + 1;
-                *(long *)(fixup_ptr) = (long)fixup->param.fptr -
-                    (long)fixup_ptr - 4;
-                break;
-            default:
-                Parrot_ex_throw_from_c_args(interp, NULL, EXCEPTION_JIT_ERROR,
-                    "Unknown fixup type:%d\n", fixup->type);
-            break;
-        }
-        next = fixup->next;
-        free(fixup);
-        fixup = next;
-    }
-    jit_info->arena.fixups = NULL;
-}
-
-static int control_word = 0x27f;
-
-#  ifdef JIT_CGP
-
-#    include <parrot/oplib/core_ops_cgp.h>
-/*
- * This is the somewhat complicated program flow
- *
- * JIT code                     prederef code
- * 1) jit_begin
- *    stack_enter
- *    call cgp_core  -->        set stack frame
- *                              jump to retaddr
- *    test EAX, 0    <--        also from HALT
- *    jnz code_start
- *    stack_leave
- *    ret
- * code_start: of JIT code
- *    jit code
- *    ....
- *
- * 2) normal_op
- *    mov prederef_code_ptr, esi
- *    call *(esi)    ---->      prederefed (non JITted code)
- *                              ....
- *    ....           <----      ret
- *    jit_code
- *    ....
- * 3) HALT == jit_end
- *    mov prederefed_op_func[0], esi
- *    jump *esi      ----->     cleanup prederef stack frame
- *                              xor eax,eax ; return 0
- *                              ret (--> after call cgp_core in 1)
- *
- */
-
-void
-Parrot_jit_begin(Parrot_jit_info_t *jit_info,
-                 PARROT_INTERP)
-{
-    jit_emit_stack_frame_enter(jit_info->native_ptr);
-    emitm_fldcw(interp, jit_info->native_ptr, &control_word);
-    emitm_pushl_r(jit_info->native_ptr, emit_EBX);
-    /* get the pc from stack:  mov 12(%ebp), %ebx */
-    emitm_movl_m_r(interp, jit_info->native_ptr, emit_EBX, emit_EBP, emit_None, 1, 12);
-    /* emit cgp_core(1, interp) */
-    /* get the interpreter from stack:  mov 8(%ebp), %eax */
-    emitm_movl_m_r(interp, jit_info->native_ptr, emit_EAX, emit_EBP, emit_None, 1, 8);
-    emitm_pushl_r(jit_info->native_ptr, emit_EAX);
-    /*
-     * TODO define the offset of the interpreter on the stack
-     *      relative to %ebp
-     */
-    emitm_pushl_i(jit_info->native_ptr, 1);
-    /* use EAX as flag, when jumping back on init, EAX==1 */
-    jit_emit_mov_ri_i(interp, jit_info->native_ptr, emit_EAX, 1);
-    if (!jit_info->objfile)
-        call_func(jit_info, (void (*)(void))cgp_core);
-#    if EXEC_CAPABLE
-    else {
-        Parrot_exec_add_text_rellocation_func(jit_info->objfile,
-            jit_info->native_ptr, "cgp_core");
-        emitm_calll(jit_info->native_ptr, EXEC_CALLDISP);
-    }
-#    endif
-    /* when cur_opcode == 1, cgp_core jumps back here
-     * when EAX == 0, the official return from HALT was called */
-    jit_emit_test_r_i(jit_info->native_ptr, emit_EAX);
-    emitm_jxs(jit_info->native_ptr, emitm_jnz, 5);
-    emitm_popl_r(jit_info->native_ptr, emit_EBX);
-    jit_emit_stack_frame_leave(jit_info->native_ptr);
-    emitm_ret(jit_info->native_ptr);
-    /* get PC = ebx to eax, jump there */
-    jit_emit_mov_rr_i(jit_info->native_ptr, emit_EAX, emit_EBX);
-    Parrot_emit_jump_to_eax(jit_info, interp);
-
-/* code_start: */
-}
-
-#  else /* JIT_CGP */
-void
-Parrot_jit_begin(Parrot_jit_info_t *jit_info,
-                 PARROT_INTERP)
-{
-    /* the generated code gets called as:
-     * (jit_code)(interp, pc)
-     * jumping to pc is the same code as used in Parrot_jit_cpcf_op()
-     */
-
-    /* Maintain the stack frame pointer for the sake of gdb */
-    jit_emit_stack_frame_enter(jit_info->native_ptr);
-    emitm_fldcw(interp, jit_info->native_ptr, &control_word);
-    /* stack:
-     *  12   pc
-     *   8   interpreter
-     *   4   retaddr
-     *   0   ebp <----- ebp
-     *  -4   ebx .. preserved regs
-     *  -8   esi ..
-     * -12   edi ..
-     * -16   interpreter
-     */
-
-    /* Save all callee-saved registers (cdecl)
-     */
-    emitm_pushl_r(jit_info->native_ptr, emit_EBX);
-    emitm_pushl_r(jit_info->native_ptr, emit_ESI);
-    emitm_pushl_r(jit_info->native_ptr, emit_EDI);
-
-    /* Cheat on op function calls by writing the interpreter arg on the stack
-     * just once. If an op function ever modifies the interpreter argument on
-     * the stack this will stop working !!! */
-
-    /* get the interpreter from stack:  mov 8(%ebp), %eax */
-    emitm_movl_m_r(interp, jit_info->native_ptr, emit_EAX, emit_EBP, emit_None, 1, 8);
-    emitm_pushl_r(jit_info->native_ptr, emit_EAX);
-
-    /* get the pc from stack:  mov 12(%ebp), %eax */
-    emitm_movl_m_r(interp, jit_info->native_ptr, emit_EAX, emit_EBP, emit_None, 1, 12);
-
-    /* jump to restart pos or first op */
-    Parrot_emit_jump_to_eax(jit_info, interp);
-}
-
-#  endif /* JIT_CGP */
-
-/*
- * create a JITted version of a PIR sub, where everything
- * resided in registers
- *
- * The sub is called as
- *
- *   opcode_t * func(Interp *i, INTVAL *sig_bits, void **args);
- *
- *   args[0] ...    NULL / return value address
- *   args[1..n] ... addresses of n arguments
- *   args[n + 1] .. opcode_t* next - ususally just returned
- */
-
-void
-Parrot_jit_begin_sub_regs(Parrot_jit_info_t *jit_info,
-                 PARROT_INTERP)
-{
-    jit_emit_stack_frame_enter(jit_info->native_ptr);
-    /* stack:
-     *  16   args
-     *  12   sig_bits
-     *   8   interpreter
-     *   4   retaddr
-     *   0   ebp <----- ebp
-     * [ -4   ebx .. preserved regs ]
-     * [ -8   edi .. preserved regs ]
-     */
-    /*
-     * check register usage of the subroutine
-     * how many we have to preserve
-     */
-    jit_save_regs(jit_info, interp);
-    /* when it's a recursive sub, we fetch params to registers
-     * and all a inner helper sub, which run with registers only
-     */
-    if (jit_info->flags & JIT_CODE_RECURSIVE) {
-        char * L1;
-        PackFile_Constant ** constants;
-        PMC *sig_result;
-        opcode_t *result;
-
-        jit_get_params_pc(jit_info, interp);
-        /* remember fixup position - call sub */
-        L1 = NATIVECODE;
-        emitm_calll(NATIVECODE, 0);
-        /* check type of return value */
-        constants = CONTEXT(interp)->constants;
-        result = CONTEXT(interp)->current_results;
-        sig_result = constants[result[1]]->u.key;
-        if (!SIG_ELEMS(sig_result))
-            goto no_result;
-        /* fetch args to %edx */
-        emitm_movl_m_r(interp, NATIVECODE, emit_EDX, emit_EBP, emit_None, 1, 16);
-        emitm_movl_m_r(interp, NATIVECODE, emit_ECX, emit_EDX, emit_None, 1, 0);
-        if (SIG_ITEM(sig_result, 0) == PARROT_ARG_FLOATVAL) {
-            jit_emit_fst_mb_n(interp, jit_info->native_ptr, emit_ECX, 0);
-        }
-        else {
-            emitm_movl_r_m(interp, NATIVECODE, emit_EAX, emit_ECX, 0, 1, 0);
-        }
-no_result:
-        /* return 0 - no branch */
-        jit_emit_bxor_rr_i(interp, NATIVECODE, emit_EAX, emit_EAX);
-        /* restore pushed callee saved */
-        jit_restore_regs(jit_info, interp);
-        jit_emit_stack_frame_leave(NATIVECODE);
-        emitm_ret(NATIVECODE);
-        /* align the inner sub */
-#  if SUB_ALIGN
-        while ((long)jit_info->native_ptr & ((1<<SUB_ALIGN) - 1)) {
-            jit_emit_noop(jit_info->native_ptr);
-        }
-#  endif
-        /* fixup call statement */
-        L1[1] = NATIVECODE - L1 - 5;
-    }
-    /* TODO be sure we got a label here in map_branch */
-}
-
-
-void
-Parrot_jit_begin_sub(Parrot_jit_info_t *jit_info,
-                 PARROT_INTERP)
-{
-}
-
-void
-jit_mov_mr_n_offs(PARROT_INTERP, Parrot_jit_info_t *jit_info,
-        int base_reg, INTVAL offs, int src_reg)
-{
-    emitm_fld(jit_info->native_ptr, src_reg);
-    jit_emit_fstore_mb_n(interp, jit_info->native_ptr, base_reg, offs);
-}
-
-void
-jit_mov_mr_offs(PARROT_INTERP, Parrot_jit_info_t *jit_info,
-        int base_reg, INTVAL offs, int src_reg)
-{
-    emitm_movl_r_m(interp, jit_info->native_ptr,
-            src_reg, base_reg, emit_None, 1, offs);
-}
-
-void
-jit_mov_rm_n_offs(PARROT_INTERP, Parrot_jit_info_t *jit_info,
-        int dst_reg, int base_reg, INTVAL offs)
-{
-    jit_emit_fload_mb_n(interp, jit_info->native_ptr, base_reg,  offs);
-    emitm_fstp(jit_info->native_ptr, (dst_reg+1));
-}
-
-void
-jit_mov_rm_offs(PARROT_INTERP, Parrot_jit_info_t *jit_info,
-        int dst_reg, int base_reg, INTVAL offs)
-{
-    emitm_movl_m_r(interp, jit_info->native_ptr,
-            dst_reg, base_reg, emit_None, 1, offs);
-}
-
-void
-Parrot_jit_emit_finit(Parrot_jit_info_t *jit_info)
-{
-    jit_emit_finit(jit_info->native_ptr);
-}
-
-void
-Parrot_jit_cpcf_op(Parrot_jit_info_t *jit_info,
-                   PARROT_INTERP)
-{
-    Parrot_jit_normal_op(jit_info, interp);
-    Parrot_emit_jump_to_eax(jit_info, interp);
-}
-
-/* autogened inside core.ops */
-
-void
-Parrot_jit_restart_op(Parrot_jit_info_t *jit_info,
-                   PARROT_INTERP)
-{
-    char *jmp_ptr, *sav_ptr;
-
-    Parrot_jit_normal_op(jit_info, interp);
-    /* test eax, if zero (e.g after trace), return from JIT */
-    jit_emit_test_r_i(jit_info->native_ptr, emit_EAX);
-    /* remember PC */
-    jmp_ptr = jit_info->native_ptr;
-    /* emit jump past exit code, dummy offset
-     * this assumes exit code is not longer then a short jump (126 bytes) */
-    emitm_jxs(jit_info->native_ptr, emitm_jnz, 0);
-    jit_emit_end(jit_info->native_ptr);
-    /* fixup above jump */
-    sav_ptr = jit_info->native_ptr;
-    jit_info->native_ptr = jmp_ptr;
-    emitm_jxs(jit_info->native_ptr, emitm_jnz, (long)(sav_ptr - jmp_ptr) - 2);
-    /* restore PC */
-    jit_info->native_ptr = sav_ptr;
-    Parrot_emit_jump_to_eax(jit_info, interp);
-}
-
-/*
- * params are put rigth to left on the stack
- * parrot registers are counted left to right
- * so this function returns for a given register type
- * the needed register number
- * TODO handel overflow params
- */
-int
-count_regs(PARROT_INTERP, char *sig, char *sig_start)
-{
-    const char *typs[] = {
-        "Ilisc",         /* I */
-        "StbB",          /* S */
-        "pP234",         /* P */
-        "Nfd"            /* N */
-    };
-    int first_reg = 0;
-    int i, found;
-
-    /* char at sig is the type to look at */
-    for (found = -1, i = 0; i < 4; i++) {
-        if (strchr(typs[i], *sig)) {
-            found = i;
-            break;
-        }
-    }
-
-    if (found == -1)
-        Parrot_ex_throw_from_c_args(interp, NULL, 1,
-            "Parrot_jit_build_call_func: sig char not found\n");
-
-    for (--sig; sig > sig_start; --sig) {
-        if (strchr(typs[found], *sig)) {
-            ++first_reg;
-        }
-    }
-    return first_reg;
-}
-
-size_t
-calc_signature_needs(const char *sig, int *strings)
-{
-    size_t stack_size = 0;
-    while (*sig) {
-        switch (*sig) {
-            case 't':
-                (*strings)++;
-                stack_size +=4;
-                break;
-            case 'd':
-                stack_size +=8;
-                break;
-            default:
-                stack_size +=4;
-                break;
-        }
-        sig++;
-    }
-    return stack_size;
-
-}
-
-/*
- * The function generated here is called as func(interp, nci_info)
- * interp   ...  8(%ebp)
- * nci_info ... 12(%ebp)
- *
- * The generate function for a specific signature looks quite similar to
- * an optimized compile of src/nci.c:pcf_x_yy(). In case of any troubles
- * just compare the disassembly.
- */
-void *
-Parrot_jit_build_call_func(PARROT_INTERP, PMC *pmc_nci, STRING *signature)
-{
-    Parrot_jit_info_t jit_info;
-    char     *pc;
-    int       i                    = 0;
-    int       arg_count            = 0;
-    int       string_buffer_count  = 0;
-    const int ST_SIZE_OF           = 124;
-    const int JIT_ALLOC_SIZE       = 1024;
-
-    /* skip over the result */
-    char      *sig                = (char *)signature->strstart + 1;
-    size_t     stack_space_needed = calc_signature_needs(sig,
-                                        &string_buffer_count);
-
-    int base_offset        = 0;
-    int strings_offset     = base_offset - (sizeof (char *) * string_buffer_count);
-    int st_offset          = strings_offset - ST_SIZE_OF;
-    int args_offset        = st_offset - stack_space_needed;
-    int temp_calls_offset  = args_offset - 16;
-    int total_stack_needed = -temp_calls_offset;
-
-    /*
-     * ESP
-     * 0-15, 16 bytes for utility calls
-     * stack_space_needed for actual NCI call
-     * st
-     * STRINGS -> char * holding space
-     * EBP
-     */
-
-    /* this ought to be enough - the caller of this function
-     * should free the function pointer returned here
-     */
-    pc = jit_info.native_ptr = jit_info.arena.start = (char *)mem_alloc_executable(JIT_ALLOC_SIZE);
-
-
-    /* this generated jit function will be called as (INTERP (EBP 8), func_ptr
-    * (ESP 12), args signature (ESP 16)) */
-
-    /* make stack frame, preserve %ebx */
-    jit_emit_stack_frame_enter(pc);
-
-    emitm_subl_i_r(pc, total_stack_needed, emit_ESP);
-
-    /* Parrot_init_arg_nci(interp, &st, "S"); */
-    /* args signature "S" */
-    emitm_movl_m_r(interp, pc, emit_EAX, emit_EBP, 0, 1, 16);
-    emitm_movl_r_m(interp, pc, emit_EAX, emit_EBP, 0, 1, temp_calls_offset + 8);
-
-    /*&st*/
-    emitm_lea_m_r(interp,  pc, emit_EAX, emit_EBP, 0, 1, st_offset);
-    emitm_movl_r_m(interp, pc, emit_EAX, emit_EBP, 0, 1, temp_calls_offset + 4);
-
-    /*interpreter*/
-    emitm_movl_m_r(interp, pc, emit_EAX, emit_EBP, 0, 1, 8);
-    emitm_movl_r_m(interp, pc, emit_EAX, emit_EBP, 0, 1, temp_calls_offset + 0);
-
-    if (sig && *sig)
-      emitm_call_cfunc(pc, Parrot_init_arg_nci);
-
-    while (*sig) {
-        emitm_movl_i_m(pc, arg_count, emit_EBP, 0, 1, temp_calls_offset + 8);
-
-        switch (*sig) {
-            case '0':    /* null ptr or such - doesn't consume a reg */
-                jit_emit_bxor_rr_i(interp, pc, emit_EAX, emit_EAX);
-                emitm_movl_m_r(interp, pc, emit_EAX, emit_EBP, 0, 1, args_offset);
-                break;
-            case 'f':
-                emitm_call_cfunc(pc, get_nci_N);
-                emitm_fstps(interp, pc, emit_EBP, 0, 1, args_offset);
-                break;
-            case 'N':
-            case 'd':
-                emitm_call_cfunc(pc, get_nci_N);
-                emitm_fstpl(interp, pc, emit_EBP, 0, 1, args_offset);
-                args_offset += 4;
-                break;
-            case 'I':   /* INTVAL */
-            case 'l':   /* long */
-            case 'i':   /* int */
-                emitm_call_cfunc(pc, get_nci_I);
-                emitm_movl_r_m(interp, pc, emit_EAX, emit_EBP, 0, 1, args_offset);
-                break;
-            case 't':   /* string, pass a cstring */
-                emitm_call_cfunc(pc, get_nci_S);
-                emitm_movl_r_m(interp, pc, emit_EAX, emit_EBP, 0, 1, temp_calls_offset + 4);
-                emitm_call_cfunc(pc, string_to_cstring_nullable);
-
-                emitm_movl_r_m(interp, pc, emit_EAX, emit_EBP, 0, 1, args_offset);
-                /* save off temporary allocation address */
-                emitm_movl_r_m(interp, pc, emit_EAX, emit_EBP, 0, 1, strings_offset);
-                strings_offset += 4;
-
-                /* reset ESP(4) */
-                emitm_lea_m_r(interp, pc, emit_EAX, emit_EBP, 0, 1, st_offset);
-                emitm_movl_r_m(interp, pc, emit_EAX, emit_EBP, 0, 1, temp_calls_offset + 4);
-                break;
-            case 's':   /* short: movswl intreg_o(base), %eax */
-                emitm_call_cfunc(pc, get_nci_I);
-                emitm_movswl_r_r(pc, emit_EAX, emit_EAX)
-                emitm_movl_r_m(interp, pc, emit_EAX, emit_EBP, 0, 1, args_offset);
-                break;
-            case 'c':   /* char: movsbl intreg_o(base), %eax */
-                emitm_call_cfunc(pc, get_nci_I);
-                emitm_movsbl_r_r(pc, emit_EAX, emit_EAX);
-                emitm_movl_r_m(interp, pc, emit_EAX, emit_EBP, 0, 1, args_offset);
-                break;
-            case 'J':   /* interpreter */
-                emitm_movl_m_r(interp, pc, emit_EAX, emit_EBP, 0, 1, 8);
-                emitm_movl_r_m(interp, pc, emit_EAX, emit_EBP, 0, 1, args_offset);
-                arg_count--;
-                break;
-            case 'p':   /* push pmc->data */
-                emitm_call_cfunc(pc, get_nci_P);
-#  if ! PMC_DATA_IN_EXT
-                /* mov pmc, %edx
-                 * mov 8(%edx), %eax
-                 * push %eax
-                 */
-                emitm_movl_m_r(interp, pc, emit_EAX, emit_EAX, 0, 1, offsetof(struct PMC, data));
-#  else
-                /* push pmc->pmc_ext->data
-                 * mov pmc, %edx
-                 * mov pmc_ext(%edx), %eax
-                 * mov data(%eax), %eax
-                 * push %eax
-                 */
-                emitm_movl_m_r(interp, pc, emit_EAX, emit_EAX, 0, 1, offsetof(struct PMC, pmc_ext));
-                emitm_movl_m_r(interp, pc, emit_EAX, emit_EAX, 0, 1, offsetof(struct PMC_EXT, data));
-#  endif
-                emitm_movl_r_m(interp, pc, emit_EAX, emit_EBP, 0, 1, args_offset);
-                break;
-            case 'O':   /* push PMC * object in P2 */
-            case 'P':   /* push PMC * */
-            case '@':
-                emitm_call_cfunc(pc, get_nci_P);
-#  if PARROT_CATCH_NULL
-                /* PMCNULL is a global */
-                jit_emit_cmp_rm_i(pc, emit_EAX, &PMCNULL);
-                emitm_jxs(pc, emitm_jne, 2); /* skip the xor */
-                jit_emit_bxor_rr_i(interp, pc, emit_EAX, emit_EAX);
-#  endif
-                emitm_movl_r_m(interp, pc, emit_EAX, emit_EBP, 0, 1, args_offset);
-                break;
-            case 'v':
-                break;
-            case 'V':
-                emitm_call_cfunc(pc, get_nci_P);
-                emitm_lea_m_r(interp, pc, emit_EAX, emit_EAX, 0, 1, offsetof(struct PMC, data));
-                /* emitm_lea_m_r(interp, pc, emit_EAX, emit_EAX, 0, 1, 0); */
-                emitm_movl_r_m(interp, pc, emit_EAX, emit_EBP, 0, 1, args_offset);
-                break;
-            case 'b':   /* buffer (void*) pass PObj_bufstart(SReg) */
-                emitm_call_cfunc(pc, get_nci_S);
-                emitm_movl_m_r(interp, pc, emit_EAX, emit_EAX, 0, 1, (size_t) &PObj_bufstart((STRING *) 0));
-                emitm_movl_r_m(interp, pc, emit_EAX, emit_EBP, 0, 1, args_offset);
-                break;
-            case 'B':   /* buffer (void**) pass &PObj_bufstart(SReg) */
-                emitm_call_cfunc(pc, get_nci_S);
-                emitm_lea_m_r(interp, pc, emit_EAX, emit_EAX, 0, 1, (size_t) &PObj_bufstart((STRING *) 0));
-                emitm_movl_r_m(interp, pc, emit_EAX, emit_EBP, 0, 1, args_offset);
-                break;
-            case 'S':
-                emitm_call_cfunc(pc, get_nci_S);
-                emitm_movl_r_m(interp, pc, emit_EAX, emit_EBP, 0, 1, args_offset);
-                break;
-
-
-            /* I have no idea how to handle these */
-            case '2':
-            case '3':
-            case '4':
-                mem_free_executable(jit_info.native_ptr);
-                return NULL;
-                break;
-                /* This might be right. Or not... */
-                /* we need the offset of PMC_int_val */
-                emitm_call_cfunc(pc, get_nci_P);
-                emitm_lea_m_r(interp, pc, emit_EAX, emit_EAX, 0, 1, (size_t) &PMC_int_val((PMC *) 0));
-                emitm_movl_r_m(interp, pc, emit_EAX, emit_EBP, 0, 1, args_offset);
-                break;
-            default:
-                Parrot_ex_throw_from_c_args(interp, NULL, EXCEPTION_JIT_ERROR,
-                    "Unknown arg Signature %c\n", *sig);
-                /*
-                 * oops unknown signature:
-                 * cleanup and try nci.c
-                 */
-                mem_free_executable(jit_info.native_ptr);
-                return NULL;
-        }
-        args_offset +=4;
-        arg_count++;
-        sig++;
-    }
-
-    emitm_addl_i_r(pc, 16, emit_ESP);
-    /* get the pmc from stack - movl 12(%ebp), %eax */
-    emitm_movl_m_r(interp, pc, emit_EAX, emit_EBP, 0, 1, 12);
-    emitm_callm(pc, emit_EAX, emit_None, emit_None, 0);
-    emitm_subl_i_r(pc, 16, emit_ESP);
-
-    /* SAVE OFF EAX */
-    emitm_movl_r_m(interp, pc, emit_EAX, emit_EBP, 0, 1, temp_calls_offset + 8);
-
-    /*&st*/
-    emitm_lea_m_r(interp, pc, emit_EAX, emit_EBP, 0, 1, st_offset);
-    emitm_movl_r_m(interp, pc, emit_EAX, emit_EBP, 0, 1, temp_calls_offset + 4);
-
-    /*interpreter*/
-    emitm_movl_m_r(interp, pc, emit_EAX, emit_EBP, 0, 1, 8);
-    emitm_movl_r_m(interp, pc, emit_EAX, emit_EBP, 0, 1, temp_calls_offset + 0);
-
-    /* RESTORE BACK EAX */
-    emitm_movl_m_r(interp, pc, emit_EAX, emit_EBP, 0, 1, temp_calls_offset + 8);
-
-    /* now place return value in registers */
-    /* first in signature is the return value */
-    sig = (char *)signature->strstart; /* the result */
-    switch (*sig) {
-        /* I have no idea how to handle these */
-        case '2':
-        case '3':
-        case '4':
-            /* get integer from pointer - untested */
-            emitm_movl_m_r(interp, pc, emit_EAX, emit_EAX, 0, 1, 0);
-            if (*sig == 2)      /* short */
-                emitm_movswl_r_r(pc, emit_EAX, emit_EAX);
-            emitm_call_cfunc(pc, set_nci_I);
-            break;
-        case 'f':
-        case 'd':
-            jit_emit_fstore_mb_n(interp, pc, emit_EBP, temp_calls_offset + 8);
-            emitm_call_cfunc(pc, set_nci_N);
-            /* pop num from st(0) and mov to reg */
-            break;
-        case 's':
-            /* movswl %ax, %eax */
-            emitm_movswl_r_r(pc, emit_EAX, emit_EAX);
-            emitm_movl_r_m(interp, pc, emit_EAX, emit_EBP, 0, 1, temp_calls_offset + 8);
-            emitm_call_cfunc(pc, set_nci_I);
-            break;
-        case 'c':
-            /* movsbl %al, %eax */
-            emitm_movsbl_r_r(pc, emit_EAX, emit_EAX);
-            emitm_movl_r_m(interp, pc, emit_EAX, emit_EBP, 0, 1, temp_calls_offset + 8);
-            emitm_call_cfunc(pc, set_nci_I);
-            break;
-        case 'I':   /* INTVAL */
-        case 'l':
-        case 'i':
-            emitm_movl_r_m(interp, pc, emit_EAX, emit_EBP, 0, 1, temp_calls_offset + 8);
-            emitm_call_cfunc(pc, set_nci_I);
-            break;
-        case 'v': /* void - do nothing */
-            break;
-        case 'P':
-            emitm_movl_r_m(interp, pc, emit_EAX, emit_EBP, 0, 1, temp_calls_offset + 8);
-            emitm_call_cfunc(pc, set_nci_P);
-            break;
-        case 'p':   /* make a new unmanaged struct */
-            /* save return value on stack */
-
-            /* save pointer p */
-            emitm_movl_r_m(interp, pc, emit_EAX, emit_EBP, 0, 1, temp_calls_offset + 12);
-
-            /* make new pmc */
-            emitm_movl_i_m(pc, enum_class_UnManagedStruct, emit_EBP, 0, 1, temp_calls_offset + 4);
-            emitm_call_cfunc(pc, pmc_new);
-
-            /* restore pointer p to EDX */
-            emitm_movl_m_r(interp, pc, emit_EDX, emit_EBP, 0, 1, temp_calls_offset + 12);
-
-            /* copy UnManagedStruct to stack for set_nci_P call */
-            emitm_movl_r_m(interp, pc, emit_EAX, emit_EBP, 0, 1, temp_calls_offset + 8);
-
-            /* eax = PMC, get return value into edx */
-            /* stuff return value into pmc->data */
-
-#  if ! PMC_DATA_IN_EXT
-            /* mov %edx, (data) %eax */
-            emitm_movl_r_m(interp, pc, emit_EDX, emit_EAX, 0, 1, offsetof(struct PMC, data));
-#  else
-            /* mov pmc_ext(%eax), %eax
-               mov %edx, data(%eax) */
-            emitm_movl_m_r(interp, pc, emit_EAX, emit_EAX, 0, 1, offsetof(struct PMC, pmc_ext));
-            emitm_movl_r_m(interp, pc, emit_EDX, emit_EAX, 0, 1, offsetof(struct PMC_EXT, data));
-#  endif
-
-            /* reset EBP(4) */
-            emitm_lea_m_r(interp, pc, emit_EAX, emit_EBP, 0, 1, st_offset);
-            emitm_movl_r_m(interp, pc, emit_EAX, emit_EBP, 0, 1, temp_calls_offset + 4);
-
-            emitm_call_cfunc(pc, set_nci_P);
-            break;
-        case 'S':
-            emitm_movl_r_m(interp, pc, emit_EAX, emit_EBP, 0, 1, temp_calls_offset + 8);
-            emitm_call_cfunc(pc, set_nci_S);
-            break;
-        case 't':   /* string */
-            /* EAX is char* */
-            emitm_movl_i_m(pc, 0, emit_EBP, 0, 1, temp_calls_offset + 8); /* len */
-
-            /* overrights address of st in EBP(4) */
-            emitm_movl_r_m(interp, pc, emit_EAX, emit_EBP, 0, 1, temp_calls_offset + 4);
-
-            emitm_call_cfunc(pc, string_from_cstring);
-
-            emitm_movl_r_m(interp, pc, emit_EAX, emit_EBP, 0, 1, temp_calls_offset + 8);
-
-            /* reset EBP(4) */
-            emitm_lea_m_r(interp, pc, emit_EAX, emit_EBP, 0, 1, st_offset);
-            emitm_movl_r_m(interp, pc, emit_EAX, emit_EBP, 0, 1, temp_calls_offset + 4);
-
-            emitm_call_cfunc(pc, set_nci_S);
-            break;
-        default:
-            Parrot_ex_throw_from_c_args(interp, NULL, EXCEPTION_JIT_ERROR,
-                "Unknown return Signature %c\n", *sig);
-            /*
-             * oops unknown signature:
-             * cleanup and try nci.c
-             */
-            mem_free_executable(jit_info.native_ptr);
-            return NULL;
-    }
-
-    /* free temporary strings */
-    strings_offset = st_offset + ST_SIZE_OF;
-    for (i=0; i<string_buffer_count; i++) {
-        emitm_movl_m_r(interp, pc, emit_EAX, emit_EBP, 0, 1, strings_offset);
-        emitm_movl_r_m(interp, pc, emit_EAX, emit_EBP, 0, 1, temp_calls_offset + 0);
-        emitm_call_cfunc(pc, string_cstring_free);
-        strings_offset += 4;
-    }
-
-    jit_emit_stack_frame_leave(pc);
-    emitm_ret(pc);
-    PARROT_ASSERT(pc - jit_info.arena.start <= JIT_ALLOC_SIZE);
-    /* could shrink arena.start here to used size */
-    PObj_active_destroy_SET(pmc_nci);
-    return (void *)D2FPTR(jit_info.arena.start);
-}
-
-const char i_map[] =
-    { emit_EDI, emit_ESI, emit_EDX, emit_ECX };
-const char floatval_map[] =
-    { 1, 2, 3, 4, 5 };         /* ST(1) .. (ST(4) */
-
-const char i_map_sub[] =
-    { emit_EDX, emit_ECX, emit_EBX, emit_EDI, emit_ESI };
-
-const jit_arch_info arch_info = {
-    jit_mov_rm_offs,
-    jit_mov_rm_n_offs,
-    jit_mov_mr_offs,
-    jit_mov_mr_n_offs,
-    Parrot_jit_dofixup,
-    (jit_arch_f)0,              /* no cache flush needed */
-    {
-        {
-            Parrot_jit_begin,   /* emit code prologue */
-            4,                  /* 4 mapped ints */
-            2,                  /* first 2 are preserved */
-            i_map,
-            4,                  /* 4 mapped float regs */
-            0,                  /* ABI sez it's not preserved */
-            floatval_map
-        },
-        /* unused */
-        {
-            Parrot_jit_begin_sub,   /* emit code prologue */
-            4,                  /* 4 mapped ints */
-            2,                  /* first 2 are *non*preserved */
-            i_map_sub,
-            4,                  /* 4 mapped float regs */
-            0,                  /* ABI sez it's not preserved */
-            floatval_map
-        },
-        /*
-         * compile a sub to registers only
-         * if a mapped count is 0, code containing this register kind
-         * will not be created
-         *
-         * TODO implement FLOATVAL arg passing and set mapped
-         * register count.
-         */
-        {
-            Parrot_jit_begin_sub_regs,   /* emit code prologue */
-            5,                  /* 5 mapped ints */
-            2,                  /* first 2 are *non*preserved */
-            i_map_sub,
-            5,                  /* TODO 0 mapped float regs */
-            5,                  /* ABI sez it's not preserved */
-            floatval_map
-        }
-    }
-};
-
-const jit_arch_info *
-Parrot_jit_init(PARROT_INTERP)
-{
-    return &arch_info;
-}

Modified: branches/jit_h_files/src/jit/i386/jit_emit.h
==============================================================================
--- branches/jit_h_files/src/jit/i386/jit_emit.h	(original)
+++ branches/jit_h_files/src/jit/i386/jit_emit.h	Tue Dec 23 12:49:30 2008
@@ -19,16 +19,62 @@
 #  define EXTERN
 #endif
 
-#  include <assert.h>
+#include <assert.h>
 #include "parrot/parrot.h"
 #include "parrot/hash.h"
 #include "parrot/oplib/ops.h"
-#include "jit.h"
+
+/*
+ * helper funcs - get argument n
+ */
+INTVAL
+get_nci_I(PARROT_INTERP, ARGMOD(call_state *st), int n)
+;
+
+FLOATVAL
+get_nci_N(PARROT_INTERP, ARGMOD(call_state *st), int n)
+;
+
+PARROT_WARN_UNUSED_RESULT
+PARROT_CANNOT_RETURN_NULL
+STRING*
+get_nci_S(PARROT_INTERP, ARGMOD(call_state *st), int n)
+;
+
+PARROT_WARN_UNUSED_RESULT
+PARROT_CANNOT_RETURN_NULL
+PMC*
+get_nci_P(PARROT_INTERP, ARGMOD(call_state *st), int n)
+;
+
+/*
+ * set return value
+ */
+void
+set_nci_I(PARROT_INTERP, ARGOUT(call_state *st), INTVAL val)
+;
+
+void
+set_nci_N(PARROT_INTERP, ARGOUT(call_state *st), FLOATVAL val)
+;
+
+void
+set_nci_S(PARROT_INTERP, ARGOUT(call_state *st), STRING *val)
+;
+
+void
+set_nci_P(PARROT_INTERP, ARGOUT(call_state *st), PMC* val)
+;
+
 
 #if defined HAVE_COMPUTED_GOTO && defined __GNUC__ && PARROT_I386_JIT_CGP
 #  define JIT_CGP
 #endif
 
+static void call_func(Parrot_jit_info_t *jit_info, void (*addr) (void));
+
+static void jit_emit_real_exception(Parrot_jit_info_t *jit_info);
+
 /*
  * get the register frame pointer
  */
@@ -88,6 +134,7 @@
 
 #define INT_REGISTERS_TO_MAP 4
 
+
 /* Scratch register. */
 
 #define ISR1 emit_EAX
@@ -124,23 +171,47 @@
 #define emit_r_m(interp, pc, reg1, b, i, s, d) \
     emit_r_X((interp), (pc), emit_reg((reg1)-1), (b), (i), (s), (d))
 
-/* ESIB byte */
-#define emit_Scale(scale) ((scale) << 6)
-#define emit_reg_Index(x) (((x)-1) << 3)
-#define emit_reg_Base(x) ((x)-1)
-
-/* Scale factor values */
-#define emit_Scale_1 emit_Scale(0)
-#define emit_Scale_2 emit_Scale(1)
-#define emit_Scale_4 emit_Scale(2)
-#define emit_Scale_8 emit_Scale(3)
 
-#define emit_Index_None ((emit_b100) << 3)
 
 #define emit_alu_X_r(X, reg) ((emit_b11 << 6) | ((X) << 3) | ((reg) - 1))
 
 #define emit_alu_r_r(reg1, reg2) emit_alu_X_r(((reg1) - 1), (reg2))
 
+int
+emit_is8bit(long disp)
+;
+
+char *
+emit_disp8_32(char *pc, int disp)
+;
+
+void
+emit_sib(PARROT_INTERP, char *pc, int scale, int i, int base)
+;
+
+char *
+emit_r_X(PARROT_INTERP, char *pc, int reg_opcode, int base, int i, int scale, long disp)
+;
+
+char *
+emit_shift_i_r(PARROT_INTERP, char *pc, int opcode, int imm, int reg)
+;
+
+char *
+emit_shift_i_m(PARROT_INTERP, char *pc, int opcode, int imm,
+               int base, int i, int scale, long disp)
+;
+
+char *
+emit_shift_r_r(PARROT_INTERP, char *pc, int opcode, int reg1, int reg2)
+;
+
+char *
+emit_shift_r_m(PARROT_INTERP, char *pc, int opcode, int reg,
+               int base, int i, int scale, long disp)
+;
+
+
 /* CDQ - need this to do multiply */
 #define emitm_cdq(pc) *((pc)++) = (char) 0x99
 
@@ -174,13 +245,61 @@
        (pc) += 4; }
 #endif /* EXEC_CAPABLE */
 
+
+static char *
+emit_pushl_m(PARROT_INTERP, char *pc, int base, int i, int scale, long disp)
+{
+    *(pc++) = (char) 0xff;
+    return emit_r_X(interp, pc, emit_reg(emit_b110), base, i, scale, disp);
+}
+
+/* POPs */
+
+static char *
+emit_popl_r(char *pc, int reg)
+{
+/* XXX kwoo:  I side with valgrind.  Is it safe to remove the obsolete code? */
+#if 0
+    /* valgrind doesn't like this and the version below is smaller anyway */
+    *(pc++) = (char) 0x8f;
+    *(pc++) = (char) emit_alu_X_r(emit_b000, reg);
+#else
+    *(pc++) = (char)(0x58 | (reg - 1));
+#endif /* 0 */
+    return pc;
+}
+
 #  define emitm_popl_r(pc, reg) \
     (pc) = emit_popl_r((pc), (reg))
 
+static char *
+emit_popl_m(PARROT_INTERP, char *pc, int base, int i, int scale, long disp)
+{
+    *(pc++) = (char) 0x8f;
+    return emit_r_X(interp, pc, emit_reg(emit_b000), base, i, scale, disp);
+}
+
+/* MOVes */
+
+static char *
+emit_movb_r_r(char *pc, int reg1, int reg2)
+{
+    *(pc++) = (char) 0x88;
+    *(pc++) = (char) emit_alu_r_r(reg1, reg2);
+    return pc;
+}
 #  define jit_emit_mov_rr_i(pc, reg2, reg1) if ((reg1) != (reg2)) { \
     *((pc)++) = (char) 0x89; \
     *((pc)++) = (char) emit_alu_r_r((reg1), (reg2)); }
 
+static char *
+emit_movb_i_r(char *pc, char imm, int reg)
+{
+    *(pc++) = (char)(0xb0 | (reg - 1));
+    *(pc++) = imm;
+    return pc;
+}
+
 #  define jit_emit_mov_ri_i(interp, pc, reg, imm) { \
     *((pc)++) = (char)(0xb8 | ((reg) - 1)); \
     *(long *)(pc) = (long)(imm); (pc) += 4; }
@@ -227,6 +346,15 @@
 #  define emitm_lea_m_r(interp, pc, reg1, b, i, s, d) \
     emitm_movX_Y_Z((interp), 0x8d, (pc), (reg1), (b), (i), (s), (d))
 
+static char *
+emit_movb_i_m(PARROT_INTERP, char *pc, char imm, int base, int i, int scale, long disp)
+{
+    *(pc++) = (char) 0xc6;
+    pc = emit_r_X(interp, pc, emit_reg(emit_b000), base, i, scale, disp);
+    *(pc++) = imm;
+    return pc;
+}
+
 #  define emitm_movl_i_m(pc, imm, b, i, s, d) { \
     *((pc)++) = (char) 0xc7; \
     (pc) = emit_r_X((interp), (pc), emit_reg(emit_b000), (b), (i), (s), (long)(d)); \
@@ -343,9 +471,65 @@
 #  define emitm_smull_r_m(pc, reg1, b, i, s, d) { \
     *(pc)++ = 0xf; \
     emitm_alul_r_m((pc), 0xaf, (reg1), (b), (i), (s), (d)); }
+
+static char *
+opt_mul(PARROT_INTERP, char *pc, int dest, INTVAL imm, int src)
+{
+    UINTVAL ld2 = ld((UINTVAL) imm);
+
+    if (imm == 0) {
+        jit_emit_mov_ri_i(interp, pc, dest, 0);
+    }
+    else if (imm > 0 && !(imm & (imm - 1))) {
+        /* positive power of 2 - do a shift */
+        jit_emit_mov_rr_i(pc, dest, src);
+        pc = emit_shift_i_r(interp, pc, emit_b100, ld2, dest);
+    }
+    else {
+        /* special small numbers */
+        switch (imm) {
+            case 3:
+                /* LEA dest, base, index, scale, displace
+                 * note: src may be dest, so can't be reused
+                 *
+                 * dest = src + src*2 */
+                emitm_lea_m_r(interp, pc, dest, src, src, 2, 0);
+                break;
+            case 5:      /* dest = src + src*4 */
+                emitm_lea_m_r(interp, pc, dest, src, src, 4, 0);
+                break;
+            case 6:     /* dest = src*3; dest += dest */
+                emitm_lea_m_r(interp, pc, dest, src, src, 2, 0);
+                jit_emit_add_rr_i(interp, pc, dest, dest);
+                break;
+            case 9:      /* dest = src + src*8 */
+                emitm_lea_m_r(interp, pc, dest, src, src, 8, 0);
+                break;
+            case 10:      /* dest = src + src*4 ; dest+= dest */
+                emitm_lea_m_r(interp, pc, dest, src, src, 4, 0);
+                jit_emit_add_rr_i(interp, pc, dest, dest);
+                break;
+            case 12:     /* dest= src*3; dest <<= 2 */
+                emitm_lea_m_r(interp, pc, dest, src, src, 2, 0);
+                pc = emit_shift_i_r(interp, pc, emit_b100, 2, dest);
+                break;
+            case 100:      /* dest = src + src*4 ; dest <<= 2; dest = 5*dest*/
+                emitm_lea_m_r(interp, pc, dest, src, src, 4, 0);
+                pc = emit_shift_i_r(interp, pc, emit_b100, 2, dest);
+                emitm_lea_m_r(interp, pc, dest, dest, dest, 4, 0);
+                break;
+            default:
+                emitm_alul_r_r(pc, 0x69, dest, src);
+                *(long *)(pc) = (long)imm;
+                pc += 4;
+        }
+    }
+    return pc;
+}
 #  define jit_emit_mul_rir_i(pc, dest, imm, src) \
        (pc) = opt_mul(interp, (pc), (dest), (imm), (src))
 
+
 #  define jit_emit_mul_ri_i(pc, r, imm) jit_emit_mul_rir_i((pc), (r), (imm), (r))
 
 #  define jit_emit_mul_RIM_ii(pc, reg, imm, ofs) \
@@ -353,6 +537,7 @@
     *(long *)(pc) = (long)(imm); \
     (pc) += 4;
 
+
 /* NEG */
 
 #  define jit_emit_neg_r_i(pc, reg) emitm_alu_imp_r((pc), emit_b011, (reg))
@@ -428,7 +613,6 @@
 #  define jit_emit_not_M_i(interp, pc, offs) emitm_notl_m((pc), emit_EBX, 0, 1, (offs))
 
 /* XCHG */
-
 #  define jit_emit_xchg_rr_i(interp, pc, r1, r2) { \
     if ((r1) != (r2)) { \
     *((pc)++) = (char) 0x87; \
@@ -509,6 +693,87 @@
 #  define jit_emit_ror_ri_i(interp, pc, reg, imm) \
     { (pc) = emit_shift_i_r((interp), (pc), emit_b001, (imm), (reg)); }
 
+static int
+intreg_is_used(Parrot_jit_info_t *jit_info, char reg)
+{
+    int i;
+    const jit_arch_regs *reg_info;
+    Parrot_jit_register_usage_t *ru = jit_info->optimizer->cur_section->ru;
+
+    reg_info = jit_info->arch_info->regs + jit_info->code_type;
+
+    for (i = 0; i < ru[0].registers_used; ++i) {
+        if (reg_info->map_I[i] == reg) {
+            return 1;
+        }
+    }
+    return 0;
+}
+
+static char *
+opt_shift_rr(PARROT_INTERP, Parrot_jit_info_t *jit_info, int dest, int count, int op)
+{
+    char *pc = jit_info->native_ptr;
+    if (count == emit_ECX) {
+        pc = emit_shift_r_r(interp, pc, op, count, dest);
+    }
+    else {
+        int saved = 0;
+        PARROT_ASSERT(count != emit_EAX);
+        if (dest == emit_EAX) {
+            if (intreg_is_used(jit_info, emit_ECX)) {
+                emitm_pushl_r(pc, emit_ECX);
+                saved = 1;
+            }
+            jit_emit_mov_rr_i(pc, emit_ECX, count);
+            pc = emit_shift_r_r(interp, pc, op, emit_ECX, dest);
+            if (saved) {
+                emitm_popl_r(pc, emit_ECX);
+            }
+
+        }
+        else if (dest == emit_ECX) {
+            jit_emit_xchg_rr_i(interp, pc, dest, count);
+            pc = emit_shift_r_r(interp, pc, op, dest, count);
+            jit_emit_xchg_rr_i(interp, pc, dest, count);
+        }
+        else {
+            jit_emit_mov_rr_i(pc, emit_EAX, emit_ECX);
+            jit_emit_mov_rr_i(pc, emit_ECX, count);
+            pc = emit_shift_r_r(interp, pc, op, emit_ECX, dest);
+            jit_emit_mov_rr_i(pc, emit_ECX, emit_EAX);
+        }
+    }
+    return pc;
+}
+static char *
+opt_shift_rm(PARROT_INTERP, Parrot_jit_info_t *jit_info, int dest, int offs, int op)
+{
+    char *pc = jit_info->native_ptr;
+    int saved = 0;
+    /* if ECX is mapped, save it */
+    if (dest != emit_ECX && intreg_is_used(jit_info, emit_ECX)) {
+        emitm_pushl_r(pc, emit_ECX);
+        saved = 1;
+    }
+    if (dest == emit_ECX) {
+        /* jit_emit_mov_RM_i(pc, emit_EAX, count); */
+        emitm_movl_m_r(interp, pc, emit_EAX, emit_EBX, emit_None, 1, offs);
+        jit_emit_xchg_rr_i(interp, pc, dest, emit_EAX);
+        pc = emit_shift_r_r(interp, pc, op, emit_ECX, emit_EAX);
+        jit_emit_xchg_rr_i(interp, pc, dest, emit_EAX);
+    }
+    else {
+        /* jit_emit_mov_RM_i(pc, emit_ECX, count); */
+        emitm_movl_m_r(interp, pc, emit_ECX, emit_EBX, emit_None, 1, offs);
+        pc = emit_shift_r_r(interp, pc, op, emit_ECX, dest);
+    }
+    if (saved) {
+        emitm_popl_r(pc, emit_ECX);
+    }
+    return pc;
+}
+
 /* interface, shift r1 by r2 bits */
 
 #  define jit_emit_shl_rr_i(interp, pc, r1, r2) \
@@ -680,8 +945,7 @@
 }
 
 /* FLD ST, ST(i), optimized FSTP(N+1);FLD(N) => FST(N+1)  */
-extern unsigned char *lastpc;
-
+static unsigned char *lastpc;
 #  define emitm_fld(pc, sti) do { \
      if ((unsigned char *)(pc) == (lastpc + 2) && \
        (int)(*lastpc) == (int)0xDD && \
@@ -1320,6 +1584,30 @@
     } \
 }
 
+/* ST(r1) /= ST(r2) */
+static char *
+div_rr_n(PARROT_INTERP, Parrot_jit_info_t *jit_info, int r1)
+{
+    char *L1;
+    static const char div_by_zero[] = "Divide by zero";
+    char *pc = jit_info->native_ptr;
+
+    jit_emit_test_r_n(pc, (char)0);   /* TOS */
+    L1 = pc;
+    emitm_jxs(pc, emitm_jnz, 0);
+    emitm_pushl_i(pc, div_by_zero);
+    emitm_pushl_i(pc, EXCEPTION_DIV_BY_ZERO);
+    emitm_pushl_i(pc, 0);    /* NULL */
+    Parrot_jit_emit_get_INTERP(interp, pc, emit_ECX);
+    emitm_pushl_r(pc, emit_ECX);
+    jit_info->native_ptr = pc;
+    jit_emit_real_exception(jit_info);
+    pc = jit_info->native_ptr;
+    /* L1: */
+    L1[1] = (char)(pc - L1 - 2);
+    emitm_fdivp(pc, (r1+1));
+    return pc;
+}
 
 #  define jit_emit_div_rr_n(interp, pc, r1, r2) \
     emitm_fld((pc), (r2)); \
@@ -1336,9 +1624,38 @@
     jit_info->native_ptr = (pc); \
     (pc) = div_rr_n((interp), jit_info, (r))
 
+static char *
+mod_rr_n(PARROT_INTERP, Parrot_jit_info_t *jit_info, int r)
+{
+    char *L1;
+    static const char div_by_zero[] = "Divide by zero";
+    char *pc = jit_info->native_ptr;
+
+    jit_emit_test_r_n(pc, (char)0);   /* TOS */
+    L1 = pc;
+    emitm_jxs(pc, emitm_jnz, 0);
+    emitm_pushl_i(pc, div_by_zero);
+    emitm_pushl_i(pc, EXCEPTION_DIV_BY_ZERO);
+    emitm_pushl_i(pc, 0);    /* NULL */
+    Parrot_jit_emit_get_INTERP(interp, pc, emit_ECX);
+    emitm_pushl_r(pc, emit_ECX);
+    jit_info->native_ptr = pc;
+    jit_emit_real_exception(jit_info);
+    pc = jit_info->native_ptr;
+    /* L1: */
+    L1[1] = (char)(pc - L1 - 2);
+    /* L2: */
+    emitm_fxch(pc, (char)1);
+    emitm_fprem(pc);
+    emitm_fstw(pc);
+    emitm_sahf(pc);
+    emitm_jxs(pc, emitm_jp, -7); /* jo L2 */
+    emitm_fstp(pc, (r+1));
+    return pc;
+}
 
 /* ST(i) %= MEM
- * please note the hardcoded jumps */
+ * please note the hardccded jumps */
 #  define jit_emit_cmod_RM_n(interp, pc, r, offs)  \
     if (r)  \
       emitm_fxch((pc), (r)); \
@@ -1375,6 +1692,7 @@
     emitm_sahf(pc); \
 }
 
+
 /* compare mem <-> ST(r) */
 #  define jit_emit_cmp_mi_n(interp, pc, mem, r) { \
     jit_emit_fload_m_n((interp), (pc), (mem)); \
@@ -1404,6 +1722,7 @@
     } \
 }
 
+
 #  define jit_emit_neg_M_i(interp, pc, offs) \
     emitm_negl_m((pc), emit_EBX, emit_None, 1, (long)(offs))
 
@@ -1434,20 +1753,351 @@
 #  define jit_emit_bxor_MI_i(pc, offs, imm) \
     emitm_xorl_i_m((pc), (imm), emit_EBX, emit_None, 1, (offs))
 
-#  define jit_emit_div_rr_i(interp, pc, r1, r2) (pc) = opt_div_rr((interp), jit_info, (r1), (r2), 1)
+/* dest /= src
+ * edx:eax /= src, quotient => eax, rem => edx
+ */
+static char *
+opt_div_rr(PARROT_INTERP, Parrot_jit_info_t *jit_info, int dest, int src, int is_div)
+{
+    char *pc = jit_info->native_ptr;
+    int saved = 0;
+    int div_ecx = 0;
+    char *L1, *L2, *L3;
+    static const char div_by_zero[] = "Divide by zero";
+
+    PARROT_ASSERT(src != emit_EAX);
 
+    if (dest != emit_EAX) {
+        jit_emit_mov_rr_i(pc, emit_EAX, dest);
+    }
+    if (dest == emit_EDX) {
+        /* all ok, we can globber it */
+    }
+    else {
+        /* if ECX is not mapped use it */
+        if (!intreg_is_used(jit_info, emit_ECX) && src == emit_EDX) {
+            jit_emit_mov_rr_i(pc, emit_ECX, emit_EDX);
+            div_ecx = 1;
+        }
+        else
+            /* if EDX is mapped, preserve EDX on stack */
+            if (intreg_is_used(jit_info, emit_EDX)) {
+                emitm_pushl_r(pc, emit_EDX);
+                saved = 1;
+                /* if EDX is the src, we need another temp register: ECX */
+                if (src == emit_EDX) {
+                    /* if ECX is mapped save it, but not if it's dest */
+                    if (intreg_is_used(jit_info, emit_ECX) &&
+                            dest != emit_ECX) {
+                        emitm_pushl_r(pc, emit_ECX);
+                        saved = 2;
+                    }
+                    /* else just use it */
+                    jit_emit_mov_rr_i(pc, emit_ECX, emit_EDX);
+                    div_ecx = 1;
+                }
+            }
+    }
+#if 0
+    jit_emit_cdq(pc);
+#else
+    /* this sequence allows 2 other instructions to run parallel */
+    if (dest != emit_EDX) {
+        jit_emit_mov_rr_i(pc, emit_EDX, emit_EAX);
+    }
+    pc = emit_shift_i_r(interp, pc, emit_b111, 31, emit_EDX); /* SAR 31 */
+#endif
+    if (div_ecx) {
+        jit_emit_test_r_i(pc, emit_ECX);
+        L1 = pc;
+        emitm_jxs(pc, emitm_jz, 0);
+        emitm_sdivl_r(pc, emit_ECX);
+        L3 = pc;
+        emitm_jumps(pc, 0);
+        /* L1: */
+        L1[1] = (char)(pc - L1 - 2);
+    }
+    else {
+        jit_emit_test_r_i(pc, src);
+        L2 = pc;
+        emitm_jxs(pc, emitm_jz, 0);
+        emitm_sdivl_r(pc, src);
+        L3 = pc;
+        emitm_jumps(pc, 0);
+        /* L2: */
+        L2[1] = (char)(pc - L2 - 2);
+    }
+    /* TODO Parrot_ex_throw_from_c_args */
+    emitm_pushl_i(pc, div_by_zero);
+    emitm_pushl_i(pc, EXCEPTION_DIV_BY_ZERO);
+    emitm_pushl_i(pc, 0);    /* NULL */
+    Parrot_jit_emit_get_INTERP(interp, pc, emit_ECX);
+    emitm_pushl_r(pc, emit_ECX);
+    jit_info->native_ptr = pc;
+    jit_emit_real_exception(jit_info);
+    pc = jit_info->native_ptr;
+    /* L3: */
+    L3[1] = (char)(pc - L3 - 2);
+    if (saved == 2) {
+        emitm_popl_r(pc, emit_ECX);
+    }
+    if (is_div) {
+        /* result = quotient in EAX */
+        if (saved) {
+            emitm_popl_r(pc, emit_EDX);
+        }
+        if (dest != emit_EAX) {
+            jit_emit_mov_rr_i(pc, dest, emit_EAX);
+        }
+    }
+    else {
+        /* result = remainder in EDX */
+        if (saved) {
+            emitm_popl_r(pc, emit_EAX);
+            jit_emit_mov_rr_i(pc, dest, emit_EDX);
+            jit_emit_mov_rr_i(pc, emit_EDX, emit_EAX);
+        }
+        else {
+            if (dest != emit_EDX)
+                jit_emit_mov_rr_i(pc, dest, emit_EDX);
+        }
+    }
+    if (!saved && div_ecx) {
+        /* restore EDX */
+        jit_emit_mov_rr_i(pc, emit_EDX, emit_ECX);
+    }
+    return pc;
+}
+
+#  define jit_emit_div_rr_i(interp, pc, r1, r2) (pc) = opt_div_rr((interp), jit_info, (r1), (r2), 1)
 #  define jit_emit_cmod_rr_i(interp, pc, r1, r2) (pc) = opt_div_rr((interp), jit_info, (r1), (r2), 0)
 
-#  define jit_emit_div_ri_i(pc, r1, imm) (pc) = opt_div_ri(interp, jit_info, (r1), (imm), 1)
 
+static char *
+opt_div_ri(PARROT_INTERP, Parrot_jit_info_t *jit_info, int dest, INTVAL imm, int is_div)
+{
+    char *pc = jit_info->native_ptr;
+
+    UINTVAL ld2 = ld((UINTVAL) imm);
+    if (is_div && imm > 1 && !(imm & (imm - 1))) {
+        /* positive power of 2 - do a shift */
+        pc = emit_shift_i_r(interp, pc, emit_b101, ld2, dest);
+    }
+    else {
+        if (dest != emit_EBX) {
+            emitm_pushl_r(pc, emit_EBX);
+            jit_emit_mov_ri_i(interp, pc, emit_EBX, imm);
+            jit_info->native_ptr = pc;
+            pc = opt_div_rr(interp, jit_info, dest, emit_EBX, is_div);
+            pc = emit_popl_r(pc, emit_EBX);
+        }
+        else {
+            emitm_pushl_r(pc, emit_EDI);
+            jit_emit_mov_ri_i(interp, pc, emit_EDI, imm);
+            jit_info->native_ptr = pc;
+            pc = opt_div_rr(interp, jit_info, dest, emit_EDI, is_div);
+            pc = emit_popl_r(pc, emit_EDI);
+        }
+    }
+    return pc;
+}
+
+#  define jit_emit_div_ri_i(pc, r1, imm) (pc) = opt_div_ri(interp, jit_info, (r1), (imm), 1)
 #  define jit_emit_cmod_ri_i(pc, r1, imm) (pc) = opt_div_ri(interp, jit_info, (r1), (imm), 0)
 
-#  define jit_emit_div_RM_i(interp, pc, r, m)  (pc) = opt_div_RM((interp), jit_info, (r), (m), 1)
+static char *
+opt_div_RM(PARROT_INTERP, Parrot_jit_info_t *jit_info, int dest, int offs, int is_div)
+{
+    char *pc = jit_info->native_ptr;
+    int saved = 0;
+
+    if (dest != emit_EAX) {
+        jit_emit_mov_rr_i(pc, emit_EAX, dest);
+    }
+    if (dest == emit_EDX) {
+        /* all ok, we can globber it */
+    }
+    else {
+        /* if ECX is mapped, push EDX on stack */
+        if (intreg_is_used(jit_info, emit_ECX)) {
+            emitm_pushl_r(pc, emit_EDX);
+            saved = 2;
+        }
+        /* if EDX is mapped, save it in ECX */
+        else if (intreg_is_used(jit_info, emit_EDX)) {
+            saved = 1;
+            jit_emit_mov_rr_i(pc, emit_ECX, emit_EDX);
+        }
+    }
+#if 0
+    jit_emit_cdq(pc);
+#else
+    /* this sequence allows 2 other instructions to run parallel */
+    jit_emit_mov_rr_i(pc, emit_EDX, emit_EAX);
+    pc = emit_shift_i_r(interp, pc, emit_b111, 31, emit_EDX); /* SAR 31 */
+#endif
+    emitm_sdivl_m(pc, emit_EBX, 0, 1, offs);
 
+    if (is_div) {
+        /* result = quotient in EAX */
+        if (saved == 1) {
+            jit_emit_mov_rr_i(pc, emit_EDX, emit_ECX);
+        }
+        if (dest != emit_EAX) {
+            jit_emit_mov_rr_i(pc, dest, emit_EAX);
+        }
+        if (saved == 2) {
+            emitm_popl_r(pc, emit_EDX);
+        }
+    }
+    else {
+        /* result = remainder in EDX */
+        if (dest != emit_EDX) {
+            jit_emit_mov_rr_i(pc, dest, emit_EDX);
+            if (saved == 1) {
+                jit_emit_mov_rr_i(pc, emit_EDX, emit_ECX);
+            }
+            else if (saved == 2)
+                emitm_popl_r(pc, emit_EDX);
+        }
+    }
+    return pc;
+}
+#  define jit_emit_div_RM_i(interp, pc, r, m)  (pc) = opt_div_RM((interp), jit_info, (r), (m), 1)
 #  define jit_emit_cmod_RM_i(interp, pc, r, m) (pc) = opt_div_RM((interp), jit_info, (r), (m), 0)
 
 enum { JIT_X86BRANCH, JIT_X86JUMP, JIT_X86CALL };
 
+static void
+jit_emit_jcc(Parrot_jit_info_t *jit_info, int code, opcode_t disp)
+{
+    long offset;
+    opcode_t opcode;
+
+    opcode = jit_info->op_i + disp;
+
+    if (opcode <= jit_info->op_i) {
+        offset = jit_info->arena.op_map[opcode].offset -
+                (jit_info->native_ptr - jit_info->arena.start);
+
+        /* If we are here, the current section must have a branch_target
+           section, I think. */
+        if (jit_info->optimizer->cur_section->branch_target ==
+            jit_info->optimizer->cur_section)
+                offset +=
+                    jit_info->optimizer->cur_section->branch_target->load_size;
+
+        if (emit_is8bit(offset - 2)) {
+            emitm_jxs(jit_info->native_ptr, code, offset - 2);
+        }
+        else {
+            emitm_jxl(jit_info->native_ptr, code, offset - 6);
+        }
+
+        return;
+    }
+
+    Parrot_jit_newfixup(jit_info);
+    jit_info->arena.fixups->type = JIT_X86BRANCH;
+    jit_info->arena.fixups->param.opcode = opcode;
+    /* If the branch is to the current section, skip the load instructions. */
+    if (jit_info->optimizer->cur_section->branch_target ==
+        jit_info->optimizer->cur_section)
+            jit_info->arena.fixups->skip =
+                (char)jit_info->optimizer->cur_section->branch_target->load_size;
+
+    emitm_jxl(jit_info->native_ptr, code, 0xc0def00d);
+}
+
+static void
+emit_jump(Parrot_jit_info_t *jit_info, opcode_t disp)
+{
+    long offset;
+    opcode_t opcode;
+
+    opcode = jit_info->op_i + disp;
+
+    if (opcode <= jit_info->op_i) {
+        offset = jit_info->arena.op_map[opcode].offset -
+                                (jit_info->native_ptr - jit_info->arena.start);
+        if (emit_is8bit(offset - 2)) {
+            emitm_jumps(jit_info->native_ptr, (char)(offset - 2));
+        }
+        else {
+            emitm_jumpl(jit_info->native_ptr, offset - 5);
+        }
+        return;
+    }
+
+    Parrot_jit_newfixup(jit_info);
+    jit_info->arena.fixups->type = JIT_X86JUMP;
+    jit_info->arena.fixups->param.opcode = opcode;
+    /* If the branch is to the current section, skip the load instructions. */
+    if (jit_info->optimizer->cur_section->branch_target ==
+        jit_info->optimizer->cur_section)
+            jit_info->arena.fixups->skip =
+                (char)jit_info->optimizer->cur_section->branch_target->load_size;
+    emitm_jumpl(jit_info->native_ptr, 0xc0def00d);
+}
+
+static void
+Parrot_emit_jump_to_eax(Parrot_jit_info_t *jit_info,
+                   PARROT_INTERP)
+{
+    /* we have to get the code pointer, which might change
+     * due too intersegment branches
+     */
+
+    /* get interpreter
+     */
+    emitm_movl_m_r(interp, jit_info->native_ptr,
+            emit_EBX, emit_EBP, emit_None, 1, INTERP_BP_OFFS);
+    if (!jit_info->objfile) {
+        /*
+         * emit interp->code->base.data
+         */
+        emitm_movl_m_r(interp, jit_info->native_ptr, emit_ECX, emit_EBX, 0, 1,
+                offsetof(Interp, code));
+        emitm_movl_m_r(interp, jit_info->native_ptr, emit_EDX, emit_ECX, 0, 1,
+                offsetof(PackFile_Segment, data));
+        /* calc code offset */
+        jit_emit_sub_rr_i(interp, jit_info->native_ptr, emit_EAX, emit_EDX);
+        /*
+         * now we have the offset of the ins in EAX
+         *
+         * interp->code->jit_info->arena->op_map
+         *
+         * TODO interleave these 2 calculations
+         */
+        emitm_movl_m_r(interp, jit_info->native_ptr, emit_EDX, emit_ECX, 0, 1,
+                offsetof(PackFile_ByteCode, jit_info));
+        emitm_lea_m_r(interp, jit_info->native_ptr, emit_EDX, emit_EDX, 0, 1,
+                offsetof(Parrot_jit_info_t, arena));
+        emitm_movl_m_r(interp, jit_info->native_ptr, emit_EDX, emit_EDX, 0, 1,
+                offsetof(Parrot_jit_arena_t, op_map));
+
+    }
+#if EXEC_CAPABLE
+    else {
+        int *reg;
+        emitm_subl_i_r(jit_info->native_ptr,
+            jit_info->objfile->bytecode_header_size, emit_EAX);
+        Parrot_exec_add_text_rellocation(jit_info->objfile,
+            jit_info->native_ptr, RTYPE_DATA, "program_code", -4);
+        reg = Parrot_exec_add_text_rellocation_reg(jit_info->objfile,
+                jit_info->native_ptr, "opcode_map", 0, 0);
+        jit_emit_mov_ri_i(interp, jit_info->native_ptr, emit_EDX, (long) reg);
+    }
+#endif
+    /* get base pointer */
+    emitm_movl_m_r(interp, jit_info->native_ptr, emit_EBX, emit_EBX, 0, 1,
+            offsetof(Interp, ctx.bp));
+
+    /* This jumps to the address in op_map[EDX + sizeof (void *) * INDEX] */
+    emitm_jumpm(jit_info->native_ptr, emit_EDX, emit_EAX,
+            sizeof (*jit_info->arena.op_map) / 4, 0);
+}
+
 #  define jit_emit_stack_frame_enter(pc) do { \
     emitm_pushl_r((pc), emit_EBP); \
     jit_emit_mov_rr_i((pc), emit_EBP, emit_ESP); \
@@ -1458,6 +2108,21 @@
     emitm_popl_r((pc), emit_EBP); \
 } while (0)
 
+
+
+static void call_func(Parrot_jit_info_t *jit_info, void (*addr) (void))
+{
+    Parrot_jit_newfixup(jit_info);
+    jit_info->arena.fixups->type = JIT_X86CALL;
+    jit_info->arena.fixups->param.fptr = D2FPTR(addr);
+    emitm_calll(jit_info->native_ptr, 0xdeafc0de);
+}
+
+static void jit_emit_real_exception(Parrot_jit_info_t *jit_info)
+{
+    call_func(jit_info, (void (*) (void)) & Parrot_ex_throw_from_c_args);
+}
+
 #if JIT_VTABLE_OPS
 
 #  undef Parrot_jit_vtable1_op
@@ -1477,11 +2142,11 @@
 #  undef Parrot_jit_vtable_unlessp_op
 #  undef Parrot_jit_vtable_newp_ic_op
 
-#  define JIT_CONST(i) (int *)(jit_info->cur_op[i] * \
+#  define CONST(i) (int *)(jit_info->cur_op[i] * \
        sizeof (PackFile_Constant) + \
        offsetof(PackFile_Constant, u))
 
-#  define JIT_CALL(f) Parrot_exec_add_text_rellocation_func(jit_info->objfile, \
+#  define CALL(f) Parrot_exec_add_text_rellocation_func(jit_info->objfile, \
        jit_info->native_ptr, (f)); \
        emitm_calll(jit_info->native_ptr, EXEC_CALLDISP);
 /* emit a call to a vtable func
@@ -1492,327 +2157,1232 @@
 #  include "parrot/oplib/ops.h"
 EXTERN INTVAL Parrot_FixedIntegerArray_get_integer_keyed_int(Interp*, PMC*, INTVAL);
 EXTERN void Parrot_FixedIntegerArray_set_integer_keyed_int(Interp*, PMC*, INTVAL, INTVAL);
-#  define JIT_ROFFS_PMC(x) REG_OFFS_PMC(jit_info->cur_op[(x)])
-#  define JIT_ROFFS_INT(x) REG_OFFS_INT(jit_info->cur_op[(x)])
+#  define ROFFS_PMC(x) REG_OFFS_PMC(jit_info->cur_op[(x)])
+#  define ROFFS_INT(x) REG_OFFS_INT(jit_info->cur_op[(x)])
+#  define NATIVECODE jit_info->native_ptr
 
-#endif /* JIT_VTABLE_OPS */
+static char*
+jit_set_i_p_ki(Parrot_jit_info_t *jit_info, PARROT_INTERP, size_t offset)
+{
+    char *L1, *L2, *L3, *L4;
+    /*
+     * mov $2, %edi
+     * mov (vtable)%edi, %eax
+     * mov (offset)%eax, %esi
+     * cmp Parrot_FixedIntegerArray_get_integer_keyed_int, %esi
+     * jne L1
+     */
+    jit_emit_mov_RM_i(interp, NATIVECODE, emit_EDI, ROFFS_PMC(2));
+    emitm_movl_m_r(interp, NATIVECODE, emit_EAX, emit_EDI, emit_None, 1,
+            offsetof(struct PMC, vtable));
+    emitm_movl_m_r(interp, NATIVECODE, emit_ESI, emit_EAX, emit_None, 1, offset);
+    jit_emit_cmp_ri_i(interp, NATIVECODE, emit_ESI,
+            Parrot_FixedIntegerArray_get_integer_keyed_int);
+    L1 = NATIVECODE;
+    emitm_jxs(NATIVECODE, emitm_jnz, 0);
+    /*
+     * mov $3, %ecx
+     * cmp %ecx, 0
+     * js L2
+     * mov (int_val)%edi, %eax
+     * cmp %ecx, $eax
+     * jge L3
+     *
+     */
+    if (MAP(3)) {
+        jit_emit_mov_rr_i(NATIVECODE, emit_ECX, MAP(3));
+    }
+    else {
+        jit_emit_mov_RM_i(interp, NATIVECODE, emit_ECX, ROFFS_INT(3));
+    }
+    /*  range check */
+    jit_emit_cmp_ri_i(interp, NATIVECODE, emit_ECX, 0);
+    L2 = NATIVECODE;
+    emitm_jxs(NATIVECODE, emitm_js, 0);
+    emitm_movl_m_r(interp, NATIVECODE, emit_EAX, emit_EDI, 0, 1,
+            offsetof(struct PMC, cache._i._int_val));
+    jit_emit_cmp_rr_i(NATIVECODE, emit_ECX, emit_EAX);
+    L3 = NATIVECODE;
+    emitm_jxs(NATIVECODE, emitm_jnl, 0);
 
-#if EXEC_CAPABLE
-#  ifdef JIT_CGP
-#    ifdef EXEC_SHARED
-#      define exec_emit_end(interp, pc) { \
-           jit_emit_mov_rm_i((pc), c, 2); \
-           Parrot_exec_add_text_rellocation(jit_info->objfile, \
-             jit_info->native_ptr, RTYPE_COM, "cgp_core", 0); \
-           emitm_movl_m_r((interp), jit_info->native_ptr, emit_ESI, emit_ESI, \
-             emit_None, 1, 0); \
-           emitm_addb_i_r(jit_info->native_ptr, \
-             (int)((ptrcast_t)((op_func_t*) \
-               (interp)->op_lib->op_func_table)[0]) - (int)cgp_core, \
-                 emit_ESI); \
-           emitm_jumpr((pc), emit_ESI); \
-         }
-#    else /* EXEC_SHARED */
-#      define exec_emit_end(interp, pc) { \
-           jit_emit_mov_ri_i((interp), (pc), emit_ESI, \
-             (int)((ptrcast_t)((op_func_t*) \
-               (interp)->op_lib->op_func_table)[0]) - (int)cgp_core); \
-           Parrot_exec_add_text_rellocation(jit_info->objfile, \
-             jit_info->native_ptr, RTYPE_COM, "cgp_core", -4); \
-           emitm_jumpr((pc), emit_ESI); \
-         }
-#    endif /* EXEC_SHARED */
+    /*
+     * mov (data)%edi, %eax
+     * mov (%eax, %ecx, 4), %eax
+     * jmp L4
+     */
+    emitm_movl_m_r(interp, NATIVECODE, emit_EAX, emit_EDI, 0, 1,
+            offsetof(struct PMC, data));
+    emitm_movl_m_r(interp, NATIVECODE, emit_EAX, emit_EAX, emit_ECX, 4, 0);
+
+    L4 = NATIVECODE;
+    emitm_jumps(NATIVECODE, 0);
+    /* L1: L2: L3: */
+    L1[1] = (char)(NATIVECODE - L1 - 2);
+    L2[1] = (char)(NATIVECODE - L2 - 2);
+    L3[1] = (char)(NATIVECODE - L3 - 2);
+    return L4;
+}
 
-#  else /* JIT_CGP */
+static char*
+jit_set_p_ki_i(Parrot_jit_info_t *jit_info, PARROT_INTERP, size_t offset)
+{
+    char *L1, *L2, *L3, *L4;
+    /*
+     * mov $1, %edi
+     * mov (vtable)%edi, %eax
+     * mov (offset)%eax, %esi
+     * cmp Parrot_FixedIntegerArray_set_integer_keyed_int, %esi
+     * jne L1
+     */
+    jit_emit_mov_RM_i(interp, NATIVECODE, emit_EDI, ROFFS_PMC(1));
+    emitm_movl_m_r(interp, NATIVECODE, emit_EAX, emit_EDI, emit_None, 1,
+            offsetof(struct PMC, vtable));
+    emitm_movl_m_r(interp, NATIVECODE, emit_ESI, emit_EAX, emit_None, 1, offset);
+    jit_emit_cmp_ri_i(interp, NATIVECODE, emit_ESI,
+            Parrot_FixedIntegerArray_set_integer_keyed_int);
+    L1 = NATIVECODE;
+    emitm_jxs(NATIVECODE, emitm_jnz, 0);
+    /*
+     * mov $2, %ecx
+     * cmp %ecx, 0
+     * js L2
+     * mov (int_val)%edi, %eax
+     * cmp %ecx, $eax
+     * jge L3
+     *
+     */
+    if (MAP(2)) {
+        jit_emit_mov_rr_i(NATIVECODE, emit_ECX, MAP(2));
+    }
+    else {
+        jit_emit_mov_RM_i(interp, NATIVECODE, emit_ECX, ROFFS_INT(2));
+    }
+    /*  range check */
+    jit_emit_cmp_ri_i(interp, NATIVECODE, emit_ECX, 0);
+    L2 = NATIVECODE;
+    emitm_jxs(NATIVECODE, emitm_js, 0);
+    emitm_movl_m_r(interp, NATIVECODE, emit_EAX, emit_EDI, 0, 1,
+            offsetof(struct PMC, cache._i._int_val));
+    jit_emit_cmp_rr_i(NATIVECODE, emit_ECX, emit_EAX);
+    L3 = NATIVECODE;
+    emitm_jxs(NATIVECODE, emitm_jnl, 0);
 
-#    define exec_emit_end(pc) jit_emit_end(pc)
+    /*
+     * mov (data)%eax, %eax
+     * mov $3, %edx
+     * mov $edx, (%eax, %ecx, 4)
+     * jmp L4
+     */
+    emitm_movl_m_r(interp, NATIVECODE, emit_EAX, emit_EDI, 0, 1,
+            offsetof(struct PMC, data));
+    if (MAP(3)) {
+        jit_emit_mov_rr_i(NATIVECODE, emit_EDX, MAP(3));
+    }
+    else {
+        jit_emit_mov_RM_i(interp, NATIVECODE, emit_EDX, ROFFS_INT(3));
+    }
+    emitm_movl_r_m(interp, NATIVECODE, emit_EDX, emit_EAX, emit_ECX, 4, 0);
 
-#  endif /* JIT_CGP */
-#endif /* EXEC_CAPABLE */
-
-#ifdef JIT_CGP
-#  define jit_emit_end(interp, pc) { \
-       jit_emit_mov_ri_i((interp), (pc), emit_ESI, \
-         (ptrcast_t)((op_func_t*)(interp)->op_lib->op_func_table) [0]); \
-       emitm_jumpr((pc), emit_ESI); \
-     }
-#else /* JIT_CGP */
-#  define jit_emit_end(pc) { \
-       jit_emit_add_ri_i((interp), (pc), emit_ESP, 4); \
-       emitm_popl_r((pc), emit_EDI); \
-       emitm_popl_r((pc), emit_ESI); \
-       emitm_popl_r((pc), emit_EBX); \
-       emitm_popl_r((pc), emit_EBP); \
-       emitm_ret(pc); \
-     }
-
-#endif /* JIT_CGP */
+    L4 = NATIVECODE;
+    emitm_jumps(NATIVECODE, 0);
+    /* L1: L2: L3: */
+    L1[1] = (char)(NATIVECODE - L1 - 2);
+    L2[1] = (char)(NATIVECODE - L2 - 2);
+    L3[1] = (char)(NATIVECODE - L3 - 2);
+    return L4;
+}
 
-#  define NATIVECODE jit_info->native_ptr
-#  define CUR_OPCODE jit_info->cur_op
-#  define JIT_CONST(i) PCONST(jit_info->cur_op[(i)])
+#  undef ROFFS_PMC
+#  undef ROFFS_INT
+#  undef NATIVECODE
 
 /*
- * if jit_emit_noop is defined, it does align a jump target
- * to 1 << JUMP_ALIGN
- * It may emit exactly one byte, or some desired padding.
- * The instructions must perform like a noop.
- *
- * Alignment effects seem to be rather processor specific and
- * it's not quite clear if the branch src or target should be
- * aligned. Turned off for now.
- *
- * s. also info gcc /align-jump
- *
- * noop; mov %esi, %esi; lea 0(%esi), %esi
- * TODO
- * 7 bytes: 8d b4 26 00 00 00 00    lea    0x0(%esi),%esi
- * 6 bytes: 8d b6 00 00 00 00       lea    0x0(%esi),%esi
- * 5 bytes: 90 8d 74 26 00          nop,   lea    0x0(%esi),%esi
- * 4 bytes: 8d 74 26 00             lea    0x0(%esi),%esi
- *
+ * for vtable calls registers are already saved back
  */
+static void
+Parrot_jit_vtable_n_op(Parrot_jit_info_t *jit_info,
+                PARROT_INTERP, int n, int *args)
+{
+    int        nvtable = op_jit[*jit_info->cur_op].extcall;
+    size_t     offset;
+    op_info_t *op_info = &interp->op_info_table[*jit_info->cur_op];
+    int        pi;
+    int        idx, i, op;
+    int        st      = 0;         /* stack pop correction */
+    char      *L4      = NULL;
+
+    /* get the offset of the first vtable func */
+    offset  = offsetof(VTABLE, absolute);
+    offset += nvtable * sizeof (void *);
+    op      = *jit_info->cur_op;
 
-#  define jit_emit_noop(pc) do { \
-     switch (((unsigned long) (pc)) & 3) { \
-       case 1: *(pc)++ = (char) 0x8d; *(pc)++ = (char) 0x76; *(pc)++ = (char) 0x00; break; \
-       case 2: *(pc)++ = (char) 0x89; *(pc)++ = (char) 0xf6; break; \
-       case 3: *(pc)++ = (char) 0x90; break; \
-     } \
-   } while (0)
+    if (op == PARROT_OP_set_i_p_ki) {
+        L4 = jit_set_i_p_ki(jit_info, interp, offset);
+    }
+    else if (op == PARROT_OP_set_p_ki_i) {
+        L4 = jit_set_p_ki_i(jit_info, interp, offset);
+    }
 
-#  define JUMP_ALIGN 0
-#  define SUB_ALIGN 0
+    /* get params $i, 0 is opcode */
+    for (idx = n; idx > 0; idx--) {
+        i  = args[idx-1];
+        pi = *(jit_info->cur_op + i);
+
+        switch (op_info->types[i - 1]) {
+            case PARROT_ARG_S:
+                emitm_movl_m_r(interp, jit_info->native_ptr,
+                        emit_EAX, emit_EBX, emit_None, 1, REG_OFFS_STR(pi));
+                emitm_pushl_r(jit_info->native_ptr, emit_EAX);
+                break;
+            case PARROT_ARG_K:
+            case PARROT_ARG_P:
+                emitm_movl_m_r(interp, jit_info->native_ptr,
+                        emit_EAX, emit_EBX, emit_None, 1, REG_OFFS_PMC(pi));
+                /* push $i, the left most Pi stays in eax, which is used
+                 * below, to call the vtable method
+                 */
+                emitm_pushl_r(jit_info->native_ptr, emit_EAX);
+                break;
+            case PARROT_ARG_KI:
+            case PARROT_ARG_I:
+                if (MAP(i))
+                    emitm_pushl_r(jit_info->native_ptr, MAP(i));
+                else {
+                    emitm_movl_m_r(interp, jit_info->native_ptr,
+                            emit_EAX, emit_EBX, emit_None, 1, REG_OFFS_INT(pi));
+                    emitm_pushl_r(jit_info->native_ptr, emit_EAX);
+                }
+                break;
+                break;
+            case PARROT_ARG_KIC:
+            case PARROT_ARG_IC:
+                /* XXX INTVAL_SIZE */
+                /* push value */
+                emitm_pushl_i(jit_info->native_ptr, pi);
+                break;
+            case PARROT_ARG_N:
+                /* push num on st(0) */
+                if (MAP(i))
+                    emitm_fld(jit_info->native_ptr, MAP(i));
+                else
+                    jit_emit_fload_mb_n(interp, jit_info->native_ptr,
+                            emit_EBX, REG_OFFS_NUM(pi));
+                goto store;
+            case PARROT_ARG_NC:
+                /*
+                 * TODO not all constants are shared between interpreters
+                 */
+#  if EXEC_CAPABLE
+                if (jit_info->objfile) {
+                    jit_emit_fload_m_n(interp, jit_info->native_ptr, CONST(i));
+                    Parrot_exec_add_text_rellocation(jit_info->objfile,
+                            jit_info->native_ptr, RTYPE_DATA, "const_table", -4);
+                }
+                else
+#  endif
+                    jit_emit_fload_m_n(interp, jit_info->native_ptr,
+                            &interp->code->const_table->
+                            constants[pi]->u.number);
+store:
+#  if NUMVAL_SIZE == 8
+                /* make room for double */
+                emitm_addb_i_r(jit_info->native_ptr, -8, emit_ESP);
+                emitm_fstpl(interp, jit_info->native_ptr, emit_ESP, emit_None, 1, 0);
+                /* additional stack adjustment */
+                st += 4;
+#  else
+                emitm_addb_i_r(jit_info->native_ptr, -12, emit_ESP);
+                emitm_fstpt(jit_info->native_ptr, emit_ESP, emit_None, 1, 0);
+                st += 8;
+#  endif
+                break;
 
-extern int jit_op_count(void);
+            case PARROT_ARG_SC:
+#  if EXEC_CAPABLE
+                if (jit_info->objfile) {
+                    emitm_pushl_m(jit_info->native_ptr, CONST(i));
+                    Parrot_exec_add_text_rellocation(jit_info->objfile,
+                            jit_info->native_ptr, RTYPE_DATA, "const_table", -4);
+                }
+                else
+#  endif
+                    emitm_pushl_i(jit_info->native_ptr,
+                            interp->code->const_table->
+                            constants[pi]->u.string);
+                break;
+
+            case PARROT_ARG_KC:
+            case PARROT_ARG_PC:
+#  if EXEC_CAPABLE
+                if (jit_info->objfile) {
+                    emitm_pushl_m(jit_info->native_ptr, CONST(i));
+                    Parrot_exec_add_text_rellocation(jit_info->objfile,
+                            jit_info->native_ptr, RTYPE_DATA,
+                            "const_table", -4);
+                }
+                else
+#  endif
+                    emitm_pushl_i(jit_info->native_ptr,
+                            interp->code->const_table->
+                            constants[pi]->u.key);
+                break;
+
+            default:
+                Parrot_ex_throw_from_c_args(interp, NULL, 1,
+                    "jit_vtable_n_op: unimp type %d, arg %d vtable %d",
+                    op_info->types[i - 1], i, nvtable);
+                break;
+        }
+    }
 
-#  define REQUIRES_CONSTANT_POOL 0
-/*
- * examples/pir/mandel.pir and t/op/jitn_14 show rounding problems
- * due to keeping intermediate results in FP registers
- * When intermediates are written back to parrot regs, rounding to
- * 64 bit is performed, which changes results slightly
- *
- * One method is to just turn off mapped floats. The other one is
- * setting a different control word (with precision control = double)
- * see emitm_fldcw above
- */
-#  define FLOAT_REGISTERS_TO_MAP 4
+    /* push interpreter */
+    Parrot_jit_emit_get_INTERP(interp, jit_info->native_ptr, emit_ECX);
+    emitm_pushl_r(jit_info->native_ptr, emit_ECX);
 
-/*
- * register usage
- * %edi, %esi ... mapped, preserved
- * %edx, %ecx ... mapped, not preserved
- * %ebx       ... base pointer for register access, preserved
- * %eax       ... scratch, return value register
- */
+    if (L4) {
+        emitm_callr(jit_info->native_ptr, emit_ESI);
+    }
+    else {
+        /* mov (offs)%eax, %eax i.e. $1->vtable */
+        emitm_movl_m_r(interp, jit_info->native_ptr, emit_EAX, emit_EAX, emit_None, 1,
+                offsetof(struct PMC, vtable));
+        /* call *(offset)eax */
+        emitm_callm(jit_info->native_ptr, emit_EAX, emit_None, emit_None, offset);
+    }
 
-extern const jit_arch_info arch_info;
-extern const char i_map_sub[];
-extern const char floatval_map[];
-extern const char i_map[];
+    emitm_addb_i_r(jit_info->native_ptr,
+            st + sizeof (void *) * (n + 1), emit_ESP);
 
-/* registers are either allocate per section or per basic block
- * set this to 1 or 0 to change allocation scheme
+    /* L4: */
+    if (L4)
+        L4[1] = (char)(jit_info->native_ptr - L4 - 2);
+}
+
+static void
+Parrot_jit_store_retval(Parrot_jit_info_t *jit_info,
+                     PARROT_INTERP)
+{
+    op_info_t *op_info = &interp->op_info_table[*jit_info->cur_op];
+    int p1 = *(jit_info->cur_op + 1);
+
+    /* return result is in EAX or ST(0) */
+    switch (op_info->types[0]) {
+        case PARROT_ARG_I:
+            emitm_movl_r_m(interp, jit_info->native_ptr,
+                    emit_EAX, emit_EBX, emit_None, 1, REG_OFFS_INT(p1));
+            break;
+        case PARROT_ARG_S:
+            emitm_movl_r_m(interp, jit_info->native_ptr,
+                    emit_EAX, emit_EBX, emit_None, 1, REG_OFFS_STR(p1));
+            break;
+        case PARROT_ARG_P:
+            emitm_movl_r_m(interp, jit_info->native_ptr,
+                    emit_EAX, emit_EBX, emit_None, 1, REG_OFFS_PMC(p1));
+            break;
+        case PARROT_ARG_N:
+            jit_emit_fstore_mb_n(interp, jit_info->native_ptr, emit_EBX,
+                    REG_OFFS_NUM(p1));
+            break;
+        default:
+            Parrot_ex_throw_from_c_args(interp, NULL, 1, "jit_vtable1r: ill LHS");
+            break;
+    }
+}
+
+/* emit a call to a vtable func
+ * $1->vtable(interp, $1)
  */
-#  define ALLOCATE_REGISTERS_PER_SECTION 1
+static void
+Parrot_jit_vtable1_op(Parrot_jit_info_t *jit_info,
+                     PARROT_INTERP)
+{
+    int a[] = { 1 };
+    Parrot_jit_vtable_n_op(jit_info, interp, 1, a);
+}
 
-/*
- * new style move function using offsets relative to the base_reg
+/* emit a call to a vtable func
+ * $1 = $2->vtable(interp, $2)
  */
-#  ifdef JIT_CGP
-#    define INTERP_BP_OFFS todo
-#  else
-#    define INTERP_BP_OFFS -16
-#  endif
+static void
+Parrot_jit_vtable1r_op(Parrot_jit_info_t *jit_info,
+                     PARROT_INTERP)
+{
+    int a[] = { 2 };
+    Parrot_jit_vtable_n_op(jit_info, interp, 1, a);
+    Parrot_jit_store_retval(jit_info, interp);
+}
 
-/* Function definitions */
 
-INTVAL get_nci_I(PARROT_INTERP, ARGMOD(call_state *st), int n);
+/* emit a call to a vtable func
+ * $1 = $2->vtable(interp, $2, $3)
+ */
+static void
+Parrot_jit_vtable_1r223_op(Parrot_jit_info_t *jit_info,
+                     PARROT_INTERP)
+{
+    int a[] = { 2 , 3};
+    Parrot_jit_vtable_n_op(jit_info, interp, 2, a);
+    Parrot_jit_store_retval(jit_info, interp);
+}
 
-FLOATVAL get_nci_N(PARROT_INTERP, ARGMOD(call_state *st), int n);
+/* emit a call to a vtable func
+ * $1 = $3->vtable(interp, $3, $2)
+ */
+static void
+Parrot_jit_vtable_1r332_op(Parrot_jit_info_t *jit_info,
+                     PARROT_INTERP)
+{
+    int a[] = { 3 , 2};
+    Parrot_jit_vtable_n_op(jit_info, interp, 2, a);
+    Parrot_jit_store_retval(jit_info, interp);
+}
+/* emit a call to a vtable func
+ * $1->vtable(interp, $1, $2)
+ */
+static void
+Parrot_jit_vtable_112_op(Parrot_jit_info_t *jit_info,
+                     PARROT_INTERP)
+{
+    int a[] = { 1, 2 };
+    Parrot_jit_vtable_n_op(jit_info, interp, 2, a);
+}
 
-PARROT_WARN_UNUSED_RESULT
-PARROT_CANNOT_RETURN_NULL
-STRING* get_nci_S(PARROT_INTERP, ARGMOD(call_state *st), int n);
+/* emit a call to a vtable func
+ * $1->vtable(interp, $1, $1)
+ */
+static void
+Parrot_jit_vtable_111_op(Parrot_jit_info_t *jit_info,
+                     PARROT_INTERP)
+{
+    int a[] = { 1, 1 };
+    Parrot_jit_vtable_n_op(jit_info, interp, 2, a);
+}
+/* emit a call to a vtable func
+ * $2->vtable(interp, $2, $1)
+ */
+static void
+Parrot_jit_vtable_221_op(Parrot_jit_info_t *jit_info,
+                     PARROT_INTERP)
+{
+    int a[] = { 2, 1 };
+    Parrot_jit_vtable_n_op(jit_info, interp, 2, a);
+}
 
-PARROT_WARN_UNUSED_RESULT
-PARROT_CANNOT_RETURN_NULL
-PMC* get_nci_P(PARROT_INTERP, ARGMOD(call_state *st), int n);
+/* emit a call to a vtable func
+ * $2->vtable(interp, $2, $3, $1)
+ */
+static void
+Parrot_jit_vtable_2231_op(Parrot_jit_info_t *jit_info,
+                     PARROT_INTERP)
+{
+    int a[] = { 2, 3, 1 };
+    Parrot_jit_vtable_n_op(jit_info, interp, 3, a);
+}
 
-void set_nci_I(PARROT_INTERP, ARGOUT(call_state *st), INTVAL val);
+/* emit a call to a vtable func
+ * $1->vtable(interp, $1, $2, $3)
+ */
+static void
+Parrot_jit_vtable_1123_op(Parrot_jit_info_t *jit_info,
+                     PARROT_INTERP)
+{
+    int a[] = { 1, 2, 3 };
+    Parrot_jit_vtable_n_op(jit_info, interp, 3, a);
+}
 
-void set_nci_N(PARROT_INTERP, ARGOUT(call_state *st), FLOATVAL val);
+/* emit a call to a vtable func
+ * $1->vtable(interp, $1, $2, $1)
+ */
+static void
+Parrot_jit_vtable_1121_op(Parrot_jit_info_t *jit_info,
+                     PARROT_INTERP)
+{
+    int a[] = { 1, 2, 1 };
+    Parrot_jit_vtable_n_op(jit_info, interp, 3, a);
+}
 
-void set_nci_S(PARROT_INTERP, ARGOUT(call_state *st), STRING *val);
 
-void set_nci_P(PARROT_INTERP, ARGOUT(call_state *st), PMC* val);
+/* if_p_ic, unless_p_ic */
+static void
+Parrot_jit_vtable_if_unless_op(Parrot_jit_info_t *jit_info,
+                     PARROT_INTERP, int unless)
+{
+    int ic = *(jit_info->cur_op + 2);   /* branch offset */
 
-int emit_is8bit(long disp);
+    /* emit call  vtable function i.e. get_bool, result eax */
+    Parrot_jit_vtable1_op(jit_info, interp);
+    /* test result */
+    jit_emit_test_r_i(jit_info->native_ptr, emit_EAX);
+    jit_emit_jcc(jit_info, unless ? emitm_jz : emitm_jnz, ic);
+}
 
-char * emit_disp8_32(char *pc, int disp);
+/* unless_p_ic */
+static void
+Parrot_jit_vtable_unlessp_op(Parrot_jit_info_t *jit_info,
+                     PARROT_INTERP)
+{
+    Parrot_jit_vtable_if_unless_op(jit_info, interp, 1);
+}
 
-void emit_sib(PARROT_INTERP, char *pc, int scale, int i, int base);
+/* if_p_ic */
+static void
+Parrot_jit_vtable_ifp_op(Parrot_jit_info_t *jit_info,
+                     PARROT_INTERP)
+{
+    Parrot_jit_vtable_if_unless_op(jit_info, interp, 0);
+}
 
-char * emit_r_X(PARROT_INTERP, char *pc, int reg_opcode, int base, int i,
-    int scale, long disp);
+/* new_p_ic */
+static void
+Parrot_jit_vtable_newp_ic_op(Parrot_jit_info_t *jit_info,
+                     PARROT_INTERP)
+{
+    int p1, i2;
+    op_info_t *op_info = &interp->op_info_table[*jit_info->cur_op];
+    size_t offset = offsetof(VTABLE, init);
+
+    PARROT_ASSERT(op_info->types[0] == PARROT_ARG_P);
+    p1 = *(jit_info->cur_op + 1);
+    i2 = *(jit_info->cur_op + 2);
+
+    if (i2 <= 0 || i2 >= interp->n_vtable_max)
+        Parrot_ex_throw_from_c_args(interp, NULL, 1,
+            "Illegal PMC enum (%d) in new", i2);
 
-char * emit_shift_i_r(PARROT_INTERP, char *pc, int opcode, int imm, int reg);
+    /* get interpreter */
+    Parrot_jit_emit_get_INTERP(interp, jit_info->native_ptr, emit_ECX);
 
-char * emit_shift_i_m(PARROT_INTERP, char *pc, int opcode, int imm,
-    int base, int i, int scale, long disp);
+    /* push pmc enum and interpreter */
+    emitm_pushl_i(jit_info->native_ptr, i2);
+    emitm_pushl_r(jit_info->native_ptr, emit_ECX);
+#  if EXEC_CAPABLE
+    if (jit_info->objfile) {
+        CALL("pmc_new_noinit");
+    }
+    else
+#  endif
+    {
+        call_func(jit_info, (void (*) (void))pmc_new_noinit);
+    }
+    /* result = eax push pmc */
+    emitm_pushl_r(jit_info->native_ptr, emit_EAX);
+    /* store in PMC too */
+    emitm_movl_r_m(interp, jit_info->native_ptr,
+            emit_EAX, emit_EBX, emit_None, 1, REG_OFFS_PMC(p1));
+    /* push interpreter */
+    Parrot_jit_emit_get_INTERP(interp, jit_info->native_ptr, emit_ECX);
+    emitm_pushl_r(jit_info->native_ptr, emit_ECX);
+    /* mov (offs)%eax, %eax i.e. $1->vtable */
+    emitm_movl_m_r(interp, jit_info->native_ptr, emit_EAX, emit_EAX, emit_None, 1,
+            offsetof(struct PMC, vtable));
+    /* call *(offset)eax */
+    emitm_callm(jit_info->native_ptr, emit_EAX, emit_None, emit_None, offset);
+    /* adjust 4 args pushed */
+    emitm_addb_i_r(jit_info->native_ptr, 16, emit_ESP);
+}
 
-char * emit_shift_r_r(PARROT_INTERP, char *pc, int opcode, int reg1, int reg2);
+#  undef IREG
+#  undef NREG
+#  undef SREG
+#  undef PREG
+#  undef CONST
+#  undef CALL
 
-char * emit_shift_r_m(PARROT_INTERP, char *pc, int opcode, int reg,
-    int base, int i, int scale, long disp);
+#endif /* JIT_VTABLE_OPS */
 
-char * emit_pushl_m(PARROT_INTERP, char *pc, int base, int i,
-    int scale, long disp);
+#if EXEC_CAPABLE
+#  ifdef JIT_CGP
+#    ifdef EXEC_SHARED
+#      define exec_emit_end(interp, pc) { \
+           jit_emit_mov_rm_i((pc), c, 2); \
+           Parrot_exec_add_text_rellocation(jit_info->objfile, \
+             jit_info->native_ptr, RTYPE_COM, "cgp_core", 0); \
+           emitm_movl_m_r((interp), jit_info->native_ptr, emit_ESI, emit_ESI, \
+             emit_None, 1, 0); \
+           emitm_addb_i_r(jit_info->native_ptr, \
+             (int)((ptrcast_t)((op_func_t*) \
+               (interp)->op_lib->op_func_table)[0]) - (int)cgp_core, \
+                 emit_ESI); \
+           emitm_jumpr((pc), emit_ESI); \
+         }
+#    else /* EXEC_SHARED */
+#      define exec_emit_end(interp, pc) { \
+           jit_emit_mov_ri_i((interp), (pc), emit_ESI, \
+             (int)((ptrcast_t)((op_func_t*) \
+               (interp)->op_lib->op_func_table)[0]) - (int)cgp_core); \
+           Parrot_exec_add_text_rellocation(jit_info->objfile, \
+             jit_info->native_ptr, RTYPE_COM, "cgp_core", -4); \
+           emitm_jumpr((pc), emit_ESI); \
+         }
+#    endif /* EXEC_SHARED */
 
-char * emit_popl_r(char *pc, int reg);
+#  else /* JIT_CGP */
 
-char * emit_popl_m(PARROT_INTERP, char *pc, int base, int i, int scale,
-    long disp);
+#    define exec_emit_end(pc) jit_emit_end(pc)
 
-char * emit_movb_r_r(char *pc, int reg1, int reg2);
+#  endif /* JIT_CGP */
+#endif /* EXEC_CAPABLE */
 
-char * emit_movb_i_r(char *pc, char imm, int reg);
+#ifdef JIT_CGP
+#  define jit_emit_end(interp, pc) { \
+       jit_emit_mov_ri_i((interp), (pc), emit_ESI, \
+         (ptrcast_t)((op_func_t*)(interp)->op_lib->op_func_table) [0]); \
+       emitm_jumpr((pc), emit_ESI); \
+     }
+#else /* JIT_CGP */
+#  define jit_emit_end(pc) { \
+       jit_emit_add_ri_i((interp), (pc), emit_ESP, 4); \
+       emitm_popl_r((pc), emit_EDI); \
+       emitm_popl_r((pc), emit_ESI); \
+       emitm_popl_r((pc), emit_EBX); \
+       emitm_popl_r((pc), emit_EBP); \
+       emitm_ret(pc); \
+     }
 
-char * emit_movb_i_m(PARROT_INTERP, char *pc, char imm, int base, int i,
-    int scale, long disp);
+#endif /* JIT_CGP */
 
-char * opt_mul(PARROT_INTERP, char *pc, int dest, INTVAL imm,
-    int src);
+#  define NATIVECODE jit_info->native_ptr
+#  define CUR_OPCODE jit_info->cur_op
+#  define CONST(i) PCONST(jit_info->cur_op[(i)])
+static void
+jit_get_params_pc(Parrot_jit_info_t *jit_info, PARROT_INTERP)
+{
+    PMC *sig_pmc;
+    INTVAL *sig_bits, i, n;
 
-int intreg_is_used(Parrot_jit_info_t *jit_info, char reg);
+    sig_pmc = CONTEXT(interp)->constants[CUR_OPCODE[1]]->u.key;
+    sig_bits = SIG_ARRAY(sig_pmc);
+    n = SIG_ELEMS(sig_pmc);
+    jit_info->n_args = n;
+    emitm_movl_m_r(interp, NATIVECODE, emit_EAX, emit_EBP, emit_None, 1, 16);
+    for (i = 0; i < n; ++i) {
+        switch (sig_bits[i] & PARROT_ARG_TYPE_MASK) {
+            case PARROT_ARG_INTVAL:
+                emitm_movl_m_r(interp, NATIVECODE, MAP(2+i), emit_EAX, emit_None,
+                        1, 4 + i*4);
+                break;
+            case PARROT_ARG_FLOATVAL:
+                emitm_movl_m_r(interp, NATIVECODE, emit_EAX, emit_EAX, emit_None,
+                        1, 4+ i*4);
+                jit_emit_fload_mb_n(interp, NATIVECODE, emit_EAX, 0);
+                emitm_fstp(NATIVECODE, (MAP(2+i) + 1));
+                if (i < n - 1)
+                    emitm_movl_m_r(interp, NATIVECODE, emit_EAX, emit_EBP,
+                            emit_None, 1, 16);
+                break;
+            default:
+                break;
+        }
+    }
+}
 
-char * opt_shift_rm(PARROT_INTERP, Parrot_jit_info_t *jit_info, int dest,
-    int offs, int op);
+/*
+ * preserve registers
+ * a) all callee saved on function entry
+ */
+static void
+jit_save_regs(Parrot_jit_info_t *jit_info, PARROT_INTERP)
+{
+    int i, used_i, save_i;
+    const jit_arch_regs *reg_info;
 
-char * div_rr_n(PARROT_INTERP, Parrot_jit_info_t *jit_info, int r1);
+    used_i = CONTEXT(interp)->n_regs_used[REGNO_INT];
+    reg_info = &jit_info->arch_info->regs[jit_info->code_type];
+    save_i = reg_info->n_preserved_I;
+    for (i = save_i; i < used_i; ++i) {
+        emitm_pushl_r(jit_info->native_ptr, reg_info->map_I[i]);
+    }
+}
 
-char * mod_rr_n(PARROT_INTERP, Parrot_jit_info_t *jit_info, int r);
+/* restore saved regs, see above */
+static void
+jit_restore_regs(Parrot_jit_info_t *jit_info, PARROT_INTERP)
+{
 
-char * opt_div_rr(PARROT_INTERP, Parrot_jit_info_t *jit_info, int dest,
-    int src, int is_div);
+    int i, used_i, save_i;
+    const jit_arch_regs *reg_info;
 
-char * opt_div_ri(PARROT_INTERP, Parrot_jit_info_t *jit_info, int dest,
-    INTVAL imm, int is_div);
+    used_i = CONTEXT(interp)->n_regs_used[REGNO_INT];
+    reg_info = &jit_info->arch_info->regs[jit_info->code_type];
+    save_i = reg_info->n_preserved_I;
+    /* note - reversed order of jit_save_regs  */
+    for (i = used_i - 1; i >= save_i; --i) {
+        emitm_popl_r(jit_info->native_ptr, reg_info->map_I[i]);
+    }
+}
 
-char * opt_div_RM(PARROT_INTERP, Parrot_jit_info_t *jit_info, int dest,
-    int offs, int is_div);
+/*
+ * preserve registers around a functioncall
+ *
+ * all used register around a call (skip >= 0 := return result
+ *
+ * TODO factor out common code
+ *      use jit_emit_mov_RM_{in} functions (load/store base indexed)
+ *      and a macro to retrive sp
+ */
+static int
+jit_save_regs_call(Parrot_jit_info_t *jit_info, PARROT_INTERP, int skip)
+{
+    int i, used_i, used_n;
+    const jit_arch_regs *reg_info;
 
-void jit_emit_jcc(Parrot_jit_info_t *jit_info, int code, opcode_t disp);
+    used_i = CONTEXT(interp)->n_regs_used[REGNO_INT];
+    used_n = CONTEXT(interp)->n_regs_used[REGNO_NUM];
+    jit_emit_sub_ri_i(interp, jit_info->native_ptr, emit_ESP,
+            (used_i * sizeof (INTVAL) + used_n * sizeof (FLOATVAL)));
+    reg_info = &jit_info->arch_info->regs[jit_info->code_type];
+    for (i = 0; i < used_i; ++i) {
+        /* XXX need 2 skip vars */
+        if (reg_info->map_I[i] == skip)
+            continue;
+        emitm_movl_r_m(interp, NATIVECODE, reg_info->map_I[i], emit_ESP,
+                            emit_None, 1,
+                            (used_n * sizeof (FLOATVAL) +
+                             i      * sizeof (INTVAL)));
+    }
+    for (i = 0; i < used_n; ++i) {
+        if (reg_info->map_F[i] == skip)
+            continue;
+        emitm_fld(NATIVECODE, reg_info->map_F[i]);
+        jit_emit_fstore_mb_n(interp, NATIVECODE, emit_ESP, (i * sizeof (FLOATVAL)));
+    }
+    return used_n;
+}
 
-void emit_jump(Parrot_jit_info_t *jit_info, opcode_t disp);
+static void
+jit_restore_regs_call(Parrot_jit_info_t *jit_info, PARROT_INTERP,
+        int skip)
+{
 
-void Parrot_emit_jump_to_eax(Parrot_jit_info_t *jit_info,
-    PARROT_INTERP);
+    int i, used_i, used_n;
+    const jit_arch_regs *reg_info;
 
-void call_func(Parrot_jit_info_t *jit_info, void (*addr) (void));
+    used_i = CONTEXT(interp)->n_regs_used[REGNO_INT];
+    used_n = CONTEXT(interp)->n_regs_used[REGNO_NUM];
+    reg_info = &jit_info->arch_info->regs[jit_info->code_type];
+
+    for (i = 0; i < used_i; ++i) {
+        if (reg_info->map_I[i] == skip)
+            continue;
+        emitm_movl_m_r(interp, NATIVECODE, reg_info->map_I[i], emit_ESP,
+                            emit_None, 1,
+                            (used_n * sizeof (FLOATVAL) +
+                             i      * sizeof (INTVAL)));
+    }
+    for (i = 0; i < used_n; ++i) {
+        if (reg_info->map_F[i] == skip)
+            continue;
+        jit_emit_fload_mb_n(interp, NATIVECODE, emit_ESP, (i * sizeof (FLOATVAL)));
+        emitm_fstp(NATIVECODE, (1+reg_info->map_F[i]));
+    }
 
-void jit_emit_real_exception(Parrot_jit_info_t *jit_info);
+    jit_emit_add_ri_i(interp, jit_info->native_ptr, emit_ESP,
+            (used_i * sizeof (INTVAL) + used_n * sizeof (FLOATVAL)));
+}
 
-char * jit_set_i_p_ki(Parrot_jit_info_t *jit_info, PARROT_INTERP,
-    size_t offset);
+static void
+jit_set_returns_pc(Parrot_jit_info_t *jit_info, PARROT_INTERP,
+        int recursive)
+{
+    PMC *sig_pmc;
+    INTVAL *sig_bits, sig;
 
-char * jit_set_p_ki_i(Parrot_jit_info_t *jit_info, PARROT_INTERP,
-    size_t offset);
+    sig_pmc = CONTEXT(interp)->constants[CUR_OPCODE[1]]->u.key;
+    if (!SIG_ELEMS(sig_pmc))
+        return;
+    sig_bits = SIG_ARRAY(sig_pmc);
+    sig = sig_bits[0];
+    if (!recursive) {
+        /* mov 16(%ebp), %eax - fetch args ptr */
+        emitm_movl_m_r(interp, NATIVECODE, emit_EAX, emit_EBP, emit_None, 1, 16);
+        emitm_movl_m_r(interp, NATIVECODE, emit_EAX, emit_EAX, emit_None, 1, 0);
+    }
+    /*
+     * recursive returns according to ABI */
+    switch (sig & (PARROT_ARG_TYPE_MASK|PARROT_ARG_CONSTANT)) {
+        case PARROT_ARG_INTVAL:
+            if (recursive) {
+                jit_emit_mov_rr_i(NATIVECODE, emit_EAX, MAP(2));
+            }
+            else {
+                emitm_movl_r_m(interp, NATIVECODE, MAP(2), emit_EAX, 0, 1, 0);
+            }
+            break;
+        case PARROT_ARG_INTVAL|PARROT_ARG_CONSTANT:
+            if (recursive) {
+                jit_emit_mov_ri_i(interp, NATIVECODE, emit_EAX, CUR_OPCODE[2]);
+            }
+            else {
+                emitm_movl_i_m(NATIVECODE, CUR_OPCODE[2], emit_EAX, 0, 1, 0);
+            }
+            break;
+        case PARROT_ARG_FLOATVAL:
+            if (recursive) {
+                jit_emit_mov_rr_n(NATIVECODE, FSR1, MAP(2));
+            }
+            else {
+                emitm_fld(NATIVECODE, MAP(2));
+                jit_emit_fstore_mb_n(interp, NATIVECODE, emit_EAX, 0);
+            }
+            break;
+        case PARROT_ARG_FLOATVAL|PARROT_ARG_CONSTANT:
+            if (recursive) {
+                jit_emit_mov_ri_n(interp, NATIVECODE, FSR1, &CONST(2)->u.number);
+            }
+            else {
+                jit_emit_mov_ri_n(interp, NATIVECODE, FSR1, &CONST(2)->u.number);
+                jit_emit_fstore_mb_n(interp, NATIVECODE, emit_EAX, 0);
+            }
+            break;
+        default:
+            Parrot_ex_throw_from_c_args(interp, NULL, 1,
+                "set_returns_jit - unknown typ");
+            break;
+    }
+}
 
-void Parrot_jit_vtable_n_op(Parrot_jit_info_t *jit_info,
-    PARROT_INTERP, int n, int *args);
+static void
+jit_set_args_pc(Parrot_jit_info_t *jit_info, PARROT_INTERP,
+        int recursive)
+{
+    PMC *sig_args, *sig_params, *sig_result;
+    INTVAL *sig_bits, sig, i, n;
+    PackFile_Constant ** constants;
+    opcode_t *params, *result;
+    char params_map;
+    int skip, used_n;
+    char collision[16];
+    const jit_arch_regs *reg_info;
+
+    reg_info = &jit_info->arch_info->regs[jit_info->code_type];
+
+    /* create args array */
+    if (!recursive)
+        Parrot_ex_throw_from_c_args(interp, NULL, 1,
+            "set_args_jit - can't do that yet ");
 
-void Parrot_jit_store_retval(Parrot_jit_info_t *jit_info,
-    PARROT_INTERP);
+    constants = CONTEXT(interp)->constants;
+    sig_args  = constants[CUR_OPCODE[1]]->u.key;
 
-void Parrot_jit_vtable1_op(Parrot_jit_info_t *jit_info, PARROT_INTERP);
+    if (!SIG_ELEMS(sig_args))
+        return;
+    params = jit_info->optimizer->sections->begin;
+    sig_params = constants[params[1]]->u.key;
+    ASSERT_SIG_PMC(sig_params);
+    sig_bits = SIG_ARRAY(sig_args);
+    n = SIG_ELEMS(sig_args);
+    /*
+     * preserve registers - need get_results, because we skip the
+     * return value
+     */
+    result = CUR_OPCODE + 2 + n + 3; /* set_args, set_p_pc */
+    PARROT_ASSERT(*result == PARROT_OP_get_results_pc);
+    sig_result = constants[result[1]]->u.key;
+    ASSERT_SIG_PMC(sig_result);
+
+    if (!SIG_ELEMS(sig_result))
+        skip = -1;
+    else
+        skip = MAP(2 + n + 3 + 2);
+    used_n = jit_save_regs_call(jit_info, interp, skip);
+    memset(collision, 0, 16);
+    for (i = 0; i < n; ++i) {
+        sig = sig_bits[i];
+        /* move args to params regs */
+        params_map = jit_info->optimizer->map_branch[2 + i];
+        switch (sig & (PARROT_ARG_TYPE_MASK|PARROT_ARG_CONSTANT)) {
+            case PARROT_ARG_INTVAL:
+                /* if the arg was already set,
+                 * we can't use the src again - fetch from stack
+                 *
+                 * XXX skip
+                 *
+                 * TODO write a general reg_move
+                 */
+                if (collision[(int)MAP(2+i)]) {
+                    int j;
+                    for (j = 0; j < reg_info->n_mapped_I; ++j) {
+                        if (reg_info->map_I[j] == MAP(2+i)) {
+                            emitm_movl_m_r(interp, NATIVECODE, params_map, emit_ESP,
+                                    emit_None, 1,
+                                    (used_n * sizeof (FLOATVAL) +
+                                     j  * sizeof (INTVAL)));
+                            break;
+                        }
+                    }
+                }
+                else {
+                    if (params_map != MAP(2+i)) {
+                        jit_emit_mov_rr_i(NATIVECODE, params_map, MAP(2 + i));
+                    }
+                }
+                collision[(int)params_map] = 1;
+                break;
+            case PARROT_ARG_INTVAL|PARROT_ARG_CONSTANT:
+                /* TODO move constants last */
+                jit_emit_mov_ri_i(interp, NATIVECODE, params_map, CUR_OPCODE[2 + i]);
+                break;
+            case PARROT_ARG_FLOATVAL:
+                if (collision[(int)MAP(2+i)]) {
+                    int j;
+                    for (j = 0; j < reg_info->n_mapped_F; ++j) {
+                        if (reg_info->map_F[j] == MAP(2+i)) {
+                            jit_emit_fload_mb_n(interp, NATIVECODE, emit_ESP, (j * sizeof (FLOATVAL)));
+                            emitm_fstp(NATIVECODE, (1+params_map));
+                            break;
+                        }
+                    }
+                }
+                else {
+                    jit_emit_mov_rr_n(NATIVECODE, params_map, MAP(2 + i));
+                }
+                collision[(int)params_map] = 1;
+                break;
+            case PARROT_ARG_FLOATVAL|PARROT_ARG_CONSTANT:
+                jit_emit_mov_ri_n(interp, NATIVECODE, params_map,
+                        &CONST(2 + i)->u.number);
+                break;
+            default:
+                Parrot_ex_throw_from_c_args(interp, NULL, 1,
+                    "set_args_jit - unknown type");
+                break;
+        }
+    }
+}
 
-void Parrot_jit_vtable1r_op(Parrot_jit_info_t *jit_info, PARROT_INTERP);
+#  undef CONST
+/*
+ * if jit_emit_noop is defined, it does align a jump target
+ * to 1 << JUMP_ALIGN
+ * It may emit exactly one byte, or some desired padding.
+ * The instructions must perform like a noop.
+ *
+ * Alignment effects seem to be rather processor specific and
+ * it's not quite clear if the branch src or target should be
+ * aligned. Turned off for now.
+ *
+ * s. also info gcc /align-jump
+ *
+ * noop; mov %esi, %esi; lea 0(%esi), %esi
+ * TODO
+ * 7 bytes: 8d b4 26 00 00 00 00    lea    0x0(%esi),%esi
+ * 6 bytes: 8d b6 00 00 00 00       lea    0x0(%esi),%esi
+ * 5 bytes: 90 8d 74 26 00          nop,   lea    0x0(%esi),%esi
+ * 4 bytes: 8d 74 26 00             lea    0x0(%esi),%esi
+ *
+ */
 
-void Parrot_jit_vtable_1r223_op(Parrot_jit_info_t *jit_info,
-    PARROT_INTERP);
+#  define jit_emit_noop(pc) do { \
+     switch (((unsigned long) (pc)) & 3) { \
+       case 1: *(pc)++ = (char) 0x8d; *(pc)++ = (char) 0x76; *(pc)++ = (char) 0x00; break; \
+       case 2: *(pc)++ = (char) 0x89; *(pc)++ = (char) 0xf6; break; \
+       case 3: *(pc)++ = (char) 0x90; break; \
+     } \
+   } while (0)
 
-void Parrot_jit_vtable_1r332_op(Parrot_jit_info_t *jit_info,
-    PARROT_INTERP);
+#  define JUMP_ALIGN 0
+#  define SUB_ALIGN 0
 
-void Parrot_jit_vtable_112_op(Parrot_jit_info_t *jit_info,
-    PARROT_INTERP);
+#if JIT_EMIT == 0
 
-void Parrot_jit_vtable_111_op(Parrot_jit_info_t *jit_info,
-    PARROT_INTERP);
+static void
+Parrot_jit_dofixup(Parrot_jit_info_t *jit_info, PARROT_INTERP)
+{
+    Parrot_jit_fixup_t *fixup, *next;
+    char *fixup_ptr;
 
-void Parrot_jit_vtable_221_op(Parrot_jit_info_t *jit_info,
-    PARROT_INTERP);
+    fixup = jit_info->arena.fixups;
 
-void Parrot_jit_vtable_2231_op(Parrot_jit_info_t *jit_info,
-    PARROT_INTERP);
+    while (fixup) {
+        switch (fixup->type) {
+        /* This fixes-up a branch to a known opcode offset -
+           32-bit displacement only */
+            case JIT_X86BRANCH:
+                fixup_ptr = Parrot_jit_fixup_target(jit_info, fixup) + 2;
+                *(long *)(fixup_ptr) =
+                    jit_info->arena.op_map[fixup->param.opcode].offset
+                        - (fixup->native_offset + 6) + fixup->skip;
+                break;
+            case JIT_X86JUMP:
+                fixup_ptr = Parrot_jit_fixup_target(jit_info, fixup) + 1;
+                *(long *)(fixup_ptr) =
+                    jit_info->arena.op_map[fixup->param.opcode].offset
+                        - (fixup->native_offset + 5) + fixup->skip;
+                break;
+            case JIT_X86CALL:
+                fixup_ptr = jit_info->arena.start + fixup->native_offset + 1;
+                *(long *)(fixup_ptr) = (long)fixup->param.fptr -
+                    (long)fixup_ptr - 4;
+                break;
+            default:
+                Parrot_ex_throw_from_c_args(interp, NULL, EXCEPTION_JIT_ERROR,
+                    "Unknown fixup type:%d\n", fixup->type);
+            break;
+        }
+        next = fixup->next;
+        free(fixup);
+        fixup = next;
+    }
+    jit_info->arena.fixups = NULL;
+}
 
-void Parrot_jit_vtable_1123_op(Parrot_jit_info_t *jit_info,
-PARROT_INTERP);
+static int control_word = 0x27f;
 
-void Parrot_jit_vtable_1121_op(Parrot_jit_info_t *jit_info,
-    PARROT_INTERP);
+#  ifdef JIT_CGP
 
-void Parrot_jit_vtable_if_unless_op(Parrot_jit_info_t *jit_info,
-    PARROT_INTERP, int unless);
+#    include <parrot/oplib/core_ops_cgp.h>
+/*
+ * This is the somewhat complicated program flow
+ *
+ * JIT code                     prederef code
+ * 1) jit_begin
+ *    stack_enter
+ *    call cgp_core  -->        set stack frame
+ *                              jump to retaddr
+ *    test EAX, 0    <--        also from HALT
+ *    jnz code_start
+ *    stack_leave
+ *    ret
+ * code_start: of JIT code
+ *    jit code
+ *    ....
+ *
+ * 2) normal_op
+ *    mov prederef_code_ptr, esi
+ *    call *(esi)    ---->      prederefed (non JITted code)
+ *                              ....
+ *    ....           <----      ret
+ *    jit_code
+ *    ....
+ * 3) HALT == jit_end
+ *    mov prederefed_op_func[0], esi
+ *    jump *esi      ----->     cleanup prederef stack frame
+ *                              xor eax,eax ; return 0
+ *                              ret (--> after call cgp_core in 1)
+ *
+ */
 
-void Parrot_jit_vtable_unlessp_op(Parrot_jit_info_t *jit_info,
-    PARROT_INTERP);
+static void
+Parrot_jit_begin(Parrot_jit_info_t *jit_info,
+                 PARROT_INTERP)
+{
+    jit_emit_stack_frame_enter(jit_info->native_ptr);
+    emitm_fldcw(interp, jit_info->native_ptr, &control_word);
+    emitm_pushl_r(jit_info->native_ptr, emit_EBX);
+    /* get the pc from stack:  mov 12(%ebp), %ebx */
+    emitm_movl_m_r(interp, jit_info->native_ptr, emit_EBX, emit_EBP, emit_None, 1, 12);
+    /* emit cgp_core(1, interp) */
+    /* get the interpreter from stack:  mov 8(%ebp), %eax */
+    emitm_movl_m_r(interp, jit_info->native_ptr, emit_EAX, emit_EBP, emit_None, 1, 8);
+    emitm_pushl_r(jit_info->native_ptr, emit_EAX);
+    /*
+     * TODO define the offset of the interpreter on the stack
+     *      relative to %ebp
+     */
+    emitm_pushl_i(jit_info->native_ptr, 1);
+    /* use EAX as flag, when jumping back on init, EAX==1 */
+    jit_emit_mov_ri_i(interp, jit_info->native_ptr, emit_EAX, 1);
+    if (!jit_info->objfile)
+        call_func(jit_info, (void (*)(void))cgp_core);
+#    if EXEC_CAPABLE
+    else {
+        Parrot_exec_add_text_rellocation_func(jit_info->objfile,
+            jit_info->native_ptr, "cgp_core");
+        emitm_calll(jit_info->native_ptr, EXEC_CALLDISP);
+    }
+#    endif
+    /* when cur_opcode == 1, cgp_core jumps back here
+     * when EAX == 0, the official return from HALT was called */
+    jit_emit_test_r_i(jit_info->native_ptr, emit_EAX);
+    emitm_jxs(jit_info->native_ptr, emitm_jnz, 5);
+    emitm_popl_r(jit_info->native_ptr, emit_EBX);
+    jit_emit_stack_frame_leave(jit_info->native_ptr);
+    emitm_ret(jit_info->native_ptr);
+    /* get PC = ebx to eax, jump there */
+    jit_emit_mov_rr_i(jit_info->native_ptr, emit_EAX, emit_EBX);
+    Parrot_emit_jump_to_eax(jit_info, interp);
 
-void Parrot_jit_vtable_ifp_op(Parrot_jit_info_t *jit_info,
-PARROT_INTERP);
+/* code_start: */
+}
 
-void Parrot_jit_vtable_newp_ic_op(Parrot_jit_info_t *jit_info,
-PARROT_INTERP);
+#  else /* JIT_CGP */
+static void
+Parrot_jit_begin(Parrot_jit_info_t *jit_info,
+                 PARROT_INTERP)
+{
+    /* the generated code gets called as:
+     * (jit_code)(interp, pc)
+     * jumping to pc is the same code as used in Parrot_jit_cpcf_op()
+     */
 
-void jit_get_params_pc(Parrot_jit_info_t *jit_info, PARROT_INTERP);
+    /* Maintain the stack frame pointer for the sake of gdb */
+    jit_emit_stack_frame_enter(jit_info->native_ptr);
+    emitm_fldcw(interp, jit_info->native_ptr, &control_word);
+    /* stack:
+     *  12   pc
+     *   8   interpreter
+     *   4   retaddr
+     *   0   ebp <----- ebp
+     *  -4   ebx .. preserved regs
+     *  -8   esi ..
+     * -12   edi ..
+     * -16   interpreter
+     */
 
-void jit_save_regs(Parrot_jit_info_t *jit_info, PARROT_INTERP);
+    /* Save all callee-saved registers (cdecl)
+     */
+    emitm_pushl_r(jit_info->native_ptr, emit_EBX);
+    emitm_pushl_r(jit_info->native_ptr, emit_ESI);
+    emitm_pushl_r(jit_info->native_ptr, emit_EDI);
+
+    /* Cheat on op function calls by writing the interpreter arg on the stack
+     * just once. If an op function ever modifies the interpreter argument on
+     * the stack this will stop working !!! */
+
+    /* get the interpreter from stack:  mov 8(%ebp), %eax */
+    emitm_movl_m_r(interp, jit_info->native_ptr, emit_EAX, emit_EBP, emit_None, 1, 8);
+    emitm_pushl_r(jit_info->native_ptr, emit_EAX);
 
-void jit_restore_regs(Parrot_jit_info_t *jit_info, PARROT_INTERP);
+    /* get the pc from stack:  mov 12(%ebp), %eax */
+    emitm_movl_m_r(interp, jit_info->native_ptr, emit_EAX, emit_EBP, emit_None, 1, 12);
 
-int jit_save_regs_call(Parrot_jit_info_t *jit_info, PARROT_INTERP, int skip);
+    /* jump to restart pos or first op */
+    Parrot_emit_jump_to_eax(jit_info, interp);
+}
 
-void jit_restore_regs_call(Parrot_jit_info_t *jit_info, PARROT_INTERP,
-    int skip);
+#  endif /* JIT_CGP */
 
-void jit_set_returns_pc(Parrot_jit_info_t *jit_info, PARROT_INTERP,
-    int recursive);
+/*
+ * create a JITted version of a PIR sub, where everything
+ * resided in registers
+ *
+ * The sub is called as
+ *
+ *   opcode_t * func(Interp *i, INTVAL *sig_bits, void **args);
+ *
+ *   args[0] ...    NULL / return value address
+ *   args[1..n] ... addresses of n arguments
+ *   args[n + 1] .. opcode_t* next - ususally just returned
+ */
 
-void jit_set_args_pc(Parrot_jit_info_t *jit_info, PARROT_INTERP,
-    int recursive);
+static void
+Parrot_jit_begin_sub_regs(Parrot_jit_info_t *jit_info,
+                 PARROT_INTERP)
+{
+    jit_emit_stack_frame_enter(jit_info->native_ptr);
+    /* stack:
+     *  16   args
+     *  12   sig_bits
+     *   8   interpreter
+     *   4   retaddr
+     *   0   ebp <----- ebp
+     * [ -4   ebx .. preserved regs ]
+     * [ -8   edi .. preserved regs ]
+     */
+    /*
+     * check register usage of the subroutine
+     * how many we have to preserve
+     */
+    jit_save_regs(jit_info, interp);
+    /* when it's a recursive sub, we fetch params to registers
+     * and all a inner helper sub, which run with registers only
+     */
+    if (jit_info->flags & JIT_CODE_RECURSIVE) {
+        char * L1;
+        PackFile_Constant ** constants;
+        PMC *sig_result;
+        opcode_t *result;
+
+        jit_get_params_pc(jit_info, interp);
+        /* remember fixup position - call sub */
+        L1 = NATIVECODE;
+        emitm_calll(NATIVECODE, 0);
+        /* check type of return value */
+        constants = CONTEXT(interp)->constants;
+        result = CONTEXT(interp)->current_results;
+        sig_result = constants[result[1]]->u.key;
+        if (!SIG_ELEMS(sig_result))
+            goto no_result;
+        /* fetch args to %edx */
+        emitm_movl_m_r(interp, NATIVECODE, emit_EDX, emit_EBP, emit_None, 1, 16);
+        emitm_movl_m_r(interp, NATIVECODE, emit_ECX, emit_EDX, emit_None, 1, 0);
+        if (SIG_ITEM(sig_result, 0) == PARROT_ARG_FLOATVAL) {
+            jit_emit_fst_mb_n(interp, jit_info->native_ptr, emit_ECX, 0);
+        }
+        else {
+            emitm_movl_r_m(interp, NATIVECODE, emit_EAX, emit_ECX, 0, 1, 0);
+        }
+no_result:
+        /* return 0 - no branch */
+        jit_emit_bxor_rr_i(interp, NATIVECODE, emit_EAX, emit_EAX);
+        /* restore pushed callee saved */
+        jit_restore_regs(jit_info, interp);
+        jit_emit_stack_frame_leave(NATIVECODE);
+        emitm_ret(NATIVECODE);
+        /* align the inner sub */
+#  if SUB_ALIGN
+        while ((long)jit_info->native_ptr & ((1<<SUB_ALIGN) - 1)) {
+            jit_emit_noop(jit_info->native_ptr);
+        }
+#  endif
+        /* fixup call statement */
+        L1[1] = NATIVECODE - L1 - 5;
+    }
+    /* TODO be sure we got a label here in map_branch */
+}
 
-void Parrot_jit_dofixup(Parrot_jit_info_t *jit_info, PARROT_INTERP);
 
-void Parrot_jit_begin(Parrot_jit_info_t *jit_info, PARROT_INTERP);
+static void
+Parrot_jit_begin_sub(Parrot_jit_info_t *jit_info,
+                 PARROT_INTERP)
+{
+}
 
-void Parrot_jit_begin(Parrot_jit_info_t *jit_info, PARROT_INTERP);
+static void
+jit_mov_mr_n_offs(PARROT_INTERP, Parrot_jit_info_t *jit_info,
+        int base_reg, INTVAL offs, int src_reg)
+{
+    emitm_fld(jit_info->native_ptr, src_reg);
+    jit_emit_fstore_mb_n(interp, jit_info->native_ptr, base_reg, offs);
+}
 
-void Parrot_jit_begin_sub_regs(Parrot_jit_info_t *jit_info,
-    PARROT_INTERP);
+static void
+jit_mov_mr_offs(PARROT_INTERP, Parrot_jit_info_t *jit_info,
+        int base_reg, INTVAL offs, int src_reg)
+{
+    emitm_movl_r_m(interp, jit_info->native_ptr,
+            src_reg, base_reg, emit_None, 1, offs);
+}
 
-void Parrot_jit_begin_sub(Parrot_jit_info_t *jit_info, PARROT_INTERP);
+static void
+jit_mov_rm_n_offs(PARROT_INTERP, Parrot_jit_info_t *jit_info,
+        int dst_reg, int base_reg, INTVAL offs)
+{
+    jit_emit_fload_mb_n(interp, jit_info->native_ptr, base_reg,  offs);
+    emitm_fstp(jit_info->native_ptr, (dst_reg+1));
+}
 
-void jit_mov_mr_n_offs(PARROT_INTERP, Parrot_jit_info_t *jit_info,
-    int base_reg, INTVAL offs, int src_reg);
+static void
+jit_mov_rm_offs(PARROT_INTERP, Parrot_jit_info_t *jit_info,
+        int dst_reg, int base_reg, INTVAL offs)
+{
+    emitm_movl_m_r(interp, jit_info->native_ptr,
+            dst_reg, base_reg, emit_None, 1, offs);
+}
 
-void jit_mov_mr_offs(PARROT_INTERP, Parrot_jit_info_t *jit_info,
-    int base_reg, INTVAL offs, int src_reg);
+#endif
 
-void jit_mov_rm_n_offs(PARROT_INTERP, Parrot_jit_info_t *jit_info,
-    int dst_reg, int base_reg, INTVAL offs);
+#if JIT_EMIT == 2
+/* generate code just once */
 
-void jit_mov_rm_offs(PARROT_INTERP, Parrot_jit_info_t *jit_info,
-    int dst_reg, int base_reg, INTVAL offs);
+static void
+Parrot_jit_emit_finit(Parrot_jit_info_t *jit_info)
+{
+    jit_emit_finit(jit_info->native_ptr);
+}
 
-void Parrot_jit_emit_finit(Parrot_jit_info_t *jit_info);
 
-/*
-void Parrot_jit_normal_op(Parrot_jit_info_t *jit_info, PARROT_INTERP);
-*/
 
-#if JIT_EMIT == 2
 #  ifdef JIT_CGP
 /*
  * XXX needs some fixing
@@ -1953,29 +3523,570 @@
 }
 
 #  endif /* JIT_CGP */
+
+void
+Parrot_jit_cpcf_op(Parrot_jit_info_t *jit_info,
+                   PARROT_INTERP)
+{
+    Parrot_jit_normal_op(jit_info, interp);
+    Parrot_emit_jump_to_eax(jit_info, interp);
+}
+
+
+/* autogened inside core.ops */
+static void
+Parrot_end_jit(Parrot_jit_info_t *jit_info, PARROT_INTERP);
+
+#  undef Parrot_jit_restart_op
+void
+Parrot_jit_restart_op(Parrot_jit_info_t *jit_info,
+                   PARROT_INTERP)
+{
+    char *jmp_ptr, *sav_ptr;
+
+    Parrot_jit_normal_op(jit_info, interp);
+    /* test eax, if zero (e.g after trace), return from JIT */
+    jit_emit_test_r_i(jit_info->native_ptr, emit_EAX);
+    /* remember PC */
+    jmp_ptr = jit_info->native_ptr;
+    /* emit jump past exit code, dummy offset
+     * this assumes exit code is not longer then a short jump (126 bytes) */
+    emitm_jxs(jit_info->native_ptr, emitm_jnz, 0);
+    Parrot_end_jit(jit_info, interp);
+    /* fixup above jump */
+    sav_ptr = jit_info->native_ptr;
+    jit_info->native_ptr = jmp_ptr;
+    emitm_jxs(jit_info->native_ptr, emitm_jnz, (long)(sav_ptr - jmp_ptr) - 2);
+    /* restore PC */
+    jit_info->native_ptr = sav_ptr;
+    Parrot_emit_jump_to_eax(jit_info, interp);
+}
+
+/*
+ * params are put rigth to left on the stack
+ * parrot registers are counted left to right
+ * so this function returns for a given register type
+ * the needed register number
+ * TODO handel overflow params
+ */
+static int
+count_regs(PARROT_INTERP, char *sig, char *sig_start)
+{
+    const char *typs[] = {
+        "Ilisc",         /* I */
+        "StbB",          /* S */
+        "pP234",         /* P */
+        "Nfd"            /* N */
+    };
+    int first_reg = 0;
+    int i, found;
+
+    /* char at sig is the type to look at */
+    for (found = -1, i = 0; i < 4; i++) {
+        if (strchr(typs[i], *sig)) {
+            found = i;
+            break;
+        }
+    }
+
+    if (found == -1)
+        Parrot_ex_throw_from_c_args(interp, NULL, 1,
+            "Parrot_jit_build_call_func: sig char not found\n");
+
+    for (--sig; sig > sig_start; --sig) {
+        if (strchr(typs[found], *sig)) {
+            ++first_reg;
+        }
+    }
+    return first_reg;
+}
+
+static size_t
+calc_signature_needs(const char *sig, int *strings)
+{
+    size_t stack_size = 0;
+    while (*sig) {
+        switch (*sig) {
+            case 't':
+                (*strings)++;
+                stack_size +=4;
+                break;
+            case 'd':
+                stack_size +=8;
+                break;
+            default:
+                stack_size +=4;
+                break;
+        }
+        sig++;
+    }
+    return stack_size;
+
+}
+/*
+ * The function generated here is called as func(interp, nci_info)
+ * interp   ...  8(%ebp)
+ * nci_info ... 12(%ebp)
+ *
+ * The generate function for a specific signature looks quite similar to
+ * an optimized compile of src/nci.c:pcf_x_yy(). In case of any troubles
+ * just compare the disassembly.
+ */
+void *
+Parrot_jit_build_call_func(PARROT_INTERP, PMC *pmc_nci, STRING *signature)
+{
+    Parrot_jit_info_t jit_info;
+    char     *pc;
+    int       i                    = 0;
+    int       arg_count            = 0;
+    int       string_buffer_count  = 0;
+    const int ST_SIZE_OF           = 124;
+    const int JIT_ALLOC_SIZE       = 1024;
+
+    /* skip over the result */
+    char      *sig                = (char *)signature->strstart + 1;
+    size_t     stack_space_needed = calc_signature_needs(sig,
+                                        &string_buffer_count);
+
+    int base_offset        = 0;
+    int strings_offset     = base_offset - (sizeof (char *) * string_buffer_count);
+    int st_offset          = strings_offset - ST_SIZE_OF;
+    int args_offset        = st_offset - stack_space_needed;
+    int temp_calls_offset  = args_offset - 16;
+    int total_stack_needed = -temp_calls_offset;
+
+    /*
+     * ESP
+     * 0-15, 16 bytes for utility calls
+     * stack_space_needed for actual NCI call
+     * st
+     * STRINGS -> char * holding space
+     * EBP
+     */
+
+    /* this ought to be enough - the caller of this function
+     * should free the function pointer returned here
+     */
+    pc = jit_info.native_ptr = jit_info.arena.start = (char *)mem_alloc_executable(JIT_ALLOC_SIZE);
+
+
+    /* this generated jit function will be called as (INTERP (EBP 8), func_ptr
+    * (ESP 12), args signature (ESP 16)) */
+
+    /* make stack frame, preserve %ebx */
+    jit_emit_stack_frame_enter(pc);
+
+    emitm_subl_i_r(pc, total_stack_needed, emit_ESP);
+
+    /* Parrot_init_arg_nci(interp, &st, "S"); */
+    /* args signature "S" */
+    emitm_movl_m_r(interp, pc, emit_EAX, emit_EBP, 0, 1, 16);
+    emitm_movl_r_m(interp, pc, emit_EAX, emit_EBP, 0, 1, temp_calls_offset + 8);
+
+    /*&st*/
+    emitm_lea_m_r(interp,  pc, emit_EAX, emit_EBP, 0, 1, st_offset);
+    emitm_movl_r_m(interp, pc, emit_EAX, emit_EBP, 0, 1, temp_calls_offset + 4);
+
+    /*interpreter*/
+    emitm_movl_m_r(interp, pc, emit_EAX, emit_EBP, 0, 1, 8);
+    emitm_movl_r_m(interp, pc, emit_EAX, emit_EBP, 0, 1, temp_calls_offset + 0);
+
+    if (sig && *sig)
+      emitm_call_cfunc(pc, Parrot_init_arg_nci);
+
+    while (*sig) {
+        emitm_movl_i_m(pc, arg_count, emit_EBP, 0, 1, temp_calls_offset + 8);
+
+        switch (*sig) {
+            case '0':    /* null ptr or such - doesn't consume a reg */
+                jit_emit_bxor_rr_i(interp, pc, emit_EAX, emit_EAX);
+                emitm_movl_m_r(interp, pc, emit_EAX, emit_EBP, 0, 1, args_offset);
+                break;
+            case 'f':
+                emitm_call_cfunc(pc, get_nci_N);
+                emitm_fstps(interp, pc, emit_EBP, 0, 1, args_offset);
+                break;
+            case 'N':
+            case 'd':
+                emitm_call_cfunc(pc, get_nci_N);
+                emitm_fstpl(interp, pc, emit_EBP, 0, 1, args_offset);
+                args_offset += 4;
+                break;
+            case 'I':   /* INTVAL */
+            case 'l':   /* long */
+            case 'i':   /* int */
+                emitm_call_cfunc(pc, get_nci_I);
+                emitm_movl_r_m(interp, pc, emit_EAX, emit_EBP, 0, 1, args_offset);
+                break;
+            case 't':   /* string, pass a cstring */
+                emitm_call_cfunc(pc, get_nci_S);
+                emitm_movl_r_m(interp, pc, emit_EAX, emit_EBP, 0, 1, temp_calls_offset + 4);
+                emitm_call_cfunc(pc, string_to_cstring_nullable);
+
+                emitm_movl_r_m(interp, pc, emit_EAX, emit_EBP, 0, 1, args_offset);
+                /* save off temporary allocation address */
+                emitm_movl_r_m(interp, pc, emit_EAX, emit_EBP, 0, 1, strings_offset);
+                strings_offset += 4;
+
+                /* reset ESP(4) */
+                emitm_lea_m_r(interp, pc, emit_EAX, emit_EBP, 0, 1, st_offset);
+                emitm_movl_r_m(interp, pc, emit_EAX, emit_EBP, 0, 1, temp_calls_offset + 4);
+                break;
+            case 's':   /* short: movswl intreg_o(base), %eax */
+                emitm_call_cfunc(pc, get_nci_I);
+                emitm_movswl_r_r(pc, emit_EAX, emit_EAX)
+                emitm_movl_r_m(interp, pc, emit_EAX, emit_EBP, 0, 1, args_offset);
+                break;
+            case 'c':   /* char: movsbl intreg_o(base), %eax */
+                emitm_call_cfunc(pc, get_nci_I);
+                emitm_movsbl_r_r(pc, emit_EAX, emit_EAX);
+                emitm_movl_r_m(interp, pc, emit_EAX, emit_EBP, 0, 1, args_offset);
+                break;
+            case 'J':   /* interpreter */
+                emitm_movl_m_r(interp, pc, emit_EAX, emit_EBP, 0, 1, 8);
+                emitm_movl_r_m(interp, pc, emit_EAX, emit_EBP, 0, 1, args_offset);
+                arg_count--;
+                break;
+            case 'p':   /* push pmc->data */
+                emitm_call_cfunc(pc, get_nci_P);
+#  if ! PMC_DATA_IN_EXT
+                /* mov pmc, %edx
+                 * mov 8(%edx), %eax
+                 * push %eax
+                 */
+                emitm_movl_m_r(interp, pc, emit_EAX, emit_EAX, 0, 1, offsetof(struct PMC, data));
+#  else
+                /* push pmc->pmc_ext->data
+                 * mov pmc, %edx
+                 * mov pmc_ext(%edx), %eax
+                 * mov data(%eax), %eax
+                 * push %eax
+                 */
+                emitm_movl_m_r(interp, pc, emit_EAX, emit_EAX, 0, 1, offsetof(struct PMC, pmc_ext));
+                emitm_movl_m_r(interp, pc, emit_EAX, emit_EAX, 0, 1, offsetof(struct PMC_EXT, data));
+#  endif
+                emitm_movl_r_m(interp, pc, emit_EAX, emit_EBP, 0, 1, args_offset);
+                break;
+            case 'O':   /* push PMC * object in P2 */
+            case 'P':   /* push PMC * */
+            case '@':
+                emitm_call_cfunc(pc, get_nci_P);
+#  if PARROT_CATCH_NULL
+                /* PMCNULL is a global */
+                jit_emit_cmp_rm_i(pc, emit_EAX, &PMCNULL);
+                emitm_jxs(pc, emitm_jne, 2); /* skip the xor */
+                jit_emit_bxor_rr_i(interp, pc, emit_EAX, emit_EAX);
+#  endif
+                emitm_movl_r_m(interp, pc, emit_EAX, emit_EBP, 0, 1, args_offset);
+                break;
+            case 'v':
+                break;
+            case 'V':
+                emitm_call_cfunc(pc, get_nci_P);
+                emitm_lea_m_r(interp, pc, emit_EAX, emit_EAX, 0, 1, offsetof(struct PMC, data));
+                /* emitm_lea_m_r(interp, pc, emit_EAX, emit_EAX, 0, 1, 0); */
+                emitm_movl_r_m(interp, pc, emit_EAX, emit_EBP, 0, 1, args_offset);
+                break;
+            case 'b':   /* buffer (void*) pass PObj_bufstart(SReg) */
+                emitm_call_cfunc(pc, get_nci_S);
+                emitm_movl_m_r(interp, pc, emit_EAX, emit_EAX, 0, 1, (size_t) &PObj_bufstart((STRING *) 0));
+                emitm_movl_r_m(interp, pc, emit_EAX, emit_EBP, 0, 1, args_offset);
+                break;
+            case 'B':   /* buffer (void**) pass &PObj_bufstart(SReg) */
+                emitm_call_cfunc(pc, get_nci_S);
+                emitm_lea_m_r(interp, pc, emit_EAX, emit_EAX, 0, 1, (size_t) &PObj_bufstart((STRING *) 0));
+                emitm_movl_r_m(interp, pc, emit_EAX, emit_EBP, 0, 1, args_offset);
+                break;
+            case 'S':
+                emitm_call_cfunc(pc, get_nci_S);
+                emitm_movl_r_m(interp, pc, emit_EAX, emit_EBP, 0, 1, args_offset);
+                break;
+
+
+            /* I have no idea how to handle these */
+            case '2':
+            case '3':
+            case '4':
+                mem_free_executable(jit_info.native_ptr);
+                return NULL;
+                break;
+                /* This might be right. Or not... */
+                /* we need the offset of PMC_int_val */
+                emitm_call_cfunc(pc, get_nci_P);
+                emitm_lea_m_r(interp, pc, emit_EAX, emit_EAX, 0, 1, (size_t) &PMC_int_val((PMC *) 0));
+                emitm_movl_r_m(interp, pc, emit_EAX, emit_EBP, 0, 1, args_offset);
+                break;
+            default:
+                Parrot_ex_throw_from_c_args(interp, NULL, EXCEPTION_JIT_ERROR,
+                    "Unknown arg Signature %c\n", *sig);
+                /*
+                 * oops unknown signature:
+                 * cleanup and try nci.c
+                 */
+                mem_free_executable(jit_info.native_ptr);
+                return NULL;
+        }
+        args_offset +=4;
+        arg_count++;
+        sig++;
+    }
+
+    emitm_addl_i_r(pc, 16, emit_ESP);
+    /* get the pmc from stack - movl 12(%ebp), %eax */
+    emitm_movl_m_r(interp, pc, emit_EAX, emit_EBP, 0, 1, 12);
+    emitm_callm(pc, emit_EAX, emit_None, emit_None, 0);
+    emitm_subl_i_r(pc, 16, emit_ESP);
+
+    /* SAVE OFF EAX */
+    emitm_movl_r_m(interp, pc, emit_EAX, emit_EBP, 0, 1, temp_calls_offset + 8);
+
+    /*&st*/
+    emitm_lea_m_r(interp, pc, emit_EAX, emit_EBP, 0, 1, st_offset);
+    emitm_movl_r_m(interp, pc, emit_EAX, emit_EBP, 0, 1, temp_calls_offset + 4);
+
+    /*interpreter*/
+    emitm_movl_m_r(interp, pc, emit_EAX, emit_EBP, 0, 1, 8);
+    emitm_movl_r_m(interp, pc, emit_EAX, emit_EBP, 0, 1, temp_calls_offset + 0);
+
+    /* RESTORE BACK EAX */
+    emitm_movl_m_r(interp, pc, emit_EAX, emit_EBP, 0, 1, temp_calls_offset + 8);
+
+    /* now place return value in registers */
+    /* first in signature is the return value */
+    sig = (char *)signature->strstart; /* the result */
+    switch (*sig) {
+        /* I have no idea how to handle these */
+        case '2':
+        case '3':
+        case '4':
+            /* get integer from pointer - untested */
+            emitm_movl_m_r(interp, pc, emit_EAX, emit_EAX, 0, 1, 0);
+            if (*sig == 2)      /* short */
+                emitm_movswl_r_r(pc, emit_EAX, emit_EAX);
+            emitm_call_cfunc(pc, set_nci_I);
+            break;
+        case 'f':
+        case 'd':
+            jit_emit_fstore_mb_n(interp, pc, emit_EBP, temp_calls_offset + 8);
+            emitm_call_cfunc(pc, set_nci_N);
+            /* pop num from st(0) and mov to reg */
+            break;
+        case 's':
+            /* movswl %ax, %eax */
+            emitm_movswl_r_r(pc, emit_EAX, emit_EAX);
+            emitm_movl_r_m(interp, pc, emit_EAX, emit_EBP, 0, 1, temp_calls_offset + 8);
+            emitm_call_cfunc(pc, set_nci_I);
+            break;
+        case 'c':
+            /* movsbl %al, %eax */
+            emitm_movsbl_r_r(pc, emit_EAX, emit_EAX);
+            emitm_movl_r_m(interp, pc, emit_EAX, emit_EBP, 0, 1, temp_calls_offset + 8);
+            emitm_call_cfunc(pc, set_nci_I);
+            break;
+        case 'I':   /* INTVAL */
+        case 'l':
+        case 'i':
+            emitm_movl_r_m(interp, pc, emit_EAX, emit_EBP, 0, 1, temp_calls_offset + 8);
+            emitm_call_cfunc(pc, set_nci_I);
+            break;
+        case 'v': /* void - do nothing */
+            break;
+        case 'P':
+            emitm_movl_r_m(interp, pc, emit_EAX, emit_EBP, 0, 1, temp_calls_offset + 8);
+            emitm_call_cfunc(pc, set_nci_P);
+            break;
+        case 'p':   /* make a new unmanaged struct */
+            /* save return value on stack */
+
+            /* save pointer p */
+            emitm_movl_r_m(interp, pc, emit_EAX, emit_EBP, 0, 1, temp_calls_offset + 12);
+
+            /* make new pmc */
+            emitm_movl_i_m(pc, enum_class_UnManagedStruct, emit_EBP, 0, 1, temp_calls_offset + 4);
+            emitm_call_cfunc(pc, pmc_new);
+
+            /* restore pointer p to EDX */
+            emitm_movl_m_r(interp, pc, emit_EDX, emit_EBP, 0, 1, temp_calls_offset + 12);
+
+            /* copy UnManagedStruct to stack for set_nci_P call */
+            emitm_movl_r_m(interp, pc, emit_EAX, emit_EBP, 0, 1, temp_calls_offset + 8);
+
+            /* eax = PMC, get return value into edx */
+            /* stuff return value into pmc->data */
+
+#  if ! PMC_DATA_IN_EXT
+            /* mov %edx, (data) %eax */
+            emitm_movl_r_m(interp, pc, emit_EDX, emit_EAX, 0, 1, offsetof(struct PMC, data));
+#  else
+            /* mov pmc_ext(%eax), %eax
+               mov %edx, data(%eax) */
+            emitm_movl_m_r(interp, pc, emit_EAX, emit_EAX, 0, 1, offsetof(struct PMC, pmc_ext));
+            emitm_movl_r_m(interp, pc, emit_EDX, emit_EAX, 0, 1, offsetof(struct PMC_EXT, data));
+#  endif
+
+            /* reset EBP(4) */
+            emitm_lea_m_r(interp, pc, emit_EAX, emit_EBP, 0, 1, st_offset);
+            emitm_movl_r_m(interp, pc, emit_EAX, emit_EBP, 0, 1, temp_calls_offset + 4);
+
+            emitm_call_cfunc(pc, set_nci_P);
+            break;
+        case 'S':
+            emitm_movl_r_m(interp, pc, emit_EAX, emit_EBP, 0, 1, temp_calls_offset + 8);
+            emitm_call_cfunc(pc, set_nci_S);
+            break;
+        case 't':   /* string */
+            /* EAX is char* */
+            emitm_movl_i_m(pc, 0, emit_EBP, 0, 1, temp_calls_offset + 8); /* len */
+
+            /* overrights address of st in EBP(4) */
+            emitm_movl_r_m(interp, pc, emit_EAX, emit_EBP, 0, 1, temp_calls_offset + 4);
+
+            emitm_call_cfunc(pc, string_from_cstring);
+
+            emitm_movl_r_m(interp, pc, emit_EAX, emit_EBP, 0, 1, temp_calls_offset + 8);
+
+            /* reset EBP(4) */
+            emitm_lea_m_r(interp, pc, emit_EAX, emit_EBP, 0, 1, st_offset);
+            emitm_movl_r_m(interp, pc, emit_EAX, emit_EBP, 0, 1, temp_calls_offset + 4);
+
+            emitm_call_cfunc(pc, set_nci_S);
+            break;
+        default:
+            Parrot_ex_throw_from_c_args(interp, NULL, EXCEPTION_JIT_ERROR,
+                "Unknown return Signature %c\n", *sig);
+            /*
+             * oops unknown signature:
+             * cleanup and try nci.c
+             */
+            mem_free_executable(jit_info.native_ptr);
+            return NULL;
+    }
+
+    /* free temporary strings */
+    strings_offset = st_offset + ST_SIZE_OF;
+    for (i=0; i<string_buffer_count; i++) {
+        emitm_movl_m_r(interp, pc, emit_EAX, emit_EBP, 0, 1, strings_offset);
+        emitm_movl_r_m(interp, pc, emit_EAX, emit_EBP, 0, 1, temp_calls_offset + 0);
+        emitm_call_cfunc(pc, string_cstring_free);
+        strings_offset += 4;
+    }
+
+    jit_emit_stack_frame_leave(pc);
+    emitm_ret(pc);
+    PARROT_ASSERT(pc - jit_info.arena.start <= JIT_ALLOC_SIZE);
+    /* could shrink arena.start here to used size */
+    PObj_active_destroy_SET(pmc_nci);
+    return (void *)D2FPTR(jit_info.arena.start);
+}
+
 #endif
 
-extern int jit_op_count(void);
+#if JIT_EMIT == 0
 
-void Parrot_jit_cpcf_op(Parrot_jit_info_t *jit_info, PARROT_INTERP);
+#  define REQUIRES_CONSTANT_POOL 0
+/*
+ * examples/pir/mandel.pir and t/op/jitn_14 show rounding problems
+ * due to keeping intermediate results in FP registers
+ * When intermediates are written back to parrot regs, rounding to
+ * 64 bit is performed, which changes results slightly
+ *
+ * One method is to just turn off mapped floats. The other one is
+ * setting a different control word (with precision control = double)
+ * see emitm_fldcw above
+ */
+#  define FLOAT_REGISTERS_TO_MAP 4
 
 /*
-void Parrot_end_jit(Parrot_jit_info_t *jit_info, PARROT_INTERP);
-*/
+ * register usage
+ * %edi, %esi ... mapped, preserved
+ * %edx, %ecx ... mapped, not preserved
+ * %ebx       ... base pointer for register access, preserved
+ * %eax       ... scratch, return value register
+ */
 
-void Parrot_jit_restart_op(Parrot_jit_info_t *jit_info, PARROT_INTERP);
+static const char i_map[] =
+    { emit_EDI, emit_ESI, emit_EDX, emit_ECX };
+static const char floatval_map[] =
+    { 1, 2, 3, 4, 5 };         /* ST(1) .. (ST(4) */
+
+static const char i_map_sub[] =
+    { emit_EDX, emit_ECX, emit_EBX, emit_EDI, emit_ESI };
+
+static const jit_arch_info arch_info = {
+    jit_mov_rm_offs,
+    jit_mov_rm_n_offs,
+    jit_mov_mr_offs,
+    jit_mov_mr_n_offs,
+    Parrot_jit_dofixup,
+    (jit_arch_f)0,              /* no cache flush needed */
+    {
+        {
+            Parrot_jit_begin,   /* emit code prologue */
+            4,                  /* 4 mapped ints */
+            2,                  /* first 2 are preserved */
+            i_map,
+            4,                  /* 4 mapped float regs */
+            0,                  /* ABI sez it's not preserved */
+            floatval_map
+        },
+        /* unused */
+        {
+            Parrot_jit_begin_sub,   /* emit code prologue */
+            4,                  /* 4 mapped ints */
+            2,                  /* first 2 are *non*preserved */
+            i_map_sub,
+            4,                  /* 4 mapped float regs */
+            0,                  /* ABI sez it's not preserved */
+            floatval_map
+        },
+        /*
+         * compile a sub to registers only
+         * if a mapped count is 0, code containing this register kind
+         * will not be created
+         *
+         * TODO implement FLOATVAL arg passing and set mapped
+         * register count.
+         */
+        {
+            Parrot_jit_begin_sub_regs,   /* emit code prologue */
+            5,                  /* 5 mapped ints */
+            2,                  /* first 2 are *non*preserved */
+            i_map_sub,
+            5,                  /* TODO 0 mapped float regs */
+            5,                  /* ABI sez it's not preserved */
+            floatval_map
+        }
+    }
+};
 
-int count_regs(PARROT_INTERP, char *sig, char *sig_start);
 
-size_t calc_signature_needs(const char *sig, int *strings);
+const jit_arch_info *
+Parrot_jit_init(PARROT_INTERP)
+{
+    return &arch_info;
+}
 
-void * Parrot_jit_build_call_func(PARROT_INTERP, PMC *pmc_nci,
-    STRING *signature);
 
+/* registers are either allocate per section or per basic block
+ * set this to 1 or 0 to change allocation scheme
+ */
+#  define ALLOCATE_REGISTERS_PER_SECTION 1
+
+/*
+ * new style move function using offsets relative to the base_reg
+ */
+#  ifdef JIT_CGP
+#    define INTERP_BP_OFFS todo
+#  else
+#    define INTERP_BP_OFFS -16
+#  endif
+
+#endif  /* JIT_EMIT */
 
 #undef INT_REGISTERS_TO_MAP
 #endif /* PARROT_I386_JIT_EMIT_H_GUARD */
 
+
 /*
  * Local variables:
  *   c-file-style: "parrot"



nntp.perl.org: Perl Programming lists via nntp and http.
Comments to Ask Bjørn Hansen at ask@perl.org | Group listing | About