From be5c83ba8e57bc67beee41bc2c7227e6b8ebd9d5 Mon Sep 17 00:00:00 2001 From: Kimplul Date: Wed, 9 Apr 2025 22:20:01 +0300 Subject: add callr_i/l/f/d --- src/ejit.c | 142 +++++++++++++++++++++++++++++++++++++++++-------------------- 1 file changed, 97 insertions(+), 45 deletions(-) (limited to 'src/ejit.c') diff --git a/src/ejit.c b/src/ejit.c index 0701b90..e8ff99e 100644 --- a/src/ejit.c +++ b/src/ejit.c @@ -545,10 +545,22 @@ void ejit_calli(struct ejit_func *s, struct ejit_func *f, size_t argc, for (size_t i = 0; i < argc; ++i) { switch (args[i].kind) { - case EJIT_OPERAND_GPR: emit_insn_ar(s, EJIT_OP_ARG, i, args[i].type, EJIT_GPR(args[i].r)); break; - case EJIT_OPERAND_FPR: emit_insn_af(s, EJIT_OP_ARG_F, i, args[i].type, EJIT_FPR(args[i].r)); break; - case EJIT_OPERAND_IMM: emit_insn_ai(s, EJIT_OP_ARG_I, i, args[i].type, args[i].r); break; - case EJIT_OPERAND_FLT: emit_insn_ad(s, EJIT_OP_ARG_FI, i, args[i].type, args[i].d); break; + case EJIT_OPERAND_GPR: + emit_insn_ar(s, EJIT_OP_ARG, i, args[i].type, EJIT_GPR(args[i].r)); + break; + + case EJIT_OPERAND_FPR: + emit_insn_af(s, EJIT_OP_ARG_F, i, args[i].type, EJIT_FPR(args[i].r)); + break; + + case EJIT_OPERAND_IMM: + emit_insn_ai(s, EJIT_OP_ARG_I, i, args[i].type, args[i].r); + break; + + case EJIT_OPERAND_FLT: + emit_insn_ad(s, EJIT_OP_ARG_FI, i, args[i].type, args[i].d); + break; + default: abort(); } } @@ -556,73 +568,113 @@ void ejit_calli(struct ejit_func *s, struct ejit_func *f, size_t argc, emit_insn_op(s, EJIT_OP_CALLI, f); } -void ejit_escapei_i(struct ejit_func *s, ejit_escape_i_t f, size_t argc, - const struct ejit_operand args[argc]) +static void ejit_callr(struct ejit_func *s, enum ejit_opcode op, struct ejit_gpr target, + size_t argc, const struct ejit_operand args[argc]) { + s->use_64 = op == EJIT_OP_CALLR_L; s->max_args = argc > s->max_args ? argc : s->max_args; + for (size_t i = 0; i < argc; ++i) { switch (args[i].kind) { - case EJIT_OPERAND_GPR: emit_insn_ar(s, EJIT_OP_ARG, i, args[i].type, EJIT_GPR(args[i].r)); break; - case EJIT_OPERAND_FPR: emit_insn_af(s, EJIT_OP_ARG_F, i, args[i].type, EJIT_FPR(args[i].r)); break; - case EJIT_OPERAND_IMM: emit_insn_ai(s, EJIT_OP_ARG_I, i, args[i].type, args[i].r); break; - case EJIT_OPERAND_FLT: emit_insn_ad(s, EJIT_OP_ARG_FI, i, args[i].type, args[i].d); break; + case EJIT_OPERAND_GPR: + emit_insn_ar(s, EJIT_OP_ARG, i, args[i].type, EJIT_GPR(args[i].r)); + break; + + case EJIT_OPERAND_FPR: + emit_insn_af(s, EJIT_OP_ARG_F, i, args[i].type, EJIT_FPR(args[i].r)); + break; + + case EJIT_OPERAND_IMM: + emit_insn_ai(s, EJIT_OP_ARG_I, i, args[i].type, args[i].r); + break; + + case EJIT_OPERAND_FLT: + emit_insn_ad(s, EJIT_OP_ARG_FI, i, args[i].type, args[i].d); + break; + default: abort(); } } - emit_insn_op(s, EJIT_OP_ESCAPEI_I, f); + emit_insn_oxr(s, op, target); } -void ejit_escapei_l(struct ejit_func *s, ejit_escape_l_t f, size_t argc, - const struct ejit_operand args[argc]) +void ejit_callr_i(struct ejit_func *s, struct ejit_gpr target, + size_t argc, const struct ejit_operand args[argc]) { - s->use_64 = true; - s->max_args = argc > s->max_args ? argc : s->max_args; - for (size_t i = 0; i < argc; ++i) { - switch (args[i].kind) { - case EJIT_OPERAND_GPR: emit_insn_ar(s, EJIT_OP_ARG, i, args[i].type, EJIT_GPR(args[i].r)); break; - case EJIT_OPERAND_FPR: emit_insn_af(s, EJIT_OP_ARG_F, i, args[i].type, EJIT_FPR(args[i].r)); break; - case EJIT_OPERAND_IMM: emit_insn_ai(s, EJIT_OP_ARG_I, i, args[i].type, args[i].r); break; - case EJIT_OPERAND_FLT: emit_insn_ad(s, EJIT_OP_ARG_FI, i, args[i].type, args[i].d); break; - default: abort(); - } - } + ejit_callr(s, EJIT_OP_CALLR_I, target, argc, args); +} + +void ejit_callr_l(struct ejit_func *s, struct ejit_gpr target, + size_t argc, const struct ejit_operand args[argc]) +{ + ejit_callr(s, EJIT_OP_CALLR_L, target, argc, args); +} - emit_insn_op(s, EJIT_OP_ESCAPEI_L, f); +void ejit_callr_f(struct ejit_func *s, struct ejit_gpr target, + size_t argc, const struct ejit_operand args[argc]) +{ + ejit_callr(s, EJIT_OP_CALLR_F, target, argc, args); } -void ejit_escapei_f(struct ejit_func *s, ejit_escape_f_t f, size_t argc, - const struct ejit_operand args[argc]) +void ejit_callr_d(struct ejit_func *s, struct ejit_gpr target, + size_t argc, const struct ejit_operand args[argc]) { + ejit_callr(s, EJIT_OP_CALLR_D, target, argc, args); +} + +static void ejit_escapei(struct ejit_func *s, enum ejit_opcode op, void *f, + size_t argc, const struct ejit_operand args[argc]) +{ + s->use_64 = op == EJIT_OP_ESCAPEI_L; s->max_args = argc > s->max_args ? argc : s->max_args; for (size_t i = 0; i < argc; ++i) { switch (args[i].kind) { - case EJIT_OPERAND_GPR: emit_insn_ar(s, EJIT_OP_ARG, i, args[i].type, EJIT_GPR(args[i].r)); break; - case EJIT_OPERAND_FPR: emit_insn_af(s, EJIT_OP_ARG_F, i, args[i].type, EJIT_FPR(args[i].r)); break; - case EJIT_OPERAND_IMM: emit_insn_ai(s, EJIT_OP_ARG_I, i, args[i].type, args[i].r); break; - case EJIT_OPERAND_FLT: emit_insn_ad(s, EJIT_OP_ARG_FI, i, args[i].type, args[i].d); break; + case EJIT_OPERAND_GPR: + emit_insn_ar(s, EJIT_OP_ARG, i, args[i].type, EJIT_GPR(args[i].r)); + break; + + case EJIT_OPERAND_FPR: + emit_insn_af(s, EJIT_OP_ARG_F, i, args[i].type, EJIT_FPR(args[i].r)); + break; + + case EJIT_OPERAND_IMM: + emit_insn_ai(s, EJIT_OP_ARG_I, i, args[i].type, args[i].r); + break; + + case EJIT_OPERAND_FLT: + emit_insn_ad(s, EJIT_OP_ARG_FI, i, args[i].type, args[i].d); + break; + default: abort(); } } - emit_insn_op(s, EJIT_OP_ESCAPEI_F, f); + emit_insn_op(s, op, f); } -void ejit_escapei_d(struct ejit_func *s, ejit_escape_d_t f, size_t argc, - const struct ejit_operand args[argc]) +void ejit_escapei_i(struct ejit_func *s, ejit_escape_i_t f, + size_t argc, const struct ejit_operand args[argc]) { - s->max_args = argc > s->max_args ? argc : s->max_args; - for (size_t i = 0; i < argc; ++i) { - switch (args[i].kind) { - case EJIT_OPERAND_GPR: emit_insn_ar(s, EJIT_OP_ARG, i, args[i].type, EJIT_GPR(args[i].r)); break; - case EJIT_OPERAND_FPR: emit_insn_af(s, EJIT_OP_ARG_F, i, args[i].type, EJIT_FPR(args[i].r)); break; - case EJIT_OPERAND_IMM: emit_insn_ai(s, EJIT_OP_ARG_I, i, args[i].type, args[i].r); break; - case EJIT_OPERAND_FLT: emit_insn_ad(s, EJIT_OP_ARG_FI, i, args[i].type, args[i].d); break; - default: abort(); - } - } + ejit_escapei(s, EJIT_OP_ESCAPEI_I, f, argc, args); +} + +void ejit_escapei_l(struct ejit_func *s, ejit_escape_l_t f, + size_t argc, const struct ejit_operand args[argc]) +{ + ejit_escapei(s, EJIT_OP_ESCAPEI_L, f, argc, args); +} - emit_insn_op(s, EJIT_OP_ESCAPEI_D, f); +void ejit_escapei_f(struct ejit_func *s, ejit_escape_f_t f, + size_t argc, const struct ejit_operand args[argc]) +{ + ejit_escapei(s, EJIT_OP_ESCAPEI_F, f, argc, args); +} + +void ejit_escapei_d(struct ejit_func *s, ejit_escape_d_t f, + size_t argc, const struct ejit_operand args[argc]) +{ + ejit_escapei(s, EJIT_OP_ESCAPEI_D, f, argc, args); } void ejit_retval(struct ejit_func *s, struct ejit_gpr r0) -- cgit v1.2.3