2 * Copyright (C) 2022 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 #define jit_arg_reg_p(i) ((i) >= 0 && (i) < 8)
21 #define jit_arg_f_reg_p(i) ((i) >= 0 && (i) < 8)
26 typedef struct jit_pointer_t jit_va_list_t;
31 #define patch(instr, node) _patch(_jit, instr, node)
32 static void _patch(jit_state_t*,jit_word_t,jit_node_t*);
35 # include "jit_loongarch-cpu.c"
36 # include "jit_loongarch-fpu.c"
42 jit_register_t _rvs[] = {
43 { rc(gpr) | 0x14, "$t8" },
44 { rc(gpr) | 0x13, "$t7" },
45 { rc(gpr) | 0x12, "$t6" },
46 { rc(gpr) | 0x11, "$t5" },
47 { rc(gpr) | 0x10, "$t4" },
48 { rc(gpr) | 0x0f, "$t3" },
49 { rc(gpr) | 0x0e, "$t2" },
50 { rc(gpr) | 0x0d, "$t1" },
51 { rc(gpr) | 0x0c, "$t0" },
52 { rc(sav) | rc(gpr) | 0x1f, "$s8" },
53 { rc(sav) | rc(gpr) | 0x1e, "$s7" },
54 { rc(sav) | rc(gpr) | 0x1d, "$s6" },
55 { rc(sav) | rc(gpr) | 0x1c, "$s5" },
56 { rc(sav) | rc(gpr) | 0x1b, "$s4" },
57 { rc(sav) | rc(gpr) | 0x1a, "$s3" },
58 { rc(sav) | rc(gpr) | 0x19, "$s2" },
59 { rc(sav) | rc(gpr) | 0x18, "$s1" },
60 { rc(sav) | rc(gpr) | 0x17, "$s0" },
61 { rc(arg) | rc(gpr) | 0x0b, "$a7" },
62 { rc(arg) | rc(gpr) | 0x0a, "$a6" },
63 { rc(arg) | rc(gpr) | 0x09, "$a5" },
64 { rc(arg) | rc(gpr) | 0x08, "$a4" },
65 { rc(arg) | rc(gpr) | 0x07, "$a3" },
66 { rc(arg) | rc(gpr) | 0x06, "$a2" },
67 { rc(arg) | rc(gpr) | 0x05, "$a1" },
68 { rc(arg) | rc(gpr) | 0x04, "$a0" },
70 { 0x15, "<reserved>" },
75 { rc(fpr) | 0x08, "$ft0" },
76 { rc(fpr) | 0x09, "$ft1" },
77 { rc(fpr) | 0x0a, "$ft2" },
78 { rc(fpr) | 0x0b, "$ft3" },
79 { rc(fpr) | 0x0c, "$ft4" },
80 { rc(fpr) | 0x0d, "$ft5" },
81 { rc(fpr) | 0x0e, "$ft6" },
82 { rc(fpr) | 0x0f, "$ft7" },
83 { rc(fpr) | 0x10, "$ft8" },
84 { rc(fpr) | 0x11, "$ft9" },
85 { rc(fpr) | 0x12, "$ft10" },
86 { rc(fpr) | 0x13, "$ft11" },
87 { rc(fpr) | 0x14, "$ft12" },
88 { rc(fpr) | 0x15, "$ft13" },
89 { rc(fpr) | 0x16, "$ft14" },
90 { rc(fpr) | 0x17, "$ft15" },
91 { rc(arg) | rc(fpr) | 0x07, "$fa7" },
92 { rc(arg) | rc(fpr) | 0x06, "$fa6" },
93 { rc(arg) | rc(fpr) | 0x05, "$fa5" },
94 { rc(arg) | rc(fpr) | 0x04, "$fa4" },
95 { rc(arg) | rc(fpr) | 0x03, "$fa3" },
96 { rc(arg) | rc(fpr) | 0x02, "$fa2" },
97 { rc(arg) | rc(fpr) | 0x01, "$fa1" },
98 { rc(arg) | rc(fpr) | 0x00, "$fa0" },
99 { rc(sav) | rc(fpr) | 0x1f, "$fs7" },
100 { rc(sav) | rc(fpr) | 0x1e, "$fs6" },
101 { rc(sav) | rc(fpr) | 0x1d, "$fs5" },
102 { rc(sav) | rc(fpr) | 0x1c, "$fs4" },
103 { rc(sav) | rc(fpr) | 0x1b, "$fs3" },
104 { rc(sav) | rc(fpr) | 0x1a, "$fs2" },
105 { rc(sav) | rc(fpr) | 0x19, "$fs1" },
106 { rc(sav) | rc(fpr) | 0x18, "$fs0" },
107 { _NOREG, "<none>" },
119 _jit_init(jit_state_t *_jit)
121 _jitc->reglen = jit_size(_rvs) - 1;
126 _jit_prolog(jit_state_t *_jit)
132 assert(jit_regset_cmp_ui(&_jitc->regarg, 0) == 0);
133 jit_regset_set_ui(&_jitc->regsav, 0);
134 offset = _jitc->functions.offset;
135 if (offset >= _jitc->functions.length) {
136 jit_realloc((jit_pointer_t *)&_jitc->functions.ptr,
137 _jitc->functions.length * sizeof(jit_function_t),
138 (_jitc->functions.length + 16) * sizeof(jit_function_t));
139 _jitc->functions.length += 16;
141 _jitc->function = _jitc->functions.ptr + _jitc->functions.offset++;
142 _jitc->function->self.size = stack_framesize;
143 _jitc->function->self.argi = _jitc->function->self.argf =
144 _jitc->function->self.aoff = _jitc->function->self.alen = 0;
145 _jitc->function->self.call = jit_call_default;
146 jit_alloc((jit_pointer_t *)&_jitc->function->regoff,
147 _jitc->reglen * sizeof(jit_int32_t));
149 /* _no_link here does not mean the jit_link() call can be removed
151 * _jitc->function->prolog = jit_new_node(jit_code_prolog);
153 _jitc->function->prolog = jit_new_node_no_link(jit_code_prolog);
154 jit_link(_jitc->function->prolog);
155 _jitc->function->prolog->w.w = offset;
156 _jitc->function->epilog = jit_new_node_no_link(jit_code_epilog);
158 * v: offset in blocks vector
159 * w: offset in functions vector
161 _jitc->function->epilog->w.w = offset;
163 jit_regset_new(&_jitc->function->regset);
167 _jit_allocai(jit_state_t *_jit, jit_int32_t length)
169 assert(_jitc->function);
171 case 0: case 1: break;
172 case 2: _jitc->function->self.aoff &= -2; break;
173 case 3: case 4: _jitc->function->self.aoff &= -4; break;
174 default: _jitc->function->self.aoff &= -8; break;
176 _jitc->function->self.aoff -= length;
177 if (!_jitc->realize) {
178 jit_inc_synth_ww(allocai, _jitc->function->self.aoff, length);
181 return (_jitc->function->self.aoff);
185 _jit_allocar(jit_state_t *_jit, jit_int32_t u, jit_int32_t v)
188 assert(_jitc->function);
189 jit_inc_synth_ww(allocar, u, v);
190 if (!_jitc->function->allocar) {
191 _jitc->function->aoffoff = jit_allocai(sizeof(jit_int32_t));
192 _jitc->function->allocar = 1;
194 reg = jit_get_reg(jit_class_gpr);
196 jit_andi(reg, reg, -16);
197 jit_ldxi_i(u, JIT_FP, _jitc->function->aoffoff);
199 jit_addr(JIT_SP, JIT_SP, reg);
200 jit_stxi_i(_jitc->function->aoffoff, JIT_FP, u);
206 _jit_ret(jit_state_t *_jit)
209 assert(_jitc->function);
213 jit_patch_at(instr, _jitc->function->epilog);
218 _jit_retr(jit_state_t *_jit, jit_int32_t u)
220 jit_inc_synth_w(retr, u);
222 jit_movr(JIT_RET, u);
229 _jit_reti(jit_state_t *_jit, jit_word_t u)
231 jit_inc_synth_w(reti, u);
232 jit_movi(JIT_RET, u);
238 _jit_retr_f(jit_state_t *_jit, jit_int32_t u)
240 jit_inc_synth_w(retr_f, u);
242 jit_movr_f(JIT_FRET, u);
250 _jit_reti_f(jit_state_t *_jit, jit_float32_t u)
252 jit_inc_synth_f(reti_f, u);
253 jit_movi_f(JIT_FRET, u);
259 _jit_retr_d(jit_state_t *_jit, jit_int32_t u)
261 jit_inc_synth_w(retr_d, u);
263 jit_movr_d(JIT_FRET, u);
271 _jit_reti_d(jit_state_t *_jit, jit_float64_t u)
273 jit_inc_synth_d(reti_d, u);
274 jit_movi_d(JIT_FRET, u);
280 _jit_epilog(jit_state_t *_jit)
282 assert(_jitc->function);
283 assert(_jitc->function->epilog->next == NULL);
284 jit_link(_jitc->function->epilog);
285 _jitc->function = NULL;
289 _jit_arg_register_p(jit_state_t *_jit, jit_node_t *u)
291 if (u->code == jit_code_arg)
292 return (jit_arg_reg_p(u->u.w));
293 assert(u->code == jit_code_arg_f || u->code == jit_code_arg_d);
294 return (jit_arg_f_reg_p(u->u.w));
298 _jit_ellipsis(jit_state_t *_jit)
300 jit_inc_synth(ellipsis);
301 if (_jitc->prepare) {
303 assert(!(_jitc->function->call.call & jit_call_varargs));
304 _jitc->function->call.call |= jit_call_varargs;
308 assert(!(_jitc->function->self.call & jit_call_varargs));
309 _jitc->function->self.call |= jit_call_varargs;
310 _jitc->function->vagp = _jitc->function->self.argi;
316 _jit_va_push(jit_state_t *_jit, jit_int32_t u)
318 jit_inc_synth_w(va_push, u);
324 _jit_arg(jit_state_t *_jit)
328 assert(_jitc->function);
329 assert(!(_jitc->function->self.call & jit_call_varargs));
330 if (jit_arg_reg_p(_jitc->function->self.argi))
331 offset = _jitc->function->self.argi++;
333 offset = _jitc->function->self.size;
334 _jitc->function->self.size += sizeof(jit_word_t);
336 node = jit_new_node_ww(jit_code_arg, offset,
337 ++_jitc->function->self.argn);
343 _jit_arg_f(jit_state_t *_jit)
347 assert(_jitc->function);
348 assert(!(_jitc->function->self.call & jit_call_varargs));
349 if (jit_arg_f_reg_p(_jitc->function->self.argf))
350 offset = _jitc->function->self.argf++;
351 else if (jit_arg_reg_p(_jitc->function->self.argi)) {
352 offset = _jitc->function->self.argi++;
356 offset = _jitc->function->self.size;
357 _jitc->function->self.size += sizeof(jit_word_t);
359 node = jit_new_node_ww(jit_code_arg_f, offset,
360 ++_jitc->function->self.argn);
366 _jit_arg_d(jit_state_t *_jit)
370 assert(_jitc->function);
371 assert(!(_jitc->function->self.call & jit_call_varargs));
372 if (jit_arg_f_reg_p(_jitc->function->self.argf))
373 offset = _jitc->function->self.argf++;
374 else if (jit_arg_reg_p(_jitc->function->self.argi)) {
375 offset = _jitc->function->self.argi++;
379 offset = _jitc->function->self.size;
380 _jitc->function->self.size += sizeof(jit_word_t);
382 node = jit_new_node_ww(jit_code_arg_d, offset,
383 ++_jitc->function->self.argn);
389 _jit_getarg_c(jit_state_t *_jit, jit_int32_t u, jit_node_t *v)
391 assert(v->code == jit_code_arg);
392 jit_inc_synth_wp(getarg_c, u, v);
393 if (jit_arg_reg_p(v->u.w))
394 jit_extr_c(u, _A0 - v->u.w);
396 jit_ldxi_c(u, JIT_FP, v->u.w);
401 _jit_getarg_uc(jit_state_t *_jit, jit_int32_t u, jit_node_t *v)
403 assert(v->code == jit_code_arg);
404 jit_inc_synth_wp(getarg_uc, u, v);
405 if (jit_arg_reg_p(v->u.w))
406 jit_extr_uc(u, _A0 - v->u.w);
408 jit_ldxi_uc(u, JIT_FP, v->u.w);
413 _jit_getarg_s(jit_state_t *_jit, jit_int32_t u, jit_node_t *v)
415 assert(v->code == jit_code_arg);
416 jit_inc_synth_wp(getarg_s, u, v);
417 if (jit_arg_reg_p(v->u.w))
418 jit_extr_s(u, _A0 - v->u.w);
420 jit_ldxi_s(u, JIT_FP, v->u.w);
425 _jit_getarg_us(jit_state_t *_jit, jit_int32_t u, jit_node_t *v)
427 assert(v->code == jit_code_arg);
428 jit_inc_synth_wp(getarg_us, u, v);
429 if (jit_arg_reg_p(v->u.w))
430 jit_extr_us(u, _A0 - v->u.w);
432 jit_ldxi_us(u, JIT_FP, v->u.w);
437 _jit_getarg_i(jit_state_t *_jit, jit_int32_t u, jit_node_t *v)
439 assert(v->code == jit_code_arg);
440 jit_inc_synth_wp(getarg_i, u, v);
441 if (jit_arg_reg_p(v->u.w))
442 jit_extr_i(u, _A0 - v->u.w);
444 jit_ldxi_i(u, JIT_FP, v->u.w);
449 _jit_getarg_ui(jit_state_t *_jit, jit_int32_t u, jit_node_t *v)
451 assert(v->code == jit_code_arg);
452 jit_inc_synth_wp(getarg_ui, u, v);
453 if (jit_arg_reg_p(v->u.w))
454 jit_extr_ui(u, _A0 - v->u.w);
456 jit_ldxi_ui(u, JIT_FP, v->u.w);
461 _jit_getarg_l(jit_state_t *_jit, jit_int32_t u, jit_node_t *v)
463 assert(v->code == jit_code_arg);
464 jit_inc_synth_wp(getarg_l, u, v);
465 if (jit_arg_reg_p(v->u.w))
466 jit_movr(u, _A0 - v->u.w);
468 jit_ldxi_l(u, JIT_FP, v->u.w);
473 _jit_putargr(jit_state_t *_jit, jit_int32_t u, jit_node_t *v)
475 assert(v->code == jit_code_arg);
476 jit_inc_synth_wp(putargr, u, v);
477 if (jit_arg_reg_p(v->u.w))
478 jit_movr(_A0 - v->u.w, u);
480 jit_stxi(v->u.w, JIT_FP, u);
485 _jit_putargi(jit_state_t *_jit, jit_word_t u, jit_node_t *v)
488 assert(v->code == jit_code_arg);
489 jit_inc_synth_wp(putargi, u, v);
490 if (jit_arg_reg_p(v->u.w))
491 jit_movi(_A0 - v->u.w, u);
493 regno = jit_get_reg(jit_class_gpr);
495 jit_stxi(v->u.w, JIT_FP, regno);
496 jit_unget_reg(regno);
502 _jit_getarg_f(jit_state_t *_jit, jit_int32_t u, jit_node_t *v)
504 assert(v->code == jit_code_arg_f);
505 jit_inc_synth_wp(getarg_f, u, v);
506 if (jit_arg_f_reg_p(v->u.w))
507 jit_movr_f(u, _FA0 - v->u.w);
508 else if (jit_arg_reg_p(v->u.w - 8))
509 jit_movr_w_f(u, JIT_RA0 - (v->u.w - 8));
511 jit_ldxi_f(u, JIT_FP, v->u.w);
516 _jit_putargr_f(jit_state_t *_jit, jit_int32_t u, jit_node_t *v)
518 assert(v->code == jit_code_arg_f);
519 jit_inc_synth_wp(putargr_f, u, v);
520 if (jit_arg_f_reg_p(v->u.w))
521 jit_movr_f(_FA0 - v->u.w, u);
522 else if (jit_arg_reg_p(v->u.w - 8))
523 jit_movr_f_w(JIT_RA0 - (v->u.w - 8), u);
525 jit_stxi_f(v->u.w, JIT_FP, u);
530 _jit_putargi_f(jit_state_t *_jit, jit_float32_t u, jit_node_t *v)
533 assert(v->code == jit_code_arg_f);
534 jit_inc_synth_fp(putargi_f, u, v);
535 if (jit_arg_f_reg_p(v->u.w))
536 jit_movi_f(_FA0 - v->u.w, u);
537 else if (jit_arg_reg_p(v->u.w - 8)) {
543 jit_movi(JIT_RA0 - (v->u.w - 8), uu.i);
546 regno = jit_get_reg(jit_class_fpr);
547 jit_movi_f(regno, u);
548 jit_stxi_f(v->u.w, JIT_FP, regno);
549 jit_unget_reg(regno);
555 _jit_getarg_d(jit_state_t *_jit, jit_int32_t u, jit_node_t *v)
557 assert(v->code == jit_code_arg_d);
558 jit_inc_synth_wp(getarg_d, u, v);
559 if (jit_arg_f_reg_p(v->u.w))
560 jit_movr_d(u, _FA0 - v->u.w);
561 else if (jit_arg_reg_p(v->u.w - 8))
562 jit_movr_w_d(u, JIT_RA0 - (v->u.w - 8));
564 jit_ldxi_d(u, JIT_FP, v->u.w);
569 _jit_putargr_d(jit_state_t *_jit, jit_int32_t u, jit_node_t *v)
571 assert(v->code == jit_code_arg_d);
572 jit_inc_synth_wp(putargr_d, u, v);
573 if (jit_arg_f_reg_p(v->u.w))
574 jit_movr_d(_FA0 - v->u.w, u);
575 else if (jit_arg_reg_p(v->u.w - 8))
576 jit_movr_d_w(JIT_RA0 - (v->u.w - 8), u);
578 jit_stxi_d(v->u.w, JIT_FP, u);
583 _jit_putargi_d(jit_state_t *_jit, jit_float64_t u, jit_node_t *v)
586 assert(v->code == jit_code_arg_d);
587 jit_inc_synth_dp(putargi_d, u, v);
588 if (jit_arg_f_reg_p(v->u.w))
589 jit_movi_d(_FA0 - v->u.w, u);
590 else if (jit_arg_reg_p(v->u.w - 8)) {
596 jit_movi(JIT_RA0 - (v->u.w - 8), uu.w);
599 regno = jit_get_reg(jit_class_fpr);
600 jit_movi_d(regno, u);
601 jit_stxi_d(v->u.w, JIT_FP, regno);
602 jit_unget_reg(regno);
608 _jit_pushargr(jit_state_t *_jit, jit_int32_t u)
610 assert(_jitc->function);
611 jit_inc_synth_w(pushargr, u);
613 if (jit_arg_reg_p(_jitc->function->call.argi)) {
614 jit_movr(_A0 - _jitc->function->call.argi, u);
615 ++_jitc->function->call.argi;
618 jit_stxi(_jitc->function->call.size, JIT_SP, u);
619 _jitc->function->call.size += sizeof(jit_word_t);
625 _jit_pushargi(jit_state_t *_jit, jit_word_t u)
628 assert(_jitc->function);
629 jit_inc_synth_w(pushargi, u);
631 if (jit_arg_reg_p(_jitc->function->call.argi)) {
632 jit_movi(_A0 - _jitc->function->call.argi, u);
633 ++_jitc->function->call.argi;
636 regno = jit_get_reg(jit_class_gpr);
638 jit_stxi(_jitc->function->call.size, JIT_SP, regno);
639 jit_unget_reg(regno);
640 _jitc->function->call.size += sizeof(jit_word_t);
646 _jit_pushargr_f(jit_state_t *_jit, jit_int32_t u)
648 assert(_jitc->function);
649 jit_inc_synth_w(pushargr_f, u);
651 if (jit_arg_f_reg_p(_jitc->function->call.argf) &&
652 !(_jitc->function->call.call & jit_call_varargs)) {
653 jit_movr_f(_FA0 - _jitc->function->call.argf, u);
654 ++_jitc->function->call.argf;
656 else if (jit_arg_reg_p(_jitc->function->call.argi)) {
657 jit_movr_f_w(_A0 - _jitc->function->call.argi, u);
658 ++_jitc->function->call.argi;
661 jit_stxi_f(_jitc->function->call.size, JIT_SP, u);
662 _jitc->function->call.size += sizeof(jit_word_t);
668 _jit_pushargi_f(jit_state_t *_jit, jit_float32_t u)
671 assert(_jitc->function);
672 jit_inc_synth_f(pushargi_f, u);
674 if (jit_arg_f_reg_p(_jitc->function->call.argf) &&
675 !(_jitc->function->call.call & jit_call_varargs)) {
676 jit_movi_f(_FA0 - _jitc->function->call.argf, u);
677 ++_jitc->function->call.argf;
679 else if (jit_arg_reg_p(_jitc->function->call.argi)) {
680 jit_movi_f_w(_A0 - _jitc->function->call.argi, u);
681 ++_jitc->function->call.argi;
684 regno = jit_get_reg(jit_class_fpr);
685 jit_movi_f(regno, u);
686 jit_stxi_f(_jitc->function->call.size, JIT_SP, regno);
687 jit_unget_reg(regno);
688 _jitc->function->call.size += sizeof(jit_word_t);
694 _jit_pushargr_d(jit_state_t *_jit, jit_int32_t u)
696 assert(_jitc->function);
697 jit_inc_synth_w(pushargr_d, u);
699 if (jit_arg_f_reg_p(_jitc->function->call.argf) &&
700 !(_jitc->function->call.call & jit_call_varargs)) {
701 jit_movr_d(_FA0 - _jitc->function->call.argf, u);
702 ++_jitc->function->call.argf;
704 else if (jit_arg_reg_p(_jitc->function->call.argi)) {
705 jit_movr_d_w(_A0 - _jitc->function->call.argi, u);
706 ++_jitc->function->call.argi;
709 jit_stxi_d(_jitc->function->call.size, JIT_SP, u);
710 _jitc->function->call.size += sizeof(jit_word_t);
716 _jit_pushargi_d(jit_state_t *_jit, jit_float64_t u)
719 assert(_jitc->function);
720 jit_inc_synth_d(pushargi_d, u);
722 if (jit_arg_f_reg_p(_jitc->function->call.argf) &&
723 !(_jitc->function->call.call & jit_call_varargs)) {
724 jit_movi_d(_FA0 - _jitc->function->call.argf, u);
725 ++_jitc->function->call.argf;
727 else if (jit_arg_reg_p(_jitc->function->call.argi)) {
728 jit_movi_d_w(_A0 - _jitc->function->call.argi, u);
729 ++_jitc->function->call.argi;
732 regno = jit_get_reg(jit_class_fpr);
733 jit_movi_d(regno, u);
734 jit_stxi_d(_jitc->function->call.size, JIT_SP, regno);
735 jit_unget_reg(regno);
736 _jitc->function->call.size += sizeof(jit_word_t);
742 _jit_regarg_p(jit_state_t *_jit, jit_node_t *node, jit_int32_t regno)
745 spec = jit_class(_rvs[regno].spec);
746 if (spec & jit_class_arg) {
748 if (regno >= 0 && regno < node->v.w)
750 if (spec & jit_class_fpr) {
751 regno = _FA0 - regno;
752 if (regno >= 0 && regno < node->w.w)
760 _jit_finishr(jit_state_t *_jit, jit_int32_t r0)
763 assert(_jitc->function);
764 jit_inc_synth_w(finishr, r0);
765 if (_jitc->function->self.alen < _jitc->function->call.size)
766 _jitc->function->self.alen = _jitc->function->call.size;
767 node = jit_callr(r0);
768 node->v.w = _jitc->function->call.argi;
769 node->w.w = _jitc->function->call.argf;
770 _jitc->function->call.argi = _jitc->function->call.argf =
771 _jitc->function->call.size = 0;
777 _jit_finishi(jit_state_t *_jit, jit_pointer_t i0)
780 assert(_jitc->function);
781 jit_inc_synth_w(finishi, (jit_word_t)i0);
782 if (_jitc->function->self.alen < _jitc->function->call.size)
783 _jitc->function->self.alen = _jitc->function->call.size;
784 node = jit_calli(i0);
785 node->v.w = _jitc->function->call.argi;
786 node->w.w = _jitc->function->call.argf;
787 _jitc->function->call.argi = _jitc->function->call.argf =
788 _jitc->function->call.size = 0;
795 _jit_retval_c(jit_state_t *_jit, jit_int32_t r0)
797 jit_inc_synth_w(retval_c, r0);
798 jit_extr_c(r0, JIT_RET);
803 _jit_retval_uc(jit_state_t *_jit, jit_int32_t r0)
805 jit_inc_synth_w(retval_uc, r0);
806 jit_extr_uc(r0, JIT_RET);
811 _jit_retval_s(jit_state_t *_jit, jit_int32_t r0)
813 jit_inc_synth_w(retval_s, r0);
814 jit_extr_s(r0, JIT_RET);
819 _jit_retval_us(jit_state_t *_jit, jit_int32_t r0)
821 jit_inc_synth_w(retval_us, r0);
822 jit_extr_us(r0, JIT_RET);
827 _jit_retval_i(jit_state_t *_jit, jit_int32_t r0)
829 jit_inc_synth_w(retval_i, r0);
830 jit_extr_i(r0, JIT_RET);
835 _jit_retval_ui(jit_state_t *_jit, jit_int32_t r0)
837 jit_inc_synth_w(retval_ui, r0);
838 jit_extr_ui(r0, JIT_RET);
843 _jit_retval_l(jit_state_t *_jit, jit_int32_t r0)
845 jit_inc_synth_w(retval_l, r0);
847 jit_movr(r0, JIT_RET);
852 _jit_retval_f(jit_state_t *_jit, jit_int32_t r0)
854 jit_inc_synth_w(retval_f, r0);
856 jit_movr_f(r0, JIT_FRET);
861 _jit_retval_d(jit_state_t *_jit, jit_int32_t r0)
863 jit_inc_synth_w(retval_d, r0);
865 jit_movr_d(r0, JIT_FRET);
870 _emit_code(jit_state_t *_jit)
880 #if DEVEL_DISASSEMBLER
883 jit_int32_t patch_offset;
885 #if DEVEL_DISASSEMBLER
889 _jitc->function = NULL;
895 undo.patch_offset = 0;
897 #define assert_data(node) /**/
898 #define case_rr(name, type) \
899 case jit_code_##name##r##type: \
900 name##r##type(rn(node->u.w), rn(node->v.w)); \
902 #define case_rw(name, type) \
903 case jit_code_##name##i##type: \
904 name##i##type(rn(node->u.w), node->v.w); \
906 #define case_wr(name, type) \
907 case jit_code_##name##i##type: \
908 name##i##type(node->u.w, rn(node->v.w)); \
910 #define case_rrr(name, type) \
911 case jit_code_##name##r##type: \
912 name##r##type(rn(node->u.w), \
913 rn(node->v.w), rn(node->w.w)); \
915 #define case_rrrr(name, type) \
916 case jit_code_##name##r##type: \
917 name##r##type(rn(node->u.q.l), rn(node->u.q.h), \
918 rn(node->v.w), rn(node->w.w)); \
920 #define case_rrw(name, type) \
921 case jit_code_##name##i##type: \
922 name##i##type(rn(node->u.w), rn(node->v.w), node->w.w); \
924 #define case_rrrw(name, type) \
925 case jit_code_##name##i##type: \
926 name##i##type(rn(node->u.q.l), rn(node->u.q.h), \
927 rn(node->v.w), node->w.w); \
929 #define case_rrf(name) \
930 case jit_code_##name##i_f: \
932 name##i_f(rn(node->u.w), rn(node->v.w), node->w.f); \
934 #define case_rrd(name) \
935 case jit_code_##name##i_d: \
937 name##i_d(rn(node->u.w), rn(node->v.w),node->w.d); \
939 #define case_wrr(name, type) \
940 case jit_code_##name##i##type: \
941 name##i##type(node->u.w, rn(node->v.w), rn(node->w.w)); \
943 #define case_brr(name, type) \
944 case jit_code_##name##r##type: \
946 assert(temp->code == jit_code_label || \
947 temp->code == jit_code_epilog); \
948 if (temp->flag & jit_flag_patch) \
949 name##r##type(temp->u.w, rn(node->v.w), \
952 word = name##r##type(_jit->pc.w, \
958 #define case_brw(name, type) \
959 case jit_code_##name##i##type: \
961 assert(temp->code == jit_code_label || \
962 temp->code == jit_code_epilog); \
963 if (temp->flag & jit_flag_patch) \
964 name##i##type(temp->u.w, \
965 rn(node->v.w), node->w.w); \
967 word = name##i##type(_jit->pc.w, \
968 rn(node->v.w), node->w.w); \
972 #define case_brf(name) \
973 case jit_code_##name##i_f: \
975 assert(temp->code == jit_code_label || \
976 temp->code == jit_code_epilog); \
977 if (temp->flag & jit_flag_patch) \
978 name##i_f(temp->u.w, rn(node->v.w), node->w.f); \
980 word = name##i_f(_jit->pc.w, rn(node->v.w), \
985 #define case_brd(name) \
986 case jit_code_##name##i_d: \
988 assert(temp->code == jit_code_label || \
989 temp->code == jit_code_epilog); \
990 if (temp->flag & jit_flag_patch) \
991 name##i_d(temp->u.w, rn(node->v.w), node->w.d); \
993 word = name##i_d(_jit->pc.w, rn(node->v.w), \
998 #if DEVEL_DISASSEMBLER
1001 for (node = _jitc->head; node; node = node->next) {
1002 if (_jit->pc.uc >= _jitc->code.end)
1005 #if DEVEL_DISASSEMBLER
1006 node->offset = (jit_uword_t)_jit->pc.w - (jit_uword_t)prevw;
1009 value = jit_classify(node->code);
1010 jit_regarg_set(node, value);
1011 switch (node->code) {
1012 case jit_code_align:
1013 /* Must align to a power of two */
1014 assert(!(node->u.w & (node->u.w - 1)));
1015 if ((word = _jit->pc.w & (node->u.w - 1)))
1016 nop(node->u.w - word);
1018 case jit_code_note: case jit_code_name:
1019 node->u.w = _jit->pc.w;
1021 case jit_code_label:
1022 /* remember label is defined */
1023 node->flag |= jit_flag_patch;
1024 node->u.w = _jit->pc.w;
1043 case_rrrr(qmul, _u);
1044 case_rrrw(qmul, _u);
1055 case_rrrr(qdiv, _u);
1056 case_rrrw(qdiv, _u);
1071 case_rr(trunc, _f_i);
1072 case_rr(trunc, _d_i);
1073 case_rr(trunc, _f_l);
1074 case_rr(trunc, _d_l);
1122 case_rr(bswap, _us);
1123 case_rr(bswap, _ui);
1124 case_rr(bswap, _ul);
1132 casr(rn(node->u.w), rn(node->v.w),
1133 rn(node->w.q.l), rn(node->w.q.h));
1136 casi(rn(node->u.w), node->v.w,
1137 rn(node->w.q.l), rn(node->w.q.h));
1143 if (node->flag & jit_flag_node) {
1145 if (temp->code == jit_code_data ||
1146 (temp->code == jit_code_label &&
1147 (temp->flag & jit_flag_patch)))
1148 movi(rn(node->u.w), temp->u.w);
1150 assert(temp->code == jit_code_label ||
1151 temp->code == jit_code_epilog);
1152 word = movi_p(rn(node->u.w), temp->u.w);
1157 movi(rn(node->u.w), node->v.w);
1201 case_brr(boadd, _u);
1202 case_brw(boadd, _u);
1205 case_brr(bxadd, _u);
1206 case_brw(bxadd, _u);
1209 case_brr(bosub, _u);
1210 case_brw(bosub, _u);
1213 case_brr(bxsub, _u);
1214 case_brw(bxsub, _u);
1241 case jit_code_movi_f:
1243 movi_f(rn(node->u.w), node->v.f);
1272 case_rrr(unord, _f);
1286 case_brr(bunlt, _f);
1288 case_brr(bunle, _f);
1290 case_brr(buneq, _f);
1292 case_brr(bunge, _f);
1294 case_brr(bungt, _f);
1296 case_brr(bltgt, _f);
1300 case_brr(bunord, _f);
1324 case jit_code_movi_d:
1326 movi_d(rn(node->u.w), node->v.d);
1355 case_rrr(unord, _d);
1369 case_brr(bunlt, _d);
1371 case_brr(bunle, _d);
1373 case_brr(buneq, _d);
1375 case_brr(bunge, _d);
1377 case_brr(bungt, _d);
1379 case_brr(bltgt, _d);
1383 case_brr(bunord, _d);
1386 jmpr(rn(node->u.w));
1389 if (node->flag & jit_flag_node) {
1391 assert(temp->code == jit_code_label ||
1392 temp->code == jit_code_epilog);
1393 if (temp->flag & jit_flag_patch)
1396 word = jmpi_p(_jit->pc.w);
1403 case jit_code_callr:
1404 callr(rn(node->u.w));
1406 case jit_code_calli:
1407 if (node->flag & jit_flag_node) {
1409 assert(temp->code == jit_code_label ||
1410 temp->code == jit_code_epilog);
1411 if (temp->flag & jit_flag_patch)
1414 word = calli_p(_jit->pc.w);
1421 case jit_code_prolog:
1422 _jitc->function = _jitc->functions.ptr + node->w.w;
1424 undo.word = _jit->pc.w;
1425 #if DEVEL_DISASSEMBLER
1428 undo.patch_offset = _jitc->patches.offset;
1433 case jit_code_epilog:
1434 assert(_jitc->function == _jitc->functions.ptr + node->w.w);
1436 for (temp = undo.node->next;
1437 temp != node; temp = temp->next) {
1438 if (temp->code == jit_code_label ||
1439 temp->code == jit_code_epilog)
1440 temp->flag &= ~jit_flag_patch;
1442 temp->flag &= ~jit_flag_patch;
1444 _jit->pc.w = undo.word;
1445 #if DEVEL_DISASSEMBLER
1448 _jitc->patches.offset = undo.patch_offset;
1449 goto restart_function;
1451 if (node->link && (word = _jit->pc.w & 3))
1453 /* remember label is defined */
1454 node->flag |= jit_flag_patch;
1455 node->u.w = _jit->pc.w;
1457 _jitc->function = NULL;
1459 case jit_code_movr_w_f:
1460 movr_w_f(rn(node->u.w), rn(node->v.w));
1462 case jit_code_movr_f_w:
1463 movr_f_w(rn(node->u.w), rn(node->v.w));
1465 case jit_code_movi_f_w:
1467 movi_f_w(rn(node->u.w), node->v.f);
1469 case jit_code_movr_w_d:
1470 movr_w_d(rn(node->u.w), rn(node->v.w));
1472 case jit_code_movr_d_w:
1473 movr_d_w(rn(node->u.w), rn(node->v.w));
1475 case jit_code_movi_d_w:
1477 movi_d_w(rn(node->u.w), node->v.d);
1479 case jit_code_va_start:
1480 vastart(rn(node->u.w));
1482 case jit_code_va_arg:
1483 vaarg(rn(node->u.w), rn(node->v.w));
1485 case jit_code_va_arg_d:
1486 vaarg_d(rn(node->u.w), rn(node->v.w));
1488 case jit_code_live: case jit_code_ellipsis:
1489 case jit_code_va_push:
1490 case jit_code_allocai: case jit_code_allocar:
1492 case jit_code_arg_f: case jit_code_arg_d:
1493 case jit_code_va_end:
1495 case jit_code_retr: case jit_code_reti:
1496 case jit_code_retr_f: case jit_code_reti_f:
1497 case jit_code_retr_d: case jit_code_reti_d:
1498 case jit_code_getarg_c: case jit_code_getarg_uc:
1499 case jit_code_getarg_s: case jit_code_getarg_us:
1500 case jit_code_getarg_i:
1501 case jit_code_getarg_ui: case jit_code_getarg_l:
1502 case jit_code_getarg_f: case jit_code_getarg_d:
1503 case jit_code_putargr: case jit_code_putargi:
1504 case jit_code_putargr_f: case jit_code_putargi_f:
1505 case jit_code_putargr_d: case jit_code_putargi_d:
1506 case jit_code_pushargr: case jit_code_pushargi:
1507 case jit_code_pushargr_f: case jit_code_pushargi_f:
1508 case jit_code_pushargr_d: case jit_code_pushargi_d:
1509 case jit_code_retval_c: case jit_code_retval_uc:
1510 case jit_code_retval_s: case jit_code_retval_us:
1511 case jit_code_retval_i:
1512 case jit_code_retval_ui: case jit_code_retval_l:
1513 case jit_code_retval_f: case jit_code_retval_d:
1514 case jit_code_prepare:
1515 case jit_code_finishr: case jit_code_finishi:
1520 if (jit_carry != _NOREG) {
1521 switch (node->code) {
1523 case jit_code_addcr: case jit_code_addci:
1524 case jit_code_addxr: case jit_code_addxi:
1525 case jit_code_subcr: case jit_code_subci:
1526 case jit_code_subxr: case jit_code_subxi:
1529 jit_unget_reg(jit_carry);
1534 jit_regarg_clr(node, value);
1535 assert(_jitc->regarg == 0 ||
1536 (jit_carry != _NOREG && _jitc->regarg == (1 << jit_carry)));
1537 assert(_jitc->synth == 0);
1538 /* update register live state */
1550 for (offset = 0; offset < _jitc->patches.offset; offset++) {
1551 node = _jitc->patches.ptr[offset].node;
1552 word = node->code == jit_code_movi ? node->v.n->u.w : node->u.n->u.w;
1553 patch_at(_jitc->patches.ptr[offset].inst, word);
1556 jit_flush(_jit->code.ptr, _jit->pc.uc);
1558 return (_jit->code.ptr);
1562 # include "jit_loongarch-cpu.c"
1563 # include "jit_loongarch-fpu.c"
1567 jit_flush(void *fptr, void *tptr)
1569 #if defined(__GNUC__)
1572 s = sysconf(_SC_PAGE_SIZE);
1573 f = (jit_word_t)fptr & -s;
1574 t = (((jit_word_t)tptr) + s - 1) & -s;
1575 __clear_cache((void *)f, (void *)t);
1580 _emit_ldxi(jit_state_t *_jit, jit_int32_t r0, jit_int32_t r1, jit_word_t i0)
1582 ldxi(rn(r0), rn(r1), i0);
1586 _emit_stxi(jit_state_t *_jit, jit_word_t i0, jit_int32_t r0, jit_int32_t r1)
1588 stxi(i0, rn(r0), rn(r1));
1592 _emit_ldxi_d(jit_state_t *_jit, jit_int32_t r0, jit_int32_t r1, jit_word_t i0)
1594 ldxi_d(rn(r0), rn(r1), i0);
1598 _emit_stxi_d(jit_state_t *_jit, jit_word_t i0, jit_int32_t r0, jit_int32_t r1)
1600 stxi_d(i0, rn(r0), rn(r1));
1604 _patch(jit_state_t *_jit, jit_word_t instr, jit_node_t *node)
1608 assert(node->flag & jit_flag_node);
1609 if (node->code == jit_code_movi)
1610 flag = node->v.n->flag;
1612 flag = node->u.n->flag;
1613 assert(!(flag & jit_flag_patch));
1614 if (_jitc->patches.offset >= _jitc->patches.length) {
1615 jit_realloc((jit_pointer_t *)&_jitc->patches.ptr,
1616 _jitc->patches.length * sizeof(jit_patch_t),
1617 (_jitc->patches.length + 1024) * sizeof(jit_patch_t));
1618 _jitc->patches.length += 1024;
1620 _jitc->patches.ptr[_jitc->patches.offset].inst = instr;
1621 _jitc->patches.ptr[_jitc->patches.offset].node = node;
1622 ++_jitc->patches.offset;