int main() { pifi nfibs; int in; /* offset of the argument */ jit_insn *ref; /* to patch the forward reference */ jit_insn *mref; /* ref of move to backpatch */ jit_insn *tp; /* location to patch */ codeBuffer = mmap(NULL, getpagesize(), PROT_READ | PROT_WRITE | PROT_EXEC, MAP_PRIVATE | MAP_ANON, -1, 0); if (codeBuffer == MAP_FAILED) { perror("mmap"); exit(0); } nfibs = (pifi) (jit_set_ip(codeBuffer).iptr); jit_prolog (1); in = jit_arg_ui (); jit_getarg_ui(JIT_V0, in); /* V0 = n */ mref= jit_movi_p(JIT_V2,jit_forward ()); /* Generate a dumb movi */ jit_jmpr(JIT_V2); /* generate some dump filler that will never be executed!*/ jit_addi_ui(JIT_V0,JIT_V0,1); jit_addi_ui(JIT_V0,JIT_V0,1); jit_addi_ui(JIT_V0,JIT_V0,1); jit_addi_ui(JIT_V0,JIT_V0,1); tp = jit_get_label (); ref = jit_blti_ui (jit_forward(), JIT_V0, 2); jit_subi_ui (JIT_V1, JIT_V0, 1); /* V1 = n-1 */ jit_subi_ui (JIT_V2, JIT_V0, 2); /* V2 = n-2 */ jit_prepare (1); jit_pusharg_ui(JIT_V1); jit_finish(nfibs); jit_retval(JIT_V1); /* V1 = nfibs(n-1) */ jit_prepare(1); jit_pusharg_ui(JIT_V2); jit_finish(nfibs); jit_retval(JIT_V2); /* V2 = nfibs(n-2) */ jit_addi_ui(JIT_V1, JIT_V1, 1); jit_addr_ui(JIT_RET, JIT_V1, JIT_V2); /* RET = V1 + V2 + 1 */ jit_ret(); jit_patch(ref); /* patch jump */ jit_movi_i(JIT_RET, 1); /* RET = 1 */ jit_ret(); jit_patch_movi(mref,tp); /* Ok. Do the back-patching */ /* call the generated code, passing 32 as an argument */ jit_flush_code(codeBuffer, jit_get_ip().ptr); #ifdef LIGHTNING_DISASSEMBLE disassemble(stderr, (char *)codeBuffer, jit_get_ip().ptr); #endif #ifndef LIGHTNING_CROSS printf("nfibs(%d) = %d\n", 32, nfibs(32)); #endif return 0; }
void push_reg(jit_value reg, Frame* frame) { struct jit* jit = frame->jit; jit_op* overflow_jump = jit_bner(frame->jit, (intptr_t) JIT_FORWARD, frame->stack_size, frame->stack_offset); jit_addi(jit, frame->stack_size, frame->stack_size, 10); jit_movr(jit, frame->accum[0], frame->stack_size); jit_muli(jit, frame->accum[0], frame->accum[0], sizeof(YValue*)); jit_prepare(jit); jit_putargr(jit, frame->stack_ptr); jit_putargr(jit, frame->accum[0]); jit_call(jit, realloc); jit_retval(jit, frame->stack_ptr); jit_patch(frame->jit, overflow_jump); jit_muli(jit, frame->accum[ACCUM_COUNT-1], frame->stack_offset, sizeof(YValue*)); jit_stxr(jit, frame->stack_ptr, frame->accum[ACCUM_COUNT-1], reg, sizeof(YValue*)); jit_addi(jit, frame->stack_offset, frame->stack_offset, 1); jit_prepare(jit); jit_putargr(jit, reg); jit_call(jit, inc_linkc); }
static void unwind_exception(jit_int32_t regval, obool_t unsafe) { jit_int32_t frame; jit_int32_t stack; jit_node_t *equal; /* Need to restore and resync thread state */ frame = GPR[FRAME] != JIT_NOREG ? GPR[FRAME] : JIT_R0; stack = GPR[STACK] != JIT_NOREG ? GPR[STACK] : JIT_R0; /* Restore fp */ jit_ldxi(frame, regval, offsetof(oexception_t, fp)); jit_stxi(offsetof(othread_t, fp), JIT_V0, frame); /* Restore sp */ if (unsafe) { /* If throw may be from another vm stack frame, need to * zero memory, or it may later be cast to the wrong object; * the logic is somewhat optimized, to zero memory before * function return instead of function call, but exceptions * break all rules. */ if (GPR[STACK] != JIT_NOREG) { jit_ldxi(GPR[STACK], regval, offsetof(oexception_t, sp)); jit_ldxi(JIT_R1, JIT_V0, offsetof(othread_t, sp)); equal = jit_beqr(GPR[STACK], JIT_R1); jit_subr(JIT_R0, GPR[STACK], JIT_R1); jit_prepare(); jit_pushargr(JIT_R1); jit_pushargi(0); jit_pushargr(JIT_R0); jit_finishi(memset); jit_patch(equal); jit_stxi(offsetof(othread_t, sp), JIT_V0, GPR[STACK]); } else { jit_ldxi(JIT_R0, regval, offsetof(oexception_t, sp)); jit_ldxi(JIT_R1, JIT_V0, offsetof(othread_t, sp)); equal = jit_beqr(JIT_R0, JIT_R1); jit_subr(JIT_R0, JIT_R0, JIT_R1); jit_prepare(); jit_pushargr(JIT_R1); jit_pushargi(0); jit_pushargr(JIT_R0); jit_finishi(memset); jit_ldxi(JIT_R0, regval, offsetof(oexception_t, sp)); jit_patch(equal); jit_stxi(offsetof(othread_t, sp), JIT_V0, JIT_R0); } } else { jit_ldxi(stack, regval, offsetof(oexception_t, sp)); jit_stxi(offsetof(othread_t, sp), JIT_V0, stack); } /* Restore this (if there is a this register) */ if (GPR[THIS] != JIT_NOREG) jit_ldxi(GPR[THIS], regval, offsetof(oexception_t, th)); /* Restore exception frame */ jit_ldxi(JIT_R0, regval, offsetof(oexception_t, ex)); jit_stxi(offsetof(othread_t, ex), JIT_V0, JIT_R0); }
int compile_blit_mono_inv(int retreg, Cell* args) { compile_arg(JIT_R0, car(args), TAG_BYTES); jit_ldr(JIT_R0, JIT_R0); // load bytes addr stack_push(JIT_R0, &stack_ptr); compile_int_arg(); compile_int_arg(); compile_int_arg(); compile_int_arg(); compile_int_arg(); compile_int_arg(); compile_int_arg(); compile_int_arg(); jit_prepare(); push_stack_arg(); push_stack_arg(); push_stack_arg(); push_stack_arg(); push_stack_arg(); push_stack_arg(); push_stack_arg(); push_stack_arg(); push_stack_arg(); // pop bytes addr jit_finishi(blit_vector1_invert); jit_movi(retreg, 0); return 1; }
static int_return_int_t generate_function_proxy (int_return_int_t func) { static jit_insn buffer[1024]; static jit_state _jit; int_return_int_t result; int arg; result = (int_return_int_t)(jit_set_ip (buffer).ptr); jit_prolog (1); arg = jit_arg_i (); jit_getarg_i (JIT_R1, arg); /* Reset `JIT_RET'. */ jit_movi_i (JIT_RET, -1); /* Invoke a FUNC. */ jit_prepare (1); jit_pusharg_i (JIT_R1); (void)jit_finish (func); /* Copy the result of FUNC from `JIT_RET' into our own result register. */ jit_retval_i (JIT_RET); jit_ret (); jit_flush_code (buffer, jit_get_ip ().ptr); return result; }
int scheme_generate_alloc_retry(mz_jit_state *jitter, int i) { GC_CAN_IGNORE jit_insn *refr; #ifdef JIT_USE_FP_OPS if (i == 2) { (void)mz_tl_sti_d_fppop(tl_scheme_jit_save_fp, JIT_FPR1, JIT_R2); } #endif JIT_UPDATE_THREAD_RSPTR(); jit_prepare(2); CHECK_LIMIT(); if (i == 1) { jit_pusharg_p(JIT_R1); jit_pusharg_p(JIT_R0); } else { (void)jit_movi_p(JIT_R0, NULL); jit_pusharg_p(JIT_R0); jit_pusharg_p(JIT_R0); } (void)mz_finish_lwe(ts_prepare_retry_alloc, refr); jit_retval(JIT_R0); if (i == 1) { mz_tl_ldi_l(JIT_R1, tl_retry_alloc_r1); } #ifdef JIT_USE_FP_OPS if (i == 2) { (void)mz_tl_ldi_d_fppush(JIT_FPR1, tl_scheme_jit_save_fp, JIT_R2); } #endif return 1; }
int compile_pixel(int retreg, Cell* args) { Cell* arg_x = car(args); if (!arg_x) return argnum_error("(pixel x y color)"); args = cdr(args); Cell* arg_y = car(args); if (!arg_y) return argnum_error("(pixel x y color)"); args = cdr(args); Cell* arg_c = car(args); if (!arg_c) return argnum_error("(pixel x y color)"); compile_arg(JIT_R0, arg_c, TAG_PURE_INT); stack_push(JIT_R0, &stack_ptr); compile_arg(JIT_R0, arg_y, TAG_PURE_INT); stack_push(JIT_R0, &stack_ptr); compile_arg(JIT_R0, arg_x, TAG_PURE_INT); stack_push(JIT_R0, &stack_ptr); jit_prepare(); stack_pop(JIT_R0, &stack_ptr); jit_pushargr(JIT_R0); stack_pop(JIT_R0, &stack_ptr); jit_pushargr(JIT_R0); stack_pop(JIT_R0, &stack_ptr); jit_pushargr(JIT_R0); jit_finishi(machine_video_set_pixel); jit_movi(retreg, 0); return 1; }
int compile_blit_string(int retreg, Cell* args, int requires) { compile_arg(JIT_R0, car(args), TAG_BYTES); // font stack_push(JIT_R0, &stack_ptr); args = cdr(args); compile_arg(JIT_R0, car(args), TAG_ANY); // string stack_push(JIT_R0, &stack_ptr); compile_int_arg(); compile_int_arg(); compile_int_arg(); compile_int_arg(); compile_int_arg(); compile_int_arg(); jit_prepare(); push_stack_arg(); // color push_stack_arg(); // h push_stack_arg(); // w push_stack_arg(); // y push_stack_arg(); // x push_stack_arg(); // cursor_pos (or -1) push_stack_arg(); // string push_stack_arg(); // font jit_finishi(blit_string1); jit_retval(retreg); box_int(retreg, requires); return 1; }
int compile_flip(int retreg) { jit_prepare(); jit_finishi(machine_video_flip); jit_movi(retreg, 0); return 1; }
static stakumilo_t generate_push_pop (void) { static const char msg[] = "we got %i\n"; stakumilo_t result; int arg; int retval; buffer = mmap(NULL, getpagesize(), PROT_READ | PROT_WRITE | PROT_EXEC, MAP_PRIVATE | MAP_ANON, -1, 0); if (buffer == MAP_FAILED) { perror("mmap"); exit(0); } result = (stakumilo_t)(jit_set_ip (buffer).ptr); jit_prolog (1); arg = jit_arg_i (); jit_getarg_i (JIT_R1, arg); /* Save R1 on the stack. */ jit_pushr_i (JIT_R1); /* Save two other registers just for the sake of using the stack. */ jit_movi_i (JIT_R0, -1); jit_movi_i (JIT_R2, -1); jit_pushr_i (JIT_R0); jit_pushr_i (JIT_R2); /* most likely need stack aligned at 16 bytes, dummy push to force align */ jit_pushr_i (JIT_R2); jit_movr_i (JIT_R0, JIT_R1); jit_movi_p (JIT_R1, msg); /* Invoke a function that may modify R1. */ jit_prepare (2); jit_pusharg_i (JIT_R0); jit_pusharg_p (JIT_R1); (void)jit_finish (display_message); /* dummy pop for the sake of calling function with 16 byte aligned stack */ jit_popr_i (JIT_R2); /* Restore the dummy registers. */ jit_popr_i (JIT_R2); jit_popr_i (JIT_R0); /* Restore R1. */ jit_popr_i (JIT_R1); jit_movr_i (JIT_RET, JIT_R1); jit_ret (); jit_flush_code (buffer, jit_get_ip ().ptr); return result; }
jit_value pop_reg(Frame* frame) { struct jit* jit = frame->jit; jit_movr(jit, frame->accum[0], frame->null_ptr); jit_op* underflow_jump = jit_beqi(jit, (intptr_t) JIT_FORWARD, frame->stack_offset, 0); jit_subi(jit, frame->stack_offset, frame->stack_offset, 1); jit_muli(jit, frame->accum[ACCUM_COUNT-1], frame->stack_offset, sizeof(YValue*)); jit_ldxr(jit, frame->accum[0], frame->stack_ptr, frame->accum[ACCUM_COUNT-1], sizeof(YValue*)); jit_patch(jit, underflow_jump); jit_prepare(jit); jit_putargr(jit, frame->accum[0]); jit_call(jit, dec_linkc); return frame->accum[0]; }
void set_reg(ssize_t r, jit_value v, Frame* frame) { if (r >= 0 && r < frame->stats->ssa_reg_count) { r = frame->stats->ssa_regs[r]->real_reg; jit_op* label = jit_beqi(frame->jit, (intptr_t) JIT_FORWARD, v, 0);; jit_prepare(frame->jit); jit_putargr(frame->jit, frame->regs[r]); jit_putargr(frame->jit, v); jit_call(frame->jit, exchange_values); jit_movr(frame->jit, frame->regs[r], v); jit_patch(frame->jit, label); } }
static stakumilo_t generate_push_pop (void) { static const char msg[] = "we got %i\n"; static char buffer[1024]; stakumilo_t result; int arg; result = (stakumilo_t)(jit_set_ip (buffer).ptr); jit_prolog (1); arg = jit_arg_i (); jit_getarg_i (JIT_R1, arg); /* Save R1 on the stack. */ jit_pushr_i (JIT_R1); /* Save two other registers just for the sake of using the stack. */ jit_movi_i (JIT_R0, -1); jit_movi_i (JIT_R2, -1); jit_pushr_i (JIT_R0); jit_pushr_i (JIT_R2); jit_movr_i (JIT_R0, JIT_R1); jit_movi_p (JIT_R1, msg); /* Invoke a function that may modify R1. */ jit_prepare (2); jit_pusharg_i (JIT_R0); jit_pusharg_p (JIT_R1); (void)jit_finish (display_message); /* Restore the dummy registers. */ jit_popr_i (JIT_R2); jit_popr_i (JIT_R0); /* Restore R1. */ jit_popr_i (JIT_R1); jit_movr_i (JIT_RET, JIT_R1); jit_ret (); jit_flush_code (buffer, jit_get_ip ().ptr); return result; }
bool compile(const Program &program, Translator &trans, Environment &env) { jit_node_t *ref; jit_node_t *fn = jit_note(NULL, 0); jit_prolog(); const int stack_base_offset = jit_allocai(32 * sizeof(double)); int stack_top_idx = 0; auto &&stackPush = [&](int reg) { jit_stxi_d(stack_base_offset + stack_top_idx * sizeof(double), JIT_FP, reg); ++stack_top_idx; }; auto &&stackPop = [&](int reg) { --stack_top_idx; jit_ldxi_d(reg, JIT_FP, stack_base_offset + stack_top_idx * sizeof(double)); return reg; }; size_t pc = 0; const size_t progsz = program.size(); while (pc < progsz) { const Instruction &instr = program[pc]; switch (instr.op) { case OP_NOP: break; case OP_PUSH: stackPush(JIT_F0); jit_movi_d(JIT_F0, instr.dval); break; case OP_ADD: { const int reg = stackPop(JIT_F1); jit_addr_d(JIT_F0, reg, JIT_F0); } break; case OP_SUB: { const int reg = stackPop(JIT_F1); jit_subr_d(JIT_F0, reg, JIT_F0); } break; case OP_MUL: { const int reg = stackPop(JIT_F1); jit_mulr_d(JIT_F0, reg, JIT_F0); } break; case OP_DIV: { const int reg = stackPop(JIT_F1); jit_divr_d(JIT_F0, reg, JIT_F0); } break; case OP_CALL: { stackPush(JIT_F0); const int sp = stack_top_idx - (instr.callop.nargs); jit_addi(JIT_R0, JIT_FP, stack_base_offset + sp * sizeof(double)); jit_prepare(); jit_pushargi((jit_word_t)&env); // 1st arg: userdata jit_pushargi(instr.callop.nargs); // 2nd arg: # of arguments jit_pushargr(JIT_R0); // 3rd arg: pointer to args on stack jit_pushargi((jit_word_t)&error_); // 4th arg: pointer to error message auto &&cb = trans.lookup(instr.callop.fidx); jit_finishi(reinterpret_cast<jit_pointer_t>(cb)); stack_top_idx -= instr.callop.nargs; // consume arguments on stack jit_retval_d(JIT_F0); jit_retval(JIT_R0); ref = jit_bnei(JIT_R0, 0); jit_reti_d(*reinterpret_cast<const double*>(&JIT_ERROR)); jit_patch(ref); } break; } ++pc; } jit_retr_d(JIT_F0); jit_epilog(); (void)jit_emit(); func_ = reinterpret_cast<JitFunction>(jit_address(fn)); return true; }
jit_pointer_t compile(const std::vector<Oper>& ops, jit_word_t *memory, const bool flush = true) { jit_prolog(); jit_movi(JIT_V0, reinterpret_cast<jit_word_t>(memory)); jit_movi(JIT_V1, 0); std::stack<Loop> loops; jit_node_t* start = jit_note(__FILE__, __LINE__); for ( size_t n=0; n<ops.size(); ++n ) { switch ( ops[n].code ) { case '<': jit_str(JIT_V0, JIT_V1); jit_subi(JIT_V0, JIT_V0, ops[n].count * sizeof(jit_word_t)); jit_ldr(JIT_V1, JIT_V0); break; case '>': jit_str(JIT_V0, JIT_V1); jit_addi(JIT_V0, JIT_V0, ops[n].count * sizeof(jit_word_t)); jit_ldr(JIT_V1, JIT_V0); break; case 'z': jit_movi(JIT_V1, 0); break; case '+': jit_addi(JIT_V1, JIT_V1, ops[n].count); break; case '-': jit_subi(JIT_V1, JIT_V1, ops[n].count); break; case '.': jit_prepare(); jit_pushargr(JIT_V1); jit_finishi(reinterpret_cast<jit_pointer_t>(putchar)); if ( flush ) { jit_prepare(); jit_pushargi(reinterpret_cast<jit_word_t>(stdout)); jit_finishi(reinterpret_cast<jit_pointer_t>(fflush)); } break; case ',': jit_prepare(); jit_finishi(reinterpret_cast<jit_pointer_t>(getchar)); jit_retval(JIT_V1); break; case '[': { Loop loop; loop.end = jit_forward(); jit_node_t *j = jit_beqi(JIT_V1, 0); jit_patch_at(j, loop.end); loop.body = jit_label(); loops.push(loop); } break; case ']': { Loop loop = loops.top(); jit_node_t *j = jit_bnei(JIT_V1, 0); jit_patch_at(j, loop.body); jit_link(loop.end); loops.pop(); break; } default: break; } } jit_node_t* stop = jit_note(__FILE__, __LINE__); jit_ret(); jit_epilog(); jit_pointer_t r = jit_emit(); fprintf(stderr, "compiled to %zu bytes\n", (char*)jit_address(stop) - (char*)jit_address(start)); return r; }
void run_gnulightning(void) { struct bfi * n = bfprog; int maxstack = 0, stackptr = 0; char *strbuf = 0; size_t maxstrlen = 0; #ifdef GNULIGHTv1 jit_insn** loopstack = 0; jit_insn *codeBuffer; void * startptr; int argp; #endif #ifdef GNULIGHTv2 jit_node_t *start, *end; /* For size of code */ jit_node_t** loopstack = 0; jit_node_t *argp; #endif if (cell_size == 8) tape_step = 1; else tape_step = sizeof(int); #ifdef GNULIGHTv1 /* TODO: Use mmap for allocating memory, the x86 execute protection * bit is on the segment so Linux has to say thay everything below * a specific address is executable. If you ask mmap for executable * memory it can put it below the current value. The mprotect() * function can't do this. */ if (total_nodes < 4096) codeBuffer = malloc(65536); else codeBuffer = malloc(16 * total_nodes); save_ptr_for_free(codeBuffer); codeptr = (codeptr_t) jit_set_ip(codeBuffer).vptr; startptr = jit_get_ip().ptr; /* Function call prolog */ jit_prolog(1); /* Get the data area pointer */ argp = jit_arg_p(); jit_getarg_p(REG_P, argp); #endif #ifdef GNULIGHTv2 init_jit(NULL); // argv[0]); _jit = jit_new_state(); start = jit_note(__FILE__, __LINE__); jit_prolog(); /* Get the data area pointer */ argp = jit_arg(); jit_getarg(REG_P, argp); #endif while(n) { switch(n->type) { case T_MOV: if (acc_loaded) acc_offset -= n->count; jit_addi(REG_P, REG_P, n->count * tape_step); break; case T_ADD: load_acc_offset(n->offset); set_acc_offset(n->offset); jit_addi(REG_ACC, REG_ACC, n->count); break; case T_SET: set_acc_offset(n->offset); if (acc_const && acc_const_val == n->count) { ; } else if (acc_const && acc_const_val+1 == n->count) { jit_addi(REG_ACC, REG_ACC, 1); } else if (acc_const && acc_const_val-1 == n->count) { jit_addi(REG_ACC, REG_ACC, -1); } else { jit_movi(REG_ACC, n->count); } acc_const = 1; acc_const_val = n->count; break; case T_CALC: if (n->offset == n->offset2 && n->count2 == 1) { load_acc_offset(n->offset); set_acc_offset(n->offset); if (n->count) jit_addi(REG_ACC, REG_ACC, n->count); } else if (n->count2 != 0) { load_acc_offset(n->offset2); set_acc_offset(n->offset); if (n->count2 == -1) jit_negr(REG_ACC, REG_ACC); else if (n->count2 != 1) jit_muli(REG_ACC, REG_ACC, n->count2); if (n->count) jit_addi(REG_ACC, REG_ACC, n->count); } else { clean_acc(); set_acc_offset(n->offset); jit_movi(REG_ACC, n->count); if (n->count2 != 0) { if (tape_step > 1) jit_ldxi_i(REG_A1, REG_P, n->offset2 * tape_step); else jit_ldxi_uc(REG_A1, REG_P, n->offset2); if (n->count2 == -1) jit_negr(REG_A1, REG_A1); else if (n->count2 != 1) jit_muli(REG_A1, REG_A1, n->count2); jit_addr(REG_ACC, REG_ACC, REG_A1); } } if (n->count3 != 0) { if (tape_step > 1) jit_ldxi_i(REG_A1, REG_P, n->offset3 * tape_step); else jit_ldxi_uc(REG_A1, REG_P, n->offset3); if (n->count3 == -1) jit_negr(REG_A1, REG_A1); else if (n->count3 != 1) jit_muli(REG_A1, REG_A1, n->count3); jit_addr(REG_ACC, REG_ACC, REG_A1); } break; case T_IF: case T_MULT: case T_CMULT: case T_WHL: load_acc_offset(n->offset); clean_acc(); acc_const = acc_loaded = 0; if (stackptr >= maxstack) { loopstack = realloc(loopstack, ((maxstack+=32)+2)*sizeof(*loopstack)); if (loopstack == 0) { perror("loop stack realloc failure"); exit(1); } } if (cell_mask > 0 && acc_hi_dirty) { if (cell_mask == 0xFF) jit_extr_uc(REG_ACC,REG_ACC); else jit_andi(REG_ACC, REG_ACC, cell_mask); } #ifdef GNULIGHTv1 loopstack[stackptr] = jit_beqi_i(jit_forward(), REG_ACC, 0); loopstack[stackptr+1] = jit_get_label(); #endif #ifdef GNULIGHTv2 loopstack[stackptr] = jit_beqi(REG_ACC, 0); loopstack[stackptr+1] = jit_label(); #endif stackptr += 2; break; case T_END: load_acc_offset(n->offset); clean_acc(); stackptr -= 2; if (stackptr < 0) { fprintf(stderr, "Code gen failure: Stack pointer negative.\n"); exit(1); } if (cell_mask > 0 && acc_hi_dirty) { if (cell_mask == 0xFF) jit_extr_uc(REG_ACC,REG_ACC); else jit_andi(REG_ACC, REG_ACC, cell_mask); } #ifdef GNULIGHTv1 jit_bnei_i(loopstack[stackptr+1], REG_ACC, 0); jit_patch(loopstack[stackptr]); #endif #ifdef GNULIGHTv2 { jit_node_t *ref; ref = jit_bnei(REG_ACC, 0); jit_patch_at(ref, loopstack[stackptr+1]); jit_patch(loopstack[stackptr]); } #endif break; case T_ENDIF: clean_acc(); acc_const = acc_loaded = 0; stackptr -= 2; if (stackptr < 0) { fprintf(stderr, "Code gen failure: Stack pointer negative.\n"); exit(1); } jit_patch(loopstack[stackptr]); break; case T_PRT: clean_acc(); load_acc_offset(n->offset); acc_loaded = 0; #ifdef GNULIGHTv1 jit_prepare_i(1); jit_pusharg_i(REG_ACC); jit_finish(putch); #endif #ifdef GNULIGHTv2 jit_prepare(); jit_pushargr(REG_ACC); jit_finishi(putch); #endif break; case T_CHR: clean_acc(); acc_const = acc_loaded = 0; if (n->count <= 0 || (n->count >= 127 && iostyle == 1) || !n->next || n->next->type != T_CHR) { jit_movi(REG_ACC, n->count); #ifdef GNULIGHTv1 jit_prepare_i(1); jit_pusharg_i(REG_ACC); jit_finish(putch); #endif #ifdef GNULIGHTv2 jit_prepare(); jit_pushargr(REG_ACC); jit_finishi(putch); #endif } else { unsigned i = 0; struct bfi * v = n; char *s; while(v->next && v->next->type == T_CHR && v->next->count > 0 && (v->next->count < 127 || iostyle != 1)) { if (i+2 > maxstrlen) { if (maxstrlen) maxstrlen *= 2; else maxstrlen = 4096; strbuf = realloc(strbuf, maxstrlen); if (!strbuf) { fprintf(stderr, "Reallocate of string buffer failed\n"); exit(42); } } strbuf[i++] = (char) /*GCC -Wconversion*/ v->count; n = v; v = v->next; } strbuf[i] = 0; s = strdup(strbuf); if (!s) { fprintf(stderr, "Save of string failed\n"); exit(43); } save_ptr_for_free(s); #ifdef GNULIGHTv1 jit_movi_p(REG_ACC, s); jit_prepare_i(1); jit_pusharg_i(REG_ACC); jit_finish(puts_without_nl); #endif #ifdef GNULIGHTv2 jit_prepare(); jit_pushargi((jit_word_t) s); jit_finishi(puts_without_nl); #endif } break; case T_INP: load_acc_offset(n->offset); set_acc_offset(n->offset); #ifdef GNULIGHTv1 jit_prepare_i(1); jit_pusharg_i(REG_ACC); jit_finish(getch); jit_retval_i(REG_ACC); #endif #ifdef GNULIGHTv2 jit_prepare(); jit_pushargr(REG_ACC); jit_finishi(getch); jit_retval(REG_ACC); #endif break; case T_STOP: #ifdef GNULIGHTv1 jit_prepare_i(0); jit_finish(failout); #endif #ifdef GNULIGHTv2 jit_prepare(); jit_finishi(failout); #endif break; case T_NOP: case T_DUMP: fprintf(stderr, "Warning on code generation: " "%s node: ptr+%d, cnt=%d, @(%d,%d).\n", tokennames[n->type], n->offset, n->count, n->line, n->col); break; default: fprintf(stderr, "Code gen error: " "%s\t" "%d:%d, %d:%d, %d:%d\n", tokennames[n->type], n->offset, n->count, n->offset2, n->count2, n->offset3, n->count3); exit(1); } n=n->next; #if 0 /*def GNULIGHTv2 */ if(n && enable_trace) { char *p, buf[250]; clean_acc(); acc_loaded = 0; sprintf(buf, "@(%d,%d)\n", n->line, n->col); p = strdup(buf); save_ptr_for_free(p); jit_prepare(); jit_pushargi((jit_word_t) p); jit_finishi(puts_without_nl); } #endif #ifdef GNULIGHTv1 /* TODO -- Check for codeBuffer overflow (add jmp to new) */ #endif } jit_ret(); if (strbuf) { maxstrlen = 0; free(strbuf); strbuf = 0; } delete_tree(); #ifdef GNULIGHTv1 jit_flush_code(startptr, jit_get_ip().ptr); if (verbose) fprintf(stderr, "Generated %d bytes of V1 GNU Lightning code, running\n", (int)(jit_get_ip().ptr - (char*)startptr)); start_runclock(); codeptr(map_hugeram()); finish_runclock(&run_time, &io_time); #endif #ifdef GNULIGHTv2 jit_epilog(); end = jit_note(__FILE__, __LINE__); codeptr = jit_emit(); if (verbose) fprintf(stderr, "Generated %d bytes of V2 GNU Lightning code, running\n", (int)((char*)jit_address(end) - (char*)jit_address(start))); jit_clear_state(); // jit_disassemble(); start_runclock(); codeptr(map_hugeram()); finish_runclock(&run_time, &io_time); #endif #if 0 /* This code writes the generated instructions to a file * so we can disassemble it using: ndisasm -b 32/64 code.bin */ { #ifdef GNULIGHTv1 char *p = startptr; int s = jit_get_ip().ptr - p; #endif #ifdef GNULIGHTv2 char *p = (char*)jit_address(start); int s = (char*)jit_address(end) - p; #endif FILE *fp = fopen("code.bin", "w"); int i; for (i = 0; i < s; ++i) { fputc(p[i], fp); } fclose(fp); } #endif #ifdef GNULIGHTv2 jit_destroy_state(); finish_jit(); #endif codeptr = 0; if (loopstack) { free(loopstack); loopstack = 0; } free_saved_memory(); }
void outrun(int ch, int count) { jit_node_t *argp; switch(ch) { case '!': if (bytecell) tape_step = 1; else tape_step = sizeof(int); init_jit(NULL); // argv[0]); _jit = jit_new_state(); start = jit_note(__FILE__, __LINE__); jit_prolog(); /* Get the data area pointer */ argp = jit_arg(); jit_getarg(REG_P, argp); break; case '~': jit_ret(); jit_epilog(); end = jit_note(__FILE__, __LINE__); codeptr = jit_emit(); jit_clear_state(); codeptr(calloc(tape_step, tapelen)); jit_destroy_state(); finish_jit(); codeptr = 0; if (loopstack) { free(loopstack); loopstack = 0; } break; case '>': jit_addi(REG_P, REG_P, count * tape_step); break; case '<': jit_subi(REG_P, REG_P, count * tape_step); break; case '+': if (tape_step>1) jit_ldr_i(REG_ACC, REG_P); else jit_ldr_uc(REG_ACC, REG_P); jit_addi(REG_ACC, REG_ACC, count); if (tape_step>1) jit_str_i(REG_P, REG_ACC); else jit_str_c(REG_P, REG_ACC); break; case '-': if (tape_step>1) jit_ldr_i(REG_ACC, REG_P); else jit_ldr_uc(REG_ACC, REG_P); jit_subi(REG_ACC, REG_ACC, count); if (tape_step>1) jit_str_i(REG_P, REG_ACC); else jit_str_c(REG_P, REG_ACC); break; case '[': if (tape_step>1) jit_ldr_i(REG_ACC, REG_P); else jit_ldr_uc(REG_ACC, REG_P); if (stackptr >= maxstack) { loopstack = realloc(loopstack, ((maxstack+=32)+2)*sizeof(*loopstack)); if (loopstack == 0) { perror("loop stack realloc failure"); exit(1); } } loopstack[stackptr] = jit_beqi(REG_ACC, 0); loopstack[stackptr+1] = jit_label(); stackptr += 2; break; case ']': if (tape_step>1) jit_ldr_i(REG_ACC, REG_P); else jit_ldr_uc(REG_ACC, REG_P); stackptr -= 2; if (stackptr < 0) { fprintf(stderr, "Code gen failure: Stack pointer negative.\n"); exit(1); } { jit_node_t *ref; ref = jit_bnei(REG_ACC, 0); jit_patch_at(ref, loopstack[stackptr+1]); jit_patch(loopstack[stackptr]); } break; case '.': if (tape_step>1) jit_ldr_i(REG_ACC, REG_P); else jit_ldr_uc(REG_ACC, REG_P); jit_prepare(); jit_pushargr(REG_ACC); jit_finishi(putchar); break; case ',': jit_prepare(); jit_pushargr(REG_ACC); jit_finishi(getchar); jit_retval(REG_ACC); if (tape_step>1) jit_str_i(REG_P, REG_ACC); else jit_str_c(REG_P, REG_ACC); break; } }