/* jit3.c                   Copyright (C) 2006-2007, Codemist Ltd */
/*                                                and J O'Connell */


/*
 * Just in time compiler.
 * This is the main section of the compiler, and it ubpacks bytecodes
 * and generates the correspdonding machine code. Although this file is
 * very long it is really just a little section for each separate
 * byte operation.
 */

/*
 * This code may be used and modified, and redistributed in binary
 * or source form, subject to the "CCL Public License", which should
 * accompany it. This license is a variant on the BSD license, and thus
 * permits use of code derived from this in either open and commercial
 * projects: but it does require that updates to this code be made
 * available back to the originators of the package.
 * Before merging other code in with this or linking this code
 * with other packages or libraries please check that the license terms
 * of the other material are compatible with those of this.
 */



/* Signature: 10fab58d 18-Jan-2007 */

#ifndef WIN32
#include <sys/mman.h>
#endif

#include "headers.h"
#include "bytes.h"
#include "jit.h"
#include "opnames.c"

#ifdef X86
#include "distorm.h"
#endif

#ifdef MEMORY_TRACE
#define next_byte (cmemory_reference((intptr_t)ppc), *ppc++)
#else
#define next_byte *ppc++
#endif

//#define WTF 1

//extern Lisp_Object *do_freebind(Lisp_Object bvec, Lisp_Object *stk);

Lisp_Object *Jdo_freebind(Lisp_Object bvec, Lisp_Object *stk)
{
   int32_t n, k;
   n = length_of_header(vechdr(bvec));
   for (k=CELL; k<n; k+=CELL)
   {   Lisp_Object v = *(Lisp_Object *)((intptr_t)bvec + k - TAG_VECTOR);
       //push(qvalue(v));
       *++stk = qvalue(v);
       qvalue(v) = C_nil;
   }
/*
 * TAG_FBIND is a value that can NEVER occur elsewhere in the Lisp system,
 * and so it unambiguously marks a block of fluid bindings on that stack.
 */
    //push2(bvec, (Lisp_Object)SPID_FBIND);
    stk[1] = bvec; stk[2] = (Lisp_Object)SPID_FBIND; stk+=2;
    return stk;
}

Lisp_Object *Jdo_freerstr(Lisp_Object *stk)
{
    Lisp_Object bv;
    int32_t n;
    //popv(1);
    stk -= 1;
    //pop(bv);
    bv = *stk--;
    n = length_of_header(vechdr(bv));
    while (n>CELL)
    {   Lisp_Object v = *(Lisp_Object *)((intptr_t)bv + n - (CELL + TAG_VECTOR));
        n -= CELL;
        qvalue(v) = *stk--;
        //pop(qvalue(v));
    }
    return stk;
}

void test()
{
        printf("\ntest\n");
        return;
}

void breakpoint()
{

        //Lisp_Object nil = C_nil;
        
//        printf("\nSTART OF JIT CODE\n");
        
//        printf("C_stack: %x\tlitvec: %x\tC_nil: %x\t&C_nil: %x\n",(Lisp_Object)C_stack,(Lisp_Object)litvec,C_nil,(Lisp_Object)&C_nil);
//        printf("stack: %x\tC_stack: %x\tC_stack[-1]: %x\tC_stack[0]: %x\tC_stack[1]: %x\n",(Lisp_Object)stack,(Lisp_Object)C_stack,C_stack[-1],C_stack[0],C_stack[1]);
printf("\nC_stack: %p\n",C_stack);        
int i;
for(i=0;i<6;i++) {
        printf("C_stack[%d]: %x ",i-5,C_stack[i-5]);
}
printf("C_nil: %p",(void *)C_nil);
        return;
}

void bytecode_breakpoint(int ppc)
{
        printf("%s\n",opnames[ppc]);
        fflush(stdout);
        return;
}

void print_ffname(char *name)
{
        printf("\n---CALLING: %s\n",name);
        fflush(stdout);
        return;
}

void Jprint3(char* name)
{
        printf("%p\n",name);
        fflush(stdout);
        return;
}

void Jprint2(char* name)
{
        printf("%s\n",name);
        fflush(stdout);
        return;
}


void Jprint()
{
        /*
         * Prints celt(qcdr(def,0))
         */
        add_imm32_rm32(20,EAX);
        mov_rm32_rm32(EAXM,EAX);
        sub_imm32_rm32(2,EAX);
        mov_rm32_rm32(EAX,ESPM);
        Jcall_abs_fn(Jprint2);
        return;
}

void push_litvec()
{
        Lisp_Object nil = C_nil;
        //push(litvec);
        *++C_stack = litvec;
        return;
}

void pop_litvec()
{
        Lisp_Object nil = C_nil;
        //pop(litvec);
        litvec = *C_stack--;
        return;
}
void Jexception_pending()
{
        load_nil_into(EAX);
        and_imm_rm32(0x1,EAX);
        put2bytes(0x85c0);//test eax, eax
        return;
}

void Jcall_error()
{
        mov_rm32_rm32_disp(EBPM,EAX,3); //mov 12(ebp), eax
        put3bytes(0xc1e004); //sal $4, eax
        inc_reg(EAX); //inc eax
        mov_rm32_rm32_disp(EAX,ESPM,3);
        mov_rm32_rm32_disp(EBPM,EAX,2); //mov 8(ebp), eax
        mov_rm32_rm32_disp(EAXM,EAX,1); //mov 4(eax), eax
        sub_imm32_rm32(0x2,EAX); //sub 2, eax
        mov_rm32_rm32(EAXM,EAX); //mov (eax), eax
        mov_rm32_rm32_disp(EAX,ESPM,2);
        put4bytes(0xbe060000); put4bytes(0x00897424); putbyte(0x04); //mov 6, 4(esp)
        put4bytes(0xc7042402); put3bytes(0x000000); //mov 2, (esp)
        Jcall_abs_fn(error); //call error
        exit_stack_pointers(); //4 chars long
        //FIXME preserve registers from before? should pop them
        return;
}

void call0(int fname)
{
        /* r1 = elt(litvec, fname) */
        load_litvec_into(EBX);
        putbyte(0xb8);put_little_endian(fname);
        put3bytes(0xc1e002); //look at CALL3
        //put2bytes(0x0303);
        put2bytes(0x01d8);
        sub_imm32_rm32(0x2,EAX);
        mov_rm32_rm32(EAXM,EAX);
        mov_rm32_rm32_disp(EAX,EBPM,-3);
        /* f345 = qfn1(r1) */
        mov_rm32_rm32_disp(EBPM,EAX,-3);
        add_imm32_rm32(0x10,EAX);
        mov_rm32_rm32(EAXM,EAX);
        mov_rm32_rm32_disp(EAX,EBPM,-8);
        //save_pc
        load_stack_into(EAX);
        mov_r32_addr(EAX,stack);
        put4bytes(0xc7442404);put4bytes(0x00000000);//mov 0, 4(esp)
        mov_rm32_rm32_disp(EBPM,EAX,-3);
        add_imm32_rm32(0x4,EAX);
        mov_rm32_rm32(EAXM,EAX);
        mov_rm32_rm32(EAX,ESPM);
        mov_rm32_rm32_disp(EBPM,EAX,-8);
        put2bytes(0xffd0);//call *eax
        store_A_reg_from(EAX);
        mov_addr_r32(&C_nil,EAX);
        store_nil_from(EAX);
        //exception pending
        mov_addr_r32(stack,EAX);
        store_stack_from(EAX);
        //restore pc
        return;
}

void call1(int fname)
{
        /* r1 = elt(litvec, fname) */
        load_litvec_into(EBX);
        putbyte(0xb8);put_little_endian(fname);
        put3bytes(0xc1e002); //look at CALL3
        put2bytes(0x01d8);
        //put2bytes(0x0303);
        sub_imm32_rm32(0x2,EAX);
        mov_rm32_rm32(EAXM,EAX);
        mov_rm32_rm32_disp(EAX,EBPM,-3);
        /* f1 = qfn1(r1) */
        mov_rm32_rm32_disp(EBPM,EAX,-3);
        add_imm32_rm32(0x8,EAX);
        mov_rm32_rm32(EAXM,EAX);
        mov_rm32_rm32_disp(EAX,EBPM,-6);
        //save_pc
        load_stack_into(EAX);
        mov_r32_addr(EAX,stack);
        load_A_reg_into(EAX);
        mov_rm32_rm32_disp(EAX,ESPM,1);
        mov_rm32_rm32_disp(EBPM,EAX,-3);
        add_imm32_rm32(0x4,EAX);
        mov_rm32_rm32(EAXM,EAX);
        mov_rm32_rm32(EAX,ESPM);
        mov_rm32_rm32_disp(EBPM,EAX,-6);
        put2bytes(0xffd0);//call *eax
        store_A_reg_from(EAX);
        mov_addr_r32(&C_nil,EAX);
        store_nil_from(EAX);
        //exception pending
        mov_addr_r32(stack,EAX);
        store_stack_from(EAX);
        //restore pc
        return;
}

void call2(int fname)
{
        /* r1 = elt(litvec, fname) */
        load_litvec_into(EBX);
        putbyte(0xb8);put_little_endian(fname);
        put3bytes(0xc1e002); //look at CALL3
        put2bytes(0x01d8);
        //put2bytes(0x0303);
        sub_imm32_rm32(0x2,EAX);
        mov_rm32_rm32(EAXM,EAX);
        mov_rm32_rm32_disp(EAX,EBPM,-3);
        /* f2 = qfn2(r1) */
        mov_rm32_rm32_disp(EBPM,EAX,-3);
        add_imm32_rm32(0xc,EAX);
        mov_rm32_rm32(EAXM,EAX);
        mov_rm32_rm32_disp(EAX,EBPM,-7);
        //save_pc
        load_stack_into(EAX);
        mov_r32_addr(EAX,stack);
        load_A_reg_into(EAX);
        mov_rm32_rm32_disp(EAX,ESPM,2);
        load_B_reg_into(EAX);
        mov_rm32_rm32(EAXM,EAX);
        mov_rm32_rm32_disp(EAX,ESPM,1);
        mov_rm32_rm32_disp(EBPM,EAX,-3);
        add_imm32_rm32(0x4,EAX);
        mov_rm32_rm32(EAXM,EAX);
        mov_rm32_rm32(EAX,ESPM);
        mov_rm32_rm32_disp(EBPM,EAX,-7);
        put2bytes(0xffd0);//call *eax
        store_A_reg_from(EAX);
        mov_addr_r32(&C_nil,EAX);
        store_nil_from(EAX);
        //exception pending
        mov_addr_r32(stack,EAX);
        store_stack_from(EAX);
        //restore pc
        return;
}

void call2r(int fname)
{
        /* r1 = elt(litvec, fname) */
        load_litvec_into(EBX);
        putbyte(0xb8);put_little_endian(fname);
        put3bytes(0xc1e002); //look at CALL3
        put2bytes(0x01d8);        
        //put2bytes(0x0303);
        sub_imm32_rm32(0x2,EAX);
        mov_rm32_rm32(EAXM,EAX);
        mov_rm32_rm32_disp(EAX,EBPM,-3);
        /* f2 = qfn2(r1) */
        mov_rm32_rm32_disp(EBPM,EAX,-3);
        add_imm32_rm32(0xc,EAX);
        mov_rm32_rm32(EAXM,EAX);
        mov_rm32_rm32_disp(EAX,EBPM,-7);
        //save_pc
        load_stack_into(EAX);
        mov_r32_addr(EAX,stack);
        load_B_reg_into(EAX);
        mov_rm32_rm32(EAXM,EAX);
        mov_rm32_rm32_disp(EAX,ESPM,2);
        load_A_reg_into(EAX);
        mov_rm32_rm32_disp(EAX,ESPM,1);
        mov_rm32_rm32_disp(EBPM,EAX,-3);
        add_imm32_rm32(0x4,EAX);
        mov_rm32_rm32(EAXM,EAX);
        mov_rm32_rm32(EAX,ESPM);
        mov_rm32_rm32_disp(EBPM,EAX,-7);
        put2bytes(0xffd0);//call *eax
        store_A_reg_from(EAX);
        mov_addr_r32(&C_nil,EAX);
        store_nil_from(EAX);
        //exception pending
        mov_addr_r32(stack,EAX);
        store_stack_from(EAX);
        //restore pc
        return;
}

void jcall2(int fname)
{
        /* r1 = elt(litvec, fname) */
        load_litvec_into(EBX);
        putbyte(0xb8);put_little_endian(fname);
        put3bytes(0xc1e002); //look at CALL3
        put2bytes(0x01d8);
        //put2bytes(0x0303);
        sub_imm32_rm32(0x2,EAX);
        mov_rm32_rm32(EAXM,EAX);
        mov_rm32_rm32_disp(EAX,EBPM,-3);
        /* f2 = qfn2(r1) */
        mov_rm32_rm32_disp(EBPM,EAX,-3);
        add_imm32_rm32(0xc,EAX);
        mov_rm32_rm32(EAXM,EAX);
        mov_rm32_rm32_disp(EAX,EBPM,-7);
#ifdef DEBUG
#endif
//FIXME add below
        
#ifndef OUT_OF_LINE
        //dec countdown
        //cmp 0, countdown
        //cond_jump(,JNS);
        //Jcall_abs_fn(deal_with_tick);
        
        //putbyte(0xa1);put_addr(&stacklimit);//mov stacklimit,eax
        mov_addr_r32(stacklimit,EAX);
        cmp_rm32_rm32_disp(EAX,EBPM,-2);
        cond_jump("jcall22",JB);
        load_stack_into(EAX);
        mov_r32_addr(EAX,stack);
        put4bytes(0xc744240c);put4bytes(0x00000000);//mov 0, 12(esp)
        put4bytes(0xc7442408);put4bytes(0x02000000);//mov 2, 8(esp)
        put4bytes(0xc7442404);put4bytes(0x00000000);//mov LC1, 4(esp) FIXME
        load_A_reg_into(EAX);
        mov_rm32_rm32(EAX,ESPM);
        Jcall_abs_fn(reclaim);
        store_A_reg_from(EAX);
        mov_addr_r32(&C_nil,EAX);
        store_nil_from(EAX);
        //exception pending
        mov_addr_r32(stack,EAX);
        store_stack_from(EAX);
#else

        mov_addr_r32(stack,EAX);
        store_stack_from(EAX);
        
#endif
        add_label("jcall22");

        /*
         * Call bytestream_interpret instead of changing ppc.
         * This has more overhead but will be quicker for
         * bytecoded fns than running code below.
         */

        //FIXME add code here
        
        /*
         * This just calls f2(qenv(r1), B_reg, A_reg)
         */
        mov_rm32_rm32_disp(EBPM,EAX,4);
        mov_r32_addr(EAX,stack);
        load_A_reg_into(EAX);
        mov_rm32_rm32_disp(EAX,ESPM,2);
        load_B_reg_into(EAX);
        mov_rm32_rm32(EAXM,EAX);
        mov_rm32_rm32_disp(EAX,ESPM,1);
        mov_rm32_rm32_disp(EBPM,EAX,-3);
        add_imm32_rm32(0x4,EAX);
        mov_rm32_rm32(EAXM,EAX);
        mov_rm32_rm32(EAX,ESPM);
        mov_rm32_rm32_disp(EBPM,EAX,-7);
        put2bytes(0xffd0);
        //really return out of bytecode stream
        mov_rm32_rm32_disp(EAX,EBPM,-15);
        exit_bytecode();
        return;
}

void Jcheck_nargs0()
{
        mov_rm32_rm32_disp(EBPM,EAX,3); //mov 0xc(%ebp), %eax
        cmp_imm_r32(0x0,EAX);
        cond_jump("L0",JE);
        Jcall_error();
        return;
}

void Jcheck_nargs3()
{
        /*
         * if (nargs != 3) return error(2, err_wrong_no_args, name_from(def),
         *                                     fixnum_of_int((int32_t)nargs));
         */
        
        mov_addr_r32(&C_nil,EAX);
        mov_rm32_rm32_disp(EAX,EBPM,-6); //nil=C_nil
        mov_rm32_rm32_disp(EBPM,EAX,3); //mov 0xc(%ebp), %eax
        cmp_imm_r32(0x3,EAX);
        cond_jump("L1",JE);
        Jcall_error();
        
        /* 
         *     va_start(aa, nargs);
         *     a = va_arg(aa, Lisp_Object);
         *     b = va_arg(aa, Lisp_Object);
         *     c = va_arg(aa, Lisp_Object);
         *     va_end(aa);
         */
        
        add_label("L1");
        lea_m32_r32_disp(EBPM,EAX,4); //leal    16(%ebp), %eax
        mov_rm32_rm32_disp(EAX,EBPM,-1); //movl    %eax, -4(%ebp)
        mov_rm32_rm32_disp(EBPM,EDX,-1); //movl    -4(%ebp), %edx
        lea_m32_r32_disp(EBPM,EAX,-1); //leal    -4(%ebp), %eax
        add_imm32_rm32(0x4,EAXM); //addl    $4, (%eax)
        mov_rm32_rm32(EDXM,EAX); //movl    (%edx), %eax
        mov_rm32_rm32_disp(EAX,EBPM,-3); //movl    %eax, -12(%ebp)
        mov_rm32_rm32_disp(EBPM,EDX,-1); //movl    -4(%ebp), %edx
        lea_m32_r32_disp(EBPM,EAX,-1); //leal    -4(%ebp), %eax
        add_imm32_rm32(0x4,EAXM); //addl    $4, (%eax)
        mov_rm32_rm32(EDXM,EAX); //movl    (%edx), %eax
        mov_rm32_rm32_disp(EAX,EBPM,-4); //movl    %eax, -16(%ebp)
        mov_rm32_rm32_disp(EBPM,EDX,-1); //movl    -4(%ebp), %edx
        lea_m32_r32_disp(EBPM,EAX,-1); //leal    -4(%ebp), %eax
        add_imm32_rm32(0x4,EAXM); //addl    $4, (%eax)
        mov_rm32_rm32(EDXM,EAX); //movl    (%edx), %eax
        mov_rm32_rm32_disp(EAX,EBPM,-5); //movl    %eax, -20(%ebp)

        //push5
        /*
        mov_addr_r32(stack,EDX); //movl    C_stack, %edx
        add_imm32_rm32(0x4,EDX); //addl    $4, %edx
        mov_rm32_rm32_disp(EBPM,EAX,-6); //movl    -24(%ebp), %eax
        add_imm32_rm32(LITVEC,EAX); //addl    $220, %eax
        mov_rm32_rm32(EAXM,EAX); //movl    (%eax), %eax
        mov_rm32_rm32(EAX,EDXM); //movl    %eax, (%edx)
        mov_addr_r32(stack,EDX); //movl    C_stack, %edx
        add_imm32_rm32(0x8,EDX); //addl    $8, %edx
        mov_rm32_rm32_disp(EBPM,EAX,-6); //movl    -24(%ebp), %eax
        add_imm32_rm32(CODEVEC,EAX); //addl    $216, %eax
        mov_rm32_rm32(EAXM,EAX); //movl    (%eax), %eax
        mov_rm32_rm32(EAX,EDXM);//movl    %eax, (%edx)
        */
        mov_addr_r32(stack,EAX); //movl    C_stack, %edx
        add_imm32_rm32(0x4,EAX); //addl    $12, %edx
        mov_rm32_rm32_disp(EBPM,EBX,-3); //movl    -12(%ebp), %eax
        mov_rm32_rm32(EBX,EAXM); //movl    %eax, (%edx)
        mov_addr_r32(stack,EAX); //movl    C_stack, %edx
        add_imm32_rm32(0x8,EAX); //addl        $16, %edx
        mov_rm32_rm32_disp(EBPM,EBX,-4); //movl    -16(%ebp), %eax
        mov_rm32_rm32(EBX,EAXM); //movl    %eax, (%edx)
        mov_addr_r32(stack,EAX); //movl    C_stack, %edx
        add_imm32_rm32(0xc,EAX); //addl        $20, %edx
        mov_rm32_rm32_disp(EBPM,EBX,-5); //movl    -20(%ebp), %eax
        mov_rm32_rm32(EBX,EAXM); //movl    %eax, (%edx)
        
        mov_addr_r32(stack,EAX);
        add_imm32_rm32(0xc,EAX);
        mov_r32_addr(EAX,stack);
        
        //add_imm8_addr(0xc,stack); //FIXME ILLEGAL INSTRUCTION?
}

