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