2 * Copyright (C) 2022-2023 Free Software Foundation, Inc.
4 * This file is part of GNU lightning.
6 * GNU lightning is free software; you can redistribute it and/or modify it
7 * under the terms of the GNU Lesser General Public License as published
8 * by the Free Software Foundation; either version 3, or (at your option)
11 * GNU lightning is distributed in the hope that it will be useful, but
12 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
13 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
14 * License for more details.
17 * Paulo Cesar Pereira de Andrade
20 /* callee save + variadic arguments
21 * align16(ra+fp+s[0-8]+fs[0-7]) + align16(a[0-7]) */
22 #define stack_framesize (144 + 64)
24 #define jit_arg_reg_p(i) ((i) >= 0 && (i) < 8)
25 #define jit_arg_f_reg_p(i) ((i) >= 0 && (i) < 8)
30 typedef struct jit_pointer_t jit_va_list_t;
35 #define compute_framesize() _compute_framesize(_jit)
36 static void _compute_framesize(jit_state_t*);
37 #define patch(instr, node) _patch(_jit, instr, node)
38 static void _patch(jit_state_t*,jit_word_t,jit_node_t*);
41 # include "jit_loongarch-cpu.c"
42 # include "jit_loongarch-fpu.c"
48 jit_register_t _rvs[] = {
49 { rc(gpr) | 0x14, "$t8" },
50 { rc(gpr) | 0x13, "$t7" },
51 { rc(gpr) | 0x12, "$t6" },
52 { rc(gpr) | 0x11, "$t5" },
53 { rc(gpr) | 0x10, "$t4" },
54 { rc(gpr) | 0x0f, "$t3" },
55 { rc(gpr) | 0x0e, "$t2" },
56 { rc(gpr) | 0x0d, "$t1" },
57 { rc(gpr) | 0x0c, "$t0" },
58 { rc(sav) | rc(gpr) | 0x1f, "$s8" },
59 { rc(sav) | rc(gpr) | 0x1e, "$s7" },
60 { rc(sav) | rc(gpr) | 0x1d, "$s6" },
61 { rc(sav) | rc(gpr) | 0x1c, "$s5" },
62 { rc(sav) | rc(gpr) | 0x1b, "$s4" },
63 { rc(sav) | rc(gpr) | 0x1a, "$s3" },
64 { rc(sav) | rc(gpr) | 0x19, "$s2" },
65 { rc(sav) | rc(gpr) | 0x18, "$s1" },
66 { rc(sav) | rc(gpr) | 0x17, "$s0" },
67 { rc(arg) | rc(gpr) | 0x0b, "$a7" },
68 { rc(arg) | rc(gpr) | 0x0a, "$a6" },
69 { rc(arg) | rc(gpr) | 0x09, "$a5" },
70 { rc(arg) | rc(gpr) | 0x08, "$a4" },
71 { rc(arg) | rc(gpr) | 0x07, "$a3" },
72 { rc(arg) | rc(gpr) | 0x06, "$a2" },
73 { rc(arg) | rc(gpr) | 0x05, "$a1" },
74 { rc(arg) | rc(gpr) | 0x04, "$a0" },
76 { 0x15, "<reserved>" },
81 { rc(fpr) | 0x08, "$ft0" },
82 { rc(fpr) | 0x09, "$ft1" },
83 { rc(fpr) | 0x0a, "$ft2" },
84 { rc(fpr) | 0x0b, "$ft3" },
85 { rc(fpr) | 0x0c, "$ft4" },
86 { rc(fpr) | 0x0d, "$ft5" },
87 { rc(fpr) | 0x0e, "$ft6" },
88 { rc(fpr) | 0x0f, "$ft7" },
89 { rc(fpr) | 0x10, "$ft8" },
90 { rc(fpr) | 0x11, "$ft9" },
91 { rc(fpr) | 0x12, "$ft10" },
92 { rc(fpr) | 0x13, "$ft11" },
93 { rc(fpr) | 0x14, "$ft12" },
94 { rc(fpr) | 0x15, "$ft13" },
95 { rc(fpr) | 0x16, "$ft14" },
96 { rc(fpr) | 0x17, "$ft15" },
97 { rc(arg) | rc(fpr) | 0x07, "$fa7" },
98 { rc(arg) | rc(fpr) | 0x06, "$fa6" },
99 { rc(arg) | rc(fpr) | 0x05, "$fa5" },
100 { rc(arg) | rc(fpr) | 0x04, "$fa4" },
101 { rc(arg) | rc(fpr) | 0x03, "$fa3" },
102 { rc(arg) | rc(fpr) | 0x02, "$fa2" },
103 { rc(arg) | rc(fpr) | 0x01, "$fa1" },
104 { rc(arg) | rc(fpr) | 0x00, "$fa0" },
105 { rc(sav) | rc(fpr) | 0x1f, "$fs7" },
106 { rc(sav) | rc(fpr) | 0x1e, "$fs6" },
107 { rc(sav) | rc(fpr) | 0x1d, "$fs5" },
108 { rc(sav) | rc(fpr) | 0x1c, "$fs4" },
109 { rc(sav) | rc(fpr) | 0x1b, "$fs3" },
110 { rc(sav) | rc(fpr) | 0x1a, "$fs2" },
111 { rc(sav) | rc(fpr) | 0x19, "$fs1" },
112 { rc(sav) | rc(fpr) | 0x18, "$fs0" },
113 { _NOREG, "<none>" },
116 static jit_int32_t iregs[] = {
117 _S0, _S1, _S2, _S3, _S4, _S5, _S6, _S7, _S8
120 static jit_int32_t fregs[] = {
121 _FS0, _FS1, _FS2, _FS3, _FS4, _FS5, _FS6, _FS7
133 _jit_init(jit_state_t *_jit)
135 _jitc->reglen = jit_size(_rvs) - 1;
140 _jit_prolog(jit_state_t *_jit)
146 assert(jit_regset_cmp_ui(&_jitc->regarg, 0) == 0);
147 jit_regset_set_ui(&_jitc->regsav, 0);
148 offset = _jitc->functions.offset;
149 if (offset >= _jitc->functions.length) {
150 jit_realloc((jit_pointer_t *)&_jitc->functions.ptr,
151 _jitc->functions.length * sizeof(jit_function_t),
152 (_jitc->functions.length + 16) * sizeof(jit_function_t));
153 _jitc->functions.length += 16;
155 _jitc->function = _jitc->functions.ptr + _jitc->functions.offset++;
156 _jitc->function->self.size = stack_framesize;
157 _jitc->function->self.argi = _jitc->function->self.argf =
158 _jitc->function->self.aoff = _jitc->function->self.alen = 0;
159 _jitc->function->self.call = jit_call_default;
160 jit_alloc((jit_pointer_t *)&_jitc->function->regoff,
161 _jitc->reglen * sizeof(jit_int32_t));
163 /* _no_link here does not mean the jit_link() call can be removed
165 * _jitc->function->prolog = jit_new_node(jit_code_prolog);
167 _jitc->function->prolog = jit_new_node_no_link(jit_code_prolog);
168 jit_link(_jitc->function->prolog);
169 _jitc->function->prolog->w.w = offset;
170 _jitc->function->epilog = jit_new_node_no_link(jit_code_epilog);
172 * v: offset in blocks vector
173 * w: offset in functions vector
175 _jitc->function->epilog->w.w = offset;
177 jit_regset_new(&_jitc->function->regset);
181 _jit_allocai(jit_state_t *_jit, jit_int32_t length)
183 assert(_jitc->function);
186 case 0: case 1: break;
187 case 2: _jitc->function->self.aoff &= -2; break;
188 case 3: case 4: _jitc->function->self.aoff &= -4; break;
189 default: _jitc->function->self.aoff &= -8; break;
191 _jitc->function->self.aoff -= length;
192 if (!_jitc->realize) {
193 jit_inc_synth_ww(allocai, _jitc->function->self.aoff, length);
196 return (_jitc->function->self.aoff);
200 _jit_allocar(jit_state_t *_jit, jit_int32_t u, jit_int32_t v)
203 assert(_jitc->function);
204 jit_inc_synth_ww(allocar, u, v);
205 if (!_jitc->function->allocar) {
206 _jitc->function->aoffoff = jit_allocai(sizeof(jit_int32_t));
207 _jitc->function->allocar = 1;
209 reg = jit_get_reg(jit_class_gpr);
211 jit_andi(reg, reg, -16);
212 jit_ldxi_i(u, JIT_FP, _jitc->function->aoffoff);
214 jit_addr(JIT_SP, JIT_SP, reg);
215 jit_stxi_i(_jitc->function->aoffoff, JIT_FP, u);
221 _jit_ret(jit_state_t *_jit)
224 assert(_jitc->function);
228 jit_patch_at(instr, _jitc->function->epilog);
233 _jit_retr(jit_state_t *_jit, jit_int32_t u, jit_code_t code)
235 jit_code_inc_synth_w(code, u);
236 jit_movr(JIT_RET, u);
242 _jit_reti(jit_state_t *_jit, jit_word_t u, jit_code_t code)
244 jit_code_inc_synth_w(code, u);
245 jit_movi(JIT_RET, u);
251 _jit_retr_f(jit_state_t *_jit, jit_int32_t u)
253 jit_inc_synth_w(retr_f, u);
255 jit_movr_f(JIT_FRET, u);
263 _jit_reti_f(jit_state_t *_jit, jit_float32_t u)
265 jit_inc_synth_f(reti_f, u);
266 jit_movi_f(JIT_FRET, u);
272 _jit_retr_d(jit_state_t *_jit, jit_int32_t u)
274 jit_inc_synth_w(retr_d, u);
276 jit_movr_d(JIT_FRET, u);
284 _jit_reti_d(jit_state_t *_jit, jit_float64_t u)
286 jit_inc_synth_d(reti_d, u);
287 jit_movi_d(JIT_FRET, u);
293 _jit_epilog(jit_state_t *_jit)
295 assert(_jitc->function);
296 assert(_jitc->function->epilog->next == NULL);
297 jit_link(_jitc->function->epilog);
298 _jitc->function = NULL;
302 _jit_arg_register_p(jit_state_t *_jit, jit_node_t *u)
304 if (u->code >= jit_code_arg_c && u->code <= jit_code_arg)
305 return (jit_arg_reg_p(u->u.w));
306 assert(u->code == jit_code_arg_f || u->code == jit_code_arg_d);
307 return (jit_arg_f_reg_p(u->u.w) || jit_arg_reg_p(u->u.w - 8));
311 _jit_ellipsis(jit_state_t *_jit)
313 jit_inc_synth(ellipsis);
315 if (_jitc->prepare) {
317 assert(!(_jitc->function->call.call & jit_call_varargs));
318 _jitc->function->call.call |= jit_call_varargs;
322 assert(!(_jitc->function->self.call & jit_call_varargs));
323 _jitc->function->self.call |= jit_call_varargs;
324 _jitc->function->vagp = _jitc->function->self.argi;
330 _jit_va_push(jit_state_t *_jit, jit_int32_t u)
332 jit_inc_synth_w(va_push, u);
338 _jit_arg(jit_state_t *_jit, jit_code_t code)
342 assert(_jitc->function);
343 assert(!(_jitc->function->self.call & jit_call_varargs));
344 #if STRONG_TYPE_CHECKING
345 assert(code >= jit_code_arg_c && code <= jit_code_arg);
347 if (jit_arg_reg_p(_jitc->function->self.argi))
348 offset = _jitc->function->self.argi++;
350 offset = _jitc->function->self.size;
351 _jitc->function->self.size += sizeof(jit_word_t);
354 node = jit_new_node_ww(code, offset,
355 ++_jitc->function->self.argn);
361 _jit_arg_f(jit_state_t *_jit)
365 assert(_jitc->function);
366 assert(!(_jitc->function->self.call & jit_call_varargs));
367 if (jit_arg_f_reg_p(_jitc->function->self.argf))
368 offset = _jitc->function->self.argf++;
369 else if (jit_arg_reg_p(_jitc->function->self.argi)) {
370 offset = _jitc->function->self.argi++;
374 offset = _jitc->function->self.size;
375 _jitc->function->self.size += sizeof(jit_word_t);
378 node = jit_new_node_ww(jit_code_arg_f, offset,
379 ++_jitc->function->self.argn);
385 _jit_arg_d(jit_state_t *_jit)
389 assert(_jitc->function);
390 assert(!(_jitc->function->self.call & jit_call_varargs));
391 if (jit_arg_f_reg_p(_jitc->function->self.argf))
392 offset = _jitc->function->self.argf++;
393 else if (jit_arg_reg_p(_jitc->function->self.argi)) {
394 offset = _jitc->function->self.argi++;
398 offset = _jitc->function->self.size;
399 _jitc->function->self.size += sizeof(jit_word_t);
402 node = jit_new_node_ww(jit_code_arg_d, offset,
403 ++_jitc->function->self.argn);
409 _jit_getarg_c(jit_state_t *_jit, jit_int32_t u, jit_node_t *v)
411 assert_arg_type(v->code, jit_code_arg_c);
412 jit_inc_synth_wp(getarg_c, u, v);
413 if (jit_arg_reg_p(v->u.w))
414 jit_extr_c(u, _A0 - v->u.w);
416 jit_node_t *node = jit_ldxi_c(u, JIT_FP, v->u.w);
417 jit_link_alist(node);
423 _jit_getarg_uc(jit_state_t *_jit, jit_int32_t u, jit_node_t *v)
425 assert_arg_type(v->code, jit_code_arg_c);
426 jit_inc_synth_wp(getarg_uc, u, v);
427 if (jit_arg_reg_p(v->u.w))
428 jit_extr_uc(u, _A0 - v->u.w);
430 jit_node_t *node = jit_ldxi_uc(u, JIT_FP, v->u.w);
431 jit_link_alist(node);
437 _jit_getarg_s(jit_state_t *_jit, jit_int32_t u, jit_node_t *v)
439 assert_arg_type(v->code, jit_code_arg_s);
440 jit_inc_synth_wp(getarg_s, u, v);
441 if (jit_arg_reg_p(v->u.w))
442 jit_extr_s(u, _A0 - v->u.w);
444 jit_node_t *node = jit_ldxi_s(u, JIT_FP, v->u.w);
445 jit_link_alist(node);
451 _jit_getarg_us(jit_state_t *_jit, jit_int32_t u, jit_node_t *v)
453 assert_arg_type(v->code, jit_code_arg_s);
454 jit_inc_synth_wp(getarg_us, u, v);
455 if (jit_arg_reg_p(v->u.w))
456 jit_extr_us(u, _A0 - v->u.w);
458 jit_node_t *node = jit_ldxi_us(u, JIT_FP, v->u.w);
459 jit_link_alist(node);
465 _jit_getarg_i(jit_state_t *_jit, jit_int32_t u, jit_node_t *v)
467 assert_arg_type(v->code, jit_code_arg_i);
468 jit_inc_synth_wp(getarg_i, u, v);
469 if (jit_arg_reg_p(v->u.w))
470 jit_extr_i(u, _A0 - v->u.w);
472 jit_node_t *node = jit_ldxi_i(u, JIT_FP, v->u.w);
473 jit_link_alist(node);
479 _jit_getarg_ui(jit_state_t *_jit, jit_int32_t u, jit_node_t *v)
481 assert_arg_type(v->code, jit_code_arg_i);
482 jit_inc_synth_wp(getarg_ui, u, v);
483 if (jit_arg_reg_p(v->u.w))
484 jit_extr_ui(u, _A0 - v->u.w);
486 jit_node_t *node = jit_ldxi_ui(u, JIT_FP, v->u.w);
487 jit_link_alist(node);
493 _jit_getarg_l(jit_state_t *_jit, jit_int32_t u, jit_node_t *v)
495 assert_arg_type(v->code, jit_code_arg_l);
496 jit_inc_synth_wp(getarg_l, u, v);
497 if (jit_arg_reg_p(v->u.w))
498 jit_movr(u, _A0 - v->u.w);
500 jit_node_t *node = jit_ldxi_l(u, JIT_FP, v->u.w);
501 jit_link_alist(node);
507 _jit_putargr(jit_state_t *_jit, jit_int32_t u, jit_node_t *v, jit_code_t code)
509 assert_putarg_type(code, v->code);
510 jit_code_inc_synth_wp(code, u, v);
511 if (jit_arg_reg_p(v->u.w))
512 jit_movr(_A0 - v->u.w, u);
514 jit_node_t *node = jit_stxi(v->u.w, JIT_FP, u);
515 jit_link_alist(node);
521 _jit_putargi(jit_state_t *_jit, jit_word_t u, jit_node_t *v, jit_code_t code)
524 assert_putarg_type(code, v->code);
525 jit_code_inc_synth_wp(code, u, v);
526 if (jit_arg_reg_p(v->u.w))
527 jit_movi(_A0 - v->u.w, u);
530 regno = jit_get_reg(jit_class_gpr);
532 node = jit_stxi(v->u.w, JIT_FP, regno);
533 jit_link_alist(node);
534 jit_unget_reg(regno);
540 _jit_getarg_f(jit_state_t *_jit, jit_int32_t u, jit_node_t *v)
542 assert(v->code == jit_code_arg_f);
543 jit_inc_synth_wp(getarg_f, u, v);
544 if (jit_arg_f_reg_p(v->u.w))
545 jit_movr_f(u, _FA0 - v->u.w);
546 else if (jit_arg_reg_p(v->u.w - 8))
547 jit_movr_w_f(u, JIT_RA0 - (v->u.w - 8));
549 jit_node_t *node = jit_ldxi_f(u, JIT_FP, v->u.w);
550 jit_link_alist(node);
556 _jit_putargr_f(jit_state_t *_jit, jit_int32_t u, jit_node_t *v)
558 assert(v->code == jit_code_arg_f);
559 jit_inc_synth_wp(putargr_f, u, v);
560 if (jit_arg_f_reg_p(v->u.w))
561 jit_movr_f(_FA0 - v->u.w, u);
562 else if (jit_arg_reg_p(v->u.w - 8))
563 jit_movr_f_w(JIT_RA0 - (v->u.w - 8), u);
565 jit_node_t *node = jit_stxi_f(v->u.w, JIT_FP, u);
566 jit_link_alist(node);
572 _jit_putargi_f(jit_state_t *_jit, jit_float32_t u, jit_node_t *v)
575 assert(v->code == jit_code_arg_f);
576 jit_inc_synth_fp(putargi_f, u, v);
577 if (jit_arg_f_reg_p(v->u.w))
578 jit_movi_f(_FA0 - v->u.w, u);
579 else if (jit_arg_reg_p(v->u.w - 8))
580 jit_movi_f_w(JIT_RA0 - (v->u.w - 8), u);
583 regno = jit_get_reg(jit_class_fpr);
584 jit_movi_f(regno, u);
585 node = jit_stxi_f(v->u.w, JIT_FP, regno);
586 jit_link_alist(node);
587 jit_unget_reg(regno);
593 _jit_getarg_d(jit_state_t *_jit, jit_int32_t u, jit_node_t *v)
595 assert(v->code == jit_code_arg_d);
596 jit_inc_synth_wp(getarg_d, u, v);
597 if (jit_arg_f_reg_p(v->u.w))
598 jit_movr_d(u, _FA0 - v->u.w);
599 else if (jit_arg_reg_p(v->u.w - 8))
600 jit_movr_w_d(u, JIT_RA0 - (v->u.w - 8));
602 jit_node_t *node = jit_ldxi_d(u, JIT_FP, v->u.w);
603 jit_link_alist(node);
609 _jit_putargr_d(jit_state_t *_jit, jit_int32_t u, jit_node_t *v)
611 assert(v->code == jit_code_arg_d);
612 jit_inc_synth_wp(putargr_d, u, v);
613 if (jit_arg_f_reg_p(v->u.w))
614 jit_movr_d(_FA0 - v->u.w, u);
615 else if (jit_arg_reg_p(v->u.w - 8))
616 jit_movr_d_w(JIT_RA0 - (v->u.w - 8), u);
618 jit_node_t *node = jit_stxi_d(v->u.w, JIT_FP, u);
619 jit_link_alist(node);
625 _jit_putargi_d(jit_state_t *_jit, jit_float64_t u, jit_node_t *v)
628 assert(v->code == jit_code_arg_d);
629 jit_inc_synth_dp(putargi_d, u, v);
630 if (jit_arg_f_reg_p(v->u.w))
631 jit_movi_d(_FA0 - v->u.w, u);
632 else if (jit_arg_reg_p(v->u.w - 8))
633 jit_movi_d_w(JIT_RA0 - (v->u.w - 8), u);
636 regno = jit_get_reg(jit_class_fpr);
637 jit_movi_d(regno, u);
638 node = jit_stxi_d(v->u.w, JIT_FP, regno);
639 jit_link_alist(node);
640 jit_unget_reg(regno);
646 _jit_pushargr(jit_state_t *_jit, jit_int32_t u, jit_code_t code)
648 assert(_jitc->function);
649 jit_code_inc_synth_w(code, u);
651 if (jit_arg_reg_p(_jitc->function->call.argi)) {
652 jit_movr(_A0 - _jitc->function->call.argi, u);
653 ++_jitc->function->call.argi;
656 jit_stxi(_jitc->function->call.size, JIT_SP, u);
657 _jitc->function->call.size += sizeof(jit_word_t);
664 _jit_pushargi(jit_state_t *_jit, jit_word_t u, jit_code_t code)
667 assert(_jitc->function);
668 jit_code_inc_synth_w(code, u);
670 if (jit_arg_reg_p(_jitc->function->call.argi)) {
671 jit_movi(_A0 - _jitc->function->call.argi, u);
672 ++_jitc->function->call.argi;
675 regno = jit_get_reg(jit_class_gpr);
677 jit_stxi(_jitc->function->call.size, JIT_SP, regno);
678 jit_unget_reg(regno);
679 _jitc->function->call.size += sizeof(jit_word_t);
686 _jit_pushargr_f(jit_state_t *_jit, jit_int32_t u)
688 assert(_jitc->function);
689 jit_inc_synth_w(pushargr_f, u);
691 if (jit_arg_f_reg_p(_jitc->function->call.argf) &&
692 !(_jitc->function->call.call & jit_call_varargs)) {
693 jit_movr_f(_FA0 - _jitc->function->call.argf, u);
694 ++_jitc->function->call.argf;
696 else if (jit_arg_reg_p(_jitc->function->call.argi)) {
697 jit_movr_f_w(_A0 - _jitc->function->call.argi, u);
698 ++_jitc->function->call.argi;
701 jit_stxi_f(_jitc->function->call.size, JIT_SP, u);
702 _jitc->function->call.size += sizeof(jit_word_t);
709 _jit_pushargi_f(jit_state_t *_jit, jit_float32_t u)
712 assert(_jitc->function);
713 jit_inc_synth_f(pushargi_f, u);
715 if (jit_arg_f_reg_p(_jitc->function->call.argf) &&
716 !(_jitc->function->call.call & jit_call_varargs)) {
717 jit_movi_f(_FA0 - _jitc->function->call.argf, u);
718 ++_jitc->function->call.argf;
720 else if (jit_arg_reg_p(_jitc->function->call.argi)) {
721 jit_movi_f_w(_A0 - _jitc->function->call.argi, u);
722 ++_jitc->function->call.argi;
725 regno = jit_get_reg(jit_class_fpr);
726 jit_movi_f(regno, u);
727 jit_stxi_f(_jitc->function->call.size, JIT_SP, regno);
728 jit_unget_reg(regno);
729 _jitc->function->call.size += sizeof(jit_word_t);
736 _jit_pushargr_d(jit_state_t *_jit, jit_int32_t u)
738 assert(_jitc->function);
739 jit_inc_synth_w(pushargr_d, u);
741 if (jit_arg_f_reg_p(_jitc->function->call.argf) &&
742 !(_jitc->function->call.call & jit_call_varargs)) {
743 jit_movr_d(_FA0 - _jitc->function->call.argf, u);
744 ++_jitc->function->call.argf;
746 else if (jit_arg_reg_p(_jitc->function->call.argi)) {
747 jit_movr_d_w(_A0 - _jitc->function->call.argi, u);
748 ++_jitc->function->call.argi;
751 jit_stxi_d(_jitc->function->call.size, JIT_SP, u);
752 _jitc->function->call.size += sizeof(jit_word_t);
759 _jit_pushargi_d(jit_state_t *_jit, jit_float64_t u)
762 assert(_jitc->function);
763 jit_inc_synth_d(pushargi_d, u);
765 if (jit_arg_f_reg_p(_jitc->function->call.argf) &&
766 !(_jitc->function->call.call & jit_call_varargs)) {
767 jit_movi_d(_FA0 - _jitc->function->call.argf, u);
768 ++_jitc->function->call.argf;
770 else if (jit_arg_reg_p(_jitc->function->call.argi)) {
771 jit_movi_d_w(_A0 - _jitc->function->call.argi, u);
772 ++_jitc->function->call.argi;
775 regno = jit_get_reg(jit_class_fpr);
776 jit_movi_d(regno, u);
777 jit_stxi_d(_jitc->function->call.size, JIT_SP, regno);
778 jit_unget_reg(regno);
779 _jitc->function->call.size += sizeof(jit_word_t);
786 _jit_regarg_p(jit_state_t *_jit, jit_node_t *node, jit_int32_t regno)
789 spec = jit_class(_rvs[regno].spec);
790 if (spec & jit_class_arg) {
792 if (regno >= 0 && regno < node->v.w)
794 if (spec & jit_class_fpr) {
795 regno = _FA0 - regno;
796 if (regno >= 0 && regno < node->w.w)
804 _jit_finishr(jit_state_t *_jit, jit_int32_t r0)
807 assert(_jitc->function);
809 jit_inc_synth_w(finishr, r0);
810 if (_jitc->function->self.alen < _jitc->function->call.size)
811 _jitc->function->self.alen = _jitc->function->call.size;
812 node = jit_callr(r0);
813 node->v.w = _jitc->function->call.argi;
814 node->w.w = _jitc->function->call.argf;
815 _jitc->function->call.argi = _jitc->function->call.argf =
816 _jitc->function->call.size = 0;
822 _jit_finishi(jit_state_t *_jit, jit_pointer_t i0)
825 assert(_jitc->function);
827 jit_inc_synth_w(finishi, (jit_word_t)i0);
828 if (_jitc->function->self.alen < _jitc->function->call.size)
829 _jitc->function->self.alen = _jitc->function->call.size;
830 node = jit_calli(i0);
831 node->v.w = _jitc->function->call.argi;
832 node->w.w = _jitc->function->call.argf;
833 _jitc->function->call.argi = _jitc->function->call.argf =
834 _jitc->function->call.size = 0;
841 _jit_retval_c(jit_state_t *_jit, jit_int32_t r0)
843 jit_inc_synth_w(retval_c, r0);
844 jit_extr_c(r0, JIT_RET);
849 _jit_retval_uc(jit_state_t *_jit, jit_int32_t r0)
851 jit_inc_synth_w(retval_uc, r0);
852 jit_extr_uc(r0, JIT_RET);
857 _jit_retval_s(jit_state_t *_jit, jit_int32_t r0)
859 jit_inc_synth_w(retval_s, r0);
860 jit_extr_s(r0, JIT_RET);
865 _jit_retval_us(jit_state_t *_jit, jit_int32_t r0)
867 jit_inc_synth_w(retval_us, r0);
868 jit_extr_us(r0, JIT_RET);
873 _jit_retval_i(jit_state_t *_jit, jit_int32_t r0)
875 jit_inc_synth_w(retval_i, r0);
876 jit_extr_i(r0, JIT_RET);
881 _jit_retval_ui(jit_state_t *_jit, jit_int32_t r0)
883 jit_inc_synth_w(retval_ui, r0);
884 jit_extr_ui(r0, JIT_RET);
889 _jit_retval_l(jit_state_t *_jit, jit_int32_t r0)
891 jit_inc_synth_w(retval_l, r0);
893 jit_movr(r0, JIT_RET);
898 _jit_retval_f(jit_state_t *_jit, jit_int32_t r0)
900 jit_inc_synth_w(retval_f, r0);
902 jit_movr_f(r0, JIT_FRET);
907 _jit_retval_d(jit_state_t *_jit, jit_int32_t r0)
909 jit_inc_synth_w(retval_d, r0);
911 jit_movr_d(r0, JIT_FRET);
916 _emit_code(jit_state_t *_jit)
927 #if DEVEL_DISASSEMBLER
930 jit_int32_t patch_offset;
932 #if DEVEL_DISASSEMBLER
936 _jitc->function = NULL;
942 undo.patch_offset = 0;
944 #define assert_data(node) /**/
945 #define case_rr(name, type) \
946 case jit_code_##name##r##type: \
947 name##r##type(rn(node->u.w), rn(node->v.w)); \
949 #define case_rw(name, type) \
950 case jit_code_##name##i##type: \
951 name##i##type(rn(node->u.w), node->v.w); \
953 #define case_wr(name, type) \
954 case jit_code_##name##i##type: \
955 name##i##type(node->u.w, rn(node->v.w)); \
957 #define case_rrr(name, type) \
958 case jit_code_##name##r##type: \
959 name##r##type(rn(node->u.w), \
960 rn(node->v.w), rn(node->w.w)); \
962 #define case_rrrr(name, type) \
963 case jit_code_##name##r##type: \
964 name##r##type(rn(node->u.q.l), rn(node->u.q.h), \
965 rn(node->v.w), rn(node->w.w)); \
967 #define case_rrw(name, type) \
968 case jit_code_##name##i##type: \
969 name##i##type(rn(node->u.w), rn(node->v.w), node->w.w); \
971 #define case_rrrw(name, type) \
972 case jit_code_##name##i##type: \
973 name##i##type(rn(node->u.q.l), rn(node->u.q.h), \
974 rn(node->v.w), node->w.w); \
976 #define case_rrf(name) \
977 case jit_code_##name##i_f: \
979 name##i_f(rn(node->u.w), rn(node->v.w), node->w.f); \
981 #define case_rrd(name) \
982 case jit_code_##name##i_d: \
984 name##i_d(rn(node->u.w), rn(node->v.w),node->w.d); \
986 #define case_wrr(name, type) \
987 case jit_code_##name##i##type: \
988 name##i##type(node->u.w, rn(node->v.w), rn(node->w.w)); \
990 #define case_brr(name, type) \
991 case jit_code_##name##r##type: \
993 assert(temp->code == jit_code_label || \
994 temp->code == jit_code_epilog); \
995 if (temp->flag & jit_flag_patch) \
996 name##r##type(temp->u.w, rn(node->v.w), \
999 word = name##r##type(_jit->pc.w, \
1002 patch(word, node); \
1005 #define case_brw(name, type) \
1006 case jit_code_##name##i##type: \
1008 assert(temp->code == jit_code_label || \
1009 temp->code == jit_code_epilog); \
1010 if (temp->flag & jit_flag_patch) \
1011 name##i##type(temp->u.w, \
1012 rn(node->v.w), node->w.w); \
1014 word = name##i##type(_jit->pc.w, \
1015 rn(node->v.w), node->w.w); \
1016 patch(word, node); \
1019 #define case_brf(name) \
1020 case jit_code_##name##i_f: \
1022 assert(temp->code == jit_code_label || \
1023 temp->code == jit_code_epilog); \
1024 if (temp->flag & jit_flag_patch) \
1025 name##i_f(temp->u.w, rn(node->v.w), node->w.f); \
1027 word = name##i_f(_jit->pc.w, rn(node->v.w), \
1029 patch(word, node); \
1032 #define case_brd(name) \
1033 case jit_code_##name##i_d: \
1035 assert(temp->code == jit_code_label || \
1036 temp->code == jit_code_epilog); \
1037 if (temp->flag & jit_flag_patch) \
1038 name##i_d(temp->u.w, rn(node->v.w), node->w.d); \
1040 word = name##i_d(_jit->pc.w, rn(node->v.w), \
1042 patch(word, node); \
1045 #if DEVEL_DISASSEMBLER
1048 for (node = _jitc->head; node; node = node->next) {
1049 if (_jit->pc.uc >= _jitc->code.end)
1052 #if DEVEL_DISASSEMBLER
1053 node->offset = (jit_uword_t)_jit->pc.w - (jit_uword_t)prevw;
1056 value = jit_classify(node->code);
1057 jit_regarg_set(node, value);
1058 switch (node->code) {
1059 case jit_code_align:
1060 /* Must align to a power of two */
1061 assert(!(node->u.w & (node->u.w - 1)));
1062 if ((word = _jit->pc.w & (node->u.w - 1)))
1063 nop(node->u.w - word);
1066 nop((node->u.w + 3) & ~3);
1068 case jit_code_note: case jit_code_name:
1069 node->u.w = _jit->pc.w;
1071 case jit_code_label:
1072 /* remember label is defined */
1073 node->flag |= jit_flag_patch;
1074 node->u.w = _jit->pc.w;
1093 case_rrrr(qmul, _u);
1094 case_rrrw(qmul, _u);
1105 case_rrrr(qdiv, _u);
1106 case_rrrw(qdiv, _u);
1125 case_rr(trunc, _f_i);
1126 case_rr(trunc, _d_i);
1127 case_rr(trunc, _f_l);
1128 case_rr(trunc, _d_l);
1176 case_rr(bswap, _us);
1177 case_rr(bswap, _ui);
1178 case_rr(bswap, _ul);
1186 casr(rn(node->u.w), rn(node->v.w),
1187 rn(node->w.q.l), rn(node->w.q.h));
1190 casi(rn(node->u.w), node->v.w,
1191 rn(node->w.q.l), rn(node->w.q.h));
1197 if (node->flag & jit_flag_node) {
1199 if (temp->code == jit_code_data ||
1200 (temp->code == jit_code_label &&
1201 (temp->flag & jit_flag_patch)))
1202 movi(rn(node->u.w), temp->u.w);
1204 assert(temp->code == jit_code_label ||
1205 temp->code == jit_code_epilog);
1206 word = movi_p(rn(node->u.w), temp->u.w);
1211 movi(rn(node->u.w), node->v.w);
1255 case_brr(boadd, _u);
1256 case_brw(boadd, _u);
1259 case_brr(bxadd, _u);
1260 case_brw(bxadd, _u);
1263 case_brr(bosub, _u);
1264 case_brw(bosub, _u);
1267 case_brr(bxsub, _u);
1268 case_brw(bxsub, _u);
1295 case jit_code_movi_f:
1297 movi_f(rn(node->u.w), node->v.f);
1326 case_rrr(unord, _f);
1340 case_brr(bunlt, _f);
1342 case_brr(bunle, _f);
1344 case_brr(buneq, _f);
1346 case_brr(bunge, _f);
1348 case_brr(bungt, _f);
1350 case_brr(bltgt, _f);
1354 case_brr(bunord, _f);
1378 case jit_code_movi_d:
1380 movi_d(rn(node->u.w), node->v.d);
1409 case_rrr(unord, _d);
1423 case_brr(bunlt, _d);
1425 case_brr(bunle, _d);
1427 case_brr(buneq, _d);
1429 case_brr(bunge, _d);
1431 case_brr(bungt, _d);
1433 case_brr(bltgt, _d);
1437 case_brr(bunord, _d);
1441 jmpr(rn(node->u.w));
1444 if (node->flag & jit_flag_node) {
1446 assert(temp->code == jit_code_label ||
1447 temp->code == jit_code_epilog);
1448 if (temp->flag & jit_flag_patch)
1451 word = _jit->code.length -
1452 (_jit->pc.uc - _jit->code.ptr);
1453 if (can_sign_extend_si26_p(word))
1454 word = jmpi(_jit->pc.w);
1456 word = jmpi_p(_jit->pc.w);
1465 case jit_code_callr:
1467 callr(rn(node->u.w));
1469 case jit_code_calli:
1470 if (node->flag & jit_flag_node) {
1472 assert(temp->code == jit_code_label ||
1473 temp->code == jit_code_epilog);
1474 if (temp->flag & jit_flag_patch)
1477 word = _jit->code.length -
1478 (_jit->pc.uc - _jit->code.ptr);
1479 if (can_sign_extend_si26_p(word))
1480 word = calli(_jit->pc.w);
1482 word = calli_p(_jit->pc.w);
1491 case jit_code_prolog:
1492 _jitc->function = _jitc->functions.ptr + node->w.w;
1494 undo.word = _jit->pc.w;
1495 memcpy(&undo.func, _jitc->function, sizeof(undo.func));
1496 #if DEVEL_DISASSEMBLER
1499 undo.patch_offset = _jitc->patches.offset;
1501 compute_framesize();
1506 case jit_code_epilog:
1507 assert(_jitc->function == _jitc->functions.ptr + node->w.w);
1509 for (temp = undo.node->next;
1510 temp != node; temp = temp->next) {
1511 if (temp->code == jit_code_label ||
1512 temp->code == jit_code_epilog)
1513 temp->flag &= ~jit_flag_patch;
1515 temp->flag &= ~jit_flag_patch;
1517 _jit->pc.w = undo.word;
1518 /* undo.func.self.aoff and undo.func.regset should not
1519 * be undone, as they will be further updated, and are
1520 * the reason of the undo. */
1521 undo.func.self.aoff = _jitc->function->frame +
1522 _jitc->function->self.aoff;
1523 undo.func.need_frame = _jitc->function->need_frame;
1524 jit_regset_set(&undo.func.regset, &_jitc->function->regset);
1525 /* allocar information also does not need to be undone */
1526 undo.func.aoffoff = _jitc->function->aoffoff;
1527 undo.func.allocar = _jitc->function->allocar;
1528 /* this will be recomputed but undo anyway to have it
1529 * better self documented.*/
1530 undo.func.need_stack = _jitc->function->need_stack;
1531 memcpy(_jitc->function, &undo.func, sizeof(undo.func));
1532 #if DEVEL_DISASSEMBLER
1535 _jitc->patches.offset = undo.patch_offset;
1537 goto restart_function;
1539 if (node->link && (word = _jit->pc.w & 3))
1541 /* remember label is defined */
1542 node->flag |= jit_flag_patch;
1543 node->u.w = _jit->pc.w;
1545 _jitc->function = NULL;
1547 case jit_code_movr_w_f:
1548 movr_w_f(rn(node->u.w), rn(node->v.w));
1550 case jit_code_movr_f_w:
1551 movr_f_w(rn(node->u.w), rn(node->v.w));
1553 case jit_code_movi_f_w:
1555 movi_f_w(rn(node->u.w), node->v.f);
1557 case jit_code_movr_w_d:
1558 movr_w_d(rn(node->u.w), rn(node->v.w));
1560 case jit_code_movr_d_w:
1561 movr_d_w(rn(node->u.w), rn(node->v.w));
1563 case jit_code_movi_d_w:
1565 movi_d_w(rn(node->u.w), node->v.d);
1567 case jit_code_va_start:
1568 vastart(rn(node->u.w));
1570 case jit_code_va_arg:
1571 vaarg(rn(node->u.w), rn(node->v.w));
1573 case jit_code_va_arg_d:
1574 vaarg_d(rn(node->u.w), rn(node->v.w));
1576 case jit_code_live: case jit_code_ellipsis:
1577 case jit_code_va_push:
1578 case jit_code_allocai: case jit_code_allocar:
1579 case jit_code_arg_c: case jit_code_arg_s:
1580 case jit_code_arg_i: case jit_code_arg_l:
1581 case jit_code_arg_f: case jit_code_arg_d:
1582 case jit_code_va_end:
1584 case jit_code_retr_c: case jit_code_reti_c:
1585 case jit_code_retr_uc: case jit_code_reti_uc:
1586 case jit_code_retr_s: case jit_code_reti_s:
1587 case jit_code_retr_us: case jit_code_reti_us:
1588 case jit_code_retr_i: case jit_code_reti_i:
1589 case jit_code_retr_ui: case jit_code_reti_ui:
1590 case jit_code_retr_l: case jit_code_reti_l:
1591 case jit_code_retr_f: case jit_code_reti_f:
1592 case jit_code_retr_d: case jit_code_reti_d:
1593 case jit_code_getarg_c: case jit_code_getarg_uc:
1594 case jit_code_getarg_s: case jit_code_getarg_us:
1595 case jit_code_getarg_i:
1596 case jit_code_getarg_ui: case jit_code_getarg_l:
1597 case jit_code_getarg_f: case jit_code_getarg_d:
1598 case jit_code_putargr_c: case jit_code_putargi_c:
1599 case jit_code_putargr_uc: case jit_code_putargi_uc:
1600 case jit_code_putargr_s: case jit_code_putargi_s:
1601 case jit_code_putargr_us: case jit_code_putargi_us:
1602 case jit_code_putargr_i: case jit_code_putargi_i:
1603 case jit_code_putargr_ui: case jit_code_putargi_ui:
1604 case jit_code_putargr_l: case jit_code_putargi_l:
1605 case jit_code_putargr_f: case jit_code_putargi_f:
1606 case jit_code_putargr_d: case jit_code_putargi_d:
1607 case jit_code_pushargr_c: case jit_code_pushargi_c:
1608 case jit_code_pushargr_uc: case jit_code_pushargi_uc:
1609 case jit_code_pushargr_s: case jit_code_pushargi_s:
1610 case jit_code_pushargr_us: case jit_code_pushargi_us:
1611 case jit_code_pushargr_i: case jit_code_pushargi_i:
1612 case jit_code_pushargr_ui: case jit_code_pushargi_ui:
1613 case jit_code_pushargr_l: case jit_code_pushargi_l:
1614 case jit_code_pushargr_f: case jit_code_pushargi_f:
1615 case jit_code_pushargr_d: case jit_code_pushargi_d:
1616 case jit_code_retval_c: case jit_code_retval_uc:
1617 case jit_code_retval_s: case jit_code_retval_us:
1618 case jit_code_retval_i:
1619 case jit_code_retval_ui: case jit_code_retval_l:
1620 case jit_code_retval_f: case jit_code_retval_d:
1621 case jit_code_prepare:
1622 case jit_code_finishr: case jit_code_finishi:
1627 if (jit_carry != _NOREG) {
1628 switch (node->code) {
1630 case jit_code_addcr: case jit_code_addci:
1631 case jit_code_addxr: case jit_code_addxi:
1632 case jit_code_subcr: case jit_code_subci:
1633 case jit_code_subxr: case jit_code_subxi:
1636 jit_unget_reg(jit_carry);
1641 jit_regarg_clr(node, value);
1642 assert(_jitc->regarg == 0 ||
1643 (jit_carry != _NOREG && _jitc->regarg == (1 << jit_carry)));
1644 assert(_jitc->synth == 0);
1645 /* update register live state */
1657 for (offset = 0; offset < _jitc->patches.offset; offset++) {
1658 node = _jitc->patches.ptr[offset].node;
1659 word = node->code == jit_code_movi ? node->v.n->u.w : node->u.n->u.w;
1660 patch_at(_jitc->patches.ptr[offset].inst, word);
1663 jit_flush(_jit->code.ptr, _jit->pc.uc);
1665 return (_jit->code.ptr);
1669 # include "jit_loongarch-cpu.c"
1670 # include "jit_loongarch-fpu.c"
1674 jit_flush(void *fptr, void *tptr)
1676 #if defined(__GNUC__)
1679 s = sysconf(_SC_PAGE_SIZE);
1680 f = (jit_word_t)fptr & -s;
1681 t = (((jit_word_t)tptr) + s - 1) & -s;
1682 __clear_cache((void *)f, (void *)t);
1687 _emit_ldxi(jit_state_t *_jit, jit_int32_t r0, jit_int32_t r1, jit_word_t i0)
1689 ldxi(rn(r0), rn(r1), i0);
1693 _emit_stxi(jit_state_t *_jit, jit_word_t i0, jit_int32_t r0, jit_int32_t r1)
1695 stxi(i0, rn(r0), rn(r1));
1699 _emit_ldxi_d(jit_state_t *_jit, jit_int32_t r0, jit_int32_t r1, jit_word_t i0)
1701 ldxi_d(rn(r0), rn(r1), i0);
1705 _emit_stxi_d(jit_state_t *_jit, jit_word_t i0, jit_int32_t r0, jit_int32_t r1)
1707 stxi_d(i0, rn(r0), rn(r1));
1711 _compute_framesize(jit_state_t *_jit)
1714 _jitc->framesize = 16; /* ra+fp */
1715 for (reg = 0; reg < jit_size(iregs); reg++)
1716 if (jit_regset_tstbit(&_jitc->function->regset, iregs[reg]))
1717 _jitc->framesize += sizeof(jit_word_t);
1719 for (reg = 0; reg < jit_size(fregs); reg++)
1720 if (jit_regset_tstbit(&_jitc->function->regset, fregs[reg]))
1721 _jitc->framesize += sizeof(jit_float64_t);
1723 /* Space to store variadic arguments */
1724 if (_jitc->function->self.call & jit_call_varargs)
1725 _jitc->framesize += (8 - _jitc->function->vagp) * 8;
1727 /* Make sure functions called have a 16 byte aligned stack */
1728 _jitc->framesize = (_jitc->framesize + 15) & -16;
1732 _patch(jit_state_t *_jit, jit_word_t instr, jit_node_t *node)
1736 assert(node->flag & jit_flag_node);
1737 if (node->code == jit_code_movi)
1738 flag = node->v.n->flag;
1740 flag = node->u.n->flag;
1741 assert(!(flag & jit_flag_patch));
1742 if (_jitc->patches.offset >= _jitc->patches.length) {
1743 jit_realloc((jit_pointer_t *)&_jitc->patches.ptr,
1744 _jitc->patches.length * sizeof(jit_patch_t),
1745 (_jitc->patches.length + 1024) * sizeof(jit_patch_t));
1746 _jitc->patches.length += 1024;
1748 _jitc->patches.ptr[_jitc->patches.offset].inst = instr;
1749 _jitc->patches.ptr[_jitc->patches.offset].node = node;
1750 ++_jitc->patches.offset;