void Jcheck_nargsn()
{
        mov_addr_r32(stack,EAX);
        mov_rm32_rm32_disp(EAX,EBPM,-4); //stack_save
        /*
        mov_addr_r32(stack,EDX);
        add_imm32_rm32(0x4,EDX);
        mov_rm32_rm32_disp(EBPM,EAX,-2);
        add_imm32_rm32(LITVEC,EAX);
        mov_rm32_rm32(EAXM,EAX);
        mov_rm32_rm32(EAX,EDXM);
        mov_addr_r32(stack,EDX);
        add_imm32_rm32(0x8,EDX);
        mov_rm32_rm32_disp(EBPM,EAX,-2);
        add_imm32_rm32(CODEVEC,EAX);
        mov_rm32_rm32(EAXM,EAX);
        mov_rm32_rm32(EAX,EDXM);
        mov_addr_r32(stack,EDX);
        add_imm32_rm32(0x8,EDX);
        mov_r32_addr(EDX,stack);
        */
        put4bytes(0x837d0c00);//cmpl $0, 12(%ebp)
        cond_jump("L2",JE);
        lea_m32_r32_disp(EBPM,EAX,4);
        mov_rm32_rm32_disp(EAX,EBPM,-5);
        mov_rm32_rm32_disp(EBPM,EAX,3);
        mov_rm32_rm32_disp(EAX,ESPM,1);
        mov_rm32_rm32_disp(EBPM,EAX,-5);
        mov_rm32_rm32(EAX,ESPM);
        Jcall_abs_fn(push_args);
        add_label("L2");
        //insert stackcheck1
        
        mov_rm32_rm32_disp(EBPM,EAX,2);
        mov_rm32_rm32(EAXM,EAX);
        mov_rm32_rm32_disp(EAX,EBPM,-1);
        mov_rm32_rm32_disp(EBPM,EAX,-1);
        put3bytes(0xc1e81c);//shrl $28,%eax
        put4bytes(0x8d148500); put3bytes(0x000000);//leal 0(,%eax,4), %edx
        mov_addr_r32(&bps_pages,EAX);
        put3bytes(0x8b0402);//movl (%edx,%eax), %eax FIXME not sure about x86
        add_imm32_rm32(0x7,EAX);
        mov_rm32_rm32(EAX,EDX);
        and_imm_rm32(0xf8,EDX);
        mov_rm32_rm32_disp(EBPM,EAX,-1);
        put3bytes(0xc1f806);//sarl 6, %eax
        put4bytes(0x25fcff3f); putbyte(0x00);//andl 4194300, %eax //little_endian
        put4bytes(0x0fb60402);//movzbl (%edx,%eax), %eax FIXME not sure about x86
        put3bytes(0x3b450c);//cmpl 12(%ebp), %eax
        cond_jump("L3",JE);
        mov_rm32_rm32_disp(EBPM,EAX,3);
        put4bytes(0x8d148500); put3bytes(0x000000);//leal 0(,%eax,4), %edx
        mov_addr_r32(stack,EAX);
        put2bytes(0x29d0);//sub %edx, %eax
        sub_imm32_rm32(0x8,EAX);
        mov_r32_addr(EAX,stack);
        Jcall_error();

        add_label("L3");//bytestream_interpret
}

void Jpop_vecs()
{
        //mov_addr_r32(stack,EDX); //mov C_stack,%edx
        //sub_imm32_rm32(0x8, EDX);
        //mov_r32_addr(EDX,stack); //mov %edx, C_stack
        //Jcall_abs_fn(dec_stack);
        //Jcall_abs_fn(dec_stack);
        /*
        
        sub_imm8_addr(0x8,stack); FIXME ILLEGAL INSTRUCTION?
        
        mov_rm32_rm32_disp(EBPM,EDX,-2); //mov -8(%ebp), %edx //C_nil
        add_imm32_rm32(CODEVEC,EDX); //add 216, %edx
        mov_addr_r32(stack,EAX); //mov C_stack, %eax
        add_imm32_rm32(0x8, EAX); //addl $0x8,%eax
        mov_rm32_rm32(EAXM,EAX); //mov (%eax),%eax
        mov_rm32_rm32(EAX,EDXM); //mov %eax, (%edx)
        mov_rm32_rm32_disp(EBPM,EDX,-2); //mov -8(%ebp), %edx //C_nil
        add_imm32_rm32(LITVEC,EDX); //add 220, %edx
        mov_addr_r32(stack,EAX); //mov C_stack, %eax
        add_imm32_rm32(0x4, EAX); //addl $0x4,%eax
        mov_rm32_rm32(EAXM,EAX); //mov (%eax),%eax
        mov_rm32_rm32(EAX,EDXM); //mov %eax, (%edx)
*/
        //move result to local var
        mov_rm32_rm32_disp(EBPM,EAX,-1); //mov -4(%ebp), %eax
        mov_rm32_rm32_disp(EAX,EBPM,-3); //mov %eax, -12(%ebp)
}
                                                

void MS_CDECL Jpush_stack(int nargs) //ifndef MEMORY_TRACE in externs.h
{
        //must align stack correctly 4 bytes for 32bit, 8 bytes for 64bit
        //and check for BASE.  nil-4 in common lisp
        
        add_label("L0");
        //Jnil_eq_C_nil();//nil=C_nil
        /*
        mov_addr_r32(stack,EDX); //mov C_stack, %edx
        add_imm32_rm32(0x4, EDX); //add 04, %edx
        mov_rm32_rm32_disp(EBPM,EAX,-2);//mov -8(%ebp), %eax //C_nil
        add_imm32_rm32(LITVEC, EAX); //add 220, %eax
        mov_rm32_rm32(EAXM,EAX); //mov (%eax),%eax
        mov_rm32_rm32(EAX,EDXM); //mov %eax, (%edx)
        mov_addr_r32(stack,EDX); //mov C_stack, %edx
        add_imm32_rm32(0x8, EDX); //add 08, %edx
        mov_rm32_rm32_disp(EBPM,EAX,-2);//mov -8(%ebp), %eax //C_nil
        add_imm32_rm32(CODEVEC, EAX); //add 216 eax
        mov_rm32_rm32(EAXM,EAX); //mov (%eax),%eax
        mov_rm32_rm32(EAX,EDXM); //mov %eax, (%edx)
        */
                                                        
        if (nargs==0)
        {
                //add_imm8_addr(0x8,stack);
                                                
        }
        
        if (nargs==1)
        {
                mov_addr_r32(stack,EAX); //mov C_stack, %edx
                add_imm32_rm32(0x4, EAX); //addl 0xc,%edx
                mov_rm32_rm32_disp(EBPM,EBX,3); //mov 0xc(%ebp), %eax
                mov_rm32_rm32(EBX,EAXM); //mov %eax,(%edx)
                
                mov_addr_r32(stack,EAX);
                add_imm32_rm32(0x4,EAX);
                mov_r32_addr(EAX,stack);
                //add_imm8_addr(0x4,stack);
        }

        
        if (nargs==2)
        {
                mov_addr_r32(stack,EAX); //mov C_stack, %edx
                add_imm32_rm32(0x4, EAX); //addl $0x0c,%edx
                mov_rm32_rm32_disp(EBPM,EBX,3); //mov 0xc(%ebp), %eax
                mov_rm32_rm32(EBX,EAXM); //mov %eax,(%edx)
                mov_addr_r32(stack,EAX); //mov C_stack, %edx
                add_imm32_rm32(0x8, EAX); //addl $0x10,%edx
                mov_rm32_rm32_disp(EBPM,EBX,4); //mov 0x10(%ebp), %eax
                mov_rm32_rm32(EBX,EAXM); //mov %eax,(%edx)
                
                mov_addr_r32(stack,EAX);
                add_imm32_rm32(0x8,EAX);
                mov_r32_addr(EAX,stack);
                //add_imm8_addr(0x8,stack);
        }
}

void Jstackcheck1(int k)
{
        /* stackcheck in #externs.h */
        //FIXME below
        //dec countdown
        //cmp 0 countdown
        //jns stackcheck10
        //test eax eax
        //jne stackcheck11
        add_disassembler_label("STACKCHECK");
        mov_addr_r32(stacklimit,EAX);
        put2bytes(0x3905);put_addr(stack);
        //mov_addr_r32(stack,EBX);
        //cmp_rm32_rm32(EAX,EBX);
        cond_jump("stackcheck11",JAE);
        jump("stackcheck12");
        add_label("stackcheck11");
        put4bytes(0xc744240c);put4bytes(0x00000000);//mov 0, 12(esp)
        put4bytes(0xc7442408);put4bytes(0x02000000);//mov 2, 8(esp)
        put4bytes(0xc7442404);put4bytes(0x65656500);//mov LC0, 4(esp) FIXME
        mov_rm32_rm32_disp(EBPM,EAX,2);//def
        mov_rm32_rm32(EAX,ESPM);
        Jcall_abs_fn(reclaim);
        mov_rm32_rm32_disp(EAX,EBPM,2);
        /*
        mov_addr_r32(&C_nil,EAX);
        mov_rm32_rm32_disp(EAX,EBPM,-6); //FIXME consistent address for nil?
        */
        //exceptionpending
        add_label("stackcheck12");//end
        return;
}

void Jcall(char *label, int pos)
{
        reloc_table *tmp;
        int offset;
        tmp = labels_table;
        while(tmp != NULL)
        {
                printf("\n%s\n",tmp->label);
                if(strcmp(label,tmp->label)==0)
                {
                        offset = tmp->pos - pos;
                        printf("\n%d\n",offset);
                }
                else tmp = tmp->next;
        }
}

void Jprepare_bytecode_compiler(int nargs)
{
        add_disassembler_label("BYTESTREAM_INTERPRET");
        if(nargs!=0 && nargs!=1 && nargs!=2 && nargs!=3) {
                mov_rm32_rm32_disp(EBPM,EAX,3);
                put4bytes(0x8d148500); put3bytes(0x000000);//leal 0(,%eax,4), %edx
                mov_addr_r32(stack,EAX);
                put2bytes(0x29d0); //sub edx, eax
                mov_rm32_rm32_disp(EAX,ESPM,2);
                mov_rm32_rm32_disp(EBPM,EAX,2);
                mov_rm32_rm32_disp(EAXM,EAX,1);
                mov_rm32_rm32_disp(EAX,ESPM,1);
                mov_rm32_rm32_disp(EBPM,EAX,-1);
                dec_reg(EAX);
                mov_rm32_rm32(EAX,ESPM);
                call_rel_fn("bytestream_interpret");
        }
        else {
                mov_addr_r32(stack,EAX); //mov C_stack, eax
                if(nargs==1) sub_imm32_rm32(0x4, EAX); //sub 4, eax
                if(nargs==2) sub_imm32_rm32(0x8, EAX); //sub 8, eax
                if(nargs==3) sub_imm32_rm32(0xc, EAX); //sub c, eax
                mov_rm32_rm32_disp(EAX,ESPM,2);
                mov_rm32_rm32_disp(EBPM,EAX,2); //mov 0x8(ebp), eax
                mov_rm32_rm32_disp(EAXM,EAX,1); //mov 0x4(eax),eax
                mov_rm32_rm32_disp(EAX,ESPM,1);
                mov_rm32_rm32_disp(EBPM,EAX,2); //mov 0x8(ebp), eax
                mov_rm32_rm32(EAXM,EAX); //mov (eax), eax
                sub_imm32_rm32(0x2, EAX); //sub 0x2, eax
                mov_rm32_rm32(EAX,ESPM);
                call_rel_fn("bytestream_interpret");
        }
}

Lisp_Object Jbpsupbv(Lisp_Object nil, Lisp_Object v)
{
        Header h;
        int32_t n;
        CSL_IGNORE(nil);
        if (!(is_bps(v))) return aerror1("bps-upbv", v);
        h = *(Header *)((char *)data_of_bps(v) - CELL);
        n = length_of_header(h) - CELL;
        //return fixnum_of_int(n-1);
        return n;
}

