/* 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 #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; kCELL) { 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> 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; ipos) { 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,"\n",calllabels->label); if(calllabels->next != NULL) calllabels = calllabels->next; } } if(jumplabels!=NULL) { if(pos == jumplabels->pos) { sprintf(buffer,"\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 */