dblFunc makeCallFunc (dblFunc theFunc) { dblFunc retVal; int dbl1, dbl2; retVal = (dblFunc) jit_get_ip ().iptr; jit_prolog (2); dbl1 = jit_arg_d (); dbl2 = jit_arg_d (); jit_prepare_d (2); jit_getarg_d (JIT_FPR0, dbl1); jit_getarg_d (JIT_FPR1, dbl2); jit_mulr_d (JIT_FPR1, JIT_FPR1, JIT_FPR0); jit_pusharg_d (JIT_FPR1); jit_pusharg_d (JIT_FPR0); jit_finish ((void *) theFunc); jit_retval_d (JIT_FPRET); jit_ret (); jit_flush_code ((char *) retVal, jit_get_ip ().ptr); #ifdef LIGHTNING_DISASSEMBLE disassemble (stderr, (char *) retVal, jit_get_ip ().ptr); #endif return retVal; }
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; }
pdfd compile_rpn (char *expr) { pdfd fn; int ofs, sp = 1; fn = (pdfd) (jit_get_ip ().dptr); jit_leaf (1); ofs = jit_arg_d (); jit_getarg_d (regs[0], ofs); while (*expr) { char buf[32]; int n; /* This scanner is much less advanced than the one in rpn.c. */ if (sscanf (expr, "%[0-9]%n", buf, &n)) { double d = strtod (buf, NULL); expr += n - 1; jit_movi_d (regs[sp], d); sp++; } else if (*expr == '+') { jit_addr_d (regs[sp - 2], regs[sp - 2], regs[sp - 1]); sp--; } else if (*expr == '-') { jit_subr_d (regs[sp - 2], regs[sp - 2], regs[sp - 1]); sp--; } else if (*expr == '*') { jit_mulr_d (regs[sp - 2], regs[sp - 2], regs[sp - 1]); sp--; } else if (*expr == '/') { jit_divr_d (regs[sp - 2], regs[sp - 2], regs[sp - 1]); sp--; } else { fprintf (stderr, "cannot compile: %s\n", expr); abort (); } ++expr; } jit_movr_d (JIT_FPRET, regs[0]); jit_ret (); jit_flush_code ((char *) fn, jit_get_ip ().ptr); #ifdef LIGHTNING_DISASSEMBLE disassemble (stderr, (char *) fn, jit_get_ip ().ptr); #endif return fn; }