int Jbytecode_compile(Lisp_Object def, int nargs)
{
        /*
         * A_reg uses register ECX
         */
        
        Lisp_Object nil = C_nil;
        register unsigned char *ppc;
        Lisp_Object code;
        if(nargs>3) {
                code = qcar(def)-1;
        }
        else {
                code = qcar(def)-2;
        }
        ppc = (unsigned char *)data_of_bps(code);
        ppc = ppc + ((int32_t)code & 3);

        int bytecodes = 0;//FIXME overflow ?
        int length = 0;
        char label[64]=""; /* used for bytecode label */

        char label1[64]="";
        char label2[64]="";
        char label3[64]="";
        char label4[64]="";
        int i; //used in loops for bytecode
        
        //Add entry to label table indicating start of bytecodes
        add_label("bytestream_interpret");
        init_stack_pointers();
        sub_imm32_rm32(0x78, ESP); //sub 0x78,esp FIXME not AMD64 comp
        //Lisp_Object nil = C_nil
        mov_addr_r32(&C_nil,EAX); //nil=C_nil
        mov_rm32_rm32_disp(EAX,EBPM,-1); //mov %eax, -4(ebp)
        //Lisp_Object *stack = C_stack
        mov_addr_r32(stack,EAX); //mov C_stack, %eax
        mov_rm32_rm32_disp(EAX,EBPM,-2); //mov %eax, -8(ebp)
        /*
        //litvec = lit = qcdr(def) passed as arg to this fn
        mov_rm32_rm32_disp(EBPM,EDX,-1);
        add_imm32_rm32(LITVEC,EDX);
        mov_rm32_rm32_disp(EBPM,EAX,3);
        mov_rm32_rm32(EAX,EDXM);
        */
        //codevec = (Lisp_Object)(((int32_t)code & ~3) + 2)
        /*
        mov_rm32_rm32_disp(EBPM,EDX,-1);
        add_imm32_rm32(CODEVEC,EDX);
        mov_rm32_rm32_disp(EBPM,EAX,2);
        and_imm_rm32(0xfc,EAX);
        add_imm32_rm32(0x2,EAX);
        mov_rm32_rm32(EAX,EDXM);
        */
        //A_reg=nil
        mov_rm32_rm32_disp(EBPM,ECX,-1);
        mov_rm32_rm32_disp(ECX,EBPM,-17);
        mov_rm32_rm32(ECX,EDI);

        Lisp_Object bytecode = Lsymbol_env(nil,elt(qcdr(def),0));
        length = Jbpsupbv(nil, qcar(bytecode));
        if(nargs>3) {
                length--;
        }
        //printf("Length: %x\n",length);
        
        for (;bytecodes<length;)
        {
#ifdef X86
                //add label for disassembler output
                add_disassembler_label(opnames[*ppc]);
#endif
                
                //add a label for each iteration through loop
                sprintf(label, "BC%x",bytecodes);
                add_label(label);
#ifdef JDEBUG
                printf("Bytecode %i: %s\tcodep: %lu\n",bytecodes,opnames[*ppc],codep);
#endif
                bytecodes++; //counter use for jump bytecodes
#define JDEBUG1
#ifdef JDEBUG1
                //print name of bytecode running now
                putbyte(0xb8); put_little_endian(*ppc);
                mov_rm32_rm32(EAX,ESPM);
                Jcall_abs_fn(bytecode_breakpoint);
#endif

/*
 * cant dirty ECX or EDX any more if using OPTIMISE_REG
 * A_reg = ECX
 * B_reg = EDX
 */
                
        switch (next_byte) // *ppc++
        {
                case OP_LOC0EXIT:
                        /* A_reg = stack[0]; */
                        load_stack_into(ECX);
                        mov_rm32_rm32(ECXM,ECX);
                        store_A_reg_from(ECX);
#ifdef COMMON
#endif
                        /* C_stack = entry_stack; */
                        load_entry_stack_into(EAX);
                        mov_r32_addr(EAX,stack);
                        /* return A_reg; */
                        load_A_reg_into(EAX);
                        //store_result_from(ECX);
                        exit_bytecode();
                        continue;

                case OP_LOC1EXIT:
                        load_stack_into(ECX);
                        sub_imm32_rm32(0x4, ECX); //sub 0x4, %eax
                        mov_rm32_rm32(ECXM,ECX); //mov (%eax), %eax
                        store_A_reg_from(ECX);
#ifdef COMMON
#endif
                        load_entry_stack_into(EAX);
                        mov_r32_addr(EAX,stack); //C_stack = entry_stack
                        load_A_reg_into(EAX);
                        //store_result_from(ECX);
                        exit_bytecode();
                        continue;

                case OP_LOC2EXIT:
                        load_stack_into(ECX);
                        sub_imm32_rm32(0x8,ECX); //sub $0x8,%eax
                        mov_rm32_rm32(ECXM,ECX); //mov (%eax),%eax
                        store_A_reg_from(ECX);
#ifdef COMMON
#endif
                        load_entry_stack_into(EAX);
                        mov_r32_addr(EAX,stack); //C_stack = entry_stack
                        load_A_reg_into(EAX);
                        //store_result_from(EAX);
                        exit_bytecode();
                        continue;

                case OP_NILEXIT:
                        load_entry_stack_into(EAX);
                        mov_r32_addr(EAX,stack); //C_stack = entry_stack
                        load_nil_into(EAX);
                        store_result_from(EAX);
                        exit_bytecode();
                        continue;

                case OP_FREEBIND:
                        load_stack_into(EAX);
                        mov_rm32_rm32_disp(EAX,ESPM,1);
                        load_litvec_into(EBX);
                        putbyte(0xb8);put_little_endian(*ppc);
                        put3bytes(0xc1e002);//sall 2, eax
                        //put2bytes(0x0303);//add_rm32_rm32(EBXM,EAX);//FIXME or 01
                        put2bytes(0x01d8); //litvec is mem now
                        sub_imm32_rm32(0x2,EAX);
                        mov_rm32_rm32(EAXM,EAX);
                        mov_rm32_rm32(EAX,ESPM);
                        Jcall_abs_fn(Jdo_freebind);
                        store_stack_from(EAX);
                        next_byte;
                        bytecodes++;
                        continue;

                case OP_FREERSTR:
                        load_stack_into(EAX);
                        mov_rm32_rm32(EAX,ESPM);
                        Jcall_abs_fn(Jdo_freerstr);
                        store_stack_from(EAX);
                        continue;

                case OP_STOREFREE:
                        load_litvec_into(EBX);
                        putbyte(0xb8);put_little_endian(*ppc);
                        put3bytes(0xc1e002);//sall 2, eax
                        put2bytes(0x01d8);//add_rm32_rm32(EBX,EAX);
                        sub_imm32_rm32(0x2,EAX);
                        mov_rm32_rm32(EAXM,EAX);
                        load_A_reg_into(EBX);
                        mov_rm32_rm32(EBX,EAXM);
                        next_byte;
                        bytecodes++;
                        continue;

                case OP_STOREFREE1:
                        load_litvec_into(EAX);
                        //mov_rm32_rm32(EAXM,EAX);
                        add_imm32_rm32(0x2,EAX);
                        mov_rm32_rm32(EAXM,EAX);
                        load_A_reg_into(EBX);
                        mov_rm32_rm32(EBX,EAXM);
                        continue;

                case OP_STOREFREE2:
                        load_litvec_into(EAX);
                        //mov_rm32_rm32(EAXM,EAX);
                        add_imm32_rm32(0x6,EAX);
                        mov_rm32_rm32(EAXM,EAX);
                        load_A_reg_into(EBX);
                        mov_rm32_rm32(EBX,EAXM);
                        continue;

                case OP_STOREFREE3:
                        load_litvec_into(EAX);
                        //mov_rm32_rm32(EAXM,EAX);
                        add_imm32_rm32(10,EAX);
                        mov_rm32_rm32(EAXM,EAX);
                        load_A_reg_into(EBX);
                        mov_rm32_rm32(EBX,EAXM);
                        continue;

                case OP_PUSHNILS:
                        for(i=0; i<*ppc; i++) {
                                load_stackaddr_into(EAX);
                                add_imm32_rm32(0x4,EAXM);
                                load_stack_into(EBX);
                                load_nil_into(EAX);
                                mov_rm32_rm32(EAX,EBXM);
                        }
                        next_byte;
                        bytecodes++;
                        continue;

                case OP_VNIL:
                        load_B_reg_into(EAX);
                        load_A_reg_into(EBX);
                        mov_rm32_rm32(EBX,EAXM);
                        load_nil_into(EAX);
                        store_A_reg_from(EAX);
#ifdef COMMON
#endif
                        continue;

                case OP_SWOP:
                        load_B_reg_into(EAX);
                        mov_rm32_rm32(EAXM,EAX);
                        mov_rm32_rm32_disp(EAX,EBPM,-3);
                        load_B_reg_into(EAX);
                        load_A_reg_into(EBX);
                        mov_rm32_rm32(EBX,EAXM);
                        mov_rm32_rm32_disp(EBPM,EAX,-3);
                        store_A_reg_from(EAX);
                        continue;

                case OP_NCONS:
#ifndef OUT_OF_LINE
                        load_fringe_into(EAX);
                        mov_rm32_rm32(EAXM,EAX);
                        sub_imm32_rm32(0x8,EAX);
                        mov_rm32_rm32_disp(EAX,EBPM,-3);
                        mov_rm32_rm32_disp(EBPM,EAX,-3);
                        load_A_reg_into(EBX);
                        mov_rm32_rm32(EBX,EAXM);
                        mov_rm32_rm32_disp(EBPM,EAX,-3);
                        load_nil_into(EBX);
                        mov_rm32_rm32_disp(EBX,EAXM,1);//FIXME ok disp?
                        load_fringe_into(EBX);
                        mov_rm32_rm32_disp(EBPM,EAX,-3);
                        mov_rm32_rm32(EAX,EBXM);
                        //FIXME heaplimit?
                        mov_rm32_rm32_disp(EBPM,EAX,-3);
                        store_A_reg_from(EAX);
#else
#endif
#ifdef COMMON
#endif
                        continue;

                case OP_XCONS:
#ifdef OUT_OF_LINE
                        load_fringe_into(EAX);
                        mov_rm32_rm32(EAXM,EAX);
                        sub_imm32_rm32(0x8,EAX);
                        mov_rm32_rm32_disp(EAX,EBPM,-3);
                        mov_rm32_rm32_disp(EBPM,EAX,-3);
                        load_A_reg_into(EBX);
                        mov_rm32_rm32(EBX,EAXM);
                        mov_rm32_rm32_disp(EBPM,EAX,-3);
                        load_B_reg_into(EBX);
                        mov_rm32_rm32(EBXM,EBX);
                        mov_rm32_rm32_disp(EBX,EAXM,1);
                        load_fringe_into(EBX);
                        mov_rm32_rm32_disp(EBPM,EAX,-3);
                        mov_rm32_rm32(EAX,EBXM);
                        //heaplimit?
                        mov_rm32_rm32_disp(EBPM,EAX,-3);
                        store_A_reg_from(EAX);
#else
#endif
#ifdef COMMON
#endif
                        continue;

                case OP_LIST2:
                        //FIXME outofline
                        //save_pc
                        load_stack_into(EAX);
                        mov_r32_addr(EAX,stack);
                        load_A_reg_into(EAX);
                        mov_rm32_rm32_disp(EAX,ESPM,1);
                        load_B_reg_into(EAX);
                        mov_rm32_rm32(EAXM,EAX);
                        mov_rm32_rm32(EAX,ESPM);
                        Jcall_abs_fn(list2);
                        store_A_reg_from(EAX);
                        mov_addr_r32(&C_nil,EAX);
                        store_nil_from(EAX);
                        //exception
                        mov_addr_r32(stack,EAX);
                        store_stack_from(EAX);
                        //restorepc
                        continue;

                case OP_ACONS:
#ifndef OUT_OF_LINE
                        load_fringe_into(EAX);
                        mov_rm32_rm32(EAXM,EAX);
                        sub_imm32_rm32(0x10,EAX);
                        mov_rm32_rm32_disp(EAX,EBPM,-3);
                        mov_rm32_rm32_disp(EBPM,ECX,-3);
                        mov_rm32_rm32_disp(EBPM,EAX,-3);
                        add_imm32_rm32(0x8,EAX);
                        mov_rm32_rm32(EAX,ECXM);
                        mov_rm32_rm32_disp(EBPM,EAX,-3);
                        load_A_reg_into(EBX);
                        mov_rm32_rm32_disp(EBX,EAXM,1); //FIXME of disp?
                        mov_rm32_rm32_disp(EBPM,EBX,-3);
                        add_imm32_rm32(0x8,EBX);
                        load_stack_into(EAX);
                        mov_rm32_rm32(EAX,ECX);
                        load_stackaddr_into(EAX);
                        sub_imm32_rm32(0x4,EAXM);
                        mov_rm32_rm32(ECXM,EAX);
                        mov_rm32_rm32(EAX,EBXM);
                        mov_rm32_rm32_disp(EBPM,ECX,-3);
                        add_imm32_rm32(0x8,ECX);
                        load_B_reg_into(EAX);
                        mov_rm32_rm32(EAXM,EAX);
                        mov_rm32_rm32_disp(EAX,ECXM,4);//FIXME ok disp?
                        load_fringe_into(ECX);
                        mov_rm32_rm32_disp(EBPM,EAX,-3);
                        mov_rm32_rm32(EAX,ECXM);
                        //heaplimit?
                        mov_rm32_rm32_disp(EBPM,EAX,-3);
                        store_A_reg_from(EAX);
#else
#endif
#ifdef COMMON
#endif
                        continue;

                case OP_LIST2STAR:
#ifndef OUT_OF_LINE
                        load_fringe_into(EAX);
                        mov_rm32_rm32(EAXM,EAX);
                        sub_imm32_rm32(0x10,EAX);
                        mov_rm32_rm32_disp(EAX,EBPM,-3);
                        mov_rm32_rm32_disp(EBPM,EBX,-3);
                        load_stack_into(EAX);
                        mov_rm32_rm32(EAX,ECX);
                        load_stackaddr_into(EAX);
                        sub_imm32_rm32(0x4,EAXM);
                        mov_rm32_rm32(ECXM,EAX);
                        mov_rm32_rm32(EAX,EBXM);
                        mov_rm32_rm32_disp(EBPM,EBX,-3);
                        mov_rm32_rm32_disp(EBPM,EAX,-3);
                        add_imm32_rm32(0x8,EAX);
                        mov_rm32_rm32_disp(EAX,EBXM,1);
                        mov_rm32_rm32_disp(EBPM,EBX,-3);
                        add_imm32_rm32(0x8,EBX);
                        load_B_reg_into(EAX);
                        mov_rm32_rm32(EAXM,EAX);
                        mov_rm32_rm32(EAX,EBXM);
                        mov_rm32_rm32_disp(EBPM,EAX,-3);
                        add_imm32_rm32(0x8,EAX);
                        load_A_reg_into(EBX);
                        mov_rm32_rm32_disp(EBX,EAXM,1);
                        load_fringe_into(EBX);
                        mov_rm32_rm32_disp(EBPM,EAX,-3);
                        mov_rm32_rm32(EAX,EBXM);
                        //heaplimit?
                        mov_rm32_rm32_disp(EBPM,EAX,-3);
                        store_A_reg_from(EAX);
#else
#endif
#ifdef COMMON
#endif
                        continue;

                case OP_ADD1:
                        make_label(label1,"ADD1",1);
                        make_label(label2,"ADD1",2);
                        load_A_reg_into(ECX);
                        and_imm_rm32(0x7, ECX);
                        cmp_imm_r32(0x1,ECX);
                        cond_jump(label1,JNE);
                        put3bytes(0x817dbc); put4bytes(0x7ffffff1);//cmp 2147483647, -68(ebp)
                        cond_jump(label1,JE);
                        put4bytes(0x8345bc10);//add 16, -68(ebp) FIXME should be for ecx
                        jump(label2); //jump to end of bytecode
#ifdef COMMON
#endif
                        /* floating, bignum or error arithmetic support */
                        add_label(label1);
                        //save_pc()
                        load_stack_into(EAX);
                        mov_r32_addr(EAX,stack);
                        put4bytes(0xb8110000);putbyte(0x00); put4bytes(0x89442404);//mov 17, 4(esp) 
                        //put4bytes(0xc7442404); put4bytes(0xf1ffffff);
                        load_A_reg_into(ECX);
                        mov_rm32_rm32(ECX,ESPM);
                        Jcall_abs_fn(plus2);
                        store_A_reg_from(EAX);
                        mov_addr_r32(&C_nil,EAX);
                        store_nil_from(EAX);
                        //exception pending?
                        mov_addr_r32(stack,EAX);
                        store_stack_from(EAX);
                        //restore_pc
#ifdef COMMON
#endif
                        add_label(label2);
                        continue;

                case OP_SUB1:
                        make_label(label1,"SUB1",1);
                        make_label(label2,"SUB1",2);
                        load_A_reg_into(ECX);
                        and_imm_rm32(0x7, ECX);
                        cmp_imm_r32(0x1,ECX);
                        cond_jump(label1,JNE);
                        put3bytes(0x817dbc); put4bytes(0x01000080);//cmp -2147483647, -68(ebp)
                        cond_jump(label1,JE);
                        put4bytes(0x836dbc10);//sub 16, -68(ebp) FIXME should be for ecx
                        jump(label2); //jump to end of bytecode
#ifdef COMMON
#endif
                        /* floating, bignum or error arithmetic support */
                        add_label(label1);
                        //save_pc()
                        load_stack_into(EAX);
                        mov_r32_addr(EAX,stack);
                        put4bytes(0xb8f1ffff);putbyte(0xff); put4bytes(0x89442404);//mov -15, 4(esp) 
                        //put4bytes(0xc7442404); put4bytes(0xf1ffffff);
                        load_A_reg_into(ECX);
                        mov_rm32_rm32(ECX,ESPM);
                        Jcall_abs_fn(plus2);
                        store_A_reg_from(EAX);
                        mov_addr_r32(&C_nil,EAX);
                        store_nil_from(EAX);
                        //exception pending?
                        mov_addr_r32(stack,EAX);
                        store_stack_from(EAX);
                        //restore_pc
#ifdef COMMON
#endif
                        add_label(label2);
                        continue;

                case OP_TIMES2:
                        //save_pc() ?
                        load_stack_into(EAX);
                        mov_r32_addr(EAX,stack);
                        load_A_reg_into(ECX);
                        mov_rm32_rm32_disp(ECX,ESPM,1);
                        load_B_reg_into(EDX);
                        mov_rm32_rm32(EDXM,EDX);
                        mov_rm32_rm32(EDX,ESPM);
                        Jcall_abs_fn(times2);
                        mov_rm32_rm32(EAX,ECX);
                        store_A_reg_from(ECX);
                        mov_addr_r32(&C_nil,EAX);
                        store_nil_from(EAX);
                        //exception pending?
                        mov_addr_r32(stack,EAX);
                        store_stack_from(EAX);
#ifdef COMMON
#endif
                        continue;

                case OP_LESSP:
                        make_label(label1,"LESSP",1);
                        make_label(label2,"LESSP",2);
                        make_label(label3,"LESSP",3);
                        make_label(label4,"LESSP",4);
                        load_B_reg_into(EAX);
                        mov_rm32_rm32(EAXM,EAX);
                        and_imm_rm32(0x7,EAX);
                        cmp_imm_r32(0x1,EAX);
                        cond_jump(label1,JNE);
                        load_A_reg_into(EAX);
                        and_imm_rm32(0x7,EAX);
                        cmp_imm_r32(0x1,EAX);
                        cond_jump(label1,JNE);
                        load_B_reg_into(EAX);
                        load_A_reg_into(EBX);
                        cmp_rm32_rm32(EBX,EAXM);
                        put3bytes(0x0f9cc0);//set al
                        put3bytes(0x0fb6c0);//movzbl al, eax
                        mov_rm32_rm32_disp(EAX,EBPM,-11);
                        jump(label2);
                        add_label(label1);
                        //save_pc
                        load_stack_into(EAX);
                        mov_r32_addr(EAX,stack);
                        load_A_reg_into(EAX);
                        mov_rm32_rm32_disp(EAX,ESPM,1);
                        load_B_reg_into(EAX);
                        mov_rm32_rm32(EAXM,EAX);
                        mov_rm32_rm32(EAX,ESPM);
                        Jcall_abs_fn(lessp2);
                        mov_rm32_rm32_disp(EAX,EBPM,-11);
                        mov_addr_r32(&C_nil,EAX);
                        store_nil_from(EAX);
                        //exception pending
                        mov_addr_r32(stack,EAX);
                        store_stack_from(EAX);
                        //restore_pc
                        add_label(label2);
                        put4bytes(0x837dd400);//cmp 0, -44ebp
                        cond_jump(label3,JE);
                        load_nil_into(EAX);
                        add_imm32_rm32(100,EAX);
                        add_imm32_rm32(100,EAX);
                        add_imm32_rm32(100,EAX);
                        add_imm32_rm32(100,EAX);
                        add_imm32_rm32(32,EAX);
                        mov_rm32_rm32(EAXM,EAX);
                        store_A_reg_from(EAX);
                        jump(label4);
                        add_label(label3);
                        load_nil_into(EAX);
                        store_A_reg_from(EAX);
                        add_label(label4);
#ifdef COMMON
#endif
                        continue;

                case OP_APPLY1:
                        make_label(label1,"APPLY1",1);
                        make_label(label2,"APPLY1",2);
                        //save_pc
                        load_B_reg_into(EAX);
                        mov_rm32_rm32(EAXM,EAX);
                        and_imm_rm32(0x7,EAX);
                        cmp_imm_r32(0x4,EAX);
                        cond_jump(label1,JNE);
                        load_B_reg_into(EAX);
                        mov_rm32_rm32(EAXM,EAX);
                        add_imm32_rm32(0x8,EAX);
                        mov_rm32_rm32(EAXM,EAX);
                        mov_rm32_rm32_disp(EAX,EBPM,-6);
                        load_stackaddr_into(EAX);
                        add_imm32_rm32(0x4,EAXM);
                        load_stack_into(EBX);
                        load_B_reg_into(EAX);
                        mov_rm32_rm32(EAXM,EAX);
                        mov_rm32_rm32(EAX,EBXM);
                        load_stack_into(EAX);
                        mov_r32_addr(EAX,stack);
                        load_A_reg_into(EAX);
                        mov_rm32_rm32_disp(EAX,ESPM,1);
                        load_B_reg_into(EAX);
                        mov_rm32_rm32(EAXM,EAX);
                        add_imm32_rm32(0x4,EAX);
                        mov_rm32_rm32(EAXM,EAX);
                        mov_rm32_rm32(EAX,ESPM);
                        mov_rm32_rm32_disp(EBPM,EAX,-6);
                        put2bytes(0xffd0); //call *eax
                        store_A_reg_from(EAX);
                        mov_addr_r32(&C_nil,EAX);
                        store_nil_from(EAX);
                        //exception pending
                        mov_addr_r32(stack,EAX);
                        store_stack_from(EAX);
                        load_stackaddr_into(EAX);
                        sub_imm32_rm32(0x4,EAXM);
                        //restore_pc
                        jump(label2);
                        add_label(label1);
                        load_stackaddr_into(EAX);
                        add_imm32_rm32(0x4,EAXM);
                        load_stack_into(EAX);
                        load_A_reg_into(EBX);
                        mov_rm32_rm32(EBX,EAXM);
                        load_stack_into(EAX);
                        mov_r32_addr(EAX,stack);
                        load_B_reg_into(EAX);
                        mov_rm32_rm32(EAXM,EAX);
                        mov_rm32_rm32_disp(EAX,ESPM,3);
                        load_nil_into(EAX);
                        mov_rm32_rm32_disp(EAX,ESPM,2);
                        putbyte(0xb8);put4bytes(0x01000000);
                        mov_rm32_rm32_disp(EAX,ESPM,1);
                        load_B_reg_into(EAX);
                        mov_rm32_rm32(EAXM,EAX);
                        mov_rm32_rm32(EAX,ESPM);
                        Jcall_abs_fn(apply);
                        store_A_reg_from(EAX);
                        mov_addr_r32(&C_nil,EAX);
                        store_nil_from(EAX);
                        //exception pending
                        mov_addr_r32(stack,EAX);
                        store_stack_from(EAX);
                        //restore_pc
                        add_label(label2);
                        continue;

                case OP_APPLY2:
                        make_label(label1,"APPLY2",1);
                        make_label(label2,"APPLY2",2);
                        //save_pc
                        load_stack_into(EAX);
                        mov_rm32_rm32(EAXM,EAX);
                        mov_rm32_rm32_disp(EAX,EBPM,-4);
                        mov_rm32_rm32_disp(EBPM,EAX,-4);
                        and_imm_rm32(0x7,EAX);
                        cmp_imm_r32(0x4,EAX);
                        cond_jump(label1,JNE);
                        mov_rm32_rm32_disp(EBPM,EAX,-4);
                        add_imm32_rm32(0xc,EAX);
                        mov_rm32_rm32(EAXM,EAX);
                        mov_rm32_rm32_disp(EAX,EBPM,-7);
                        load_stack_into(EAX);
                        mov_r32_addr(EAX,stack);
                        load_A_reg_into(EAX);
                        mov_rm32_rm32_disp(EAX,ESPM,2);
                        load_B_reg_into(EAX);
                        mov_rm32_rm32(EAXM,EAX);
                        mov_rm32_rm32_disp(EAX,ESPM,1);
                        mov_rm32_rm32_disp(EBPM,EAX,-4);
                        add_imm32_rm32(0x4,EAX);
                        mov_rm32_rm32(EAXM,EAX);
                        mov_rm32_rm32(EAX,ESPM);
                        mov_rm32_rm32_disp(EBPM,EAX,-7);
                        put2bytes(0xffd0); //call *eax
                        store_A_reg_from(EAX);
                        mov_addr_r32(&C_nil,EAX);
                        store_nil_from(EAX);
                        //exception pending
                        mov_addr_r32(stack,EAX);
                        store_stack_from(EAX);
                        load_stackaddr_into(EAX);
                        sub_imm32_rm32(0x4,EAXM);
                        //restore_pc
                        jump(label2);
                        add_label(label1);
                        load_stack_into(EBX);
                        load_B_reg_into(EAX);
                        mov_rm32_rm32(EAXM,EAX);
                        mov_rm32_rm32(EAX,EBXM);
                        load_stackaddr_into(EAX);
                        add_imm32_rm32(0x4,EAXM);
                        load_stack_into(EAX);
                        load_A_reg_into(EBX);
                        mov_rm32_rm32(EBX,EAXM);
                        load_stack_into(EAX);
                        mov_r32_addr(EAX,stack);
                        mov_rm32_rm32_disp(EBPM,EAX,-4);
                        mov_rm32_rm32_disp(EAX,ESPM,3);
                        load_nil_into(EAX);
                        mov_rm32_rm32_disp(EAX,ESPM,2);
                        putbyte(0xb8);put4bytes(0x02000000);
                        mov_rm32_rm32_disp(EAX,ESPM,1);
                        mov_rm32_rm32_disp(EBPM,EAX,-4);
                        mov_rm32_rm32(EAX,ESPM);
                        Jcall_abs_fn(apply);
                        store_A_reg_from(EAX);
                        mov_addr_r32(&C_nil,EAX);
                        store_nil_from(EAX);
                        //exception pending
                        mov_addr_r32(stack,EAX);
                        store_stack_from(EAX);
                        //restore_pc
                        add_label(label2);
                        continue;


                case OP_GETV:
//FIXME add below

#ifndef OUT_OF_LINE
                        //FIXME add checks
                        load_B_reg_into(EBX);
                        load_A_reg_into(EAX);
                        put3bytes(0xc1f804);//sarl 4, eax
                        put3bytes(0xc1e002);//sall 2, eax
                        put2bytes(0x0303);//add_rm32_rm32(EBXM,EAX);
                        sub_imm32_rm32(0x2,EAX);
                        mov_rm32_rm32(EAXM,EAX);
                        store_A_reg_from(EAX);
#else
                        //FIXME doesnt work?
                        //savepc
                        load_stack_into(EAX);
                        mov_r32_addr(EAX,stack);
                        load_A_reg_into(EAX);
                        mov_rm32_rm32_disp(EAX,ESPM,2);
                        load_B_reg_into(EAX);
                        mov_rm32_rm32(EAXM,EAX);
                        mov_rm32_rm32_disp(EAX,ESPM,1);
                        load_nil_into(EAX);
                        mov_rm32_rm32(EAX,ESPM);
                        Jcall_abs_fn(Lgetv);
                        store_A_reg_from(EAX);
                        mov_addr_r32(&C_nil,EAX);
                        store_nil_from(EAX);
                        //exception pending
                        mov_addr_r32(stack,EAX);
                        store_stack_from(EAX);
                        //restorepc
#endif
#ifdef COMMON
#endif
                        continue;

                case OP_LOC0LOC1:
                        load_B_reg_into(EDX);
                        load_stack_into(EAX);
                        mov_rm32_rm32(EAXM,EAX);
                        mov_rm32_rm32(EAX,EDXM);
                        load_stack_into(ECX);
                        sub_imm32_rm32(0x4,ECX);
                        mov_rm32_rm32(ECXM,ECX);
                        store_A_reg_from(ECX);
#ifdef COMMON
#endif
                        continue;

                case OP_LOC1LOC2:
                        load_B_reg_into(EDX);
                        load_stack_into(EAX);
                        sub_imm32_rm32(0x4,EAX);
                        mov_rm32_rm32(EAXM,EAX);
                        mov_rm32_rm32(EAX,EDXM);
                        load_stack_into(ECX);
                        sub_imm32_rm32(0x8,ECX);
                        mov_rm32_rm32(ECXM,ECX);
                        store_A_reg_from(ECX);
#ifdef COMMON
#endif
                        continue;

                case OP_LOC2LOC3:
                        load_B_reg_into(EDX);
                        load_stack_into(EAX);
                        sub_imm32_rm32(0x8,EAX);
                        mov_rm32_rm32(EAXM,EAX);
                        mov_rm32_rm32(EAX,EDXM);
                        load_stack_into(ECX);
                        sub_imm32_rm32(0xc,ECX);
                        mov_rm32_rm32(ECXM,ECX);
                        store_A_reg_from(ECX);
#ifdef COMMON
#endif
                        continue;
                        
                case OP_LOC1LOC0:
                        load_B_reg_into(EDX);
                        load_stack_into(EAX);
                        sub_imm32_rm32(0x4,EAX);
                        mov_rm32_rm32(EAXM,EAX);
                        mov_rm32_rm32(EAX,EDXM);
                        load_stack_into(ECX);
                        mov_rm32_rm32(ECXM,ECX);
                        store_A_reg_from(ECX);
#ifdef COMMON
#endif
                        continue;

                case OP_LOC2LOC1:
                        load_B_reg_into(EDX);
                        load_stack_into(EAX);
                        sub_imm32_rm32(0x8,EAX);
                        mov_rm32_rm32(EAXM,EAX);
                        mov_rm32_rm32(EAX,EDXM);
                        load_stack_into(ECX);
                        sub_imm32_rm32(0x4,ECX);
                        mov_rm32_rm32(ECXM,ECX);
                        store_A_reg_from(ECX);
#ifdef COMMON
#endif
                        continue;

                case OP_LOC3LOC2:
                        load_B_reg_into(EDX);
                        load_stack_into(EAX);
                        sub_imm32_rm32(0xc,EAX);
                        mov_rm32_rm32(EAXM,EAX);
                        mov_rm32_rm32(EAX,EDXM);
                        load_stack_into(ECX);
                        sub_imm32_rm32(0x8,ECX);
                        mov_rm32_rm32(ECXM,ECX);
                        store_A_reg_from(ECX);
#ifdef COMMON
#endif
                        continue;

                case OP_CDRLOC0:
                        make_label(label1,"CDRLOC0",1);
                        load_B_reg_into(EDX);
                        load_A_reg_into(ECX);
                        mov_rm32_rm32(ECX,EDXM);
                        load_stack_into(ECX);
                        mov_rm32_rm32(ECXM,ECX);
                        store_A_reg_from(ECX);
                        load_A_reg_into(ECX);
                        and_imm_rm32(0x7,ECX);
                        put2bytes(0x85c9); //test ecx,ecx
                        cond_jump(label1,JE);
                        //mov $1, CSLerrcode
                        load_stack_into(EAX);
                        mov_r32_addr(EAX,stack);
                        jump("error_1_A");//jmp error_1_A //FIXME
                        add_label(label1);
                        load_A_reg_into(ECX);
                        mov_rm32_rm32_disp(ECXM,ECX,1);
                        store_A_reg_from(ECX);
#ifdef COMMON
#endif
                        continue;

                case OP_CDRLOC1:
                        make_label(label1,"CDRLOC1",1);
                        load_B_reg_into(EDX);
                        load_A_reg_into(ECX);
                        mov_rm32_rm32(ECX,EDXM);
                        load_stack_into(ECX);
                        sub_imm32_rm32(0x4,ECX);
                        mov_rm32_rm32(ECXM,ECX);
                        store_A_reg_from(ECX);
                        load_A_reg_into(ECX);
                        and_imm_rm32(0x7,ECX);
                        put2bytes(0x85c9); //test ecx,ecx
                        cond_jump(label1,JE);
                        //mov $1, CSLerrcode
                        load_stack_into(EAX);
                        mov_r32_addr(EAX,stack);
                        jump("error_1_A");//jmp error_1_A //FIXME
                        add_label(label1);
                        load_A_reg_into(ECX);
                        mov_rm32_rm32_disp(ECXM,ECX,1);
                        store_A_reg_from(ECX);
#ifdef COMMON
#endif
                        continue;

                case OP_CDRLOC2:
                        make_label(label1,"CDRLOC2",1);
                        load_B_reg_into(EDX);
                        load_A_reg_into(ECX);
                        mov_rm32_rm32(ECX,EDXM);
                        load_stack_into(ECX);
                        sub_imm32_rm32(0x8,ECX);
                        mov_rm32_rm32(ECXM,ECX);
                        store_A_reg_from(ECX);
                        load_A_reg_into(ECX);
                        and_imm_rm32(0x7,ECX);
                        put2bytes(0x85c9); //test ecx,ecx
                        cond_jump(label1,JE);
                        //mov $1, CSLerrcode
                        load_stack_into(EAX);
                        mov_r32_addr(EAX,stack);
                        jump("error_1_A");//jmp error_1_A //FIXME
                        add_label(label1);
                        load_A_reg_into(ECX);
                        mov_rm32_rm32_disp(ECXM,ECX,1);
                        store_A_reg_from(ECX);
#ifdef COMMON
#endif
                        continue;

                case OP_CDRLOC3:
                        make_label(label1,"CDRLOC3",1);
                        load_B_reg_into(EDX);
                        load_A_reg_into(ECX);
                        mov_rm32_rm32(ECX,EDXM);
                        load_stack_into(ECX);
                        sub_imm32_rm32(0xc,ECX);
                        mov_rm32_rm32(ECXM,ECX);
                        store_A_reg_from(ECX);
                        load_A_reg_into(ECX);
                        and_imm_rm32(0x7,ECX);
                        put2bytes(0x85c9); //test ecx,ecx
                        cond_jump(label1,JE);
                        //mov $1, CSLerrcode
                        load_stack_into(EAX);
                        mov_r32_addr(EAX,stack);
                        jump("error_1_A");//jmp error_1_A //FIXME
                        add_label(label1);
                        load_A_reg_into(ECX);
                        mov_rm32_rm32_disp(ECXM,ECX,1);
                        store_A_reg_from(ECX);
#ifdef COMMON
#endif
                        continue;

                case OP_CDRLOC4:
                        make_label(label1,"CDRLOC4",1);
                        load_B_reg_into(EDX);
                        load_A_reg_into(ECX);
                        mov_rm32_rm32(ECX,EDXM);
                        load_stack_into(ECX);
                        sub_imm32_rm32(0x10,ECX);
                        mov_rm32_rm32(ECXM,ECX);
                        store_A_reg_from(ECX);
                        load_A_reg_into(ECX);
                        and_imm_rm32(0x7,ECX);
                        put2bytes(0x85c9); //test ecx,ecx
                        cond_jump(label1,JE);
                        //mov $1, CSLerrcode
                        load_stack_into(EAX);
                        mov_r32_addr(EAX,stack);
                        jump("error_1_A");//jmp error_1_A //FIXME
                        add_label(label1);
                        load_A_reg_into(ECX);
                        mov_rm32_rm32_disp(ECXM,ECX,1);
                        store_A_reg_from(ECX);
#ifdef COMMON
#endif
                        continue;

                case OP_CDRLOC5:
                        make_label(label1,"CDRLOC5",1);
                        load_B_reg_into(EDX);
                        load_A_reg_into(ECX);
                        mov_rm32_rm32(ECX,EDXM);
                        load_stack_into(ECX);
                        sub_imm32_rm32(0x14,ECX);
                        mov_rm32_rm32(ECXM,ECX);
                        store_A_reg_from(ECX);
                        load_A_reg_into(ECX);
                        and_imm_rm32(0x7,ECX);
                        put2bytes(0x85c9); //test ecx,ecx
                        cond_jump(label1,JE);
                        //mov $1, CSLerrcode
                        load_stack_into(EAX);
                        mov_r32_addr(EAX,stack);
                        jump("error_1_A");//jmp error_1_A //FIXME
                        add_label(label1);
                        load_A_reg_into(ECX);
                        mov_rm32_rm32_disp(ECXM,ECX,1);
                        store_A_reg_from(ECX);
#ifdef COMMON
#endif
                        continue;

                case OP_CAARLOC0:
                        load_B_reg_into(EAX);
                        load_A_reg_into(EBX);
                        mov_rm32_rm32(EBX,EAXM);
                        load_stack_into(EAX);
                        mov_rm32_rm32(EAXM,EAX);
                        store_A_reg_from(EAX);
                        continue;
                        
                case OP_CAARLOC1:
                        load_B_reg_into(EAX);
                        load_A_reg_into(EBX);
                        mov_rm32_rm32(EBX,EAXM);
                        load_stack_into(EAX);
                        sub_imm32_rm32(4,EAX);
                        mov_rm32_rm32(EAXM,EAX);
                        store_A_reg_from(EAX);
                        continue;
                
                case OP_CAARLOC2:
                        load_B_reg_into(EAX);
                        load_A_reg_into(EBX);
                        mov_rm32_rm32(EBX,EAXM);
                        load_stack_into(EAX);
                        sub_imm32_rm32(8,EAX);
                        mov_rm32_rm32(EAXM,EAX);
                        store_A_reg_from(EAX);
                        continue;

                case OP_CAARLOC3:
                        load_B_reg_into(EAX);
                        load_A_reg_into(EBX);
                        mov_rm32_rm32(EBX,EAXM);
                        load_stack_into(EAX);
                        sub_imm32_rm32(12,EAX);
                        mov_rm32_rm32(EAXM,EAX);
                        store_A_reg_from(EAX);
                        continue;

                case OP_CAAR:
                        make_label(label1,"CAAR",1);
                        make_label(label2,"CAAR",2);
                        make_label(label3,"CAAR",3);
                        make_label(label4,"CAAR",4);
                        load_A_reg_into(EAX);
                        and_imm_rm32(0x7,EAX);
                        put2bytes(0x85c0);
                        cond_jump(label1,JNE);
                        load_A_reg_into(EAX);
                        mov_rm32_rm32(EAXM,EAX);
                        store_A_reg_from(EAX);
                        jump(label2);
                        add_label(label1);
                        /*FIXME add error_1_a */
                        add_label(label2);
                        load_A_reg_into(EAX);
                        and_imm_rm32(0x7,EAX);
                        put2bytes(0x85c0);
                        cond_jump(label3,JNE);
                        load_A_reg_into(EAX);
                        mov_rm32_rm32(EAXM,EAX);
                        store_A_reg_from(EAX);
                        jump(label4);
                        add_label(label3);
                        //FIXME error_1_A
                        add_label(label4);
                        continue;

                case OP_CADR:
                        make_label(label1,"CADR",1);
                        make_label(label2,"CADR",2);
                        make_label(label3,"CADR",3);
                        make_label(label4,"CADR",4);
                        load_A_reg_into(EAX);
                        and_imm_rm32(7,EAX);
                        put2bytes(0x85c0);
                        cond_jump(label1,JNE);
                        load_A_reg_into(EAX);
                        mov_rm32_rm32_disp(EAXM,EAX,1);
                        store_A_reg_from(EAX);
                        jump(label2);
                        add_label(label1);
                        //FIXME error_1_A
                        add_label(label2);
                        load_A_reg_into(EAX);
                        and_imm_rm32(7,EAX);
                        put2bytes(0x85c0);
                        cond_jump(label3,JNE);
                        load_A_reg_into(EAX);
                        mov_rm32_rm32(EAXM,EAX);
                        store_A_reg_from(EAX);
                        jump(label4);
                        add_label(label3);
                        //FIXME error_1_A
                        add_label(label4);
                        continue;

                case OP_CDAR:
                        make_label(label1,"CDAR",1);
                        make_label(label2,"CDAR",2);
                        make_label(label3,"CDAR",3);
                        make_label(label4,"CDAR",4);
                        load_A_reg_into(EAX);
                        and_imm_rm32(7,EAX);
                        put2bytes(0x85c0);
                        cond_jump(label1,JNE);
                        load_A_reg_into(EAX);
                        mov_rm32_rm32(EAXM,EAX);
                        store_A_reg_from(EAX);
                        jump(label2);
                        add_label(label1);
                        //FIXME error_1_A
                        add_label(label2);
                        load_A_reg_into(EAX);
                        and_imm_rm32(7,EAX);
                        put2bytes(0x85c0);
                        cond_jump(label3,JNE);
                        load_A_reg_into(EAX);
                        mov_rm32_rm32_disp(EAXM,EAX,1);
                        store_A_reg_from(EAX);
                        jump(label4);
                        add_label(label3);
                        //FIXME error_1_A
                        add_label(label4);
                        continue;

                case OP_CDDR:
                        make_label(label1,"CDDR",1);
                        make_label(label2,"CDDR",2);
                        make_label(label3,"CDDR",3);
                        make_label(label4,"CDDR",4);
                        load_A_reg_into(EAX);
                        and_imm_rm32(0x7,EAX);
                        put2bytes(0x85c0);//test eax, eax
                        cond_jump(label1,JNE);
                        load_A_reg_into(EBX);
                        mov_rm32_rm32_disp(EBXM,EBX,1);//mov 4(ebx),ebx
                        store_A_reg_from(EBX);
                        jump(label2);
                        add_label(label1);
                        /*FIXME add error_1_A stuff */
                        add_label(label2);
                        load_A_reg_into(EAX);
                        and_imm_rm32(0x7,EAX);
                        put2bytes(0x85c0);//test eax, eax
                        cond_jump(label3,JNE);
                        load_A_reg_into(EBX);
                        mov_rm32_rm32_disp(EBXM,EBX,1);//mov 4(ebx),ebx
                        store_A_reg_from(EBX);
                        jump(label4);
                        add_label(label3);
                        //FIXME add error_1_A
                        add_label(label4); //END
                        continue;

                case OP_JUMPL0NIL:
                        load_stack_into(EAX);
                        mov_rm32_rm32(EAXM,EAX);
                        cmp_rm32_rm32_disp(EBPM,EAX,-1);
                        make_bc_label();
                        cond_jump(label,JE);
                        next_byte;
                        bytecodes++;
                        continue;

                case OP_JUMPL0T:
                        load_stack_into(EAX);
                        mov_rm32_rm32(EAXM,EAX);
                        cmp_rm32_rm32_disp(EBPM,EAX,-1);
                        make_bc_label();
                        cond_jump(label,JNE);
                        next_byte;
                        bytecodes++;
                        continue;

                case OP_JUMPL1NIL:
                        load_stack_into(EAX);
                        sub_imm32_rm32(0x4,EAX);
                        mov_rm32_rm32(EAXM,EAX);
                        cmp_rm32_rm32_disp(EBPM,EAX,-1);
                        make_bc_label();
                        cond_jump(label,JE);
                        next_byte;
                        bytecodes++;
                        continue;

                case OP_JUMPL1T:
                        load_stack_into(EAX);
                        sub_imm32_rm32(0x4,EAX);
                        mov_rm32_rm32(EAXM,EAX);
                        cmp_rm32_rm32_disp(EBPM,EAX,-1);
                        make_bc_label();
                        cond_jump(label,JNE);
                        next_byte;
                        bytecodes++;
                        continue;

                case OP_JUMPL2NIL:
                        load_stack_into(EAX);
                        sub_imm32_rm32(0x8,EAX);
                        mov_rm32_rm32(EAXM,EAX);
                        cmp_rm32_rm32_disp(EBPM,EAX,-1);
                        make_bc_label();
                        cond_jump(label,JE);
                        next_byte;
                        bytecodes++;
                        continue;

                case OP_JUMPL2T:
                        load_stack_into(EAX);
                        sub_imm32_rm32(0x8,EAX);
                        mov_rm32_rm32(EAXM,EAX);
                        cmp_rm32_rm32_disp(EBPM,EAX,-1);
                        make_bc_label();
                        cond_jump(label,JNE);
                        next_byte;
                        bytecodes++;
                        continue;

                case OP_JUMPL3NIL:
                        load_stack_into(EAX);
                        sub_imm32_rm32(0xc,EAX);
                        mov_rm32_rm32(EAXM,EAX);
                        cmp_rm32_rm32_disp(EBPM,EAX,-1);
                        make_bc_label();
                        cond_jump(label,JE);
                        next_byte;
                        bytecodes++;
                        continue;

                case OP_JUMPL3T:
                        load_stack_into(EAX);
                        sub_imm32_rm32(0xc,EAX);
                        mov_rm32_rm32(EAXM,EAX);
                        cmp_rm32_rm32_disp(EBPM,EAX,-1);
                        make_bc_label();
                        cond_jump(label,JNE);
                        next_byte;
                        bytecodes++;
                        continue;

                case OP_JUMPL4NIL:
                        load_stack_into(EAX);
                        sub_imm32_rm32(0x10,EAX);
                        mov_rm32_rm32(EAXM,EAX);
                        cmp_rm32_rm32_disp(EBPM,EAX,-1);
                        make_bc_label();
                        cond_jump(label,JE);
                        next_byte;
                        bytecodes++;
                        continue;

                case OP_JUMPL4T:
                        load_stack_into(EAX);
                        sub_imm32_rm32(0x10,EAX);
                        mov_rm32_rm32(EAXM,EAX);
                        cmp_rm32_rm32_disp(EBPM,EAX,-1);
                        make_bc_label();
                        cond_jump(label,JNE);
                        next_byte;
                        bytecodes++;
                        continue;

                case OP_JUMPL0ATOM:
                        load_stack_into(EAX);
                        mov_rm32_rm32(EAXM,EAX);
                        and_imm_rm32(0x7,EAX);
                        put2bytes(0x85c0);//test eax, eax
                        make_bc_label();
                        cond_jump(label,JNE);
                        next_byte;
                        bytecodes++;
                        continue;

                case OP_JUMPL0NATOM:
                        load_stack_into(EAX);
                        mov_rm32_rm32(EAXM,EAX);
                        and_imm_rm32(0x7,EAX);
                        put2bytes(0x85c0);//test eax, eax
                        make_bc_label();
                        cond_jump(label,JE);
                        next_byte;
                        bytecodes++;
                        continue;

                case OP_JUMPL1ATOM:
                        load_stack_into(EAX);
                        sub_imm32_rm32(0x4,EAX);
                        mov_rm32_rm32(EAXM,EAX);
                        and_imm_rm32(0x7,EAX);
                        put2bytes(0x85c0);//test eax, eax
                        make_bc_label();
                        cond_jump(label,JNE);
                        next_byte;
                        bytecodes++;
                        continue;

                case OP_JUMPL1NATOM:
                        load_stack_into(EAX);
                        sub_imm32_rm32(0x4,EAX);
                        mov_rm32_rm32(EAXM,EAX);
                        and_imm_rm32(0x7,EAX);
                        put2bytes(0x85c0);//test eax, eax
                        make_bc_label();
                        cond_jump(label,JE);
                        next_byte;
                        bytecodes++;
                        continue;

                case OP_JUMPL2ATOM:
                        load_stack_into(EAX);
                        sub_imm32_rm32(0x8,EAX);
                        mov_rm32_rm32(EAXM,EAX);
                        and_imm_rm32(0x7,EAX);
                        put2bytes(0x85c0);//test eax, eax
                        make_bc_label();
                        cond_jump(label,JNE);
                        next_byte;
                        bytecodes++;
                        continue;

                case OP_JUMPL2NATOM:
                        load_stack_into(EAX);
                        sub_imm32_rm32(0x8,EAX);
                        mov_rm32_rm32(EAXM,EAX);
                        and_imm_rm32(0x7,EAX);
                        put2bytes(0x85c0);//test eax, eax
                        make_bc_label();
                        cond_jump(label,JE);
                        next_byte;
                        bytecodes++;
                        continue;

                case OP_JUMPL3ATOM:
                        load_stack_into(EAX);
                        sub_imm32_rm32(0xc,EAX);
                        mov_rm32_rm32(EAXM,EAX);
                        and_imm_rm32(0x7,EAX);
                        put2bytes(0x85c0);//test eax, eax
                        make_bc_label();
                        cond_jump(label,JNE);
                        next_byte;
                        bytecodes++;
                        continue;

                case OP_JUMPL3NATOM:
                        load_stack_into(EAX);
                        sub_imm32_rm32(0xc,EAX);
                        mov_rm32_rm32(EAXM,EAX);
                        and_imm_rm32(0x7,EAX);
                        put2bytes(0x85c0);//test eax, eax
                        make_bc_label();
                        cond_jump(label,JE);
                        next_byte;
                        bytecodes++;
                        continue;

                case OP_JUMPLIT1EQ:
                        load_litvec_into(EAX);
                        //mov_rm32_rm32(EAXM,EAX);
                        add_imm32_rm32(0x2,EAX);
                        load_A_reg_into(EBX);
                        cmp_rm32_rm32(EBX,EAXM);
                        make_bc_label();
                        cond_jump(label,JE);
                        next_byte;
                        bytecodes++;
                        continue;

                case OP_JUMPLIT1NE:
                        load_litvec_into(EAX);
                        //mov_rm32_rm32(EAXM,EAX);
                        add_imm32_rm32(0x2,EAX);
                        load_A_reg_into(EBX);
                        cmp_rm32_rm32(EBX,EAXM);
                        make_bc_label();
                        cond_jump(label,JNE);
                        next_byte;
                        bytecodes++;
                        continue;

                case OP_JUMPLIT2EQ:
                        load_litvec_into(EAX);
                        //mov_rm32_rm32(EAXM,EAX);
                        add_imm32_rm32(0x6,EAX);
                        load_A_reg_into(EBX);
                        cmp_rm32_rm32(EBX,EAXM);
                        make_bc_label();
                        cond_jump(label,JE);
                        next_byte;
                        bytecodes++;
                        continue;

                case OP_JUMPLIT2NE:
                        load_litvec_into(EAX);
                        //mov_rm32_rm32(EAXM,EAX);
                        add_imm32_rm32(0x6,EAX);
                        load_A_reg_into(EBX);
                        cmp_rm32_rm32(EBX,EAXM);
                        make_bc_label();
                        cond_jump(label,JNE);
                        next_byte;
                        bytecodes++;
                        continue;

                case OP_JUMPLIT3EQ:
                        load_litvec_into(EAX);
                        //mov_rm32_rm32(EAXM,EAX);
                        add_imm32_rm32(0xa,EAX);
                        load_A_reg_into(EBX);
                        cmp_rm32_rm32(EBX,EAXM);
                        make_bc_label();
                        cond_jump(label,JE);
                        next_byte;
                        bytecodes++;
                        continue;

                case OP_JUMPLIT3NE:
                        load_litvec_into(EAX);
                        //mov_rm32_rm32(EAXM,EAX);
                        add_imm32_rm32(0xa,EAX);
                        load_A_reg_into(EBX);
                        cmp_rm32_rm32(EBX,EAXM);
                        make_bc_label();
                        cond_jump(label,JNE);
                        next_byte;
                        bytecodes++;
                        continue;

                case OP_JUMPLIT4EQ:
                        load_litvec_into(EAX);
                        //mov_rm32_rm32(EAXM,EAX);
                        add_imm32_rm32(0xe,EAX);
                        load_A_reg_into(EBX);
                        cmp_rm32_rm32(EBX,EAXM);
                        make_bc_label();
                        cond_jump(label,JE);
                        next_byte;
                        bytecodes++;
                        continue;

                case OP_JUMPLIT4NE:
                        load_litvec_into(EAX);
                        //mov_rm32_rm32(EAXM,EAX);
                        add_imm32_rm32(0xe,EAX);
                        load_A_reg_into(EBX);
                        cmp_rm32_rm32(EBX,EAXM);
                        make_bc_label();
                        cond_jump(label,JNE);
                        next_byte;
                        bytecodes++;
                        continue;
/*
                case OP_JUMPLITEQ:
                        load_litvec_into(EAX);
                        //mov_rm32_rm32(EAXM,EAX);
                        add_rm32_rm32(EBXM,EAX);
                        sub_imm32_rm32(0x2,EAX);
                        load_A_reg_into(EBX);
                        cmp_rm32_rm32(EBX,EAXM);
                        make_bc_label();
                        cond_jump(label,JE);
                        next_byte;
                        bytecodes++;
                        continue;

                case OP_JUMPLITNE:
                        load_litvec_into(EAX);
                        //mov_rm32_rm32(EAXM,EAX);
                        add_imm32_rm32(0x2,EAX);
                        load_A_reg_into(EBX);
                        cmp_rm32_rm32(EBX,EAXM);
                        make_bc_label();
                        cond_jump(label,JNE);
                        next_byte;
                        bytecodes++;
                        continue;
*/
                case OP_JUMPB1NIL:
                        putbyte(0xb8); put_little_endian(*ppc); //mov *ppc, eax
                        next_byte;
                        bytecodes++;
                        put3bytes(0x8b0485);
                        put_addr(&one_arg_functions);//mov two_arg_functions(,%eax,4), %eax
                        mov_rm32_rm32_disp(EAX,EBPM,-6);
                        //save_pc() ?
                        load_stack_into(EAX);
                        mov_r32_addr(EAX,stack);
                        load_A_reg_into(ECX);
                        mov_rm32_rm32_disp(ECX,ESPM,1);
                        load_nil_into(EAX);
                        mov_rm32_rm32(EAX,ESPM);
                        mov_rm32_rm32_disp(EBPM,EAX,-6);
                        put2bytes(0xffd0); //call *eax
                        mov_rm32_rm32(EAX,ECX);
                        store_A_reg_from(ECX);
                        mov_addr_r32(&C_nil,EAX);
                        store_nil_from(EAX);
                        //exception pending?
                        mov_addr_r32(stack,EAX);
                        store_stack_from(EAX);
                        //restore_pc() ?
                        load_A_reg_into(EAX);
                        cmp_rm32_rm32_disp(EBPM,EAX,-1);
                        make_bc_label();
                        cond_jump(label,JE);
                        next_byte;
                        bytecodes++;
                        continue;
                        
                case OP_JUMPB1T:
                        putbyte(0xb8); put_little_endian(*ppc); //mov *ppc, eax
                        next_byte;
                        bytecodes++;
                        put3bytes(0x8b0485);
                        put_addr(&one_arg_functions);//mov two_arg_functions(,%eax,4), %eax
                        mov_rm32_rm32_disp(EAX,EBPM,-6);
                        //save_pc() ?
                        load_stack_into(EAX);
                        mov_r32_addr(EAX,stack);
                        load_A_reg_into(ECX);
                        mov_rm32_rm32_disp(ECX,ESPM,1);
                        load_nil_into(EAX);
                        mov_rm32_rm32(EAX,ESPM);
                        mov_rm32_rm32_disp(EBPM,EAX,-6);
                        put2bytes(0xffd0); //call *eax
                        mov_rm32_rm32(EAX,ECX);
                        store_A_reg_from(ECX);
                        mov_addr_r32(&C_nil,EAX);
                        store_nil_from(EAX);
                        //exception pending?
                        mov_addr_r32(stack,EAX);
                        store_stack_from(EAX);
                        //restore_pc() ?
                        load_A_reg_into(EAX);
                        cmp_rm32_rm32_disp(EBPM,EAX,-1);
                        make_bc_label();
                        cond_jump(label,JNE);
                        next_byte;
                        bytecodes++;
                        continue;

                case OP_JUMPNATOM:
                        load_A_reg_into(EAX);
                        and_imm_rm32(0x7,EAX);
                        put2bytes(0x85c0);//test eax eax
                        make_bc_label();
                        cond_jump(label,JE);
                        next_byte;
                        bytecodes++;
                        continue;

                case OP_JUMPNE:
                        load_B_reg_into(EDX);
                        load_A_reg_into(ECX);
                        cmp_rm32_rm32(ECX,EDXM);
                        make_bc_label();
                        cond_jump(label,JNE);
                        next_byte; //skip past offset in next bytecode
                        bytecodes++;
                        continue;
/*
                case OP_JUMPEQUAL:
                        load_B_reg_into(EDX);
                        load_A_reg_into(ECX);
                        cmp_rm32_rm32(ECX,EDXM);
                        make_bc_label();
                        cond_jump(label,JE);
                        next_byte;
                        bytecodes++;
                        printf("\nblah\n");
                        continue;
*/        
                case OP_JUMP_B:
                        make_label(label1,"JUMP_B",1);
#ifndef OUT_OF_LINE
                        //FIXME countdown stuff
                        mov_addr_r32(stacklimit,EAX);
                        cmp_rm32_rm32_disp(EAX,EBPM,-2);
                        cond_jump(label1,JB);
                        load_stack_into(EAX);
                        mov_r32_addr(EAX,stack);
                        put4bytes(0xc744240c);put4bytes(0x00000000);//mov 0, 12(esp)
                        put4bytes(0xc7442408);put4bytes(0x02000000);//mov 2, 8(esp)
                        put4bytes(0xc7442404);put4bytes(0x00000000);//mov LC1, 4(esp) FIXME
                        load_A_reg_into(EAX);
                        mov_rm32_rm32(EAX,ESPM);
                        Jcall_abs_fn(reclaim);
                        store_A_reg_from(EAX);
                        mov_addr_r32(&C_nil,EAX);
                        store_nil_from(EAX);
                        //exception
                        mov_addr_r32(stack,EAX);
                        store_stack_from(EAX);
                                                
#else
#endif

                        add_label(label1);
                        make_bc_label_backwards()
                        jump(label);
                        next_byte;
                        bytecodes++;
                        continue;

                case OP_CALL0_0:
                        call0(0);
                        continue;

                case OP_CALL0_1:
                        call0(1);
                        continue;

                case OP_CALL0_2:
                        call0(2);
                        continue;

                case OP_CALL0_3:
                        call0(3);
                        continue;

                case OP_CALL0:
                        call0(*ppc);
                        next_byte;
                        bytecodes++;
                        continue;

                case OP_JCALL:
                        switch((*ppc >> 5) & 0x7) {
                                //case 0: Jcall0(*ppc & 0x1f);
                                //case 1: {
                                //                call1(*ppc & 0x1f);
                                //                break;
                                //        }
                                case 2: {
                                                jcall2(*ppc & 0x1f);
                                                break;
                                        }
                                //case 3: Jcall3(*ppc & 0x1f);
                                //default: Jcalln(*ppc & 0x1f);
                        }
                        next_byte;
                        bytecodes++;
                        continue;

                case OP_JCALLN:
                        /* must next_byte 2x */
                        switch(next_byte) {
                                case 2: {
                                                jcall2(*ppc);
                                                break;
                                        }
                        }
                        next_byte;
                        bytecodes++;
                        bytecodes++;
                        continue;

                case OP_CALL1_0:
                        //FIXME must preserve codevec and litvec for all 0
                        //or not?
                        /*
                         * this fn just gotos call1 like CALL1_1 
                         * instead of being a special case
                         */
                        call1(0);
                        continue;

                case OP_CALL1_1:
                        call1(1);
                        continue;

                case OP_CALL1_2:
                        call1(2);
                        continue;

                case OP_CALL1_3:
                        call1(3);
                        continue;

                case OP_CALL1_4:
                        call1(4);
                        continue;

                case OP_CALL1_5:
                        call1(5);
                        continue;

                case OP_CALL1:
                        call1(*ppc);
                        next_byte;
                        bytecodes++;
                        continue;

                case OP_CALL2_0:
                        /*
                         * this fn just gotos call2 like CALL2_1
                         * instead of being a special case
                         */
                        call2(0);
                        continue;

                case OP_CALL2_1:
                        call2(1);
                        continue;

                case OP_CALL2_2:
                        call2(2);
                        continue;

                case OP_CALL2_3:
                        call2(3);
                        continue;

                case OP_CALL2_4:
                        call2(4);
                        continue;

                case OP_CALL2:
                        call2(*ppc);
                        next_byte;
                        bytecodes++;
                        continue;

                case OP_CALL2R:
                        call2r(*ppc);
                        next_byte;
                        bytecodes++;
                        continue;
                        
                case OP_CALL3:
                        //Jcall_abs_fn(breakpoint);
                        load_litvec_into(EBX);
                        putbyte(0xb8);put_little_endian(*ppc);//mov next_byte, eax
                        //put3bytes(0x0fb600);//movzbl (eax), eax
                        //putbyte(0xb8); put4bytes(0x00000000);
                        put3bytes(0xc1e002);//sall 2, eax
                        put2bytes(0x01d8); //add_rm32_rm32(EBX,EAX);
                        //put2bytes(0x0303);//add_rm32_rm32(EBXM,EAX);//FIXME or 01
                        sub_imm32_rm32(0x2,EAX);
                        mov_rm32_rm32(EAXM,EAX);
                        mov_rm32_rm32_disp(EAX,EBPM,-3);
                        
                        /* extra code to print what you are calling */
                        
                        mov_rm32_rm32_disp(EBPM,EAX,-3);
                        add_imm32_rm32(0x10,EAX);
                        mov_rm32_rm32(EAXM,EAX);
                        mov_rm32_rm32_disp(EAX,EBPM,-8);
                        
                        //save_pc
                        load_stack_into(EAX);
                        mov_rm32_rm32(EAX,EBX);
                        load_stackaddr_into(EAX);
                        sub_imm32_rm32(0x4,EAXM);
                        mov_rm32_rm32(EBXM,EAX);
                        mov_rm32_rm32_disp(EAX,EBPM,-4);
                        load_stack_into(EAX);
                        mov_r32_addr(EAX,stack);
                        //Jcall_abs_fn(breakpoint);
                        //Jcall_abs_fn(push_litvec);
                        load_A_reg_into(EAX);
                        mov_rm32_rm32_disp(EAX,ESPM,4);
                        load_B_reg_into(EAX);
                        mov_rm32_rm32(EAXM,EAX);
                        mov_rm32_rm32_disp(EAX,ESPM,3);
                        mov_rm32_rm32_disp(EBPM,EAX,-4);
                        mov_rm32_rm32_disp(EAX,ESPM,2);
                        put4bytes(0xb8030000);putbyte(0x00); put4bytes(0x89442404);//mov 3, 4(esp)
                        mov_rm32_rm32_disp(EBPM,EAX,-3);
                        add_imm32_rm32(0x4,EAX);
                        mov_rm32_rm32(EAXM,EAX);
                        mov_rm32_rm32(EAX,ESPM);
                        mov_rm32_rm32_disp(EBPM,EAX,-8);
                        //Jpush(1,EDI);
                        put2bytes(0xffd0);//call *eax
                        //Jpop(1,EDI);
                        store_A_reg_from(EAX);
                        mov_addr_r32(&C_nil,EAX);
                        store_nil_from(EAX);
                        //Jcall_abs_fn(pop_litvec);
                        //Jexception_pending();
                        //cond_jump("call_error_exit",JNE);
                        mov_addr_r32(stack,EAX);
                        store_stack_from(EAX);
                        //restore_pc
                        next_byte;
                        bytecodes++;
                        continue;

                case OP_BUILTIN0:
                        putbyte(0xb8); put_little_endian(*ppc); //mov *ppc, eax
                        next_byte;
                        bytecodes++;
                        put3bytes(0x8b0485);
                        put_addr(&zero_arg_functions);//mov two_arg_functions(,%eax,4), %eax
                        mov_rm32_rm32_disp(EAX,EBPM,-8);
                        //save_pc() ?
                        load_stack_into(EAX);
                        mov_r32_addr(EAX,stack);
                        put4bytes(0xc7442404);put4bytes(0x00000000);//mov 0, 4(esp)
                        load_nil_into(EAX);
                        mov_rm32_rm32(EAX,ESPM);
                        mov_rm32_rm32_disp(EBPM,EAX,-8);
                        put2bytes(0xffd0); //call *eax
                        //mov_rm32_rm32(EAX,ECX);
                        store_A_reg_from(EAX);
                        mov_addr_r32(&C_nil,EAX);
                        store_nil_from(EAX);
                        //exception pending? FIXME
                        mov_addr_r32(stack,EAX);
                        store_stack_from(EAX);
                        //restore_pc() ?
                        continue;

                case OP_BUILTIN2R:
                        putbyte(0xb8); put_little_endian(*ppc); //mov *ppc, eax
                        next_byte;
                        bytecodes++;
                        put3bytes(0x8b0485);
                        put_addr(&two_arg_functions);//mov two_arg_functions(,%eax,4), %eax
                        mov_rm32_rm32_disp(EAX,EBPM,-7);
                        //save_pc() ?
                        load_stack_into(EAX);
                        mov_r32_addr(EAX,stack);
                        load_B_reg_into(ECX);
                        mov_rm32_rm32(ECXM,ECX);
                        mov_rm32_rm32_disp(ECX,ESPM,2);
                        load_A_reg_into(EDX);
                        mov_rm32_rm32_disp(EDX,ESPM,1);
                        load_nil_into(EAX);
                        mov_rm32_rm32(EAX,ESPM);
                        mov_rm32_rm32_disp(EBPM,EAX,-7);
                        put2bytes(0xffd0); //call *eax
                        //mov_rm32_rm32(EAX,ECX);
                        store_A_reg_from(EAX);
                        mov_addr_r32(&C_nil,EAX);
                        store_nil_from(EAX);
                        //exception pending? FIXME
                        mov_addr_r32(stack,EAX);
                        store_stack_from(EAX);
                        //restore_pc() ?
                        continue;

                case OP_BUILTIN3:
                        putbyte(0xb8); put_little_endian(*ppc); //mov *ppc, eax
                        next_byte;
                        bytecodes++;
                        put3bytes(0x8b0485);
                        put_addr(&three_arg_functions);//mov two_arg_functions(,%eax,4), %eax
                        mov_rm32_rm32_disp(EAX,EBPM,-8);
                        //save_pc() ?
                        load_stack_into(EAX);
                        mov_r32_addr(EAX,stack);
                        load_A_reg_into(ECX);
                        mov_rm32_rm32_disp(ECX,ESPM,4);
                        load_B_reg_into(EDX);
                        mov_rm32_rm32(EDXM,EDX);
                        mov_rm32_rm32_disp(EDX,ESPM,3);
                        mov_rm32_rm32_disp(EBPM,EAX,-3);
                        mov_rm32_rm32_disp(EAX,ESPM,2);
                        put4bytes(0xc7442403);put4bytes(0x00000000);//mov 0, 4(esp)
                        load_nil_into(EAX);
                        mov_rm32_rm32(EAX,ESPM);
                        mov_rm32_rm32_disp(EBPM,EAX,-8);
                        put2bytes(0xffd0); //call *eax
                        //mov_rm32_rm32(EAX,ECX);
                        store_A_reg_from(EAX);
                        mov_addr_r32(&C_nil,EAX);
                        store_nil_from(EAX);
                        //exception pending? FIXME
                        mov_addr_r32(stack,EAX);
                        store_stack_from(EAX);
                        //restore_pc() ?
                        continue;
/*
                case OP_LOADLOC:
                        load_B_reg_into(EDX);
                        load_A_reg_into(ECX);
                        mov_rm32_rm32(ECX,EDXM);
                        putbyte(0xb8); put_little_endian(*ppc); //mov *ppc, eax
                        continue;
*/                        
                case OP_LOADLOC0:
                        load_B_reg_into(EDX);
                        load_A_reg_into(ECX);
                        mov_rm32_rm32(ECX,EDXM);
                        load_stack_into(ECX);
                        mov_rm32_rm32(ECXM,ECX);
                        store_A_reg_from(ECX);
#ifdef COMMON
#endif
                        continue;
                
                case OP_LOADLOC1:
                        load_B_reg_into(EDX);
                        load_A_reg_into(ECX);
                        mov_rm32_rm32(ECX,EDXM);
                        load_stack_into(ECX);
                        sub_imm32_rm32(0x4,ECX);
                        mov_rm32_rm32(ECXM,ECX);
                        store_A_reg_from(ECX);
#ifdef COMMON
#endif
                        continue;

                case OP_LOADLOC2:
                        load_B_reg_into(EDX);
                        load_A_reg_into(ECX);
                        mov_rm32_rm32(ECX,EDXM);
                        load_stack_into(ECX);
                        sub_imm32_rm32(0x8,ECX);
                        mov_rm32_rm32(ECXM,ECX);
                        store_A_reg_from(ECX);
#ifdef COMMON
#endif
                        continue;

                case OP_LOADLOC3:
                        load_B_reg_into(EDX);
                        load_A_reg_into(ECX);
                        mov_rm32_rm32(ECX,EDXM);
                        load_stack_into(ECX);
                        sub_imm32_rm32(0xc,ECX);
                        mov_rm32_rm32(ECXM,ECX);
                        store_A_reg_from(ECX);
#ifdef COMMON
#endif
                        continue;

                case OP_LOADLOC4:
                        load_B_reg_into(EDX);
                        load_A_reg_into(ECX);
                        mov_rm32_rm32(ECX,EDXM);
                        load_stack_into(ECX);
                        sub_imm32_rm32(0x10,ECX);
                        mov_rm32_rm32(ECXM,ECX);
                        store_A_reg_from(ECX);
#ifdef COMMON
#endif
                        continue;

                case OP_LOADLOC5:
                        load_B_reg_into(EDX);
                        load_A_reg_into(ECX);
                        mov_rm32_rm32(ECX,EDXM);
                        load_stack_into(ECX);
                        sub_imm32_rm32(0x14,ECX);
                        mov_rm32_rm32(ECXM,ECX);
                        store_A_reg_from(ECX);
#ifdef COMMON
#endif
                        continue;

                case OP_LOADLOC6:
                        load_B_reg_into(EDX);
                        load_A_reg_into(ECX);
                        mov_rm32_rm32(ECX,EDXM);
                        load_stack_into(ECX);
                        sub_imm32_rm32(0x18,ECX);
                        mov_rm32_rm32(ECXM,ECX);
                        store_A_reg_from(ECX);
#ifdef COMMON
#endif
                        continue;

                case OP_LOADLOC7:
                        load_B_reg_into(EDX);
                        load_A_reg_into(ECX);
                        mov_rm32_rm32(ECX,EDXM);
                        load_stack_into(ECX);
                        sub_imm32_rm32(0x1c,ECX);
                        mov_rm32_rm32(ECXM,ECX);
                        store_A_reg_from(ECX);
#ifdef COMMON
#endif
                        continue;

                case OP_LOADLOC8:
                        load_B_reg_into(EDX);
                        load_A_reg_into(ECX);
                        mov_rm32_rm32(ECX,EDXM);
                        load_stack_into(ECX);
                        sub_imm32_rm32(0x20,ECX);
                        mov_rm32_rm32(ECXM,ECX);
                        store_A_reg_from(ECX);
#ifdef COMMON
#endif
                        continue;

                case OP_LOADLOC9:
                        load_B_reg_into(EDX);
                        load_A_reg_into(ECX);
                        mov_rm32_rm32(ECX,EDXM);
                        load_stack_into(ECX);
                        sub_imm32_rm32(0x24,ECX);
                        mov_rm32_rm32(ECXM,ECX);
                        store_A_reg_from(ECX);
#ifdef COMMON
#endif
                        continue;

                case OP_LOADLOC10:
                        load_B_reg_into(EDX);
                        load_A_reg_into(ECX);
                        mov_rm32_rm32(ECX,EDXM);
                        load_stack_into(ECX);
                        sub_imm32_rm32(0x28,ECX);
                        mov_rm32_rm32(ECXM,ECX);
                        store_A_reg_from(ECX);
#ifdef COMMON
#endif
                        continue;

                case OP_LOADLOC11:
                        load_B_reg_into(EDX);
                        load_A_reg_into(ECX);
                        mov_rm32_rm32(ECX,EDXM);
                        load_stack_into(ECX);
                        sub_imm32_rm32(0x2c,ECX);
                        mov_rm32_rm32(ECXM,ECX);
                        store_A_reg_from(ECX);
#ifdef COMMON
#endif
                        continue;

                case OP_CAR:
                        make_label(label1,"CAR",1);
                        make_label(label2,"CAR",2);
                        load_A_reg_into(EAX);
                        and_imm_rm32(0x7,EAX);
                        put2bytes(0x85c0);//test eax eax
                        cond_jump(label1,JNE);
                        load_A_reg_into(EAX);
                        mov_rm32_rm32(EAXM,EAX);
                        store_A_reg_from(EAX);
                        jump(label2);
                        add_label(label1);
                        //mov 0 csl FIXME
                        //stack
                        jump("error_1_A");
                        add_label(label2);//end
#ifdef COMMON
#endif
                        continue;
                        
                case OP_CARLOC0:
                        make_label(label1,"CARLOC0",1);
                        load_B_reg_into(EDX);
                        load_A_reg_into(ECX);
                        mov_rm32_rm32(ECX,EDXM);
                        load_stack_into(ECX);
                        mov_rm32_rm32(ECXM,ECX);
                        store_A_reg_from(ECX);
                        load_A_reg_into(ECX);
                        and_imm_rm32(0x7,ECX);
                        put2bytes(0x85c9); //test ecx,ecx
                        cond_jump(label1,JE);
                        //mov $0, CSLerrcode
                        load_stack_into(EAX);
                        mov_r32_addr(EAX,stack);
                        //jmp error_1_A //FIXME
                        add_label(label1);
                        load_A_reg_into(ECX);
                        mov_rm32_rm32(ECXM,ECX);
                        store_A_reg_from(ECX);
#ifdef COMMON
#endif
                        continue;

                case OP_CARLOC1:
                        make_label(label1,"CARLOC1",1);
                        load_B_reg_into(EDX);
                        load_A_reg_into(ECX);
                        mov_rm32_rm32(ECX,EDXM);
                        load_stack_into(ECX);
                        sub_imm32_rm32(0x4,ECX);
                        mov_rm32_rm32(ECXM,ECX);
                        store_A_reg_from(ECX);
                        load_A_reg_into(ECX);
                        and_imm_rm32(0x7,ECX);
                        put2bytes(0x85c9); //test ecx,ecx
                        cond_jump(label1,JE);
                        //mov $0, CSLerrcode
                        load_stack_into(EAX);
                        mov_r32_addr(EAX,stack);
                        //jmp error_1_A //FIXME
                        add_label(label1);
                        load_A_reg_into(ECX);
                        mov_rm32_rm32(ECXM,ECX);
                        store_A_reg_from(ECX);
#ifdef COMMON
#endif
                        continue;

                case OP_CARLOC2:
                        make_label(label1,"CARLOC2",1);
                        load_B_reg_into(EDX);
                        load_A_reg_into(ECX);
                        mov_rm32_rm32(ECX,EDXM);
                        load_stack_into(ECX);
                        sub_imm32_rm32(0x8,ECX);
                        mov_rm32_rm32(ECXM,ECX);
                        store_A_reg_from(ECX);
                        load_A_reg_into(ECX);
                        and_imm_rm32(0x7,ECX);
                        put2bytes(0x85c9); //test ecx,ecx
                        cond_jump(label1,JE);
                        //mov $0, CSLerrcode
                        load_stack_into(EAX);
                        mov_r32_addr(EAX,stack);
                        //jmp error_1_A //FIXME
                        add_label(label1);
                        load_A_reg_into(ECX);
                        mov_rm32_rm32(ECXM,ECX);
                        store_A_reg_from(ECX);
#ifdef COMMON
#endif
                        continue;

                case OP_CARLOC3:
                        make_label(label1,"CARLOC3",1);
                        load_B_reg_into(EDX);
                        load_A_reg_into(ECX);
                        mov_rm32_rm32(ECX,EDXM);
                        load_stack_into(ECX);
                        sub_imm32_rm32(0xc,ECX);
                        mov_rm32_rm32(ECXM,ECX);
                        store_A_reg_from(ECX);
                        load_A_reg_into(ECX);
                        and_imm_rm32(0x7,ECX);
                        put2bytes(0x85c9); //test ecx,ecx
                        cond_jump(label1,JE);
                        //mov $0, CSLerrcode
                        load_stack_into(EAX);
                        mov_r32_addr(EAX,stack);
                        //jmp error_1_A //FIXME
                        add_label(label1);
                        load_A_reg_into(ECX);
                        mov_rm32_rm32(ECXM,ECX);
                        store_A_reg_from(ECX);
#ifdef COMMON
#endif
                        continue;

                case OP_CARLOC4:
                        make_label(label1,"CARLOC4",1);
                        load_B_reg_into(EDX);
                        load_A_reg_into(ECX);
                        mov_rm32_rm32(ECX,EDXM);
                        load_stack_into(ECX);
                        sub_imm32_rm32(0x10,ECX);
                        mov_rm32_rm32(ECXM,ECX);
                        store_A_reg_from(ECX);
                        load_A_reg_into(ECX);
                        and_imm_rm32(0x7,ECX);
                        put2bytes(0x85c9); //test ecx,ecx
                        cond_jump(label1,JE);
                        //mov $0, CSLerrcode
                        load_stack_into(EAX);
                        mov_r32_addr(EAX,stack);
                        //jmp error_1_A //FIXME
                        add_label(label1);
                        load_A_reg_into(ECX);
                        mov_rm32_rm32(ECXM,ECX);
                        store_A_reg_from(ECX);
#ifdef COMMON
#endif
                        continue;

                case OP_CARLOC5:
                        make_label(label1,"CARLOC5",1);
                        load_B_reg_into(EDX);
                        load_A_reg_into(ECX);
                        mov_rm32_rm32(ECX,EDXM);
                        load_stack_into(ECX);
                        sub_imm32_rm32(0x14,ECX);
                        mov_rm32_rm32(ECXM,ECX);
                        store_A_reg_from(ECX);
                        load_A_reg_into(ECX);
                        and_imm_rm32(0x7,ECX);
                        put2bytes(0x85c9); //test ecx,ecx
                        cond_jump(label1,JE);
                        //mov $0, CSLerrcode
                        load_stack_into(EAX);
                        mov_r32_addr(EAX,stack);
                        //jmp error_1_A //FIXME
                        add_label(label1);
                        load_A_reg_into(ECX);
                        mov_rm32_rm32(ECXM,ECX);
                        store_A_reg_from(ECX);
#ifdef COMMON
#endif
                        continue;

                case OP_CARLOC6:
                        make_label(label1,"CARLOC6",1);
                        load_B_reg_into(EDX);
                        load_A_reg_into(ECX);
                        mov_rm32_rm32(ECX,EDXM);
                        load_stack_into(ECX);
                        sub_imm32_rm32(0x18,ECX);
                        mov_rm32_rm32(ECXM,ECX);
                        store_A_reg_from(ECX);
                        load_A_reg_into(ECX);
                        and_imm_rm32(0x7,ECX);
                        put2bytes(0x85c9); //test ecx,ecx
                        cond_jump(label1,JE);
                        //mov $0, CSLerrcode
                        load_stack_into(EAX);
                        mov_r32_addr(EAX,stack);
                        //jmp error_1_A //FIXME
                        add_label(label1);
                        load_A_reg_into(ECX);
                        mov_rm32_rm32(ECXM,ECX);
                        store_A_reg_from(ECX);
#ifdef COMMON
#endif
                        continue;

                case OP_CARLOC7:
                        make_label(label1,"CARLOC7",1);
                        load_B_reg_into(EDX);
                        load_A_reg_into(ECX);
                        mov_rm32_rm32(ECX,EDXM);
                        load_stack_into(ECX);
                        sub_imm32_rm32(0x1c,ECX);
                        mov_rm32_rm32(ECXM,ECX);
                        store_A_reg_from(ECX);
                        load_A_reg_into(ECX);
                        and_imm_rm32(0x7,ECX);
                        put2bytes(0x85c9); //test ecx,ecx
                        cond_jump(label1,JE);
                        //mov $0, CSLerrcode
                        load_stack_into(EAX);
                        mov_r32_addr(EAX,stack);
                        //jmp error_1_A //FIXME
                        add_label(label1);
                        load_A_reg_into(ECX);
                        mov_rm32_rm32(ECXM,ECX);
                        store_A_reg_from(ECX);
#ifdef COMMON
#endif
                        continue;

                case OP_CARLOC8:
                        make_label(label1,"CARLOC8",1);
                        load_B_reg_into(EDX);
                        load_A_reg_into(ECX);
                        mov_rm32_rm32(ECX,EDXM);
                        load_stack_into(ECX);
                        sub_imm32_rm32(0x20,ECX);
                        mov_rm32_rm32(ECXM,ECX);
                        store_A_reg_from(ECX);
                        load_A_reg_into(ECX);
                        and_imm_rm32(0x7,ECX);
                        put2bytes(0x85c9); //test ecx,ecx
                        cond_jump(label1,JE);
                        //mov $0, CSLerrcode
                        load_stack_into(EAX);
                        mov_r32_addr(EAX,stack);
                        //jmp error_1_A //FIXME
                        add_label(label1);
                        load_A_reg_into(ECX);
                        mov_rm32_rm32(ECXM,ECX);
                        store_A_reg_from(ECX);
#ifdef COMMON
#endif
                        continue;

                case OP_CARLOC9:
                        make_label(label1,"CARLOC9",1);
                        load_B_reg_into(EDX);
                        load_A_reg_into(ECX);
                        mov_rm32_rm32(ECX,EDXM);
                        load_stack_into(ECX);
                        sub_imm32_rm32(0x24,ECX);
                        mov_rm32_rm32(ECXM,ECX);
                        store_A_reg_from(ECX);
                        load_A_reg_into(ECX);
                        and_imm_rm32(0x7,ECX);
                        put2bytes(0x85c9); //test ecx,ecx
                        cond_jump(label1,JE);
                        //mov $0, CSLerrcode
                        load_stack_into(EAX);
                        mov_r32_addr(EAX,stack);
                        //jmp error_1_A //FIXME
                        add_label(label1);
                        load_A_reg_into(ECX);
                        mov_rm32_rm32(ECXM,ECX);
                        store_A_reg_from(ECX);
#ifdef COMMON
#endif
                        continue;

                case OP_CARLOC10:
                        make_label(label1,"CARLOC10",1);
                        load_B_reg_into(EDX);
                        load_A_reg_into(ECX);
                        mov_rm32_rm32(ECX,EDXM);
                        load_stack_into(ECX);
                        sub_imm32_rm32(0x28,ECX);
                        mov_rm32_rm32(ECXM,ECX);
                        store_A_reg_from(ECX);
                        load_A_reg_into(ECX);
                        and_imm_rm32(0x7,ECX);
                        put2bytes(0x85c9); //test ecx,ecx
                        cond_jump(label1,JE);
                        //mov $0, CSLerrcode
                        load_stack_into(EAX);
                        mov_r32_addr(EAX,stack);
                        //jmp error_1_A //FIXME
                        add_label(label1);
                        load_A_reg_into(ECX);
                        mov_rm32_rm32(ECXM,ECX);
                        store_A_reg_from(ECX);
#ifdef COMMON
#endif
                        continue;

                case OP_CARLOC11:
                        make_label(label1,"CARLOC11",1);
                        load_B_reg_into(EDX);
                        load_A_reg_into(ECX);
                        mov_rm32_rm32(ECX,EDXM);
                        load_stack_into(ECX);
                        sub_imm32_rm32(0x2c,ECX);
                        mov_rm32_rm32(ECXM,ECX);
                        store_A_reg_from(ECX);
                        load_A_reg_into(ECX);
                        and_imm_rm32(0x7,ECX);
                        put2bytes(0x85c9); //test ecx,ecx
                        cond_jump(label1,JE);
                        //mov $0, CSLerrcode
                        load_stack_into(EAX);
                        mov_r32_addr(EAX,stack);
                        //jmp error_1_A //FIXME
                        add_label(label1);
                        load_A_reg_into(ECX);
                        mov_rm32_rm32(ECXM,ECX);
                        store_A_reg_from(ECX);
#ifdef COMMON
#endif
                        continue;

                case OP_CDR:
                        make_label(label1,"CDR",1);
                        make_label(label2,"CDR",2);
                        load_A_reg_into(EAX);
                        and_imm_rm32(0x7,EAX);
                        put2bytes(0x85c0);//test eax, eax
                        cond_jump(label1,JNE);
                        load_A_reg_into(EAX);
                        mov_rm32_rm32_disp(EAXM,EAX,1);
                        store_A_reg_from(EAX);
                        jump(label2);
                        add_label(label1);
                        //mov 1, csler
                        //stack
                        jump("error_1_A");//FIXME
                        add_label(label2);//end

#ifdef COMMON
#endif
                        continue;
                        
                case OP_STORELOC0:
                        load_stack_into(EAX);
                        load_A_reg_into(ECX);
                        mov_rm32_rm32(ECX,EAXM);
                        continue;

                case OP_STORELOC1:
                        load_stack_into(EAX);
                        sub_imm32_rm32(0x4,EAX);
                        load_A_reg_into(ECX);
                        mov_rm32_rm32(ECX,EAXM);
                        continue;

                case OP_STORELOC2:
                        load_stack_into(EAX);
                        sub_imm32_rm32(0x8,EAX);
                        load_A_reg_into(ECX);
                        mov_rm32_rm32(ECX,EAXM);
                        continue;

                case OP_STORELOC3:
                        load_stack_into(EAX);
                        sub_imm32_rm32(0xc,EAX);
                        load_A_reg_into(ECX);
                        mov_rm32_rm32(ECX,EAXM);
                        continue;

                case OP_STORELOC4:
                        load_stack_into(EAX);
                        sub_imm32_rm32(0x10,EAX);
                        load_A_reg_into(ECX);
                        mov_rm32_rm32(ECX,EAXM);
                        continue;

                case OP_STORELOC5:
                        load_stack_into(EAX);
                        sub_imm32_rm32(0x14,EAX);
                        load_A_reg_into(ECX);
                        mov_rm32_rm32(ECX,EAXM);
                        continue;

                case OP_STORELOC6:
                        load_stack_into(EAX);
                        sub_imm32_rm32(0x18,EAX);
                        load_A_reg_into(ECX);
                        mov_rm32_rm32(ECX,EAXM);
                        continue;

                case OP_STORELOC7:
                        load_stack_into(EAX);
                        sub_imm32_rm32(0x1c,EAX);
                        load_A_reg_into(ECX);
                        mov_rm32_rm32(ECX,EAXM);
                        continue;
                
                case OP_LOADLIT:
                        load_B_reg_into(EDX);
                        load_A_reg_into(ECX);
                        mov_rm32_rm32(ECX,EDXM);
                        load_litvec_into(EBX);
                        putbyte(0xb8); put_little_endian(*ppc); //ppc in eax
                        put3bytes(0xc1e002);//sall 2, eax
                        //put2bytes(0x0303);//add (ebx), eax FIXME not sure
                        put2bytes(0x01d8);
                        sub_imm32_rm32(0x2,EAX);
                        mov_rm32_rm32(EAXM,ECX);
                        store_A_reg_from(ECX);
                        next_byte;
                        bytecodes++;
#ifdef COMMON
#endif
                        continue;
                        
                case OP_LOADLIT1:
                        load_B_reg_into(EDX);
                        load_A_reg_into(ECX);
                        mov_rm32_rm32(ECX,EDXM);
                        load_litvec_into(ECX);
                        //mov_rm32_rm32(ECXM,ECX);
                        add_imm32_rm32(0x2,ECX);
                        mov_rm32_rm32(ECXM,ECX);
                        store_A_reg_from(ECX);
#ifdef COMMON
#endif
                        continue;

                case OP_LOADLIT2:
                        load_B_reg_into(EDX);
                        load_A_reg_into(ECX);
                        mov_rm32_rm32(ECX,EDXM);
                        load_litvec_into(ECX);
                        //mov_rm32_rm32(ECXM,ECX);
                        add_imm32_rm32(0x6,ECX);
                        mov_rm32_rm32(ECXM,ECX);
                        store_A_reg_from(ECX);
#ifdef COMMON
#endif
                        continue;

                case OP_LOADLIT3:
                        load_B_reg_into(EDX);
                        load_A_reg_into(ECX);
                        mov_rm32_rm32(ECX,EDXM);
                        load_litvec_into(ECX);
                        //mov_rm32_rm32(ECXM,ECX);
                        add_imm32_rm32(0xa,ECX);
                        mov_rm32_rm32(ECXM,ECX);
                        store_A_reg_from(ECX);
#ifdef COMMON
#endif
                        continue;

                case OP_LOADLIT4:
                        load_B_reg_into(EDX);
                        load_A_reg_into(ECX);
                        mov_rm32_rm32(ECX,EDXM);
                        load_litvec_into(ECX);
                        //mov_rm32_rm32(ECXM,ECX);
                        add_imm32_rm32(0xe,ECX);
                        mov_rm32_rm32(ECXM,ECX);
                        store_A_reg_from(ECX);
#ifdef COMMON
#endif
                        continue;

                case OP_LOADLIT5:
                        load_B_reg_into(EDX);
                        load_A_reg_into(ECX);
                        mov_rm32_rm32(ECX,EDXM);
                        load_litvec_into(ECX);
                        //mov_rm32_rm32(ECXM,ECX);
                        add_imm32_rm32(0x12,ECX);
                        mov_rm32_rm32(ECXM,ECX);
                        store_A_reg_from(ECX);
#ifdef COMMON
#endif
                        continue;
                
                case OP_LOADLIT6:
                        load_B_reg_into(EDX);
                        load_A_reg_into(ECX);
                        mov_rm32_rm32(ECX,EDXM);
                        load_litvec_into(ECX);
                        //mov_rm32_rm32(ECXM,ECX);
                        add_imm32_rm32(0x16,ECX);
                        mov_rm32_rm32(ECXM,ECX);
                        store_A_reg_from(ECX);
#ifdef COMMON
#endif
                        continue;

                case OP_LOADLIT7:
                        load_B_reg_into(EDX);
                        load_A_reg_into(ECX);
                        mov_rm32_rm32(ECX,EDXM);
                        load_litvec_into(ECX);
                        //mov_rm32_rm32(ECXM,ECX);
                        add_imm32_rm32(0x1a,ECX);
                        mov_rm32_rm32(ECXM,ECX);
                        store_A_reg_from(ECX);
#ifdef COMMON
#endif
                        continue;

                case OP_LOADFREE:
                        load_B_reg_into(EAX);
                        load_A_reg_into(EBX);
                        mov_rm32_rm32(EBX,EAXM);
                        load_litvec_into(EBX);
                        putbyte(0xb8); put_little_endian(*ppc);
                        put3bytes(0xc1e002);//sall 2, eax
                        put2bytes(0x01d8);//add_rm32_rm32(EBX,EAX);
                        sub_imm32_rm32(2,EAX);
                        mov_rm32_rm32(EAXM,EAX);
                        mov_rm32_rm32(EAXM,EAX);
                        store_A_reg_from(EAX);
                        next_byte;
                        bytecodes++;
#ifdef COMMON
#endif
                        continue;

                case OP_LOADFREE1:
                        load_B_reg_into(EAX);
                        load_A_reg_into(EBX);
                        mov_rm32_rm32(EBX,EAXM);
                        load_litvec_into(EAX);
                        //mov_rm32_rm32(EAXM,EAX);
                        add_imm32_rm32(0x2,EAX);
                        mov_rm32_rm32(EAXM,EAX);
                        mov_rm32_rm32(EAXM,EAX);
                        store_A_reg_from(EAX);
#ifdef COMMON
#endif
                        continue;

                case OP_LOADFREE2:
                        load_B_reg_into(EAX);
                        load_A_reg_into(EBX);
                        mov_rm32_rm32(EBX,EAXM);
                        load_litvec_into(EAX);
                        //mov_rm32_rm32(EAXM,EAX);
                        add_imm32_rm32(0x6,EAX);
                        mov_rm32_rm32(EAXM,EAX);
                        mov_rm32_rm32(EAXM,EAX);
                        store_A_reg_from(EAX);
#ifdef COMMON
#endif
                        continue;

                case OP_LOADFREE3:
                        load_B_reg_into(EAX);
                        load_A_reg_into(EBX);
                        mov_rm32_rm32(EBX,EAXM);
                        load_litvec_into(EAX);
                        //mov_rm32_rm32(EAXM,EAX);
                        add_imm32_rm32(10,EAX);
                        mov_rm32_rm32(EAXM,EAX);
                        mov_rm32_rm32(EAXM,EAX);
                        store_A_reg_from(EAX);
#ifdef COMMON
#endif
                        continue;

                case OP_LOADFREE4:
                        load_B_reg_into(EAX);
                        load_A_reg_into(EBX);
                        mov_rm32_rm32(EBX,EAXM);
                        load_litvec_into(EAX);
                        //mov_rm32_rm32(EAXM,EAX);
                        add_imm32_rm32(14,EAX);
                        mov_rm32_rm32(EAXM,EAX);
                        mov_rm32_rm32(EAXM,EAX);
                        store_A_reg_from(EAX);
#ifdef COMMON
#endif
                        continue;

                case OP_JUMPNIL:
                        load_A_reg_into(EAX);
                        cmp_rm32_rm32_disp(EBPM,EAX,-1);
                        make_bc_label();
                        cond_jump(label,JE);
                        next_byte;
                        bytecodes++;
                        continue;
                        
                case OP_JUMPT:
                        load_A_reg_into(EAX);
                        cmp_rm32_rm32_disp(EBPM,EAX,-1);
                        make_bc_label();
                        cond_jump(label,JNE);
                        next_byte;
                        bytecodes++;
                        continue;

                case OP_BUILTIN1:
                        putbyte(0xb8); put_little_endian(*ppc); //mov *ppc, eax
                        next_byte;
                        bytecodes++;
                        put3bytes(0x8b0485);
                        put_addr(&one_arg_functions);//mov two_arg_functions(,%eax,4), %eax
                        mov_rm32_rm32_disp(EAX,EBPM,-7);
                        //save_pc() ?
                        load_stack_into(EAX);
                        mov_r32_addr(EAX,stack);
                        load_A_reg_into(ECX);
                        mov_rm32_rm32_disp(ECX,ESPM,1);
                        load_nil_into(EAX);
                        mov_rm32_rm32(EAX,ESPM);
                        mov_rm32_rm32_disp(EBPM,EAX,-7);
                        put2bytes(0xffd0); //call *eax
                        mov_rm32_rm32(EAX,ECX);
                        store_A_reg_from(ECX);
                        mov_addr_r32(&C_nil,EAX);
                        store_nil_from(EAX);
                        //exception pending? FIXME
                        mov_addr_r32(stack,EAX);
                        store_stack_from(EAX);
                        //restore_pc() ?
                        continue;

                case OP_BUILTIN2:
                        putbyte(0xb8); put_little_endian(*ppc); //mov *ppc, eax
                        next_byte;
                        bytecodes++;
                        put3bytes(0x8b0485);
                        put_addr(&two_arg_functions);//mov two_arg_functions(,%eax,4), %eax
                        mov_rm32_rm32_disp(EAX,EBPM,-7);
                        //save_pc() ?
                        load_stack_into(EAX);
                        mov_r32_addr(EAX,stack);
                        load_A_reg_into(ECX);
                        mov_rm32_rm32_disp(ECX,ESPM,2);
                        load_B_reg_into(EDX);
                        mov_rm32_rm32(EDXM,EDX);
                        mov_rm32_rm32_disp(EDX,ESPM,1);
                        load_nil_into(EAX);
                        mov_rm32_rm32(EAX,ESPM);
                        mov_rm32_rm32_disp(EBPM,EAX,-7);
                        put2bytes(0xffd0); //call *eax
                        mov_rm32_rm32(EAX,ECX);
                        store_A_reg_from(ECX);
                        mov_addr_r32(&C_nil,EAX);
                        store_nil_from(EAX);
                        //exception pending? FIXME
                        mov_addr_r32(stack,EAX);
                        store_stack_from(EAX);
                        //restore_pc() ?
                        continue;
                
                case OP_EXIT:
                        load_entry_stack_into(EAX);
                        mov_r32_addr(EAX,stack);
                        load_A_reg_into(EAX);
                        //store_result_from(ECX);
                        exit_bytecode();
                        continue;

                case OP_PUSH:
                        load_stackaddr_into(EAX);
                        add_imm32_rm32(0x4,EAXM);
                        load_stack_into(EAX);
                        load_A_reg_into(EBX);
                        mov_rm32_rm32(EBX,EAXM);

                        //load_stack_into(EAX);
                        //add_imm32_rm32(0x4,EAXM);
                        continue;

                case OP_PUSHNIL:
                        load_stackaddr_into(EAX);
                        add_imm32_rm32(0x4,EAXM);
                        load_stack_into(EBX);
                        load_nil_into(EAX);
                        mov_rm32_rm32(EAX,EBXM);
                        continue;

                case OP_PUSHNIL2:
                        /*
                        load_stack_into(EAX);
                        mov_rm32_rm32(EAX,ESPM);
                        Jcall_abs_fn(Jprint3);
                        Jcall_abs_fn(breakpoint);
                        */
                        load_stack_into(EAX);
                        add_imm32_rm32(0x4,EAX);
                        load_nil_into(EBX);
                        mov_rm32_rm32(EBX,EAXM);
                        load_stack_into(EAX);
                        add_imm32_rm32(0x8,EAX);
                        load_nil_into(EBX);
                        mov_rm32_rm32(EBX,EAXM);
                        load_stackaddr_into(EAX);
                        add_imm32_rm32(0x8,EAXM);
                        
                        //load_stack_into(EAX);
                        //add_imm32_rm32(0x8,EAXM);
                        /*
                        load_stack_into(EAX);
                        mov_rm32_rm32(EAX,ESPM);
                        Jcall_abs_fn(Jprint3);
                        Jcall_abs_fn(breakpoint);
                        */
                        continue;

                case OP_PUSHNIL3:
                        load_stack_into(EAX);
                        add_imm32_rm32(0x4,EAX);
                        load_nil_into(EBX);
                        mov_rm32_rm32(EBX,EAXM);
                        load_stack_into(EAX);
                        add_imm32_rm32(0x8,EAX);
                        load_nil_into(EBX);
                        mov_rm32_rm32(EBX,EAXM);
                        load_stack_into(EAX);
                        add_imm32_rm32(0xc,EAX);
                        load_nil_into(EBX);
                        mov_rm32_rm32(EBX,EAXM);
                        lea_m32_r32_disp(EBPM,EAX,-3);
                        add_imm32_rm32(0xc,EAXM);
                        continue;

                case OP_POP:
                        load_B_reg_into(EAX);
                        load_A_reg_into(EBX);
                        mov_rm32_rm32(EBX,EAXM);
                        load_stack_into(EAX);
                        mov_rm32_rm32(EAX,EBX);
                        load_stackaddr_into(EAX);
                        sub_imm32_rm32(0x4,EAXM);
                        mov_rm32_rm32(EBXM,EBX);
                        store_A_reg_from(EBX);
#ifdef COMMON
#endif
                        continue;

                case OP_LOSE:
                        load_stackaddr_into(EAX);
                        sub_imm32_rm32(0x4,EAXM);
                        continue;

                case OP_LOSE2:
                        load_stackaddr_into(EAX);
                        sub_imm32_rm32(0x8,EAXM);
                        continue;

                case OP_LOSE3:
                        load_stackaddr_into(EAX);
                        sub_imm32_rm32(12,EAXM);
                        continue;

                case OP_LOSES:
                        putbyte(0xb8);put_little_endian(*ppc);
                        put4bytes(0x8d148500); put3bytes(0x000000);//leal 0(,%eax,4), %edx
                        //FIXME is above lea necessary?
                        load_stackaddr_into(EBX);
                        sub_imm32_rm32(EDX,EBXM);
                        next_byte;
                        bytecodes++;
                        continue;

                case OP_CONS:
#ifndef OUT_OF_LINE
                        make_label(label1,"CONS",1);
                        make_label(label2,"CONS",2);
                        load_fringe_into(EAX);
                        mov_rm32_rm32(EAXM,EAX);
                        sub_imm32_rm32(0x8,EAX);
                        mov_rm32_rm32_disp(EAX,EBPM,-3);
                        load_B_reg_into(EDX);
                        mov_rm32_rm32(EDXM,EDX);
                        mov_rm32_rm32(EDX,EAXM);
                        mov_rm32_rm32_disp(EBPM,EAX,-3);
                        load_A_reg_into(ECX);
                        mov_rm32_rm32_disp(ECX,EAXM,1);
                        load_fringe_into(EBX);
                        mov_rm32_rm32_disp(EBPM,EAX,-3);
                        mov_rm32_rm32(EAX,EBXM);
                        load_heaplimit_into(EAX);
                        mov_rm32_rm32(EAXM,EAX);
                        cmp_rm32_rm32_disp(EAX,EBPM,-3);
                        cond_jump(label1,JA);
                        //save_pc
                        load_stack_into(EAX);
                        mov_r32_addr(EAX,stack);
                        put4bytes(0xb8000000);putbyte(0x00); put4bytes(0x8944240c);//mov 0, 12(esp)
                        put4bytes(0xb8030000);putbyte(0x00); put4bytes(0x89442408);//mov 3, 8(esp)
                        //mov LC34, 4(esp) FIXME for text at end
                        mov_rm32_rm32_disp(EBPM,EAX,-3);
                        mov_rm32_rm32(EAX,ESPM);
                        Jcall_abs_fn(reclaim);
                        store_A_reg_from(EAX);
                        mov_addr_r32(&C_nil,EAX);
                        store_nil_from(EAX);
                        //exception pending?
                        mov_addr_r32(stack,EAX);
                        store_stack_from(EAX);
                        //restore_pc();
                        jump(label2);
                        
                        add_label(label1);
                        mov_rm32_rm32_disp(EBPM,ECX,-3);
                        store_A_reg_from(ECX);
#else
                        //save_pc() ?
                        load_stack_into(EAX);
                        mov_r32_addr(EAX,stack);
                        load_A_reg_into(ECX);
                        mov_rm32_rm32_disp(ECX,ESPM,1);
                        load_B_reg_into(EDX);
                        mov_rm32_rm32(EDXM,EDX);
                        mov_rm32_rm32(EDX,ESPM);
                        Jcall_abs_fn(cons);
                        mov_rm32_rm32(EAX,ECX);
                        store_A_reg_from(ECX);
                        mov_addr_r32(&C_nil,EAX);
                        store_nil_from(EAX);
                        //exception pending?
                        mov_addr_r32(stack,EAX);
                        store_stack_from(EAX);
#endif
#ifdef DEBUG
#endif
#ifdef COMMON
#endif
                        add_label(label2);
                        continue;

               default: printf("Error: cant translate bytecode %s\n",opnames[*(ppc-1)]);
                        return -1;
        }
        }
        return 0;
}

