1 #include <lightning.h>
2 #include <stdio.h>
3
4 /* Simple test for arguments handling, that also shows how to use
5 * arguments to store values.
6 * Register arguments, if available, are very fast, but are also
7 * very volatile on some ports, because some ports will do C calls
8 * to implement division, remainder, sometimes multiplication, or
9 * some float operations.
10 * Arguments in registers should be fetched in the prolog of the
11 * function, and if they must be saved, they should be saved in
12 * the prolog.
13 * The predicate macro "jit_arg_register_p(arg)" allows knowing if
14 * an argument lives in a register, where it is known for being a very
15 * fast to read/write temporary storage.
16 */
17
18 #define W jit_word_t
19 #define F jit_float32_t
20 #define D jit_float64_t
21
22 jit_state_t *_jit;
23
24 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)25 cw(W a1, W a2, W a3, W a4, W a5, W a6, W a7, W a8,
26 W a9, W a10, W a11, W a12, W a13, W a14, W a15, W a16)
27 {
28 if ( a1 != 1 || a2 != 2 || a3 != 3 || a4 != 4 ||
29 a5 != 5 || a6 != 6 || a7 != 7 || a8 != 8 ||
30 a9 != 9 || a10 != 10 || a11 != 11 || a12 != 12 ||
31 a13 != 13 || a14 != 14 || a15 != 15 || a16 != 16)
32 abort();
33 }
34
35 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)36 cf(F a1, F a2, F a3, F a4, F a5, F a6, F a7, F a8,
37 F a9, F a10, F a11, F a12, F a13, F a14, F a15, F a16)
38 {
39 if ( a1 != 1 || a2 != 2 || a3 != 3 || a4 != 4 ||
40 a5 != 5 || a6 != 6 || a7 != 7 || a8 != 8 ||
41 a9 != 9 || a10 != 10 || a11 != 11 || a12 != 12 ||
42 a13 != 13 || a14 != 14 || a15 != 15 || a16 != 16)
43 abort();
44 }
45
46 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)47 cd(D a1, D a2, D a3, D a4, D a5, D a6, D a7, D a8,
48 D a9, D a10, D a11, D a12, D a13, D a14, D a15, D a16)
49 {
50 if ( a1 != 1 || a2 != 2 || a3 != 3 || a4 != 4 ||
51 a5 != 5 || a6 != 6 || a7 != 7 || a8 != 8 ||
52 a9 != 9 || a10 != 10 || a11 != 11 || a12 != 12 ||
53 a13 != 13 || a14 != 14 || a15 != 15 || a16 != 16)
54 abort();
55 }
56
57 int
main(int argc,char * argv[])58 main(int argc, char *argv[])
59 {
60 void (*code)(void);
61 jit_node_t *jmp, *pass;
62 jit_node_t *jw, *jf, *jd;
63 jit_int32_t s1, s2, s3, s4, s5, s6, s7, s8,
64 s9, s10, s11, s12, s13, s14, s15, s16;
65 jit_node_t *a1, *a2, *a3, *a4, *a5, *a6, *a7, *a8,
66 *a9, *a10, *a11, *a12, *a13, *a14, *a15, *a16;
67
68 init_jit(argv[0]);
69 _jit = jit_new_state();
70
71 /* jump to "main" label */
72 jmp = jit_jmpi();
73
74 /* Create jit function that
75 * o Receives 16 word arguments
76 * o Save in the stack any register argument. Also force register
77 * arguments to be clobbered to properly make the test
78 * o Calls a C function that receives 16 word arguments, with
79 * values different from the ones received by this function
80 * o Reload from stack any register argument
81 * o Validated all arguments were not modified in the known
82 * cases it could have been clobbered
83 */
84 jw = jit_label();
85 jit_name("jw");
86 jit_note(__FILE__, __LINE__);
87 jit_prolog();
88 a1 = jit_arg();
89 a2 = jit_arg();
90 a3 = jit_arg();
91 a4 = jit_arg();
92 a5 = jit_arg();
93 a6 = jit_arg();
94 a7 = jit_arg();
95 a8 = jit_arg();
96 a9 = jit_arg();
97 a10 = jit_arg();
98 a11 = jit_arg();
99 a12 = jit_arg();
100 a13 = jit_arg();
101 a14 = jit_arg();
102 a15 = jit_arg();
103 a16 = jit_arg();
104 #define SAVE_ARG(N) \
105 do { \
106 if (jit_arg_register_p(a##N)) { \
107 s##N = jit_allocai(sizeof(W)); \
108 jit_getarg(JIT_R0, a##N); \
109 jit_stxi(s##N, JIT_FP, JIT_R0); \
110 jit_putargi(-1, a##N); \
111 } \
112 } while (0)
113 SAVE_ARG(1);
114 SAVE_ARG(2);
115 SAVE_ARG(3);
116 SAVE_ARG(4);
117 SAVE_ARG(5);
118 SAVE_ARG(6);
119 SAVE_ARG(7);
120 SAVE_ARG(8);
121 SAVE_ARG(9);
122 SAVE_ARG(10);
123 SAVE_ARG(11);
124 SAVE_ARG(12);
125 SAVE_ARG(13);
126 SAVE_ARG(14);
127 SAVE_ARG(15);
128 SAVE_ARG(16);
129 #undef SAVE_ARG
130 jit_prepare();
131 {
132 jit_pushargi(1);
133 jit_pushargi(2);
134 jit_pushargi(3);
135 jit_pushargi(4);
136 jit_pushargi(5);
137 jit_pushargi(6);
138 jit_pushargi(7);
139 jit_pushargi(8);
140 jit_pushargi(9);
141 jit_pushargi(10);
142 jit_pushargi(11);
143 jit_pushargi(12);
144 jit_pushargi(13);
145 jit_pushargi(14);
146 jit_pushargi(15);
147 jit_pushargi(16);
148 }
149 jit_finishi(cw);
150 #define LOAD_ARG(N) \
151 do { \
152 if (jit_arg_register_p(a##N)) { \
153 jit_ldxi(JIT_R0, JIT_FP, s##N); \
154 jit_putargr(JIT_R0, a##N); \
155 } \
156 } while (0)
157 LOAD_ARG(1);
158 LOAD_ARG(2);
159 LOAD_ARG(3);
160 LOAD_ARG(4);
161 LOAD_ARG(5);
162 LOAD_ARG(6);
163 LOAD_ARG(7);
164 LOAD_ARG(8);
165 LOAD_ARG(9);
166 LOAD_ARG(10);
167 LOAD_ARG(11);
168 LOAD_ARG(12);
169 LOAD_ARG(13);
170 LOAD_ARG(14);
171 LOAD_ARG(15);
172 LOAD_ARG(16);
173 #undef LOAD_ARG
174 pass = jit_forward();
175 #define CHECK_ARG(N) \
176 do { \
177 jit_getarg(JIT_R0, a##N); \
178 jit_patch_at(jit_beqi(JIT_R0, 17 - N), pass); \
179 } while (0)
180 CHECK_ARG(1);
181 CHECK_ARG(2);
182 CHECK_ARG(3);
183 CHECK_ARG(4);
184 CHECK_ARG(5);
185 CHECK_ARG(6);
186 CHECK_ARG(7);
187 CHECK_ARG(8);
188 CHECK_ARG(9);
189 CHECK_ARG(10);
190 CHECK_ARG(11);
191 CHECK_ARG(12);
192 CHECK_ARG(13);
193 CHECK_ARG(14);
194 CHECK_ARG(15);
195 CHECK_ARG(16);
196 #undef CHECK_ARG
197 jit_calli(abort);
198 jit_link(pass);
199 jit_ret();
200 jit_epilog();
201
202 /* Create jit function that
203 * o Receives 16 float arguments
204 * o Save in the stack any register argument. Also force register
205 * arguments to be clobbered to properly make the test
206 * o Calls a C function that receives 16 float arguments, with
207 * values different from the ones received by this function
208 * o Reload from stack any register argument
209 * o Validated all arguments were not modified in the known
210 * cases it could have been clobbered
211 */
212 jf = jit_label();
213 jit_name("jf");
214 jit_note(__FILE__, __LINE__);
215 jit_prolog();
216 a1 = jit_arg_f();
217 a2 = jit_arg_f();
218 a3 = jit_arg_f();
219 a4 = jit_arg_f();
220 a5 = jit_arg_f();
221 a6 = jit_arg_f();
222 a7 = jit_arg_f();
223 a8 = jit_arg_f();
224 a9 = jit_arg_f();
225 a10 = jit_arg_f();
226 a11 = jit_arg_f();
227 a12 = jit_arg_f();
228 a13 = jit_arg_f();
229 a14 = jit_arg_f();
230 a15 = jit_arg_f();
231 a16 = jit_arg_f();
232 #define SAVE_ARG(N) \
233 do { \
234 if (jit_arg_register_p(a##N)) { \
235 s##N = jit_allocai(sizeof(F)); \
236 jit_getarg_f(JIT_F0, a##N); \
237 jit_stxi_f(s##N, JIT_FP, JIT_F0); \
238 jit_putargi_f(-1, a##N); \
239 } \
240 } while (0)
241 SAVE_ARG(1);
242 SAVE_ARG(2);
243 SAVE_ARG(3);
244 SAVE_ARG(4);
245 SAVE_ARG(5);
246 SAVE_ARG(6);
247 SAVE_ARG(7);
248 SAVE_ARG(8);
249 SAVE_ARG(9);
250 SAVE_ARG(10);
251 SAVE_ARG(11);
252 SAVE_ARG(12);
253 SAVE_ARG(13);
254 SAVE_ARG(14);
255 SAVE_ARG(15);
256 SAVE_ARG(16);
257 #undef SAVE_ARG
258 jit_prepare();
259 {
260 jit_pushargi_f(1);
261 jit_pushargi_f(2);
262 jit_pushargi_f(3);
263 jit_pushargi_f(4);
264 jit_pushargi_f(5);
265 jit_pushargi_f(6);
266 jit_pushargi_f(7);
267 jit_pushargi_f(8);
268 jit_pushargi_f(9);
269 jit_pushargi_f(10);
270 jit_pushargi_f(11);
271 jit_pushargi_f(12);
272 jit_pushargi_f(13);
273 jit_pushargi_f(14);
274 jit_pushargi_f(15);
275 jit_pushargi_f(16);
276 }
277 jit_finishi(cf);
278 #define LOAD_ARG(N) \
279 do { \
280 if (jit_arg_register_p(a##N)) { \
281 jit_ldxi_f(JIT_F0, JIT_FP, s##N); \
282 jit_putargr_f(JIT_F0, a##N); \
283 } \
284 } while (0)
285 LOAD_ARG(1);
286 LOAD_ARG(2);
287 LOAD_ARG(3);
288 LOAD_ARG(4);
289 LOAD_ARG(5);
290 LOAD_ARG(6);
291 LOAD_ARG(7);
292 LOAD_ARG(8);
293 LOAD_ARG(9);
294 LOAD_ARG(10);
295 LOAD_ARG(11);
296 LOAD_ARG(12);
297 LOAD_ARG(13);
298 LOAD_ARG(14);
299 LOAD_ARG(15);
300 LOAD_ARG(16);
301 #undef LOAD_ARG
302 pass = jit_forward();
303 #define CHECK_ARG(N) \
304 do { \
305 jit_getarg_f(JIT_F0, a##N); \
306 jit_patch_at(jit_beqi_f(JIT_F0, 17 - N), pass); \
307 } while (0)
308 CHECK_ARG(1);
309 CHECK_ARG(2);
310 CHECK_ARG(3);
311 CHECK_ARG(4);
312 CHECK_ARG(5);
313 CHECK_ARG(6);
314 CHECK_ARG(7);
315 CHECK_ARG(8);
316 CHECK_ARG(9);
317 CHECK_ARG(10);
318 CHECK_ARG(11);
319 CHECK_ARG(12);
320 CHECK_ARG(13);
321 CHECK_ARG(14);
322 CHECK_ARG(15);
323 CHECK_ARG(16);
324 #undef CHECK_ARG
325 jit_calli(abort);
326 jit_link(pass);
327 jit_ret();
328 jit_epilog();
329
330 /* Create jit function that
331 * o Receives 16 double arguments
332 * o Save in the stack any register argument. Also force register
333 * arguments to be clobbered to properly make the test
334 * o Calls a C function that receives 16 double arguments, with
335 * values different from the ones received by this function
336 * o Reload from stack any register argument
337 * o Validated all arguments were not modified in the known
338 * cases it could have been clobbered
339 */
340 jd = jit_label();
341 jit_name("jd");
342 jit_note(__FILE__, __LINE__);
343 jit_prolog();
344 a1 = jit_arg_d();
345 a2 = jit_arg_d();
346 a3 = jit_arg_d();
347 a4 = jit_arg_d();
348 a5 = jit_arg_d();
349 a6 = jit_arg_d();
350 a7 = jit_arg_d();
351 a8 = jit_arg_d();
352 a9 = jit_arg_d();
353 a10 = jit_arg_d();
354 a11 = jit_arg_d();
355 a12 = jit_arg_d();
356 a13 = jit_arg_d();
357 a14 = jit_arg_d();
358 a15 = jit_arg_d();
359 a16 = jit_arg_d();
360 #define SAVE_ARG(N) \
361 do { \
362 if (jit_arg_register_p(a##N)) { \
363 s##N = jit_allocai(sizeof(D)); \
364 jit_getarg_d(JIT_F0, a##N); \
365 jit_stxi_d(s##N, JIT_FP, JIT_F0); \
366 jit_putargi_d(-1, a##N); \
367 } \
368 } while (0)
369 SAVE_ARG(1);
370 SAVE_ARG(2);
371 SAVE_ARG(3);
372 SAVE_ARG(4);
373 SAVE_ARG(5);
374 SAVE_ARG(6);
375 SAVE_ARG(7);
376 SAVE_ARG(8);
377 SAVE_ARG(9);
378 SAVE_ARG(10);
379 SAVE_ARG(11);
380 SAVE_ARG(12);
381 SAVE_ARG(13);
382 SAVE_ARG(14);
383 SAVE_ARG(15);
384 SAVE_ARG(16);
385 #undef SAVE_ARG
386 jit_prepare();
387 {
388 jit_pushargi_d(1);
389 jit_pushargi_d(2);
390 jit_pushargi_d(3);
391 jit_pushargi_d(4);
392 jit_pushargi_d(5);
393 jit_pushargi_d(6);
394 jit_pushargi_d(7);
395 jit_pushargi_d(8);
396 jit_pushargi_d(9);
397 jit_pushargi_d(10);
398 jit_pushargi_d(11);
399 jit_pushargi_d(12);
400 jit_pushargi_d(13);
401 jit_pushargi_d(14);
402 jit_pushargi_d(15);
403 jit_pushargi_d(16);
404 }
405 jit_finishi(cd);
406 #define LOAD_ARG(N) \
407 do { \
408 if (jit_arg_register_p(a##N)) { \
409 jit_ldxi_d(JIT_F0, JIT_FP, s##N); \
410 jit_putargr_d(JIT_F0, a##N); \
411 } \
412 } while (0)
413 LOAD_ARG(1);
414 LOAD_ARG(2);
415 LOAD_ARG(3);
416 LOAD_ARG(4);
417 LOAD_ARG(5);
418 LOAD_ARG(6);
419 LOAD_ARG(7);
420 LOAD_ARG(8);
421 LOAD_ARG(9);
422 LOAD_ARG(10);
423 LOAD_ARG(11);
424 LOAD_ARG(12);
425 LOAD_ARG(13);
426 LOAD_ARG(14);
427 LOAD_ARG(15);
428 LOAD_ARG(16);
429 #undef LOAD_ARG
430 pass = jit_forward();
431 #define CHECK_ARG(N) \
432 do { \
433 jit_getarg_d(JIT_F0, a##N); \
434 jit_patch_at(jit_beqi_d(JIT_F0, 17 - N), pass); \
435 } while (0)
436 CHECK_ARG(1);
437 CHECK_ARG(2);
438 CHECK_ARG(3);
439 CHECK_ARG(4);
440 CHECK_ARG(5);
441 CHECK_ARG(6);
442 CHECK_ARG(7);
443 CHECK_ARG(8);
444 CHECK_ARG(9);
445 CHECK_ARG(10);
446 CHECK_ARG(11);
447 CHECK_ARG(12);
448 CHECK_ARG(13);
449 CHECK_ARG(14);
450 CHECK_ARG(15);
451 CHECK_ARG(16);
452 #undef CHECK_ARG
453 jit_calli(abort);
454 jit_link(pass);
455 jit_ret();
456 jit_epilog();
457
458 /* Create a jit function that calls the 3 previous ones.
459 * o First call the function that receives 16 word arguments
460 * o Then call the function that receives 16 float arguments
461 * o Finally call the function that receives 16 double arguments
462 */
463 jit_patch(jmp);
464 jit_name("main");
465 jit_note(__FILE__, __LINE__);
466 jit_prolog();
467 jit_prepare();
468 {
469 jit_pushargi(16);
470 jit_pushargi(15);
471 jit_pushargi(14);
472 jit_pushargi(13);
473 jit_pushargi(12);
474 jit_pushargi(11);
475 jit_pushargi(10);
476 jit_pushargi(9);
477 jit_pushargi(8);
478 jit_pushargi(7);
479 jit_pushargi(6);
480 jit_pushargi(5);
481 jit_pushargi(4);
482 jit_pushargi(3);
483 jit_pushargi(2);
484 jit_pushargi(1);
485 }
486 jit_patch_at(jit_finishi(NULL), jw);
487 jit_prepare();
488 {
489 jit_pushargi_f(16);
490 jit_pushargi_f(15);
491 jit_pushargi_f(14);
492 jit_pushargi_f(13);
493 jit_pushargi_f(12);
494 jit_pushargi_f(11);
495 jit_pushargi_f(10);
496 jit_pushargi_f(9);
497 jit_pushargi_f(8);
498 jit_pushargi_f(7);
499 jit_pushargi_f(6);
500 jit_pushargi_f(5);
501 jit_pushargi_f(4);
502 jit_pushargi_f(3);
503 jit_pushargi_f(2);
504 jit_pushargi_f(1);
505 }
506 jit_patch_at(jit_finishi(NULL), jf);
507 jit_prepare();
508 {
509 jit_pushargi_d(16);
510 jit_pushargi_d(15);
511 jit_pushargi_d(14);
512 jit_pushargi_d(13);
513 jit_pushargi_d(12);
514 jit_pushargi_d(11);
515 jit_pushargi_d(10);
516 jit_pushargi_d(9);
517 jit_pushargi_d(8);
518 jit_pushargi_d(7);
519 jit_pushargi_d(6);
520 jit_pushargi_d(5);
521 jit_pushargi_d(4);
522 jit_pushargi_d(3);
523 jit_pushargi_d(2);
524 jit_pushargi_d(1);
525 }
526 jit_patch_at(jit_finishi(NULL), jd);
527 jit_ret();
528 jit_epilog();
529
530 code = jit_emit();
531 jit_clear_state();
532
533 (*code)();
534
535 jit_destroy_state();
536 finish_jit();
537 return (0);
538 }
539