OSDN Git Service

tcg/loongarch64: Implement tcg_out_call
[qmiga/qemu.git] / tcg / loongarch64 / tcg-target.c.inc
1 /*
2  * Tiny Code Generator for QEMU
3  *
4  * Copyright (c) 2021 WANG Xuerui <git@xen0n.name>
5  *
6  * Based on tcg/riscv/tcg-target.c.inc
7  *
8  * Copyright (c) 2018 SiFive, Inc
9  * Copyright (c) 2008-2009 Arnaud Patard <arnaud.patard@rtp-net.org>
10  * Copyright (c) 2009 Aurelien Jarno <aurelien@aurel32.net>
11  * Copyright (c) 2008 Fabrice Bellard
12  *
13  * Permission is hereby granted, free of charge, to any person obtaining a copy
14  * of this software and associated documentation files (the "Software"), to deal
15  * in the Software without restriction, including without limitation the rights
16  * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
17  * copies of the Software, and to permit persons to whom the Software is
18  * furnished to do so, subject to the following conditions:
19  *
20  * The above copyright notice and this permission notice shall be included in
21  * all copies or substantial portions of the Software.
22  *
23  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
24  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
25  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
26  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
27  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
28  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
29  * THE SOFTWARE.
30  */
31
32 #ifdef CONFIG_DEBUG_TCG
33 static const char * const tcg_target_reg_names[TCG_TARGET_NB_REGS] = {
34     "zero",
35     "ra",
36     "tp",
37     "sp",
38     "a0",
39     "a1",
40     "a2",
41     "a3",
42     "a4",
43     "a5",
44     "a6",
45     "a7",
46     "t0",
47     "t1",
48     "t2",
49     "t3",
50     "t4",
51     "t5",
52     "t6",
53     "t7",
54     "t8",
55     "r21", /* reserved in the LP64* ABI, hence no ABI name */
56     "s9",
57     "s0",
58     "s1",
59     "s2",
60     "s3",
61     "s4",
62     "s5",
63     "s6",
64     "s7",
65     "s8"
66 };
67 #endif
68
69 static const int tcg_target_reg_alloc_order[] = {
70     /* Registers preserved across calls */
71     /* TCG_REG_S0 reserved for TCG_AREG0 */
72     TCG_REG_S1,
73     TCG_REG_S2,
74     TCG_REG_S3,
75     TCG_REG_S4,
76     TCG_REG_S5,
77     TCG_REG_S6,
78     TCG_REG_S7,
79     TCG_REG_S8,
80     TCG_REG_S9,
81
82     /* Registers (potentially) clobbered across calls */
83     TCG_REG_T0,
84     TCG_REG_T1,
85     TCG_REG_T2,
86     TCG_REG_T3,
87     TCG_REG_T4,
88     TCG_REG_T5,
89     TCG_REG_T6,
90     TCG_REG_T7,
91     TCG_REG_T8,
92
93     /* Argument registers, opposite order of allocation.  */
94     TCG_REG_A7,
95     TCG_REG_A6,
96     TCG_REG_A5,
97     TCG_REG_A4,
98     TCG_REG_A3,
99     TCG_REG_A2,
100     TCG_REG_A1,
101     TCG_REG_A0,
102 };
103
104 static const int tcg_target_call_iarg_regs[] = {
105     TCG_REG_A0,
106     TCG_REG_A1,
107     TCG_REG_A2,
108     TCG_REG_A3,
109     TCG_REG_A4,
110     TCG_REG_A5,
111     TCG_REG_A6,
112     TCG_REG_A7,
113 };
114
115 static const int tcg_target_call_oarg_regs[] = {
116     TCG_REG_A0,
117     TCG_REG_A1,
118 };
119
120 #define TCG_CT_CONST_ZERO  0x100
121 #define TCG_CT_CONST_S12   0x200
122 #define TCG_CT_CONST_N12   0x400
123 #define TCG_CT_CONST_U12   0x800
124 #define TCG_CT_CONST_C12   0x1000
125 #define TCG_CT_CONST_WSZ   0x2000
126
127 #define ALL_GENERAL_REGS      MAKE_64BIT_MASK(0, 32)
128 /*
129  * For softmmu, we need to avoid conflicts with the first 5
130  * argument registers to call the helper.  Some of these are
131  * also used for the tlb lookup.
132  */
133 #ifdef CONFIG_SOFTMMU
134 #define SOFTMMU_RESERVE_REGS  MAKE_64BIT_MASK(TCG_REG_A0, 5)
135 #else
136 #define SOFTMMU_RESERVE_REGS  0
137 #endif
138
139
140 static inline tcg_target_long sextreg(tcg_target_long val, int pos, int len)
141 {
142     return sextract64(val, pos, len);
143 }
144
145 /* test if a constant matches the constraint */
146 static bool tcg_target_const_match(int64_t val, TCGType type, int ct)
147 {
148     if (ct & TCG_CT_CONST) {
149         return true;
150     }
151     if ((ct & TCG_CT_CONST_ZERO) && val == 0) {
152         return true;
153     }
154     if ((ct & TCG_CT_CONST_S12) && val == sextreg(val, 0, 12)) {
155         return true;
156     }
157     if ((ct & TCG_CT_CONST_N12) && -val == sextreg(-val, 0, 12)) {
158         return true;
159     }
160     if ((ct & TCG_CT_CONST_U12) && val >= 0 && val <= 0xfff) {
161         return true;
162     }
163     if ((ct & TCG_CT_CONST_C12) && ~val >= 0 && ~val <= 0xfff) {
164         return true;
165     }
166     if ((ct & TCG_CT_CONST_WSZ) && val == (type == TCG_TYPE_I32 ? 32 : 64)) {
167         return true;
168     }
169     return false;
170 }
171
172 /*
173  * Relocations
174  */
175
176 /*
177  * Relocation records defined in LoongArch ELF psABI v1.00 is way too
178  * complicated; a whopping stack machine is needed to stuff the fields, at
179  * the very least one SOP_PUSH and one SOP_POP (of the correct format) are
180  * needed.
181  *
182  * Hence, define our own simpler relocation types. Numbers are chosen as to
183  * not collide with potential future additions to the true ELF relocation
184  * type enum.
185  */
186
187 /* Field Sk16, shifted right by 2; suitable for conditional jumps */
188 #define R_LOONGARCH_BR_SK16     256
189 /* Field Sd10k16, shifted right by 2; suitable for B and BL */
190 #define R_LOONGARCH_BR_SD10K16  257
191
192 static bool reloc_br_sk16(tcg_insn_unit *src_rw, const tcg_insn_unit *target)
193 {
194     const tcg_insn_unit *src_rx = tcg_splitwx_to_rx(src_rw);
195     intptr_t offset = (intptr_t)target - (intptr_t)src_rx;
196
197     tcg_debug_assert((offset & 3) == 0);
198     offset >>= 2;
199     if (offset == sextreg(offset, 0, 16)) {
200         *src_rw = deposit64(*src_rw, 10, 16, offset);
201         return true;
202     }
203
204     return false;
205 }
206
207 static bool reloc_br_sd10k16(tcg_insn_unit *src_rw,
208                              const tcg_insn_unit *target)
209 {
210     const tcg_insn_unit *src_rx = tcg_splitwx_to_rx(src_rw);
211     intptr_t offset = (intptr_t)target - (intptr_t)src_rx;
212
213     tcg_debug_assert((offset & 3) == 0);
214     offset >>= 2;
215     if (offset == sextreg(offset, 0, 26)) {
216         *src_rw = deposit64(*src_rw, 0, 10, offset >> 16); /* slot d10 */
217         *src_rw = deposit64(*src_rw, 10, 16, offset); /* slot k16 */
218         return true;
219     }
220
221     return false;
222 }
223
224 static bool patch_reloc(tcg_insn_unit *code_ptr, int type,
225                         intptr_t value, intptr_t addend)
226 {
227     tcg_debug_assert(addend == 0);
228     switch (type) {
229     case R_LOONGARCH_BR_SK16:
230         return reloc_br_sk16(code_ptr, (tcg_insn_unit *)value);
231     case R_LOONGARCH_BR_SD10K16:
232         return reloc_br_sd10k16(code_ptr, (tcg_insn_unit *)value);
233     default:
234         g_assert_not_reached();
235     }
236 }
237
238 #include "tcg-insn-defs.c.inc"
239
240 /*
241  * TCG intrinsics
242  */
243
244 static void tcg_out_mb(TCGContext *s, TCGArg a0)
245 {
246     /* Baseline LoongArch only has the full barrier, unfortunately.  */
247     tcg_out_opc_dbar(s, 0);
248 }
249
250 static bool tcg_out_mov(TCGContext *s, TCGType type, TCGReg ret, TCGReg arg)
251 {
252     if (ret == arg) {
253         return true;
254     }
255     switch (type) {
256     case TCG_TYPE_I32:
257     case TCG_TYPE_I64:
258         /*
259          * Conventional register-register move used in LoongArch is
260          * `or dst, src, zero`.
261          */
262         tcg_out_opc_or(s, ret, arg, TCG_REG_ZERO);
263         break;
264     default:
265         g_assert_not_reached();
266     }
267     return true;
268 }
269
270 static bool imm_part_needs_loading(bool high_bits_are_ones,
271                                    tcg_target_long part)
272 {
273     if (high_bits_are_ones) {
274         return part != -1;
275     } else {
276         return part != 0;
277     }
278 }
279
280 /* Loads a 32-bit immediate into rd, sign-extended.  */
281 static void tcg_out_movi_i32(TCGContext *s, TCGReg rd, int32_t val)
282 {
283     tcg_target_long lo = sextreg(val, 0, 12);
284     tcg_target_long hi12 = sextreg(val, 12, 20);
285
286     /* Single-instruction cases.  */
287     if (lo == val) {
288         /* val fits in simm12: addi.w rd, zero, val */
289         tcg_out_opc_addi_w(s, rd, TCG_REG_ZERO, val);
290         return;
291     }
292     if (0x800 <= val && val <= 0xfff) {
293         /* val fits in uimm12: ori rd, zero, val */
294         tcg_out_opc_ori(s, rd, TCG_REG_ZERO, val);
295         return;
296     }
297
298     /* High bits must be set; load with lu12i.w + optional ori.  */
299     tcg_out_opc_lu12i_w(s, rd, hi12);
300     if (lo != 0) {
301         tcg_out_opc_ori(s, rd, rd, lo & 0xfff);
302     }
303 }
304
305 static void tcg_out_movi(TCGContext *s, TCGType type, TCGReg rd,
306                          tcg_target_long val)
307 {
308     /*
309      * LoongArch conventionally loads 64-bit immediates in at most 4 steps,
310      * with dedicated instructions for filling the respective bitfields
311      * below:
312      *
313      *        6                   5                   4               3
314      *  3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2
315      * +-----------------------+---------------------------------------+...
316      * |          hi52         |                  hi32                 |
317      * +-----------------------+---------------------------------------+...
318      *       3                   2                   1
319      *     1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0
320      * ...+-------------------------------------+-------------------------+
321      *    |                 hi12                |            lo           |
322      * ...+-------------------------------------+-------------------------+
323      *
324      * Check if val belong to one of the several fast cases, before falling
325      * back to the slow path.
326      */
327
328     intptr_t pc_offset;
329     tcg_target_long val_lo, val_hi, pc_hi, offset_hi;
330     tcg_target_long hi32, hi52;
331     bool rd_high_bits_are_ones;
332
333     /* Value fits in signed i32.  */
334     if (type == TCG_TYPE_I32 || val == (int32_t)val) {
335         tcg_out_movi_i32(s, rd, val);
336         return;
337     }
338
339     /* PC-relative cases.  */
340     pc_offset = tcg_pcrel_diff(s, (void *)val);
341     if (pc_offset == sextreg(pc_offset, 0, 22) && (pc_offset & 3) == 0) {
342         /* Single pcaddu2i.  */
343         tcg_out_opc_pcaddu2i(s, rd, pc_offset >> 2);
344         return;
345     }
346
347     if (pc_offset == (int32_t)pc_offset) {
348         /* Offset within 32 bits; load with pcalau12i + ori.  */
349         val_lo = sextreg(val, 0, 12);
350         val_hi = val >> 12;
351         pc_hi = (val - pc_offset) >> 12;
352         offset_hi = val_hi - pc_hi;
353
354         tcg_debug_assert(offset_hi == sextreg(offset_hi, 0, 20));
355         tcg_out_opc_pcalau12i(s, rd, offset_hi);
356         if (val_lo != 0) {
357             tcg_out_opc_ori(s, rd, rd, val_lo & 0xfff);
358         }
359         return;
360     }
361
362     hi32 = sextreg(val, 32, 20);
363     hi52 = sextreg(val, 52, 12);
364
365     /* Single cu52i.d case.  */
366     if (ctz64(val) >= 52) {
367         tcg_out_opc_cu52i_d(s, rd, TCG_REG_ZERO, hi52);
368         return;
369     }
370
371     /* Slow path.  Initialize the low 32 bits, then concat high bits.  */
372     tcg_out_movi_i32(s, rd, val);
373     rd_high_bits_are_ones = (int32_t)val < 0;
374
375     if (imm_part_needs_loading(rd_high_bits_are_ones, hi32)) {
376         tcg_out_opc_cu32i_d(s, rd, hi32);
377         rd_high_bits_are_ones = hi32 < 0;
378     }
379
380     if (imm_part_needs_loading(rd_high_bits_are_ones, hi52)) {
381         tcg_out_opc_cu52i_d(s, rd, rd, hi52);
382     }
383 }
384
385 static void tcg_out_ext8u(TCGContext *s, TCGReg ret, TCGReg arg)
386 {
387     tcg_out_opc_andi(s, ret, arg, 0xff);
388 }
389
390 static void tcg_out_ext16u(TCGContext *s, TCGReg ret, TCGReg arg)
391 {
392     tcg_out_opc_bstrpick_w(s, ret, arg, 0, 15);
393 }
394
395 static void tcg_out_ext32u(TCGContext *s, TCGReg ret, TCGReg arg)
396 {
397     tcg_out_opc_bstrpick_d(s, ret, arg, 0, 31);
398 }
399
400 static void tcg_out_ext8s(TCGContext *s, TCGReg ret, TCGReg arg)
401 {
402     tcg_out_opc_sext_b(s, ret, arg);
403 }
404
405 static void tcg_out_ext16s(TCGContext *s, TCGReg ret, TCGReg arg)
406 {
407     tcg_out_opc_sext_h(s, ret, arg);
408 }
409
410 static void tcg_out_ext32s(TCGContext *s, TCGReg ret, TCGReg arg)
411 {
412     tcg_out_opc_addi_w(s, ret, arg, 0);
413 }
414
415 static void tcg_out_clzctz(TCGContext *s, LoongArchInsn opc,
416                            TCGReg a0, TCGReg a1, TCGReg a2,
417                            bool c2, bool is_32bit)
418 {
419     if (c2) {
420         /*
421          * Fast path: semantics already satisfied due to constraint and
422          * insn behavior, single instruction is enough.
423          */
424         tcg_debug_assert(a2 == (is_32bit ? 32 : 64));
425         /* all clz/ctz insns belong to DJ-format */
426         tcg_out32(s, encode_dj_insn(opc, a0, a1));
427         return;
428     }
429
430     tcg_out32(s, encode_dj_insn(opc, TCG_REG_TMP0, a1));
431     /* a0 = a1 ? REG_TMP0 : a2 */
432     tcg_out_opc_maskeqz(s, TCG_REG_TMP0, TCG_REG_TMP0, a1);
433     tcg_out_opc_masknez(s, a0, a2, a1);
434     tcg_out_opc_or(s, a0, TCG_REG_TMP0, a0);
435 }
436
437 static void tcg_out_setcond(TCGContext *s, TCGCond cond, TCGReg ret,
438                             TCGReg arg1, TCGReg arg2, bool c2)
439 {
440     TCGReg tmp;
441
442     if (c2) {
443         tcg_debug_assert(arg2 == 0);
444     }
445
446     switch (cond) {
447     case TCG_COND_EQ:
448         if (c2) {
449             tmp = arg1;
450         } else {
451             tcg_out_opc_sub_d(s, ret, arg1, arg2);
452             tmp = ret;
453         }
454         tcg_out_opc_sltui(s, ret, tmp, 1);
455         break;
456     case TCG_COND_NE:
457         if (c2) {
458             tmp = arg1;
459         } else {
460             tcg_out_opc_sub_d(s, ret, arg1, arg2);
461             tmp = ret;
462         }
463         tcg_out_opc_sltu(s, ret, TCG_REG_ZERO, tmp);
464         break;
465     case TCG_COND_LT:
466         tcg_out_opc_slt(s, ret, arg1, arg2);
467         break;
468     case TCG_COND_GE:
469         tcg_out_opc_slt(s, ret, arg1, arg2);
470         tcg_out_opc_xori(s, ret, ret, 1);
471         break;
472     case TCG_COND_LE:
473         tcg_out_setcond(s, TCG_COND_GE, ret, arg2, arg1, false);
474         break;
475     case TCG_COND_GT:
476         tcg_out_setcond(s, TCG_COND_LT, ret, arg2, arg1, false);
477         break;
478     case TCG_COND_LTU:
479         tcg_out_opc_sltu(s, ret, arg1, arg2);
480         break;
481     case TCG_COND_GEU:
482         tcg_out_opc_sltu(s, ret, arg1, arg2);
483         tcg_out_opc_xori(s, ret, ret, 1);
484         break;
485     case TCG_COND_LEU:
486         tcg_out_setcond(s, TCG_COND_GEU, ret, arg2, arg1, false);
487         break;
488     case TCG_COND_GTU:
489         tcg_out_setcond(s, TCG_COND_LTU, ret, arg2, arg1, false);
490         break;
491     default:
492         g_assert_not_reached();
493         break;
494     }
495 }
496
497 /*
498  * Branch helpers
499  */
500
501 static const struct {
502     LoongArchInsn op;
503     bool swap;
504 } tcg_brcond_to_loongarch[] = {
505     [TCG_COND_EQ] =  { OPC_BEQ,  false },
506     [TCG_COND_NE] =  { OPC_BNE,  false },
507     [TCG_COND_LT] =  { OPC_BGT,  true  },
508     [TCG_COND_GE] =  { OPC_BLE,  true  },
509     [TCG_COND_LE] =  { OPC_BLE,  false },
510     [TCG_COND_GT] =  { OPC_BGT,  false },
511     [TCG_COND_LTU] = { OPC_BGTU, true  },
512     [TCG_COND_GEU] = { OPC_BLEU, true  },
513     [TCG_COND_LEU] = { OPC_BLEU, false },
514     [TCG_COND_GTU] = { OPC_BGTU, false }
515 };
516
517 static void tcg_out_brcond(TCGContext *s, TCGCond cond, TCGReg arg1,
518                            TCGReg arg2, TCGLabel *l)
519 {
520     LoongArchInsn op = tcg_brcond_to_loongarch[cond].op;
521
522     tcg_debug_assert(op != 0);
523
524     if (tcg_brcond_to_loongarch[cond].swap) {
525         TCGReg t = arg1;
526         arg1 = arg2;
527         arg2 = t;
528     }
529
530     /* all conditional branch insns belong to DJSk16-format */
531     tcg_out_reloc(s, s->code_ptr, R_LOONGARCH_BR_SK16, l, 0);
532     tcg_out32(s, encode_djsk16_insn(op, arg1, arg2, 0));
533 }
534
535 static void tcg_out_call_int(TCGContext *s, const tcg_insn_unit *arg, bool tail)
536 {
537     TCGReg link = tail ? TCG_REG_ZERO : TCG_REG_RA;
538     ptrdiff_t offset = tcg_pcrel_diff(s, arg);
539
540     tcg_debug_assert((offset & 3) == 0);
541     if (offset == sextreg(offset, 0, 28)) {
542         /* short jump: +/- 256MiB */
543         if (tail) {
544             tcg_out_opc_b(s, offset >> 2);
545         } else {
546             tcg_out_opc_bl(s, offset >> 2);
547         }
548     } else if (offset == sextreg(offset, 0, 38)) {
549         /* long jump: +/- 256GiB */
550         tcg_target_long lo = sextreg(offset, 0, 18);
551         tcg_target_long hi = offset - lo;
552         tcg_out_opc_pcaddu18i(s, TCG_REG_TMP0, hi >> 18);
553         tcg_out_opc_jirl(s, link, TCG_REG_TMP0, lo >> 2);
554     } else {
555         /* far jump: 64-bit */
556         tcg_target_long lo = sextreg((tcg_target_long)arg, 0, 18);
557         tcg_target_long hi = (tcg_target_long)arg - lo;
558         tcg_out_movi(s, TCG_TYPE_PTR, TCG_REG_TMP0, hi);
559         tcg_out_opc_jirl(s, link, TCG_REG_TMP0, lo >> 2);
560     }
561 }
562
563 static void tcg_out_call(TCGContext *s, const tcg_insn_unit *arg)
564 {
565     tcg_out_call_int(s, arg, false);
566 }
567
568 /*
569  * Entry-points
570  */
571
572 static void tcg_out_op(TCGContext *s, TCGOpcode opc,
573                        const TCGArg args[TCG_MAX_OP_ARGS],
574                        const int const_args[TCG_MAX_OP_ARGS])
575 {
576     TCGArg a0 = args[0];
577     TCGArg a1 = args[1];
578     TCGArg a2 = args[2];
579     int c2 = const_args[2];
580
581     switch (opc) {
582     case INDEX_op_mb:
583         tcg_out_mb(s, a0);
584         break;
585
586     case INDEX_op_goto_ptr:
587         tcg_out_opc_jirl(s, TCG_REG_ZERO, a0, 0);
588         break;
589
590     case INDEX_op_br:
591         tcg_out_reloc(s, s->code_ptr, R_LOONGARCH_BR_SD10K16, arg_label(a0),
592                       0);
593         tcg_out_opc_b(s, 0);
594         break;
595
596     case INDEX_op_brcond_i32:
597     case INDEX_op_brcond_i64:
598         tcg_out_brcond(s, a2, a0, a1, arg_label(args[3]));
599         break;
600
601     case INDEX_op_ext8s_i32:
602     case INDEX_op_ext8s_i64:
603         tcg_out_ext8s(s, a0, a1);
604         break;
605
606     case INDEX_op_ext8u_i32:
607     case INDEX_op_ext8u_i64:
608         tcg_out_ext8u(s, a0, a1);
609         break;
610
611     case INDEX_op_ext16s_i32:
612     case INDEX_op_ext16s_i64:
613         tcg_out_ext16s(s, a0, a1);
614         break;
615
616     case INDEX_op_ext16u_i32:
617     case INDEX_op_ext16u_i64:
618         tcg_out_ext16u(s, a0, a1);
619         break;
620
621     case INDEX_op_ext32u_i64:
622     case INDEX_op_extu_i32_i64:
623         tcg_out_ext32u(s, a0, a1);
624         break;
625
626     case INDEX_op_ext32s_i64:
627     case INDEX_op_extrl_i64_i32:
628     case INDEX_op_ext_i32_i64:
629         tcg_out_ext32s(s, a0, a1);
630         break;
631
632     case INDEX_op_extrh_i64_i32:
633         tcg_out_opc_srai_d(s, a0, a1, 32);
634         break;
635
636     case INDEX_op_not_i32:
637     case INDEX_op_not_i64:
638         tcg_out_opc_nor(s, a0, a1, TCG_REG_ZERO);
639         break;
640
641     case INDEX_op_nor_i32:
642     case INDEX_op_nor_i64:
643         if (c2) {
644             tcg_out_opc_ori(s, a0, a1, a2);
645             tcg_out_opc_nor(s, a0, a0, TCG_REG_ZERO);
646         } else {
647             tcg_out_opc_nor(s, a0, a1, a2);
648         }
649         break;
650
651     case INDEX_op_andc_i32:
652     case INDEX_op_andc_i64:
653         if (c2) {
654             /* guaranteed to fit due to constraint */
655             tcg_out_opc_andi(s, a0, a1, ~a2);
656         } else {
657             tcg_out_opc_andn(s, a0, a1, a2);
658         }
659         break;
660
661     case INDEX_op_orc_i32:
662     case INDEX_op_orc_i64:
663         if (c2) {
664             /* guaranteed to fit due to constraint */
665             tcg_out_opc_ori(s, a0, a1, ~a2);
666         } else {
667             tcg_out_opc_orn(s, a0, a1, a2);
668         }
669         break;
670
671     case INDEX_op_and_i32:
672     case INDEX_op_and_i64:
673         if (c2) {
674             tcg_out_opc_andi(s, a0, a1, a2);
675         } else {
676             tcg_out_opc_and(s, a0, a1, a2);
677         }
678         break;
679
680     case INDEX_op_or_i32:
681     case INDEX_op_or_i64:
682         if (c2) {
683             tcg_out_opc_ori(s, a0, a1, a2);
684         } else {
685             tcg_out_opc_or(s, a0, a1, a2);
686         }
687         break;
688
689     case INDEX_op_xor_i32:
690     case INDEX_op_xor_i64:
691         if (c2) {
692             tcg_out_opc_xori(s, a0, a1, a2);
693         } else {
694             tcg_out_opc_xor(s, a0, a1, a2);
695         }
696         break;
697
698     case INDEX_op_extract_i32:
699         tcg_out_opc_bstrpick_w(s, a0, a1, a2, a2 + args[3] - 1);
700         break;
701     case INDEX_op_extract_i64:
702         tcg_out_opc_bstrpick_d(s, a0, a1, a2, a2 + args[3] - 1);
703         break;
704
705     case INDEX_op_deposit_i32:
706         tcg_out_opc_bstrins_w(s, a0, a2, args[3], args[3] + args[4] - 1);
707         break;
708     case INDEX_op_deposit_i64:
709         tcg_out_opc_bstrins_d(s, a0, a2, args[3], args[3] + args[4] - 1);
710         break;
711
712     case INDEX_op_bswap16_i32:
713     case INDEX_op_bswap16_i64:
714         tcg_out_opc_revb_2h(s, a0, a1);
715         if (a2 & TCG_BSWAP_OS) {
716             tcg_out_ext16s(s, a0, a0);
717         } else if ((a2 & (TCG_BSWAP_IZ | TCG_BSWAP_OZ)) == TCG_BSWAP_OZ) {
718             tcg_out_ext16u(s, a0, a0);
719         }
720         break;
721
722     case INDEX_op_bswap32_i32:
723         /* All 32-bit values are computed sign-extended in the register.  */
724         a2 = TCG_BSWAP_OS;
725         /* fallthrough */
726     case INDEX_op_bswap32_i64:
727         tcg_out_opc_revb_2w(s, a0, a1);
728         if (a2 & TCG_BSWAP_OS) {
729             tcg_out_ext32s(s, a0, a0);
730         } else if ((a2 & (TCG_BSWAP_IZ | TCG_BSWAP_OZ)) == TCG_BSWAP_OZ) {
731             tcg_out_ext32u(s, a0, a0);
732         }
733         break;
734
735     case INDEX_op_bswap64_i64:
736         tcg_out_opc_revb_d(s, a0, a1);
737         break;
738
739     case INDEX_op_clz_i32:
740         tcg_out_clzctz(s, OPC_CLZ_W, a0, a1, a2, c2, true);
741         break;
742     case INDEX_op_clz_i64:
743         tcg_out_clzctz(s, OPC_CLZ_D, a0, a1, a2, c2, false);
744         break;
745
746     case INDEX_op_ctz_i32:
747         tcg_out_clzctz(s, OPC_CTZ_W, a0, a1, a2, c2, true);
748         break;
749     case INDEX_op_ctz_i64:
750         tcg_out_clzctz(s, OPC_CTZ_D, a0, a1, a2, c2, false);
751         break;
752
753     case INDEX_op_shl_i32:
754         if (c2) {
755             tcg_out_opc_slli_w(s, a0, a1, a2 & 0x1f);
756         } else {
757             tcg_out_opc_sll_w(s, a0, a1, a2);
758         }
759         break;
760     case INDEX_op_shl_i64:
761         if (c2) {
762             tcg_out_opc_slli_d(s, a0, a1, a2 & 0x3f);
763         } else {
764             tcg_out_opc_sll_d(s, a0, a1, a2);
765         }
766         break;
767
768     case INDEX_op_shr_i32:
769         if (c2) {
770             tcg_out_opc_srli_w(s, a0, a1, a2 & 0x1f);
771         } else {
772             tcg_out_opc_srl_w(s, a0, a1, a2);
773         }
774         break;
775     case INDEX_op_shr_i64:
776         if (c2) {
777             tcg_out_opc_srli_d(s, a0, a1, a2 & 0x3f);
778         } else {
779             tcg_out_opc_srl_d(s, a0, a1, a2);
780         }
781         break;
782
783     case INDEX_op_sar_i32:
784         if (c2) {
785             tcg_out_opc_srai_w(s, a0, a1, a2 & 0x1f);
786         } else {
787             tcg_out_opc_sra_w(s, a0, a1, a2);
788         }
789         break;
790     case INDEX_op_sar_i64:
791         if (c2) {
792             tcg_out_opc_srai_d(s, a0, a1, a2 & 0x3f);
793         } else {
794             tcg_out_opc_sra_d(s, a0, a1, a2);
795         }
796         break;
797
798     case INDEX_op_rotl_i32:
799         /* transform into equivalent rotr/rotri */
800         if (c2) {
801             tcg_out_opc_rotri_w(s, a0, a1, (32 - a2) & 0x1f);
802         } else {
803             tcg_out_opc_sub_w(s, TCG_REG_TMP0, TCG_REG_ZERO, a2);
804             tcg_out_opc_rotr_w(s, a0, a1, TCG_REG_TMP0);
805         }
806         break;
807     case INDEX_op_rotl_i64:
808         /* transform into equivalent rotr/rotri */
809         if (c2) {
810             tcg_out_opc_rotri_d(s, a0, a1, (64 - a2) & 0x3f);
811         } else {
812             tcg_out_opc_sub_w(s, TCG_REG_TMP0, TCG_REG_ZERO, a2);
813             tcg_out_opc_rotr_d(s, a0, a1, TCG_REG_TMP0);
814         }
815         break;
816
817     case INDEX_op_rotr_i32:
818         if (c2) {
819             tcg_out_opc_rotri_w(s, a0, a1, a2 & 0x1f);
820         } else {
821             tcg_out_opc_rotr_w(s, a0, a1, a2);
822         }
823         break;
824     case INDEX_op_rotr_i64:
825         if (c2) {
826             tcg_out_opc_rotri_d(s, a0, a1, a2 & 0x3f);
827         } else {
828             tcg_out_opc_rotr_d(s, a0, a1, a2);
829         }
830         break;
831
832     case INDEX_op_add_i32:
833         if (c2) {
834             tcg_out_opc_addi_w(s, a0, a1, a2);
835         } else {
836             tcg_out_opc_add_w(s, a0, a1, a2);
837         }
838         break;
839     case INDEX_op_add_i64:
840         if (c2) {
841             tcg_out_opc_addi_d(s, a0, a1, a2);
842         } else {
843             tcg_out_opc_add_d(s, a0, a1, a2);
844         }
845         break;
846
847     case INDEX_op_sub_i32:
848         if (c2) {
849             tcg_out_opc_addi_w(s, a0, a1, -a2);
850         } else {
851             tcg_out_opc_sub_w(s, a0, a1, a2);
852         }
853         break;
854     case INDEX_op_sub_i64:
855         if (c2) {
856             tcg_out_opc_addi_d(s, a0, a1, -a2);
857         } else {
858             tcg_out_opc_sub_d(s, a0, a1, a2);
859         }
860         break;
861
862     case INDEX_op_mul_i32:
863         tcg_out_opc_mul_w(s, a0, a1, a2);
864         break;
865     case INDEX_op_mul_i64:
866         tcg_out_opc_mul_d(s, a0, a1, a2);
867         break;
868
869     case INDEX_op_mulsh_i32:
870         tcg_out_opc_mulh_w(s, a0, a1, a2);
871         break;
872     case INDEX_op_mulsh_i64:
873         tcg_out_opc_mulh_d(s, a0, a1, a2);
874         break;
875
876     case INDEX_op_muluh_i32:
877         tcg_out_opc_mulh_wu(s, a0, a1, a2);
878         break;
879     case INDEX_op_muluh_i64:
880         tcg_out_opc_mulh_du(s, a0, a1, a2);
881         break;
882
883     case INDEX_op_div_i32:
884         tcg_out_opc_div_w(s, a0, a1, a2);
885         break;
886     case INDEX_op_div_i64:
887         tcg_out_opc_div_d(s, a0, a1, a2);
888         break;
889
890     case INDEX_op_divu_i32:
891         tcg_out_opc_div_wu(s, a0, a1, a2);
892         break;
893     case INDEX_op_divu_i64:
894         tcg_out_opc_div_du(s, a0, a1, a2);
895         break;
896
897     case INDEX_op_rem_i32:
898         tcg_out_opc_mod_w(s, a0, a1, a2);
899         break;
900     case INDEX_op_rem_i64:
901         tcg_out_opc_mod_d(s, a0, a1, a2);
902         break;
903
904     case INDEX_op_remu_i32:
905         tcg_out_opc_mod_wu(s, a0, a1, a2);
906         break;
907     case INDEX_op_remu_i64:
908         tcg_out_opc_mod_du(s, a0, a1, a2);
909         break;
910
911     case INDEX_op_setcond_i32:
912     case INDEX_op_setcond_i64:
913         tcg_out_setcond(s, args[3], a0, a1, a2, c2);
914         break;
915
916     case INDEX_op_mov_i32:  /* Always emitted via tcg_out_mov.  */
917     case INDEX_op_mov_i64:
918     case INDEX_op_call:     /* Always emitted via tcg_out_call.  */
919     default:
920         g_assert_not_reached();
921     }
922 }
923
924 static TCGConstraintSetIndex tcg_target_op_def(TCGOpcode op)
925 {
926     switch (op) {
927     case INDEX_op_goto_ptr:
928         return C_O0_I1(r);
929
930     case INDEX_op_brcond_i32:
931     case INDEX_op_brcond_i64:
932         return C_O0_I2(rZ, rZ);
933
934     case INDEX_op_ext8s_i32:
935     case INDEX_op_ext8s_i64:
936     case INDEX_op_ext8u_i32:
937     case INDEX_op_ext8u_i64:
938     case INDEX_op_ext16s_i32:
939     case INDEX_op_ext16s_i64:
940     case INDEX_op_ext16u_i32:
941     case INDEX_op_ext16u_i64:
942     case INDEX_op_ext32s_i64:
943     case INDEX_op_ext32u_i64:
944     case INDEX_op_extu_i32_i64:
945     case INDEX_op_extrl_i64_i32:
946     case INDEX_op_extrh_i64_i32:
947     case INDEX_op_ext_i32_i64:
948     case INDEX_op_not_i32:
949     case INDEX_op_not_i64:
950     case INDEX_op_extract_i32:
951     case INDEX_op_extract_i64:
952     case INDEX_op_bswap16_i32:
953     case INDEX_op_bswap16_i64:
954     case INDEX_op_bswap32_i32:
955     case INDEX_op_bswap32_i64:
956     case INDEX_op_bswap64_i64:
957         return C_O1_I1(r, r);
958
959     case INDEX_op_andc_i32:
960     case INDEX_op_andc_i64:
961     case INDEX_op_orc_i32:
962     case INDEX_op_orc_i64:
963         /*
964          * LoongArch insns for these ops don't have reg-imm forms, but we
965          * can express using andi/ori if ~constant satisfies
966          * TCG_CT_CONST_U12.
967          */
968         return C_O1_I2(r, r, rC);
969
970     case INDEX_op_shl_i32:
971     case INDEX_op_shl_i64:
972     case INDEX_op_shr_i32:
973     case INDEX_op_shr_i64:
974     case INDEX_op_sar_i32:
975     case INDEX_op_sar_i64:
976     case INDEX_op_rotl_i32:
977     case INDEX_op_rotl_i64:
978     case INDEX_op_rotr_i32:
979     case INDEX_op_rotr_i64:
980         return C_O1_I2(r, r, ri);
981
982     case INDEX_op_add_i32:
983     case INDEX_op_add_i64:
984         return C_O1_I2(r, r, rI);
985
986     case INDEX_op_and_i32:
987     case INDEX_op_and_i64:
988     case INDEX_op_nor_i32:
989     case INDEX_op_nor_i64:
990     case INDEX_op_or_i32:
991     case INDEX_op_or_i64:
992     case INDEX_op_xor_i32:
993     case INDEX_op_xor_i64:
994         /* LoongArch reg-imm bitops have their imms ZERO-extended */
995         return C_O1_I2(r, r, rU);
996
997     case INDEX_op_clz_i32:
998     case INDEX_op_clz_i64:
999     case INDEX_op_ctz_i32:
1000     case INDEX_op_ctz_i64:
1001         return C_O1_I2(r, r, rW);
1002
1003     case INDEX_op_setcond_i32:
1004     case INDEX_op_setcond_i64:
1005         return C_O1_I2(r, r, rZ);
1006
1007     case INDEX_op_deposit_i32:
1008     case INDEX_op_deposit_i64:
1009         /* Must deposit into the same register as input */
1010         return C_O1_I2(r, 0, rZ);
1011
1012     case INDEX_op_sub_i32:
1013     case INDEX_op_sub_i64:
1014         return C_O1_I2(r, rZ, rN);
1015
1016     case INDEX_op_mul_i32:
1017     case INDEX_op_mul_i64:
1018     case INDEX_op_mulsh_i32:
1019     case INDEX_op_mulsh_i64:
1020     case INDEX_op_muluh_i32:
1021     case INDEX_op_muluh_i64:
1022     case INDEX_op_div_i32:
1023     case INDEX_op_div_i64:
1024     case INDEX_op_divu_i32:
1025     case INDEX_op_divu_i64:
1026     case INDEX_op_rem_i32:
1027     case INDEX_op_rem_i64:
1028     case INDEX_op_remu_i32:
1029     case INDEX_op_remu_i64:
1030         return C_O1_I2(r, rZ, rZ);
1031
1032     default:
1033         g_assert_not_reached();
1034     }
1035 }