#include #include /* Simple test for arguments handling, that also shows how to use * arguments to store values. * Register arguments, if available, are very fast, but are also * very volatile on some ports, because some ports will do C calls * to implement division, remainder, sometimes multiplication, or * some float operations. * Arguments in registers should be fetched in the prolog of the * function, and if they must be saved, they should be saved in * the prolog. * The predicate macro "jit_arg_register_p(arg)" allows knowing if * an argument lives in a register, where it is known for being a very * fast to read/write temporary storage. */ #define W jit_word_t #define F jit_float32_t #define D jit_float64_t jit_state_t *_jit; void cw(W a1, W a2, W a3, W a4, W a5, W a6, W a7, W a8, W a9, W a10, W a11, W a12, W a13, W a14, W a15, W a16) { if ( a1 != 1 || a2 != 2 || a3 != 3 || a4 != 4 || a5 != 5 || a6 != 6 || a7 != 7 || a8 != 8 || a9 != 9 || a10 != 10 || a11 != 11 || a12 != 12 || a13 != 13 || a14 != 14 || a15 != 15 || a16 != 16) abort(); } void cf(F a1, F a2, F a3, F a4, F a5, F a6, F a7, F a8, F a9, F a10, F a11, F a12, F a13, F a14, F a15, F a16) { if ( a1 != 1 || a2 != 2 || a3 != 3 || a4 != 4 || a5 != 5 || a6 != 6 || a7 != 7 || a8 != 8 || a9 != 9 || a10 != 10 || a11 != 11 || a12 != 12 || a13 != 13 || a14 != 14 || a15 != 15 || a16 != 16) abort(); } void cd(D a1, D a2, D a3, D a4, D a5, D a6, D a7, D a8, D a9, D a10, D a11, D a12, D a13, D a14, D a15, D a16) { if ( a1 != 1 || a2 != 2 || a3 != 3 || a4 != 4 || a5 != 5 || a6 != 6 || a7 != 7 || a8 != 8 || a9 != 9 || a10 != 10 || a11 != 11 || a12 != 12 || a13 != 13 || a14 != 14 || a15 != 15 || a16 != 16) abort(); } int main(int argc, char *argv[]) { void (*code)(void); jit_node_t *jmp, *pass; jit_node_t *jw, *jf, *jd; jit_int32_t s1, s2, s3, s4, s5, s6, s7, s8, s9, s10, s11, s12, s13, s14, s15, s16; jit_node_t *a1, *a2, *a3, *a4, *a5, *a6, *a7, *a8, *a9, *a10, *a11, *a12, *a13, *a14, *a15, *a16; init_jit(argv[0]); _jit = jit_new_state(); /* jump to "main" label */ jmp = jit_jmpi(); /* Create jit function that * o Receives 16 word arguments * o Save in the stack any register argument. Also force register * arguments to be clobbered to properly make the test * o Calls a C function that receives 16 word arguments, with * values different from the ones received by this function * o Reload from stack any register argument * o Validated all arguments were not modified in the known * cases it could have been clobbered */ jw = jit_label(); jit_name("jw"); jit_note(__FILE__, __LINE__); jit_prolog(); a1 = jit_arg(); a2 = jit_arg(); a3 = jit_arg(); a4 = jit_arg(); a5 = jit_arg(); a6 = jit_arg(); a7 = jit_arg(); a8 = jit_arg(); a9 = jit_arg(); a10 = jit_arg(); a11 = jit_arg(); a12 = jit_arg(); a13 = jit_arg(); a14 = jit_arg(); a15 = jit_arg(); a16 = jit_arg(); #define SAVE_ARG(N) \ do { \ if (jit_arg_register_p(a##N)) { \ s##N = jit_allocai(sizeof(W)); \ jit_getarg(JIT_R0, a##N); \ jit_stxi(s##N, JIT_FP, JIT_R0); \ jit_putargi(-1, a##N); \ } \ } while (0) SAVE_ARG(1); SAVE_ARG(2); SAVE_ARG(3); SAVE_ARG(4); SAVE_ARG(5); SAVE_ARG(6); SAVE_ARG(7); SAVE_ARG(8); SAVE_ARG(9); SAVE_ARG(10); SAVE_ARG(11); SAVE_ARG(12); SAVE_ARG(13); SAVE_ARG(14); SAVE_ARG(15); SAVE_ARG(16); #undef SAVE_ARG jit_prepare(); { jit_pushargi(1); jit_pushargi(2); jit_pushargi(3); jit_pushargi(4); jit_pushargi(5); jit_pushargi(6); jit_pushargi(7); jit_pushargi(8); jit_pushargi(9); jit_pushargi(10); jit_pushargi(11); jit_pushargi(12); jit_pushargi(13); jit_pushargi(14); jit_pushargi(15); jit_pushargi(16); } jit_finishi(cw); #define LOAD_ARG(N) \ do { \ if (jit_arg_register_p(a##N)) { \ jit_ldxi(JIT_R0, JIT_FP, s##N); \ jit_putargr(JIT_R0, a##N); \ } \ } while (0) LOAD_ARG(1); LOAD_ARG(2); LOAD_ARG(3); LOAD_ARG(4); LOAD_ARG(5); LOAD_ARG(6); LOAD_ARG(7); LOAD_ARG(8); LOAD_ARG(9); LOAD_ARG(10); LOAD_ARG(11); LOAD_ARG(12); LOAD_ARG(13); LOAD_ARG(14); LOAD_ARG(15); LOAD_ARG(16); #undef LOAD_ARG pass = jit_forward(); #define CHECK_ARG(N) \ do { \ jit_getarg(JIT_R0, a##N); \ jit_patch_at(jit_beqi(JIT_R0, 17 - N), pass); \ } while (0) CHECK_ARG(1); CHECK_ARG(2); CHECK_ARG(3); CHECK_ARG(4); CHECK_ARG(5); CHECK_ARG(6); CHECK_ARG(7); CHECK_ARG(8); CHECK_ARG(9); CHECK_ARG(10); CHECK_ARG(11); CHECK_ARG(12); CHECK_ARG(13); CHECK_ARG(14); CHECK_ARG(15); CHECK_ARG(16); #undef CHECK_ARG jit_calli(abort); jit_link(pass); jit_ret(); jit_epilog(); /* Create jit function that * o Receives 16 float arguments * o Save in the stack any register argument. Also force register * arguments to be clobbered to properly make the test * o Calls a C function that receives 16 float arguments, with * values different from the ones received by this function * o Reload from stack any register argument * o Validated all arguments were not modified in the known * cases it could have been clobbered */ jf = jit_label(); jit_name("jf"); jit_note(__FILE__, __LINE__); jit_prolog(); a1 = jit_arg_f(); a2 = jit_arg_f(); a3 = jit_arg_f(); a4 = jit_arg_f(); a5 = jit_arg_f(); a6 = jit_arg_f(); a7 = jit_arg_f(); a8 = jit_arg_f(); a9 = jit_arg_f(); a10 = jit_arg_f(); a11 = jit_arg_f(); a12 = jit_arg_f(); a13 = jit_arg_f(); a14 = jit_arg_f(); a15 = jit_arg_f(); a16 = jit_arg_f(); #define SAVE_ARG(N) \ do { \ if (jit_arg_register_p(a##N)) { \ s##N = jit_allocai(sizeof(F)); \ jit_getarg_f(JIT_F0, a##N); \ jit_stxi_f(s##N, JIT_FP, JIT_F0); \ jit_putargi_f(-1, a##N); \ } \ } while (0) SAVE_ARG(1); SAVE_ARG(2); SAVE_ARG(3); SAVE_ARG(4); SAVE_ARG(5); SAVE_ARG(6); SAVE_ARG(7); SAVE_ARG(8); SAVE_ARG(9); SAVE_ARG(10); SAVE_ARG(11); SAVE_ARG(12); SAVE_ARG(13); SAVE_ARG(14); SAVE_ARG(15); SAVE_ARG(16); #undef SAVE_ARG jit_prepare(); { jit_pushargi_f(1); jit_pushargi_f(2); jit_pushargi_f(3); jit_pushargi_f(4); jit_pushargi_f(5); jit_pushargi_f(6); jit_pushargi_f(7); jit_pushargi_f(8); jit_pushargi_f(9); jit_pushargi_f(10); jit_pushargi_f(11); jit_pushargi_f(12); jit_pushargi_f(13); jit_pushargi_f(14); jit_pushargi_f(15); jit_pushargi_f(16); } jit_finishi(cf); #define LOAD_ARG(N) \ do { \ if (jit_arg_register_p(a##N)) { \ jit_ldxi_f(JIT_F0, JIT_FP, s##N); \ jit_putargr_f(JIT_F0, a##N); \ } \ } while (0) LOAD_ARG(1); LOAD_ARG(2); LOAD_ARG(3); LOAD_ARG(4); LOAD_ARG(5); LOAD_ARG(6); LOAD_ARG(7); LOAD_ARG(8); LOAD_ARG(9); LOAD_ARG(10); LOAD_ARG(11); LOAD_ARG(12); LOAD_ARG(13); LOAD_ARG(14); LOAD_ARG(15); LOAD_ARG(16); #undef LOAD_ARG pass = jit_forward(); #define CHECK_ARG(N) \ do { \ jit_getarg_f(JIT_F0, a##N); \ jit_patch_at(jit_beqi_f(JIT_F0, 17 - N), pass); \ } while (0) CHECK_ARG(1); CHECK_ARG(2); CHECK_ARG(3); CHECK_ARG(4); CHECK_ARG(5); CHECK_ARG(6); CHECK_ARG(7); CHECK_ARG(8); CHECK_ARG(9); CHECK_ARG(10); CHECK_ARG(11); CHECK_ARG(12); CHECK_ARG(13); CHECK_ARG(14); CHECK_ARG(15); CHECK_ARG(16); #undef CHECK_ARG jit_calli(abort); jit_link(pass); jit_ret(); jit_epilog(); /* Create jit function that * o Receives 16 double arguments * o Save in the stack any register argument. Also force register * arguments to be clobbered to properly make the test * o Calls a C function that receives 16 double arguments, with * values different from the ones received by this function * o Reload from stack any register argument * o Validated all arguments were not modified in the known * cases it could have been clobbered */ jd = jit_label(); jit_name("jd"); jit_note(__FILE__, __LINE__); jit_prolog(); a1 = jit_arg_d(); a2 = jit_arg_d(); a3 = jit_arg_d(); a4 = jit_arg_d(); a5 = jit_arg_d(); a6 = jit_arg_d(); a7 = jit_arg_d(); a8 = jit_arg_d(); a9 = jit_arg_d(); a10 = jit_arg_d(); a11 = jit_arg_d(); a12 = jit_arg_d(); a13 = jit_arg_d(); a14 = jit_arg_d(); a15 = jit_arg_d(); a16 = jit_arg_d(); #define SAVE_ARG(N) \ do { \ if (jit_arg_register_p(a##N)) { \ s##N = jit_allocai(sizeof(D)); \ jit_getarg_d(JIT_F0, a##N); \ jit_stxi_d(s##N, JIT_FP, JIT_F0); \ jit_putargi_d(-1, a##N); \ } \ } while (0) SAVE_ARG(1); SAVE_ARG(2); SAVE_ARG(3); SAVE_ARG(4); SAVE_ARG(5); SAVE_ARG(6); SAVE_ARG(7); SAVE_ARG(8); SAVE_ARG(9); SAVE_ARG(10); SAVE_ARG(11); SAVE_ARG(12); SAVE_ARG(13); SAVE_ARG(14); SAVE_ARG(15); SAVE_ARG(16); #undef SAVE_ARG jit_prepare(); { jit_pushargi_d(1); jit_pushargi_d(2); jit_pushargi_d(3); jit_pushargi_d(4); jit_pushargi_d(5); jit_pushargi_d(6); jit_pushargi_d(7); jit_pushargi_d(8); jit_pushargi_d(9); jit_pushargi_d(10); jit_pushargi_d(11); jit_pushargi_d(12); jit_pushargi_d(13); jit_pushargi_d(14); jit_pushargi_d(15); jit_pushargi_d(16); } jit_finishi(cd); #define LOAD_ARG(N) \ do { \ if (jit_arg_register_p(a##N)) { \ jit_ldxi_d(JIT_F0, JIT_FP, s##N); \ jit_putargr_d(JIT_F0, a##N); \ } \ } while (0) LOAD_ARG(1); LOAD_ARG(2); LOAD_ARG(3); LOAD_ARG(4); LOAD_ARG(5); LOAD_ARG(6); LOAD_ARG(7); LOAD_ARG(8); LOAD_ARG(9); LOAD_ARG(10); LOAD_ARG(11); LOAD_ARG(12); LOAD_ARG(13); LOAD_ARG(14); LOAD_ARG(15); LOAD_ARG(16); #undef LOAD_ARG pass = jit_forward(); #define CHECK_ARG(N) \ do { \ jit_getarg_d(JIT_F0, a##N); \ jit_patch_at(jit_beqi_d(JIT_F0, 17 - N), pass); \ } while (0) CHECK_ARG(1); CHECK_ARG(2); CHECK_ARG(3); CHECK_ARG(4); CHECK_ARG(5); CHECK_ARG(6); CHECK_ARG(7); CHECK_ARG(8); CHECK_ARG(9); CHECK_ARG(10); CHECK_ARG(11); CHECK_ARG(12); CHECK_ARG(13); CHECK_ARG(14); CHECK_ARG(15); CHECK_ARG(16); #undef CHECK_ARG jit_calli(abort); jit_link(pass); jit_ret(); jit_epilog(); /* Create a jit function that calls the 3 previous ones. * o First call the function that receives 16 word arguments * o Then call the function that receives 16 float arguments * o Finally call the function that receives 16 double arguments */ jit_patch(jmp); jit_name("main"); jit_note(__FILE__, __LINE__); jit_prolog(); jit_prepare(); { jit_pushargi(16); jit_pushargi(15); jit_pushargi(14); jit_pushargi(13); jit_pushargi(12); jit_pushargi(11); jit_pushargi(10); jit_pushargi(9); jit_pushargi(8); jit_pushargi(7); jit_pushargi(6); jit_pushargi(5); jit_pushargi(4); jit_pushargi(3); jit_pushargi(2); jit_pushargi(1); } jit_patch_at(jit_finishi(NULL), jw); jit_prepare(); { jit_pushargi_f(16); jit_pushargi_f(15); jit_pushargi_f(14); jit_pushargi_f(13); jit_pushargi_f(12); jit_pushargi_f(11); jit_pushargi_f(10); jit_pushargi_f(9); jit_pushargi_f(8); jit_pushargi_f(7); jit_pushargi_f(6); jit_pushargi_f(5); jit_pushargi_f(4); jit_pushargi_f(3); jit_pushargi_f(2); jit_pushargi_f(1); } jit_patch_at(jit_finishi(NULL), jf); jit_prepare(); { jit_pushargi_d(16); jit_pushargi_d(15); jit_pushargi_d(14); jit_pushargi_d(13); jit_pushargi_d(12); jit_pushargi_d(11); jit_pushargi_d(10); jit_pushargi_d(9); jit_pushargi_d(8); jit_pushargi_d(7); jit_pushargi_d(6); jit_pushargi_d(5); jit_pushargi_d(4); jit_pushargi_d(3); jit_pushargi_d(2); jit_pushargi_d(1); } jit_patch_at(jit_finishi(NULL), jd); jit_ret(); jit_epilog(); code = jit_emit(); jit_clear_state(); (*code)(); jit_destroy_state(); finish_jit(); return (0); }