void build_gotos(Lisp_Object def, int nargs)
{
        /* all fns jumped from bytecode_compile so in same frame */
        
        /* call3 */
        
        add_label("call_error_exit");
        
        /* error_1_A */
        add_label("error_1_A");
        Jcall_abs_fn(test);
#ifdef BUILDGOTOSDONE
        load_stack_into(EAX);
        mov_r32_addr(EAX,stack);
        load_A_reg_into(ECX);
        //mov ecx, 8(esp)
        //mov CSLerrcode, eax
        //mov eax, 4(esp)
        //mov 1, (esp)
        Jcall_abs_fn(error);
        mov_addr_r32(&C_nil, EAX);
        store_nil_from(EAX);
        load_nil_into(EAX);
        //xor 1, eax
        mov_r32_addr(EAX, &C_nil);
        mov_addr_r32(&C_nil, EAX);
        store_nil_from(EAX);
        jump("pop_stack_and_exit");

        /* pop_stack_and_exit */
        add_label("pop_stack_and_exit");
        mov_addr_r32(stack,EAX);
        store_stack_from(EAX);
        load_nil_into(EAX);
        //add_imm_r32(0x64, EAX);
        mov_rm32_rm32(EAXM,EAX);
        //and_imm_r32(0xff, EAX); //FIXME imm32?
        //test eax, eax
        cond_jump("pop_stack_and_exit0", JE);
        //mov LC36, (esp)
        Jcall_abs_fn(err_printf);
        load_litvec_into(EAX);
        //mov_rm32_rm32(EAXM,EAX);
        sub_imm32_rm32(0x2, EAX);
        mov_rm32_rm32(EAXM,EAX);
        mov_rm32_rm32(EAX,ESPM); //FIXME correct x86 code?
        Jcall_abs_fn(loop_print_error);
        //mov LC13, (esp)
        Jcall_abs_fn(err_printf);
        mov_addr_r32(&C_nil, EAX);
        store_nil_from(EAX);
        load_nil_into(EAX);
        //and_imm_r32(0x1, EAX);
        //test eax, eax
        cond_jump("pop_stack_and_exit0", JE);
        load_nil_into(EAX);
        //xor 1, eax
        mov_r32_addr(EAX,&C_nil);//FIXME macro for flipexception
        mov_addr_r32(&C_nil, EAX);
        store_nil_from(EAX);
        add_label("pop_stack_and_exit0");
        //mov 1, 4(esp)
        load_entry_stack_into(EAX);
        //mov eax, (esp)
        Jcall_abs_fn(unwind_stack);
        mov_addr_r32(stack, EAX);
        cmp_rm32_rm32_disp(EBPM,EAX,4);
        cond_jump("pop_stack_and_exit1", JNE);
        //mov 0, -44(ebp)
        jump("pop_stack_and_exit2");
        add_label("pop_stack_and_exit1");
        mov_addr_r32(stack,EAX);
        store_stack_from(EAX);
        load_stackaddr_into(EAX);
        //sub_imm32_rm32(0x8,EAXM); FIXME mem loc
        mov_rm32_rm32_disp(EBPM,EAX,-2);
        add_imm32_rm32(0x8, EAX);
        mov_rm32_rm32(EAXM,EAX);
        mov_rm32_rm32_disp(EAX,EBPM,-3);
        load_stack_into(EAX);
        add_imm32_rm32(0x4,EAX);
        mov_rm32_rm32(EAXM,EAX);
        mov_rm32_rm32_disp(EAX,EBPM,-4);
        load_stack_into(EAX);
        mov_r32_addr(EAX,stack);
        mov_rm32_rm32_disp(EBPM,EAX,-4);
        //sar 4, eax
        mov_rm32_rm32_disp(EAX,EBPM,-11);
        mov_rm32_rm32_disp(EBPM,EAX,-3);
        //cmp 0x3c2 (EAX)
        cond_jump("pop_stack_and_exit2",JNE);
        //5436
        add_label("pop_stack_and_exit2"); //FIXME shouldnt be here
#endif
}

