void _jit_putargi_d(jit_state_t *_jit, jit_float64_t u, jit_node_t *v) { jit_int32_t regno, gpr; assert(v->code == jit_code_arg_d); regno = jit_get_reg(jit_class_fpr); jit_movi_d(regno, u); if (jit_arg_d_reg_p(v->u.w)) { jit_stxi_d(-8, JIT_FP, regno); jit_ldxi(_I0 + v->u.w, JIT_FP, -8); jit_ldxi(_I0 + v->u.w + 1, JIT_FP, -4); } else if (jit_arg_reg_p(v->u.w)) { gpr = jit_get_reg(jit_class_gpr); jit_stxi_d(-8, JIT_FP, regno); jit_ldxi(_I0 + v->u.w, JIT_FP, -8); jit_ldxi(gpr, JIT_FP, -4); jit_stxi(stack_framesize, JIT_FP, gpr); jit_unget_reg(gpr); } else if ((v->u.w & 7) == 0) jit_stxi_d(v->u.w, JIT_FP, regno); else { jit_stxi_d(-8, JIT_FP, regno); gpr = jit_get_reg(jit_class_gpr); jit_ldxi(gpr, JIT_FP, -8); jit_stxi(v->u.w, JIT_FP, gpr); jit_ldxi(gpr, JIT_FP, -4); jit_stxi(v->u.w + 4, JIT_FP, gpr); jit_unget_reg(gpr); } jit_unget_reg(regno); }
void _jit_pushargi_d(jit_state_t *_jit, jit_float64_t u) { jit_int32_t regno; regno = jit_get_reg(jit_class_fpr); jit_movi_d(regno, u); if (jit_arg_d_reg_p(_jitc->function->call.argi)) { jit_stxi_d(-8, JIT_FP, regno); jit_ldxi(_O0 + _jitc->function->call.argi, JIT_FP, -8); jit_ldxi(_O0 + _jitc->function->call.argi + 1, JIT_FP, -4); _jitc->function->call.argi += 2; } else if (jit_arg_reg_p(_jitc->function->call.argi)) { jit_stxi_f(-8, JIT_FP, regno); jit_ldxi(_O0 + _jitc->function->call.argi, JIT_FP, -8); ++_jitc->function->call.argi; jit_stxi_f(stack_framesize, JIT_SP, regno + 1); _jitc->function->call.size += sizeof(jit_float32_t); } else { jit_stxi_f(_jitc->function->call.size + stack_framesize, JIT_SP, regno); jit_stxi_f(_jitc->function->call.size + stack_framesize + 4, JIT_SP, regno + 1); _jitc->function->call.size += sizeof(jit_float64_t); } jit_unget_reg(regno); }
void _jit_pushargr_d(jit_state_t *_jit, jit_int32_t u) { if (jit_arg_d_reg_p(_jitc->function->call.argi)) { jit_stxi_d(-8, JIT_FP, u); jit_ldxi(_O0 + _jitc->function->call.argi, JIT_FP, -8); jit_ldxi(_O0 + _jitc->function->call.argi + 1, JIT_FP, -4); _jitc->function->call.argi += 2; } else if (jit_arg_reg_p(_jitc->function->call.argi)) { jit_stxi_f(-8, JIT_FP, u); jit_ldxi(_O0 + _jitc->function->call.argi, JIT_FP, -8); ++_jitc->function->call.argi; jit_stxi_f(stack_framesize, JIT_SP, u + 1); _jitc->function->call.size += sizeof(jit_float32_t); } else { jit_stxi_f(_jitc->function->call.size + stack_framesize, JIT_SP, u); jit_stxi_f(_jitc->function->call.size + stack_framesize + 4, JIT_SP, u + 1); _jitc->function->call.size += sizeof(jit_float64_t); } }
void _JIT_stack_push(jit_state_t *_jit, int reg, int *sp) { jit_stxi_d(*sp, JIT_FP, reg); *sp += sizeof(double); }
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; }