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; }
mod_t generate_modi (int operand) { mod_t result; int arg; 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 = (mod_t)(jit_set_ip (buffer).iptr); jit_leaf (1); arg = jit_arg_i (); jit_getarg_i (JIT_R1, arg); jit_modi_i (JIT_R2, JIT_R1, operand); jit_movr_i (JIT_RET, JIT_R2); jit_ret (); jit_flush_code (buffer, jit_get_ip ().ptr); return result; }
int main() { static jit_insn codeBuffer[1024]; static jit_state _jit; pvfi myFunction; /* ptr to generated code */ char *start, *end; /* a couple of labels */ int ofs; /* to get the argument */ myFunction = (pvfi) (jit_set_ip(codeBuffer).vptr); start = jit_get_ip().ptr; jit_prolog(1); ofs = jit_arg_i(); jit_movi_p(JIT_R0, "looks like %d bytes sufficed\n"); jit_getarg_i(JIT_R1, ofs); jit_prepare_i(2); jit_pusharg_i(JIT_R1); /* push in reverse order */ jit_pusharg_p(JIT_R0); jit_finish(display_message); jit_ret(); end = jit_get_ip().ptr; jit_flush_code(codeBuffer, end); #ifdef LIGHTNING_DISASSEMBLE disassemble(stderr, codeBuffer, end); #endif #ifndef LIGHTNING_CROSS /* call the generated code, passing its size as argument */ myFunction(sizeof(codeBuffer)); #endif return 0; }
static divider_t generate_divider (int operand, unsigned int *size) { divider_t result; int arg; 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 = (divider_t)(jit_set_ip (buffer).iptr); jit_leaf (1); arg = jit_arg_i (); jit_getarg_i (JIT_R1, arg); jit_divi_i (JIT_R2, JIT_R1, operand); jit_movr_i (JIT_RET, JIT_R2); jit_ret (); jit_flush_code (buffer, jit_get_ip ().ptr); *size = (jit_insn *)jit_get_ip ().ptr - buffer; return result; }
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; }
int main() { pifii myFunction= (pifii) (jit_set_ip(codeBuffer).iptr); int ofs; /* offset of the argument */ jit_leaf(2); ofs = jit_arg_i(); jit_getarg_i(JIT_R0, ofs); ofs = jit_arg_i(); jit_getarg_i(JIT_R1, ofs); jit_addr_i(JIT_RET, JIT_R0, JIT_R1); jit_ret(); jit_flush_code(codeBuffer, jit_get_ip().ptr); /* call the generated code, passing its size as argument */ #ifdef LIGHTNING_DISASSEMBLE disassemble(stderr, codeBuffer, jit_get_ip().ptr); #endif #ifndef LIGHTNING_CROSS printf("%d + %d = %d\n", 5, 4, myFunction(5, 4)); #endif return 0; }
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; }
mod_t generate_modi (int operand) { static char buffer[1024]; mod_t result; int arg; result = (mod_t)(jit_set_ip (buffer).iptr); jit_leaf (1); arg = jit_arg_i (); jit_getarg_i (JIT_R1, arg); jit_modi_i (JIT_R2, JIT_R1, operand); jit_movr_i (JIT_RET, JIT_R2); jit_ret (); jit_flush_code (buffer, jit_get_ip ().ptr); return result; }
int main() { pvfi myFunction; /* ptr to generated code */ char *start, *end; /* a couple of labels */ int ofs; /* to get the argument */ codeBuffer = mmap(NULL, getpagesize(), PROT_READ | PROT_WRITE | PROT_EXEC, MAP_PRIVATE | MAP_ANON, -1, 0); if (codeBuffer == MAP_FAILED) { perror("mmap"); exit(0); } myFunction = (pvfi) (jit_set_ip(codeBuffer).vptr); start = jit_get_ip().ptr; jit_prolog(1); ofs = jit_arg_i(); jit_movi_p(JIT_R0, "looks like %d bytes sufficed\n"); jit_getarg_i(JIT_R1, ofs); jit_prepare_i(2); jit_pusharg_i(JIT_R1); /* push in reverse order */ jit_pusharg_p(JIT_R0); jit_finish(display_message); jit_ret(); end = jit_get_ip().ptr; jit_flush_code(codeBuffer, end); #ifdef LIGHTNING_DISASSEMBLE disassemble(stderr, codeBuffer, end); #endif #ifndef LIGHTNING_CROSS /* call the generated code, with a dummy argument */ myFunction(1024); #endif return 0; }
/* This function does all of lexing, parsing, and picking a good order of evaluation... Needless to say, this is not the best possible design, but it avoids cluttering everything with globals. */ pifi compile_rpn (char *expr) { struct stack_element stack[32]; int sp = 0; int curr_tos = -1; /* stack element currently in R0 */ int spill_base, spill_sp; pifi fn; int ofs; fn = (pifi) (jit_get_ip ().iptr); jit_leaf (1); ofs = jit_arg_i (); spill_sp = spill_base = jit_allocai (32 * sizeof (int)); while (*expr) { int with_imm; int imm; int tok; int src1, src2; /* This is the lexer. */ switch (*expr) { case ' ': case '\t': expr++; continue; case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9': stack[sp].kind = IMM; stack[sp++].imm = strtol (expr, &expr, 0); continue; case 'x': expr++; stack[sp++].kind = ARG; continue; case '~': /* NOT. Implemented as a XOR with -1. */ stack[sp].kind = IMM; stack[sp++].imm = ~0; tok = '^'; break; case '_': /* Unary minus. Transform to 0 - X and go on. Also used to enter negative constants (32_ = -32). */ expr++; stack[sp] = stack[sp - 1]; /* Ensure CURR_TOS is correct. */ if (curr_tos == sp - 1) curr_tos = sp; stack[sp - 1].kind = IMM; stack[sp - 1].imm = 0; sp++; tok = '-'; break; case '+': case '-': case '*': case '/': case '%': case '&': case '|': case '^': case '=': tok = *expr++; break; case '!': /* Get != */ expr++; assert (*expr == '='); tok = NE; break; case '<': /* Get <, <<, <= */ if (expr[1] == '=') expr += 2, tok = LE; else if (expr[1] == '<') expr += 2, tok = LSH; else expr++, tok = '<'; break; case '>': /* Get >, >>, >>>, >= */ if (expr[1] == '=') expr += 2, tok = GE; else if (expr[1] == '>' && expr[2] == '>') expr += 3, tok = RSHU; else if (expr[1] == '>') expr += 2, tok = RSH; else expr++, tok = '>'; break; default: abort (); } assert (sp >= 2); /* Constant folding. */ if (stack[sp - 1].kind == IMM && stack[sp - 2].kind == IMM) { stack[sp - 2].imm = fold (stack[sp - 2].imm, stack[sp - 1].imm, tok); sp--; continue; } /* If possible, ensure that the constant is the RHS, possibly by changing TOK (if it is a comparison). */ if (stack[sp - 2].kind == IMM) { int swapped_operation = swap_op (tok); if (swapped_operation) { tok = swapped_operation; stack[sp - 2].kind = stack[sp - 1].kind; stack[sp - 1].kind = IMM; stack[sp - 1].imm = stack[sp - 2].imm; /* Ensure CURR_TOS is correct. */ if (curr_tos == sp - 1) curr_tos = sp - 2; } } /* Get the second argument into a register, if not an immediate. Also decide which argument will be prepared into JIT_R0 and which will be prepared into JIT_V0. */ with_imm = 0; src1 = JIT_R0; src2 = JIT_V0; switch (stack[sp - 1].kind) { case IMM: /* RHS is an immediate, use an immediate instruction. */ with_imm = 1; imm = stack[sp - 1].imm; break; case EXPR: /* RHS is an expression, check if it is already in JIT_R0. */ if (curr_tos == sp - 1) { /* Invert the two sources. */ src1 = JIT_V0; src2 = JIT_R0; } else popr (JIT_V0, &spill_sp); curr_tos = -1; break; case ARG: jit_getarg_i (JIT_V0, ofs); break; } /* Get the first argument into a register indicated by SRC1. */ switch (stack[sp - 2].kind) { case IMM: /* LHS is an immediate, check if we must spill the top of stack. */ if (curr_tos != -1) { pushr (JIT_R0, &spill_sp); curr_tos = -1; } jit_movi_i (src1, stack[sp - 2].imm); break; case EXPR: /* LHS is an expression, check if it is already in JIT_R0. */ if (curr_tos != sp - 2) { popr (src1, &spill_sp); curr_tos = -1; } else assert (src1 == JIT_R0); break; case ARG: if (curr_tos != -1) { pushr (JIT_R0, &spill_sp); curr_tos = -1; } jit_getarg_i (src1, ofs); break; } /* Set up the new stack entry, which is cached in R0. */ sp -= 2; curr_tos = sp; stack[sp++].kind = EXPR; /* Perform the computation. */ if (with_imm) gen_reg_imm (src1, imm, tok); else gen_reg_reg (src1, src2, tok); } assert (sp == 1); switch (stack[0].kind) { case IMM: jit_movi_i (JIT_RET, stack[0].imm); break; case EXPR: assert (curr_tos == 0); jit_movr_i (JIT_RET, JIT_R0); break; case ARG: jit_getarg_i (JIT_V0, ofs); break; } 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; }