void jit_divr(int dreg, int sreg) { jit_movr(0,dreg); jit_movr(1,sreg); jit_call(inline_div,"div"); if (dreg!=0) jit_movr(dreg,0); // call the c lib function // later: http://thinkingeek.com/2013/08/11/arm-assembler-raspberry-pi-chapter-15/ }
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); }
void _jit_putargr(jit_state_t *_jit, jit_int32_t u, jit_node_t *v) { assert(v->code == jit_code_arg); if (jit_arg_reg_p(v->u.w)) jit_movr(_I0 + v->u.w, u); else jit_stxi(v->u.w, JIT_FP, u); }
void _jit_getarg_i(jit_state_t *_jit, jit_int32_t u, jit_node_t *v) { assert(v->code == jit_code_arg); if (jit_arg_reg_p(v->u.w)) jit_movr(u, _I0 + v->u.w); else jit_ldxi_i(u, JIT_FP, v->u.w); }
void _jit_retr(jit_state_t *_jit, jit_int32_t u) { if (JIT_RET != u) jit_movr(JIT_RET, u); else jit_live(JIT_RET); jit_ret(); }
void _jit_pushargr(jit_state_t *_jit, jit_int32_t u) { if (jit_arg_reg_p(_jitc->function->call.argi)) { jit_movr(_O0 + _jitc->function->call.argi, u); ++_jitc->function->call.argi; } else { jit_stxi(_jitc->function->call.size + stack_framesize, JIT_SP, u); _jitc->function->call.size += sizeof(jit_word_t); } }
jit_value pop_int(Frame* frame) { jit_value reg = pop_reg(frame); struct jit* jit = frame->jit; jit_ldxi(jit, frame->accum[1], reg, offsetof(YValue, type), sizeof(void*)); jit_movi(jit, frame->accum[2], 0); jit_op* not_int_jump = jit_bner(jit, (intptr_t) JIT_FORWARD, frame->accum[1], frame->IntType); jit_ldxi(jit, frame->accum[2], reg, offsetof(YInteger, value), sizeof(int64_t)); jit_patch(jit, not_int_jump); jit_movr(jit, frame->accum[0], frame->accum[2]); 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); } }
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]; }
jit_node_t *compile_rpn(char *expr) { jit_node_t *in, *fn; int stack_base, stack_ptr; fn = jit_note(NULL, 0); jit_prolog(); in = jit_arg(); stack_ptr = stack_base = jit_allocai (32 * sizeof (int)); jit_getarg_i(JIT_R2, in); while (*expr) { char buf[32]; int n; if (sscanf(expr, "%[0-9]%n", buf, &n)) { expr += n - 1; stack_push(JIT_R0, &stack_ptr); jit_movi(JIT_R0, atoi(buf)); } else if (*expr == 'x') { stack_push(JIT_R0, &stack_ptr); jit_movr(JIT_R0, JIT_R2); } else if (*expr == '+') { stack_pop(JIT_R1, &stack_ptr); jit_addr(JIT_R0, JIT_R1, JIT_R0); } else if (*expr == '-') { stack_pop(JIT_R1, &stack_ptr); jit_subr(JIT_R0, JIT_R1, JIT_R0); } else if (*expr == '*') { stack_pop(JIT_R1, &stack_ptr); jit_mulr(JIT_R0, JIT_R1, JIT_R0); } else if (*expr == '/') { stack_pop(JIT_R1, &stack_ptr); jit_divr(JIT_R0, JIT_R1, JIT_R0); } else { fprintf(stderr, "cannot compile: %s\n", expr); abort(); } ++expr; } jit_retr(JIT_R0); jit_epilog(); return fn; }
void jit_ret() { jit_movr(15,14); // lr -> pc }
void jit_modr(int dreg, int sreg) { jit_movr(0,dreg); jit_movr(1,sreg); jit_call(inline_mod,"mod"); if (dreg!=0) jit_movr(dreg,0); }
void jit_callr(int reg) { code[code_idx++] = 0xe92d4000; // stmfd sp!, {lr} jit_movr(14,15); jit_movr(15,reg); code[code_idx++] = 0xe8bd4000; // ldmfd sp!, {lr} }
void jit_call(void* func, char* note) { code[code_idx++] = 0xe92d4000; // stmfd sp!, {lr} jit_movr(14,15); jit_lea(15,func); code[code_idx++] = 0xe8bd4000; // ldmfd sp!, {lr} }
void _jit_retval_i(jit_state_t *_jit, jit_int32_t r0) { if (r0 != _O0) jit_movr(r0, _O0); }