#ifdef X86
void Jdisassemble(char *compiledcode)
{
/*
 * Try to disassemble... This used the "distorm" disassembler,
 * which can handle 32-bit or 64-bit x86 code. It is obviously not
 * relevant for other architectures. In principle much of the rest
 * of the JIT framework could be ported to eg powerpc, sparc, etc, so
 * the test on X86 is limited to just this bit right now. Later on
 * the whole JIT framework will need to sense the architecture in use and
 * only translate in cases where it knows how to. For that it should make
 * a run-time check on linker_type (in machineid.c) rather than trust to
 * a compile-time choice. Perhaps I should do that here...
 */
   {   _DecodedInst *instrout;
        instrout = (_DecodedInst*) malloc(codep*sizeof(_DecodedInst));
        unsigned long icount;
        int i, j, pos, p;
        reloc_table *dislabels = disassembler_labels;
        reloc_table *labels = labels_table;
        reloc_table *calllabels = callers_table;
        reloc_table *jumplabels = jumpers_table;
        //variables_table *varlabels = vars_table;
        char buffer[80];
        i = distorm_decode((unsigned long)compiledcode,
                      (unsigned char *)compiledcode,
                      (unsigned long)codep,
                      Decode32Bits,           /* 32-bit mode */
                      instrout,               /* where the output goes */
                      codep*sizeof(_DecodedInst),                 /* size of output array */
                      &icount);               /* gets amount of output used */
        printf("distorm64 return code = %d, count=%d\n", i, (int)icount);
        fflush(stdout);
        p = 0;
        pos = 0;
        for (i=0; i<icount; i++)
        {   
                buffer[0] = 0;
                unsigned int len = instrout[i].instructionHex.length;
            unsigned char *s = instrout[i].instructionHex.p;
            
            /* Need to do this in case label is in middle of instruction */
            for(j=0; j<instrout[i].size; j++, pos++) {
                    /* Make sure you don't dereference garbage first */
                    /* there can be multiple labels per pos */
                    if(dislabels!=NULL) {
                            while(pos == dislabels->pos) {
                                    printf("===============[ %s ]===============\n",dislabels->label);
                                    if(dislabels->next != NULL) {
                                            dislabels = dislabels->next;
                                    }
                                    else break; //end of list
                            }
                    }
                    /* there can be multiple labels per pos */
                    if(labels!=NULL) {
                            while(pos == labels->pos) {
                                    printf("<%s: >\n",labels->label);
                                    if(labels->next != NULL) {
                                            labels = labels->next;
                                    }
                                    else break;
                            }
                    }
                                                        
                    if(calllabels!=NULL) {
                            if(pos == calllabels->pos) {
                                    sprintf(buffer,"<CALL: %s>\n",calllabels->label);
                                    if(calllabels->next != NULL) calllabels = calllabels->next;
                            }
                    }
                    if(jumplabels!=NULL) {
                            if(pos == jumplabels->pos) {
                                    sprintf(buffer,"<JUMP: %s>\n",jumplabels->label);
                                    if(jumplabels->next != NULL) jumplabels = jumplabels->next;
                            }
                    }
                    
            }
            printf("  %.8x: %-24s", (int)instrout[i].offset, s);
/*
 * The hex version of the instruction will usually be fairly short,
 * so I put it in a 24-char field and wrap after it if it was too
 * long for that.
 */
            if (len > 24) printf("\n%34s", " ");
            printf(" %s %s\n",
                instrout[i].mnemonic.p,
                instrout[i].operands.p);
            fflush(stdout);
            printf("%s",buffer);
            //pos += instrout[i].size;
        }
        printf("disassembly complete\n");
        fflush(stdout);
    }
}
#endif /* X86 */

void print_dis()
{
        reloc_table *labels = labels_table;
        while(labels != NULL)
        {
                printf("%s\t%lu",labels->label,labels->pos);
                labels=labels->next;
        }
}

#ifdef x86arch
char* Jcompile(Lisp_Object def, int nargs)
{
        int compile_ok = 0;
        
        //initialise linkage data
        labels_table = NULL;
        callers_table = NULL;
        jumpers_table = NULL;
        vars_table = NULL;
        disassembler_labels = NULL;
        codebuffer[0] = 0;
        startcode();

add_disassembler_label("START");
        
        //move ebp and esp around for start of function call
        init_stack_pointers();

        //Lisp_Object nil = C_nil
        //add 0x38 to esp
        //put the address of C_nil in -8(%ebp) as a local var
        Jsetup_nil();

        Jpush(6,EAX,EBX,EDX,ECX,ESI,EDI); //preserve state of registers

#ifdef WTF
        Jcall_abs_fn(push_litvec);
        Jcall_abs_fn(push_litvec);
        Jcall_abs_fn(push_litvec);
#endif
#ifdef JDEBUG2
        /*
         * Prints name of function being run for debugging
         * beware! ffname gets clobbered by gc
         */
        char *ffname = &celt(qpname(elt(qcdr(def), 0)), 0);
        CSL_IGNORE(ffname);
        putbyte(0xb8); put_addr(ffname);
        mov_rm32_rm32(EAX,ESPM);
        Jcall_abs_fn(print_ffname);
#endif
        
#ifdef JDEBUG
        //Jcall_abs_fn(breakpoint);
#endif
        
        if(nargs==0) {
                Jcheck_nargs0();
                Jpush_stack(0);
                //Jstackcheck1(0);
        }
        
        if(nargs==1 || nargs==2) {
                //push(litvec, codevec, a) || push(litvec, codevec, a, b)
                Jpush_stack(nargs); //push onto C_stack
                //if (nargs==1) Jstackcheck1(3);
                //else Jstackcheck1(4);
        }
        if(nargs==3) {
                //if (nargs != 3) return error(2, err_wrong_no_args, name_from(def),fixnum_of_int((int32_t)nargs));
                Jcheck_nargs3();
                //Jstackcheck1(3);
        }
        if(nargs!=0 && nargs!=1 && nargs!=2 && nargs!=3) {
                //nargs == n
                Jcheck_nargsn();
                //FIXME stackcheck
        }
        Jstackcheck1(nargs);

        //Jcall_abs_fn(breakpoint);
        
        //prepare for a function call to the bytecoded data
        //compiled bytecodes are stored at the end of codebuffer so we make
        //a call to it from here then link back
        Jprepare_bytecode_compiler(nargs);
        
        //store result from bytestream_interpret(eax) in -4(ebp)
        mov_rm32_rm32_disp(EAX,EBPM,-1); //mov eax, -4(ebp)
        
        //nil = C_nil
        //Jnil_eq_C_nil();
        
        //pop(codevec, litvec)
        Jpop_vecs();
        
        //remove local vars from stack -- DONE IN exit_stack_pointers()
        //strcat(Jcode, "83c428"); //add 0x28, %esp

#ifdef JDEBUG
        //Jcall_abs_fn(breakpoint);
#endif

        Jpop(6,EDI,ESI,ECX,EDX,EBX,EAX);
#ifdef WTF
        Jcall_abs_fn(pop_litvec);
        Jcall_abs_fn(pop_litvec);
        Jcall_abs_fn(pop_litvec);
#endif
        //%eax = result
        Jresult();
        
        exit_stack_pointers();

        if(Jbytecode_compile(def, nargs)==0) {
                compile_ok = 1;
        }

        if(compile_ok == 0) {
                printf("Error - couldn't compile\n");
                return NULL;
        }

        build_gotos(def,nargs);

        //print_dis();
        
        //fix relocation address
        reloc_vars();
        reloc_jumps();
        reloc_calls();

#ifdef X86
        if(compile_ok == 1) Jdisassemble(codebuffer);
#endif
        
        free_labels_table(labels_table);
        free_labels_table(callers_table);
        free_labels_table(jumpers_table);
        free_var_table(vars_table);
        free_labels_table(disassembler_labels);
        
        //printf("\n%s\n",codebuffer);
        printf("JIT COMPILED: %lu bytes\n", codep);
        
        return codebuffer;
}
#endif //x86arch

/* end of jit3.c */
