Merge tag 'pull-trivial-patches' of https://gitlab.com/mjt0k/qemu into staging
[qemu/ar7.git] / tcg / loongarch64 / tcg-target.c.inc
blobbaf5fc38195d923a1b75f9562bbb0d25966b36ce
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  */
32 #include "../tcg-ldst.c.inc"
33 #include <asm/hwcap.h>
35 #ifdef CONFIG_DEBUG_TCG
36 static const char * const tcg_target_reg_names[TCG_TARGET_NB_REGS] = {
37     "zero",
38     "ra",
39     "tp",
40     "sp",
41     "a0",
42     "a1",
43     "a2",
44     "a3",
45     "a4",
46     "a5",
47     "a6",
48     "a7",
49     "t0",
50     "t1",
51     "t2",
52     "t3",
53     "t4",
54     "t5",
55     "t6",
56     "t7",
57     "t8",
58     "r21", /* reserved in the LP64* ABI, hence no ABI name */
59     "s9",
60     "s0",
61     "s1",
62     "s2",
63     "s3",
64     "s4",
65     "s5",
66     "s6",
67     "s7",
68     "s8"
70 #endif
72 static const int tcg_target_reg_alloc_order[] = {
73     /* Registers preserved across calls */
74     /* TCG_REG_S0 reserved for TCG_AREG0 */
75     TCG_REG_S1,
76     TCG_REG_S2,
77     TCG_REG_S3,
78     TCG_REG_S4,
79     TCG_REG_S5,
80     TCG_REG_S6,
81     TCG_REG_S7,
82     TCG_REG_S8,
83     TCG_REG_S9,
85     /* Registers (potentially) clobbered across calls */
86     TCG_REG_T0,
87     TCG_REG_T1,
88     TCG_REG_T2,
89     TCG_REG_T3,
90     TCG_REG_T4,
91     TCG_REG_T5,
92     TCG_REG_T6,
93     TCG_REG_T7,
94     TCG_REG_T8,
96     /* Argument registers, opposite order of allocation.  */
97     TCG_REG_A7,
98     TCG_REG_A6,
99     TCG_REG_A5,
100     TCG_REG_A4,
101     TCG_REG_A3,
102     TCG_REG_A2,
103     TCG_REG_A1,
104     TCG_REG_A0,
107 static const int tcg_target_call_iarg_regs[] = {
108     TCG_REG_A0,
109     TCG_REG_A1,
110     TCG_REG_A2,
111     TCG_REG_A3,
112     TCG_REG_A4,
113     TCG_REG_A5,
114     TCG_REG_A6,
115     TCG_REG_A7,
118 static TCGReg tcg_target_call_oarg_reg(TCGCallReturnKind kind, int slot)
120     tcg_debug_assert(kind == TCG_CALL_RET_NORMAL);
121     tcg_debug_assert(slot >= 0 && slot <= 1);
122     return TCG_REG_A0 + slot;
125 #ifndef CONFIG_SOFTMMU
126 #define USE_GUEST_BASE     (guest_base != 0)
127 #define TCG_GUEST_BASE_REG TCG_REG_S1
128 #endif
130 #define TCG_CT_CONST_ZERO  0x100
131 #define TCG_CT_CONST_S12   0x200
132 #define TCG_CT_CONST_S32   0x400
133 #define TCG_CT_CONST_U12   0x800
134 #define TCG_CT_CONST_C12   0x1000
135 #define TCG_CT_CONST_WSZ   0x2000
137 #define ALL_GENERAL_REGS   MAKE_64BIT_MASK(0, 32)
139 static inline tcg_target_long sextreg(tcg_target_long val, int pos, int len)
141     return sextract64(val, pos, len);
144 /* test if a constant matches the constraint */
145 static bool tcg_target_const_match(int64_t val, TCGType type, int ct)
147     if (ct & TCG_CT_CONST) {
148         return true;
149     }
150     if ((ct & TCG_CT_CONST_ZERO) && val == 0) {
151         return true;
152     }
153     if ((ct & TCG_CT_CONST_S12) && val == sextreg(val, 0, 12)) {
154         return true;
155     }
156     if ((ct & TCG_CT_CONST_S32) && val == (int32_t)val) {
157         return true;
158     }
159     if ((ct & TCG_CT_CONST_U12) && val >= 0 && val <= 0xfff) {
160         return true;
161     }
162     if ((ct & TCG_CT_CONST_C12) && ~val >= 0 && ~val <= 0xfff) {
163         return true;
164     }
165     if ((ct & TCG_CT_CONST_WSZ) && val == (type == TCG_TYPE_I32 ? 32 : 64)) {
166         return true;
167     }
168     return false;
172  * Relocations
173  */
176  * Relocation records defined in LoongArch ELF psABI v1.00 is way too
177  * complicated; a whopping stack machine is needed to stuff the fields, at
178  * the very least one SOP_PUSH and one SOP_POP (of the correct format) are
179  * needed.
181  * Hence, define our own simpler relocation types. Numbers are chosen as to
182  * not collide with potential future additions to the true ELF relocation
183  * type enum.
184  */
186 /* Field Sk16, shifted right by 2; suitable for conditional jumps */
187 #define R_LOONGARCH_BR_SK16     256
188 /* Field Sd10k16, shifted right by 2; suitable for B and BL */
189 #define R_LOONGARCH_BR_SD10K16  257
191 static bool reloc_br_sk16(tcg_insn_unit *src_rw, const tcg_insn_unit *target)
193     const tcg_insn_unit *src_rx = tcg_splitwx_to_rx(src_rw);
194     intptr_t offset = (intptr_t)target - (intptr_t)src_rx;
196     tcg_debug_assert((offset & 3) == 0);
197     offset >>= 2;
198     if (offset == sextreg(offset, 0, 16)) {
199         *src_rw = deposit64(*src_rw, 10, 16, offset);
200         return true;
201     }
203     return false;
206 static bool reloc_br_sd10k16(tcg_insn_unit *src_rw,
207                              const tcg_insn_unit *target)
209     const tcg_insn_unit *src_rx = tcg_splitwx_to_rx(src_rw);
210     intptr_t offset = (intptr_t)target - (intptr_t)src_rx;
212     tcg_debug_assert((offset & 3) == 0);
213     offset >>= 2;
214     if (offset == sextreg(offset, 0, 26)) {
215         *src_rw = deposit64(*src_rw, 0, 10, offset >> 16); /* slot d10 */
216         *src_rw = deposit64(*src_rw, 10, 16, offset); /* slot k16 */
217         return true;
218     }
220     return false;
223 static bool patch_reloc(tcg_insn_unit *code_ptr, int type,
224                         intptr_t value, intptr_t addend)
226     tcg_debug_assert(addend == 0);
227     switch (type) {
228     case R_LOONGARCH_BR_SK16:
229         return reloc_br_sk16(code_ptr, (tcg_insn_unit *)value);
230     case R_LOONGARCH_BR_SD10K16:
231         return reloc_br_sd10k16(code_ptr, (tcg_insn_unit *)value);
232     default:
233         g_assert_not_reached();
234     }
237 #include "tcg-insn-defs.c.inc"
240  * TCG intrinsics
241  */
243 static void tcg_out_mb(TCGContext *s, TCGArg a0)
245     /* Baseline LoongArch only has the full barrier, unfortunately.  */
246     tcg_out_opc_dbar(s, 0);
249 static bool tcg_out_mov(TCGContext *s, TCGType type, TCGReg ret, TCGReg arg)
251     if (ret == arg) {
252         return true;
253     }
254     switch (type) {
255     case TCG_TYPE_I32:
256     case TCG_TYPE_I64:
257         /*
258          * Conventional register-register move used in LoongArch is
259          * `or dst, src, zero`.
260          */
261         tcg_out_opc_or(s, ret, arg, TCG_REG_ZERO);
262         break;
263     default:
264         g_assert_not_reached();
265     }
266     return true;
269 /* Loads a 32-bit immediate into rd, sign-extended.  */
270 static void tcg_out_movi_i32(TCGContext *s, TCGReg rd, int32_t val)
272     tcg_target_long lo = sextreg(val, 0, 12);
273     tcg_target_long hi12 = sextreg(val, 12, 20);
275     /* Single-instruction cases.  */
276     if (hi12 == 0) {
277         /* val fits in uimm12: ori rd, zero, val */
278         tcg_out_opc_ori(s, rd, TCG_REG_ZERO, val);
279         return;
280     }
281     if (hi12 == sextreg(lo, 12, 20)) {
282         /* val fits in simm12: addi.w rd, zero, val */
283         tcg_out_opc_addi_w(s, rd, TCG_REG_ZERO, val);
284         return;
285     }
287     /* High bits must be set; load with lu12i.w + optional ori.  */
288     tcg_out_opc_lu12i_w(s, rd, hi12);
289     if (lo != 0) {
290         tcg_out_opc_ori(s, rd, rd, lo & 0xfff);
291     }
294 static void tcg_out_movi(TCGContext *s, TCGType type, TCGReg rd,
295                          tcg_target_long val)
297     /*
298      * LoongArch conventionally loads 64-bit immediates in at most 4 steps,
299      * with dedicated instructions for filling the respective bitfields
300      * below:
301      *
302      *        6                   5                   4               3
303      *  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
304      * +-----------------------+---------------------------------------+...
305      * |          hi52         |                  hi32                 |
306      * +-----------------------+---------------------------------------+...
307      *       3                   2                   1
308      *     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
309      * ...+-------------------------------------+-------------------------+
310      *    |                 hi12                |            lo           |
311      * ...+-------------------------------------+-------------------------+
312      *
313      * Check if val belong to one of the several fast cases, before falling
314      * back to the slow path.
315      */
317     intptr_t pc_offset;
318     tcg_target_long val_lo, val_hi, pc_hi, offset_hi;
319     tcg_target_long hi12, hi32, hi52;
321     /* Value fits in signed i32.  */
322     if (type == TCG_TYPE_I32 || val == (int32_t)val) {
323         tcg_out_movi_i32(s, rd, val);
324         return;
325     }
327     /* PC-relative cases.  */
328     pc_offset = tcg_pcrel_diff(s, (void *)val);
329     if (pc_offset == sextreg(pc_offset, 0, 22) && (pc_offset & 3) == 0) {
330         /* Single pcaddu2i.  */
331         tcg_out_opc_pcaddu2i(s, rd, pc_offset >> 2);
332         return;
333     }
335     if (pc_offset == (int32_t)pc_offset) {
336         /* Offset within 32 bits; load with pcalau12i + ori.  */
337         val_lo = sextreg(val, 0, 12);
338         val_hi = val >> 12;
339         pc_hi = (val - pc_offset) >> 12;
340         offset_hi = val_hi - pc_hi;
342         tcg_debug_assert(offset_hi == sextreg(offset_hi, 0, 20));
343         tcg_out_opc_pcalau12i(s, rd, offset_hi);
344         if (val_lo != 0) {
345             tcg_out_opc_ori(s, rd, rd, val_lo & 0xfff);
346         }
347         return;
348     }
350     hi12 = sextreg(val, 12, 20);
351     hi32 = sextreg(val, 32, 20);
352     hi52 = sextreg(val, 52, 12);
354     /* Single cu52i.d case.  */
355     if ((hi52 != 0) && (ctz64(val) >= 52)) {
356         tcg_out_opc_cu52i_d(s, rd, TCG_REG_ZERO, hi52);
357         return;
358     }
360     /* Slow path.  Initialize the low 32 bits, then concat high bits.  */
361     tcg_out_movi_i32(s, rd, val);
363     /* Load hi32 and hi52 explicitly when they are unexpected values. */
364     if (hi32 != sextreg(hi12, 20, 20)) {
365         tcg_out_opc_cu32i_d(s, rd, hi32);
366     }
368     if (hi52 != sextreg(hi32, 20, 12)) {
369         tcg_out_opc_cu52i_d(s, rd, rd, hi52);
370     }
373 static void tcg_out_addi(TCGContext *s, TCGType type, TCGReg rd,
374                          TCGReg rs, tcg_target_long imm)
376     tcg_target_long lo12 = sextreg(imm, 0, 12);
377     tcg_target_long hi16 = sextreg(imm - lo12, 16, 16);
379     /*
380      * Note that there's a hole in between hi16 and lo12:
381      *
382      *       3                   2                   1                   0
383      *     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
384      * ...+-------------------------------+-------+-----------------------+
385      *    |             hi16              |       |          lo12         |
386      * ...+-------------------------------+-------+-----------------------+
387      *
388      * For bits within that hole, it's more efficient to use LU12I and ADD.
389      */
390     if (imm == (hi16 << 16) + lo12) {
391         if (hi16) {
392             tcg_out_opc_addu16i_d(s, rd, rs, hi16);
393             rs = rd;
394         }
395         if (type == TCG_TYPE_I32) {
396             tcg_out_opc_addi_w(s, rd, rs, lo12);
397         } else if (lo12) {
398             tcg_out_opc_addi_d(s, rd, rs, lo12);
399         } else {
400             tcg_out_mov(s, type, rd, rs);
401         }
402     } else {
403         tcg_out_movi(s, type, TCG_REG_TMP0, imm);
404         if (type == TCG_TYPE_I32) {
405             tcg_out_opc_add_w(s, rd, rs, TCG_REG_TMP0);
406         } else {
407             tcg_out_opc_add_d(s, rd, rs, TCG_REG_TMP0);
408         }
409     }
412 static bool tcg_out_xchg(TCGContext *s, TCGType type, TCGReg r1, TCGReg r2)
414     return false;
417 static void tcg_out_addi_ptr(TCGContext *s, TCGReg rd, TCGReg rs,
418                              tcg_target_long imm)
420     /* This function is only used for passing structs by reference. */
421     g_assert_not_reached();
424 static void tcg_out_ext8u(TCGContext *s, TCGReg ret, TCGReg arg)
426     tcg_out_opc_andi(s, ret, arg, 0xff);
429 static void tcg_out_ext16u(TCGContext *s, TCGReg ret, TCGReg arg)
431     tcg_out_opc_bstrpick_w(s, ret, arg, 0, 15);
434 static void tcg_out_ext32u(TCGContext *s, TCGReg ret, TCGReg arg)
436     tcg_out_opc_bstrpick_d(s, ret, arg, 0, 31);
439 static void tcg_out_ext8s(TCGContext *s, TCGType type, TCGReg ret, TCGReg arg)
441     tcg_out_opc_sext_b(s, ret, arg);
444 static void tcg_out_ext16s(TCGContext *s, TCGType type, TCGReg ret, TCGReg arg)
446     tcg_out_opc_sext_h(s, ret, arg);
449 static void tcg_out_ext32s(TCGContext *s, TCGReg ret, TCGReg arg)
451     tcg_out_opc_addi_w(s, ret, arg, 0);
454 static void tcg_out_exts_i32_i64(TCGContext *s, TCGReg ret, TCGReg arg)
456     if (ret != arg) {
457         tcg_out_ext32s(s, ret, arg);
458     }
461 static void tcg_out_extu_i32_i64(TCGContext *s, TCGReg ret, TCGReg arg)
463     tcg_out_ext32u(s, ret, arg);
466 static void tcg_out_extrl_i64_i32(TCGContext *s, TCGReg ret, TCGReg arg)
468     tcg_out_ext32s(s, ret, arg);
471 static void tcg_out_clzctz(TCGContext *s, LoongArchInsn opc,
472                            TCGReg a0, TCGReg a1, TCGReg a2,
473                            bool c2, bool is_32bit)
475     if (c2) {
476         /*
477          * Fast path: semantics already satisfied due to constraint and
478          * insn behavior, single instruction is enough.
479          */
480         tcg_debug_assert(a2 == (is_32bit ? 32 : 64));
481         /* all clz/ctz insns belong to DJ-format */
482         tcg_out32(s, encode_dj_insn(opc, a0, a1));
483         return;
484     }
486     tcg_out32(s, encode_dj_insn(opc, TCG_REG_TMP0, a1));
487     /* a0 = a1 ? REG_TMP0 : a2 */
488     tcg_out_opc_maskeqz(s, TCG_REG_TMP0, TCG_REG_TMP0, a1);
489     tcg_out_opc_masknez(s, a0, a2, a1);
490     tcg_out_opc_or(s, a0, TCG_REG_TMP0, a0);
493 #define SETCOND_INV    TCG_TARGET_NB_REGS
494 #define SETCOND_NEZ    (SETCOND_INV << 1)
495 #define SETCOND_FLAGS  (SETCOND_INV | SETCOND_NEZ)
497 static int tcg_out_setcond_int(TCGContext *s, TCGCond cond, TCGReg ret,
498                                TCGReg arg1, tcg_target_long arg2, bool c2)
500     int flags = 0;
502     switch (cond) {
503     case TCG_COND_EQ:    /* -> NE  */
504     case TCG_COND_GE:    /* -> LT  */
505     case TCG_COND_GEU:   /* -> LTU */
506     case TCG_COND_GT:    /* -> LE  */
507     case TCG_COND_GTU:   /* -> LEU */
508         cond = tcg_invert_cond(cond);
509         flags ^= SETCOND_INV;
510         break;
511     default:
512         break;
513     }
515     switch (cond) {
516     case TCG_COND_LE:
517     case TCG_COND_LEU:
518         /*
519          * If we have a constant input, the most efficient way to implement
520          * LE is by adding 1 and using LT.  Watch out for wrap around for LEU.
521          * We don't need to care for this for LE because the constant input
522          * is still constrained to int32_t, and INT32_MAX+1 is representable
523          * in the 64-bit temporary register.
524          */
525         if (c2) {
526             if (cond == TCG_COND_LEU) {
527                 /* unsigned <= -1 is true */
528                 if (arg2 == -1) {
529                     tcg_out_movi(s, TCG_TYPE_REG, ret, !(flags & SETCOND_INV));
530                     return ret;
531                 }
532                 cond = TCG_COND_LTU;
533             } else {
534                 cond = TCG_COND_LT;
535             }
536             arg2 += 1;
537         } else {
538             TCGReg tmp = arg2;
539             arg2 = arg1;
540             arg1 = tmp;
541             cond = tcg_swap_cond(cond);    /* LE -> GE */
542             cond = tcg_invert_cond(cond);  /* GE -> LT */
543             flags ^= SETCOND_INV;
544         }
545         break;
546     default:
547         break;
548     }
550     switch (cond) {
551     case TCG_COND_NE:
552         flags |= SETCOND_NEZ;
553         if (!c2) {
554             tcg_out_opc_xor(s, ret, arg1, arg2);
555         } else if (arg2 == 0) {
556             ret = arg1;
557         } else if (arg2 >= 0 && arg2 <= 0xfff) {
558             tcg_out_opc_xori(s, ret, arg1, arg2);
559         } else {
560             tcg_out_addi(s, TCG_TYPE_REG, ret, arg1, -arg2);
561         }
562         break;
564     case TCG_COND_LT:
565     case TCG_COND_LTU:
566         if (c2) {
567             if (arg2 >= -0x800 && arg2 <= 0x7ff) {
568                 if (cond == TCG_COND_LT) {
569                     tcg_out_opc_slti(s, ret, arg1, arg2);
570                 } else {
571                     tcg_out_opc_sltui(s, ret, arg1, arg2);
572                 }
573                 break;
574             }
575             tcg_out_movi(s, TCG_TYPE_REG, TCG_REG_TMP0, arg2);
576             arg2 = TCG_REG_TMP0;
577         }
578         if (cond == TCG_COND_LT) {
579             tcg_out_opc_slt(s, ret, arg1, arg2);
580         } else {
581             tcg_out_opc_sltu(s, ret, arg1, arg2);
582         }
583         break;
585     default:
586         g_assert_not_reached();
587         break;
588     }
590     return ret | flags;
593 static void tcg_out_setcond(TCGContext *s, TCGCond cond, TCGReg ret,
594                             TCGReg arg1, tcg_target_long arg2, bool c2)
596     int tmpflags = tcg_out_setcond_int(s, cond, ret, arg1, arg2, c2);
598     if (tmpflags != ret) {
599         TCGReg tmp = tmpflags & ~SETCOND_FLAGS;
601         switch (tmpflags & SETCOND_FLAGS) {
602         case SETCOND_INV:
603             /* Intermediate result is boolean: simply invert. */
604             tcg_out_opc_xori(s, ret, tmp, 1);
605             break;
606         case SETCOND_NEZ:
607             /* Intermediate result is zero/non-zero: test != 0. */
608             tcg_out_opc_sltu(s, ret, TCG_REG_ZERO, tmp);
609             break;
610         case SETCOND_NEZ | SETCOND_INV:
611             /* Intermediate result is zero/non-zero: test == 0. */
612             tcg_out_opc_sltui(s, ret, tmp, 1);
613             break;
614         default:
615             g_assert_not_reached();
616         }
617     }
620 static void tcg_out_movcond(TCGContext *s, TCGCond cond, TCGReg ret,
621                             TCGReg c1, tcg_target_long c2, bool const2,
622                             TCGReg v1, TCGReg v2)
624     int tmpflags = tcg_out_setcond_int(s, cond, TCG_REG_TMP0, c1, c2, const2);
625     TCGReg t;
627     /* Standardize the test below to t != 0. */
628     if (tmpflags & SETCOND_INV) {
629         t = v1, v1 = v2, v2 = t;
630     }
632     t = tmpflags & ~SETCOND_FLAGS;
633     if (v1 == TCG_REG_ZERO) {
634         tcg_out_opc_masknez(s, ret, v2, t);
635     } else if (v2 == TCG_REG_ZERO) {
636         tcg_out_opc_maskeqz(s, ret, v1, t);
637     } else {
638         tcg_out_opc_masknez(s, TCG_REG_TMP2, v2, t); /* t ? 0 : v2 */
639         tcg_out_opc_maskeqz(s, TCG_REG_TMP1, v1, t); /* t ? v1 : 0 */
640         tcg_out_opc_or(s, ret, TCG_REG_TMP1, TCG_REG_TMP2);
641     }
645  * Branch helpers
646  */
648 static const struct {
649     LoongArchInsn op;
650     bool swap;
651 } tcg_brcond_to_loongarch[] = {
652     [TCG_COND_EQ] =  { OPC_BEQ,  false },
653     [TCG_COND_NE] =  { OPC_BNE,  false },
654     [TCG_COND_LT] =  { OPC_BGT,  true  },
655     [TCG_COND_GE] =  { OPC_BLE,  true  },
656     [TCG_COND_LE] =  { OPC_BLE,  false },
657     [TCG_COND_GT] =  { OPC_BGT,  false },
658     [TCG_COND_LTU] = { OPC_BGTU, true  },
659     [TCG_COND_GEU] = { OPC_BLEU, true  },
660     [TCG_COND_LEU] = { OPC_BLEU, false },
661     [TCG_COND_GTU] = { OPC_BGTU, false }
664 static void tcg_out_brcond(TCGContext *s, TCGCond cond, TCGReg arg1,
665                            TCGReg arg2, TCGLabel *l)
667     LoongArchInsn op = tcg_brcond_to_loongarch[cond].op;
669     tcg_debug_assert(op != 0);
671     if (tcg_brcond_to_loongarch[cond].swap) {
672         TCGReg t = arg1;
673         arg1 = arg2;
674         arg2 = t;
675     }
677     /* all conditional branch insns belong to DJSk16-format */
678     tcg_out_reloc(s, s->code_ptr, R_LOONGARCH_BR_SK16, l, 0);
679     tcg_out32(s, encode_djsk16_insn(op, arg1, arg2, 0));
682 static void tcg_out_call_int(TCGContext *s, const tcg_insn_unit *arg, bool tail)
684     TCGReg link = tail ? TCG_REG_ZERO : TCG_REG_RA;
685     ptrdiff_t offset = tcg_pcrel_diff(s, arg);
687     tcg_debug_assert((offset & 3) == 0);
688     if (offset == sextreg(offset, 0, 28)) {
689         /* short jump: +/- 256MiB */
690         if (tail) {
691             tcg_out_opc_b(s, offset >> 2);
692         } else {
693             tcg_out_opc_bl(s, offset >> 2);
694         }
695     } else if (offset == sextreg(offset, 0, 38)) {
696         /* long jump: +/- 256GiB */
697         tcg_target_long lo = sextreg(offset, 0, 18);
698         tcg_target_long hi = offset - lo;
699         tcg_out_opc_pcaddu18i(s, TCG_REG_TMP0, hi >> 18);
700         tcg_out_opc_jirl(s, link, TCG_REG_TMP0, lo >> 2);
701     } else {
702         /* far jump: 64-bit */
703         tcg_target_long lo = sextreg((tcg_target_long)arg, 0, 18);
704         tcg_target_long hi = (tcg_target_long)arg - lo;
705         tcg_out_movi(s, TCG_TYPE_PTR, TCG_REG_TMP0, hi);
706         tcg_out_opc_jirl(s, link, TCG_REG_TMP0, lo >> 2);
707     }
710 static void tcg_out_call(TCGContext *s, const tcg_insn_unit *arg,
711                          const TCGHelperInfo *info)
713     tcg_out_call_int(s, arg, false);
717  * Load/store helpers
718  */
720 static void tcg_out_ldst(TCGContext *s, LoongArchInsn opc, TCGReg data,
721                          TCGReg addr, intptr_t offset)
723     intptr_t imm12 = sextreg(offset, 0, 12);
725     if (offset != imm12) {
726         intptr_t diff = tcg_pcrel_diff(s, (void *)offset);
728         if (addr == TCG_REG_ZERO && diff == (int32_t)diff) {
729             imm12 = sextreg(diff, 0, 12);
730             tcg_out_opc_pcaddu12i(s, TCG_REG_TMP2, (diff - imm12) >> 12);
731         } else {
732             tcg_out_movi(s, TCG_TYPE_PTR, TCG_REG_TMP2, offset - imm12);
733             if (addr != TCG_REG_ZERO) {
734                 tcg_out_opc_add_d(s, TCG_REG_TMP2, TCG_REG_TMP2, addr);
735             }
736         }
737         addr = TCG_REG_TMP2;
738     }
740     switch (opc) {
741     case OPC_LD_B:
742     case OPC_LD_BU:
743     case OPC_LD_H:
744     case OPC_LD_HU:
745     case OPC_LD_W:
746     case OPC_LD_WU:
747     case OPC_LD_D:
748     case OPC_ST_B:
749     case OPC_ST_H:
750     case OPC_ST_W:
751     case OPC_ST_D:
752         tcg_out32(s, encode_djsk12_insn(opc, data, addr, imm12));
753         break;
754     default:
755         g_assert_not_reached();
756     }
759 static void tcg_out_ld(TCGContext *s, TCGType type, TCGReg arg,
760                        TCGReg arg1, intptr_t arg2)
762     bool is_32bit = type == TCG_TYPE_I32;
763     tcg_out_ldst(s, is_32bit ? OPC_LD_W : OPC_LD_D, arg, arg1, arg2);
766 static void tcg_out_st(TCGContext *s, TCGType type, TCGReg arg,
767                        TCGReg arg1, intptr_t arg2)
769     bool is_32bit = type == TCG_TYPE_I32;
770     tcg_out_ldst(s, is_32bit ? OPC_ST_W : OPC_ST_D, arg, arg1, arg2);
773 static bool tcg_out_sti(TCGContext *s, TCGType type, TCGArg val,
774                         TCGReg base, intptr_t ofs)
776     if (val == 0) {
777         tcg_out_st(s, type, TCG_REG_ZERO, base, ofs);
778         return true;
779     }
780     return false;
784  * Load/store helpers for SoftMMU, and qemu_ld/st implementations
785  */
787 static bool tcg_out_goto(TCGContext *s, const tcg_insn_unit *target)
789     tcg_out_opc_b(s, 0);
790     return reloc_br_sd10k16(s->code_ptr - 1, target);
793 static const TCGLdstHelperParam ldst_helper_param = {
794     .ntmp = 1, .tmp = { TCG_REG_TMP0 }
797 static bool tcg_out_qemu_ld_slow_path(TCGContext *s, TCGLabelQemuLdst *l)
799     MemOp opc = get_memop(l->oi);
801     /* resolve label address */
802     if (!reloc_br_sk16(l->label_ptr[0], tcg_splitwx_to_rx(s->code_ptr))) {
803         return false;
804     }
806     tcg_out_ld_helper_args(s, l, &ldst_helper_param);
807     tcg_out_call_int(s, qemu_ld_helpers[opc & MO_SIZE], false);
808     tcg_out_ld_helper_ret(s, l, false, &ldst_helper_param);
809     return tcg_out_goto(s, l->raddr);
812 static bool tcg_out_qemu_st_slow_path(TCGContext *s, TCGLabelQemuLdst *l)
814     MemOp opc = get_memop(l->oi);
816     /* resolve label address */
817     if (!reloc_br_sk16(l->label_ptr[0], tcg_splitwx_to_rx(s->code_ptr))) {
818         return false;
819     }
821     tcg_out_st_helper_args(s, l, &ldst_helper_param);
822     tcg_out_call_int(s, qemu_st_helpers[opc & MO_SIZE], false);
823     return tcg_out_goto(s, l->raddr);
826 typedef struct {
827     TCGReg base;
828     TCGReg index;
829     TCGAtomAlign aa;
830 } HostAddress;
832 bool tcg_target_has_memory_bswap(MemOp memop)
834     return false;
837 /* We expect to use a 12-bit negative offset from ENV.  */
838 #define MIN_TLB_MASK_TABLE_OFS  -(1 << 11)
841  * For softmmu, perform the TLB load and compare.
842  * For useronly, perform any required alignment tests.
843  * In both cases, return a TCGLabelQemuLdst structure if the slow path
844  * is required and fill in @h with the host address for the fast path.
845  */
846 static TCGLabelQemuLdst *prepare_host_addr(TCGContext *s, HostAddress *h,
847                                            TCGReg addr_reg, MemOpIdx oi,
848                                            bool is_ld)
850     TCGType addr_type = s->addr_type;
851     TCGLabelQemuLdst *ldst = NULL;
852     MemOp opc = get_memop(oi);
853     MemOp a_bits;
855     h->aa = atom_and_align_for_opc(s, opc, MO_ATOM_IFALIGN, false);
856     a_bits = h->aa.align;
858 #ifdef CONFIG_SOFTMMU
859     unsigned s_bits = opc & MO_SIZE;
860     int mem_index = get_mmuidx(oi);
861     int fast_ofs = tlb_mask_table_ofs(s, mem_index);
862     int mask_ofs = fast_ofs + offsetof(CPUTLBDescFast, mask);
863     int table_ofs = fast_ofs + offsetof(CPUTLBDescFast, table);
865     ldst = new_ldst_label(s);
866     ldst->is_ld = is_ld;
867     ldst->oi = oi;
868     ldst->addrlo_reg = addr_reg;
870     tcg_out_ld(s, TCG_TYPE_PTR, TCG_REG_TMP0, TCG_AREG0, mask_ofs);
871     tcg_out_ld(s, TCG_TYPE_PTR, TCG_REG_TMP1, TCG_AREG0, table_ofs);
873     tcg_out_opc_srli_d(s, TCG_REG_TMP2, addr_reg,
874                     s->page_bits - CPU_TLB_ENTRY_BITS);
875     tcg_out_opc_and(s, TCG_REG_TMP2, TCG_REG_TMP2, TCG_REG_TMP0);
876     tcg_out_opc_add_d(s, TCG_REG_TMP2, TCG_REG_TMP2, TCG_REG_TMP1);
878     /* Load the tlb comparator and the addend.  */
879     QEMU_BUILD_BUG_ON(HOST_BIG_ENDIAN);
880     tcg_out_ld(s, addr_type, TCG_REG_TMP0, TCG_REG_TMP2,
881                is_ld ? offsetof(CPUTLBEntry, addr_read)
882                      : offsetof(CPUTLBEntry, addr_write));
883     tcg_out_ld(s, TCG_TYPE_PTR, TCG_REG_TMP2, TCG_REG_TMP2,
884                offsetof(CPUTLBEntry, addend));
886     /*
887      * For aligned accesses, we check the first byte and include the alignment
888      * bits within the address.  For unaligned access, we check that we don't
889      * cross pages using the address of the last byte of the access.
890      */
891     if (a_bits < s_bits) {
892         unsigned a_mask = (1u << a_bits) - 1;
893         unsigned s_mask = (1u << s_bits) - 1;
894         tcg_out_addi(s, addr_type, TCG_REG_TMP1, addr_reg, s_mask - a_mask);
895     } else {
896         tcg_out_mov(s, addr_type, TCG_REG_TMP1, addr_reg);
897     }
898     tcg_out_opc_bstrins_d(s, TCG_REG_TMP1, TCG_REG_ZERO,
899                           a_bits, s->page_bits - 1);
901     /* Compare masked address with the TLB entry.  */
902     ldst->label_ptr[0] = s->code_ptr;
903     tcg_out_opc_bne(s, TCG_REG_TMP0, TCG_REG_TMP1, 0);
905     h->index = TCG_REG_TMP2;
906 #else
907     if (a_bits) {
908         ldst = new_ldst_label(s);
910         ldst->is_ld = is_ld;
911         ldst->oi = oi;
912         ldst->addrlo_reg = addr_reg;
914         /*
915          * Without micro-architecture details, we don't know which of
916          * bstrpick or andi is faster, so use bstrpick as it's not
917          * constrained by imm field width. Not to say alignments >= 2^12
918          * are going to happen any time soon.
919          */
920         tcg_out_opc_bstrpick_d(s, TCG_REG_TMP1, addr_reg, 0, a_bits - 1);
922         ldst->label_ptr[0] = s->code_ptr;
923         tcg_out_opc_bne(s, TCG_REG_TMP1, TCG_REG_ZERO, 0);
924     }
926     h->index = USE_GUEST_BASE ? TCG_GUEST_BASE_REG : TCG_REG_ZERO;
927 #endif
929     if (addr_type == TCG_TYPE_I32) {
930         h->base = TCG_REG_TMP0;
931         tcg_out_ext32u(s, h->base, addr_reg);
932     } else {
933         h->base = addr_reg;
934     }
936     return ldst;
939 static void tcg_out_qemu_ld_indexed(TCGContext *s, MemOp opc, TCGType type,
940                                     TCGReg rd, HostAddress h)
942     /* Byte swapping is left to middle-end expansion.  */
943     tcg_debug_assert((opc & MO_BSWAP) == 0);
945     switch (opc & MO_SSIZE) {
946     case MO_UB:
947         tcg_out_opc_ldx_bu(s, rd, h.base, h.index);
948         break;
949     case MO_SB:
950         tcg_out_opc_ldx_b(s, rd, h.base, h.index);
951         break;
952     case MO_UW:
953         tcg_out_opc_ldx_hu(s, rd, h.base, h.index);
954         break;
955     case MO_SW:
956         tcg_out_opc_ldx_h(s, rd, h.base, h.index);
957         break;
958     case MO_UL:
959         if (type == TCG_TYPE_I64) {
960             tcg_out_opc_ldx_wu(s, rd, h.base, h.index);
961             break;
962         }
963         /* fallthrough */
964     case MO_SL:
965         tcg_out_opc_ldx_w(s, rd, h.base, h.index);
966         break;
967     case MO_UQ:
968         tcg_out_opc_ldx_d(s, rd, h.base, h.index);
969         break;
970     default:
971         g_assert_not_reached();
972     }
975 static void tcg_out_qemu_ld(TCGContext *s, TCGReg data_reg, TCGReg addr_reg,
976                             MemOpIdx oi, TCGType data_type)
978     TCGLabelQemuLdst *ldst;
979     HostAddress h;
981     ldst = prepare_host_addr(s, &h, addr_reg, oi, true);
982     tcg_out_qemu_ld_indexed(s, get_memop(oi), data_type, data_reg, h);
984     if (ldst) {
985         ldst->type = data_type;
986         ldst->datalo_reg = data_reg;
987         ldst->raddr = tcg_splitwx_to_rx(s->code_ptr);
988     }
991 static void tcg_out_qemu_st_indexed(TCGContext *s, MemOp opc,
992                                     TCGReg rd, HostAddress h)
994     /* Byte swapping is left to middle-end expansion.  */
995     tcg_debug_assert((opc & MO_BSWAP) == 0);
997     switch (opc & MO_SIZE) {
998     case MO_8:
999         tcg_out_opc_stx_b(s, rd, h.base, h.index);
1000         break;
1001     case MO_16:
1002         tcg_out_opc_stx_h(s, rd, h.base, h.index);
1003         break;
1004     case MO_32:
1005         tcg_out_opc_stx_w(s, rd, h.base, h.index);
1006         break;
1007     case MO_64:
1008         tcg_out_opc_stx_d(s, rd, h.base, h.index);
1009         break;
1010     default:
1011         g_assert_not_reached();
1012     }
1015 static void tcg_out_qemu_st(TCGContext *s, TCGReg data_reg, TCGReg addr_reg,
1016                             MemOpIdx oi, TCGType data_type)
1018     TCGLabelQemuLdst *ldst;
1019     HostAddress h;
1021     ldst = prepare_host_addr(s, &h, addr_reg, oi, false);
1022     tcg_out_qemu_st_indexed(s, get_memop(oi), data_reg, h);
1024     if (ldst) {
1025         ldst->type = data_type;
1026         ldst->datalo_reg = data_reg;
1027         ldst->raddr = tcg_splitwx_to_rx(s->code_ptr);
1028     }
1032  * Entry-points
1033  */
1035 static const tcg_insn_unit *tb_ret_addr;
1037 static void tcg_out_exit_tb(TCGContext *s, uintptr_t a0)
1039     /* Reuse the zeroing that exists for goto_ptr.  */
1040     if (a0 == 0) {
1041         tcg_out_call_int(s, tcg_code_gen_epilogue, true);
1042     } else {
1043         tcg_out_movi(s, TCG_TYPE_PTR, TCG_REG_A0, a0);
1044         tcg_out_call_int(s, tb_ret_addr, true);
1045     }
1048 static void tcg_out_goto_tb(TCGContext *s, int which)
1050     /*
1051      * Direct branch, or load indirect address, to be patched
1052      * by tb_target_set_jmp_target.  Check indirect load offset
1053      * in range early, regardless of direct branch distance,
1054      * via assert within tcg_out_opc_pcaddu2i.
1055      */
1056     uintptr_t i_addr = get_jmp_target_addr(s, which);
1057     intptr_t i_disp = tcg_pcrel_diff(s, (void *)i_addr);
1059     set_jmp_insn_offset(s, which);
1060     tcg_out_opc_pcaddu2i(s, TCG_REG_TMP0, i_disp >> 2);
1062     /* Finish the load and indirect branch. */
1063     tcg_out_ld(s, TCG_TYPE_PTR, TCG_REG_TMP0, TCG_REG_TMP0, 0);
1064     tcg_out_opc_jirl(s, TCG_REG_ZERO, TCG_REG_TMP0, 0);
1065     set_jmp_reset_offset(s, which);
1068 void tb_target_set_jmp_target(const TranslationBlock *tb, int n,
1069                               uintptr_t jmp_rx, uintptr_t jmp_rw)
1071     uintptr_t d_addr = tb->jmp_target_addr[n];
1072     ptrdiff_t d_disp = (ptrdiff_t)(d_addr - jmp_rx) >> 2;
1073     tcg_insn_unit insn;
1075     /* Either directly branch, or load slot address for indirect branch. */
1076     if (d_disp == sextreg(d_disp, 0, 26)) {
1077         insn = encode_sd10k16_insn(OPC_B, d_disp);
1078     } else {
1079         uintptr_t i_addr = (uintptr_t)&tb->jmp_target_addr[n];
1080         intptr_t i_disp = i_addr - jmp_rx;
1081         insn = encode_dsj20_insn(OPC_PCADDU2I, TCG_REG_TMP0, i_disp >> 2);
1082     }
1084     qatomic_set((tcg_insn_unit *)jmp_rw, insn);
1085     flush_idcache_range(jmp_rx, jmp_rw, 4);
1088 static void tcg_out_op(TCGContext *s, TCGOpcode opc,
1089                        const TCGArg args[TCG_MAX_OP_ARGS],
1090                        const int const_args[TCG_MAX_OP_ARGS])
1092     TCGArg a0 = args[0];
1093     TCGArg a1 = args[1];
1094     TCGArg a2 = args[2];
1095     int c2 = const_args[2];
1097     switch (opc) {
1098     case INDEX_op_mb:
1099         tcg_out_mb(s, a0);
1100         break;
1102     case INDEX_op_goto_ptr:
1103         tcg_out_opc_jirl(s, TCG_REG_ZERO, a0, 0);
1104         break;
1106     case INDEX_op_br:
1107         tcg_out_reloc(s, s->code_ptr, R_LOONGARCH_BR_SD10K16, arg_label(a0),
1108                       0);
1109         tcg_out_opc_b(s, 0);
1110         break;
1112     case INDEX_op_brcond_i32:
1113     case INDEX_op_brcond_i64:
1114         tcg_out_brcond(s, a2, a0, a1, arg_label(args[3]));
1115         break;
1117     case INDEX_op_extrh_i64_i32:
1118         tcg_out_opc_srai_d(s, a0, a1, 32);
1119         break;
1121     case INDEX_op_not_i32:
1122     case INDEX_op_not_i64:
1123         tcg_out_opc_nor(s, a0, a1, TCG_REG_ZERO);
1124         break;
1126     case INDEX_op_nor_i32:
1127     case INDEX_op_nor_i64:
1128         if (c2) {
1129             tcg_out_opc_ori(s, a0, a1, a2);
1130             tcg_out_opc_nor(s, a0, a0, TCG_REG_ZERO);
1131         } else {
1132             tcg_out_opc_nor(s, a0, a1, a2);
1133         }
1134         break;
1136     case INDEX_op_andc_i32:
1137     case INDEX_op_andc_i64:
1138         if (c2) {
1139             /* guaranteed to fit due to constraint */
1140             tcg_out_opc_andi(s, a0, a1, ~a2);
1141         } else {
1142             tcg_out_opc_andn(s, a0, a1, a2);
1143         }
1144         break;
1146     case INDEX_op_orc_i32:
1147     case INDEX_op_orc_i64:
1148         if (c2) {
1149             /* guaranteed to fit due to constraint */
1150             tcg_out_opc_ori(s, a0, a1, ~a2);
1151         } else {
1152             tcg_out_opc_orn(s, a0, a1, a2);
1153         }
1154         break;
1156     case INDEX_op_and_i32:
1157     case INDEX_op_and_i64:
1158         if (c2) {
1159             tcg_out_opc_andi(s, a0, a1, a2);
1160         } else {
1161             tcg_out_opc_and(s, a0, a1, a2);
1162         }
1163         break;
1165     case INDEX_op_or_i32:
1166     case INDEX_op_or_i64:
1167         if (c2) {
1168             tcg_out_opc_ori(s, a0, a1, a2);
1169         } else {
1170             tcg_out_opc_or(s, a0, a1, a2);
1171         }
1172         break;
1174     case INDEX_op_xor_i32:
1175     case INDEX_op_xor_i64:
1176         if (c2) {
1177             tcg_out_opc_xori(s, a0, a1, a2);
1178         } else {
1179             tcg_out_opc_xor(s, a0, a1, a2);
1180         }
1181         break;
1183     case INDEX_op_extract_i32:
1184         tcg_out_opc_bstrpick_w(s, a0, a1, a2, a2 + args[3] - 1);
1185         break;
1186     case INDEX_op_extract_i64:
1187         tcg_out_opc_bstrpick_d(s, a0, a1, a2, a2 + args[3] - 1);
1188         break;
1190     case INDEX_op_deposit_i32:
1191         tcg_out_opc_bstrins_w(s, a0, a2, args[3], args[3] + args[4] - 1);
1192         break;
1193     case INDEX_op_deposit_i64:
1194         tcg_out_opc_bstrins_d(s, a0, a2, args[3], args[3] + args[4] - 1);
1195         break;
1197     case INDEX_op_bswap16_i32:
1198     case INDEX_op_bswap16_i64:
1199         tcg_out_opc_revb_2h(s, a0, a1);
1200         if (a2 & TCG_BSWAP_OS) {
1201             tcg_out_ext16s(s, TCG_TYPE_REG, a0, a0);
1202         } else if ((a2 & (TCG_BSWAP_IZ | TCG_BSWAP_OZ)) == TCG_BSWAP_OZ) {
1203             tcg_out_ext16u(s, a0, a0);
1204         }
1205         break;
1207     case INDEX_op_bswap32_i32:
1208         /* All 32-bit values are computed sign-extended in the register.  */
1209         a2 = TCG_BSWAP_OS;
1210         /* fallthrough */
1211     case INDEX_op_bswap32_i64:
1212         tcg_out_opc_revb_2w(s, a0, a1);
1213         if (a2 & TCG_BSWAP_OS) {
1214             tcg_out_ext32s(s, a0, a0);
1215         } else if ((a2 & (TCG_BSWAP_IZ | TCG_BSWAP_OZ)) == TCG_BSWAP_OZ) {
1216             tcg_out_ext32u(s, a0, a0);
1217         }
1218         break;
1220     case INDEX_op_bswap64_i64:
1221         tcg_out_opc_revb_d(s, a0, a1);
1222         break;
1224     case INDEX_op_clz_i32:
1225         tcg_out_clzctz(s, OPC_CLZ_W, a0, a1, a2, c2, true);
1226         break;
1227     case INDEX_op_clz_i64:
1228         tcg_out_clzctz(s, OPC_CLZ_D, a0, a1, a2, c2, false);
1229         break;
1231     case INDEX_op_ctz_i32:
1232         tcg_out_clzctz(s, OPC_CTZ_W, a0, a1, a2, c2, true);
1233         break;
1234     case INDEX_op_ctz_i64:
1235         tcg_out_clzctz(s, OPC_CTZ_D, a0, a1, a2, c2, false);
1236         break;
1238     case INDEX_op_shl_i32:
1239         if (c2) {
1240             tcg_out_opc_slli_w(s, a0, a1, a2 & 0x1f);
1241         } else {
1242             tcg_out_opc_sll_w(s, a0, a1, a2);
1243         }
1244         break;
1245     case INDEX_op_shl_i64:
1246         if (c2) {
1247             tcg_out_opc_slli_d(s, a0, a1, a2 & 0x3f);
1248         } else {
1249             tcg_out_opc_sll_d(s, a0, a1, a2);
1250         }
1251         break;
1253     case INDEX_op_shr_i32:
1254         if (c2) {
1255             tcg_out_opc_srli_w(s, a0, a1, a2 & 0x1f);
1256         } else {
1257             tcg_out_opc_srl_w(s, a0, a1, a2);
1258         }
1259         break;
1260     case INDEX_op_shr_i64:
1261         if (c2) {
1262             tcg_out_opc_srli_d(s, a0, a1, a2 & 0x3f);
1263         } else {
1264             tcg_out_opc_srl_d(s, a0, a1, a2);
1265         }
1266         break;
1268     case INDEX_op_sar_i32:
1269         if (c2) {
1270             tcg_out_opc_srai_w(s, a0, a1, a2 & 0x1f);
1271         } else {
1272             tcg_out_opc_sra_w(s, a0, a1, a2);
1273         }
1274         break;
1275     case INDEX_op_sar_i64:
1276         if (c2) {
1277             tcg_out_opc_srai_d(s, a0, a1, a2 & 0x3f);
1278         } else {
1279             tcg_out_opc_sra_d(s, a0, a1, a2);
1280         }
1281         break;
1283     case INDEX_op_rotl_i32:
1284         /* transform into equivalent rotr/rotri */
1285         if (c2) {
1286             tcg_out_opc_rotri_w(s, a0, a1, (32 - a2) & 0x1f);
1287         } else {
1288             tcg_out_opc_sub_w(s, TCG_REG_TMP0, TCG_REG_ZERO, a2);
1289             tcg_out_opc_rotr_w(s, a0, a1, TCG_REG_TMP0);
1290         }
1291         break;
1292     case INDEX_op_rotl_i64:
1293         /* transform into equivalent rotr/rotri */
1294         if (c2) {
1295             tcg_out_opc_rotri_d(s, a0, a1, (64 - a2) & 0x3f);
1296         } else {
1297             tcg_out_opc_sub_w(s, TCG_REG_TMP0, TCG_REG_ZERO, a2);
1298             tcg_out_opc_rotr_d(s, a0, a1, TCG_REG_TMP0);
1299         }
1300         break;
1302     case INDEX_op_rotr_i32:
1303         if (c2) {
1304             tcg_out_opc_rotri_w(s, a0, a1, a2 & 0x1f);
1305         } else {
1306             tcg_out_opc_rotr_w(s, a0, a1, a2);
1307         }
1308         break;
1309     case INDEX_op_rotr_i64:
1310         if (c2) {
1311             tcg_out_opc_rotri_d(s, a0, a1, a2 & 0x3f);
1312         } else {
1313             tcg_out_opc_rotr_d(s, a0, a1, a2);
1314         }
1315         break;
1317     case INDEX_op_add_i32:
1318         if (c2) {
1319             tcg_out_addi(s, TCG_TYPE_I32, a0, a1, a2);
1320         } else {
1321             tcg_out_opc_add_w(s, a0, a1, a2);
1322         }
1323         break;
1324     case INDEX_op_add_i64:
1325         if (c2) {
1326             tcg_out_addi(s, TCG_TYPE_I64, a0, a1, a2);
1327         } else {
1328             tcg_out_opc_add_d(s, a0, a1, a2);
1329         }
1330         break;
1332     case INDEX_op_sub_i32:
1333         if (c2) {
1334             tcg_out_addi(s, TCG_TYPE_I32, a0, a1, -a2);
1335         } else {
1336             tcg_out_opc_sub_w(s, a0, a1, a2);
1337         }
1338         break;
1339     case INDEX_op_sub_i64:
1340         if (c2) {
1341             tcg_out_addi(s, TCG_TYPE_I64, a0, a1, -a2);
1342         } else {
1343             tcg_out_opc_sub_d(s, a0, a1, a2);
1344         }
1345         break;
1347     case INDEX_op_mul_i32:
1348         tcg_out_opc_mul_w(s, a0, a1, a2);
1349         break;
1350     case INDEX_op_mul_i64:
1351         tcg_out_opc_mul_d(s, a0, a1, a2);
1352         break;
1354     case INDEX_op_mulsh_i32:
1355         tcg_out_opc_mulh_w(s, a0, a1, a2);
1356         break;
1357     case INDEX_op_mulsh_i64:
1358         tcg_out_opc_mulh_d(s, a0, a1, a2);
1359         break;
1361     case INDEX_op_muluh_i32:
1362         tcg_out_opc_mulh_wu(s, a0, a1, a2);
1363         break;
1364     case INDEX_op_muluh_i64:
1365         tcg_out_opc_mulh_du(s, a0, a1, a2);
1366         break;
1368     case INDEX_op_div_i32:
1369         tcg_out_opc_div_w(s, a0, a1, a2);
1370         break;
1371     case INDEX_op_div_i64:
1372         tcg_out_opc_div_d(s, a0, a1, a2);
1373         break;
1375     case INDEX_op_divu_i32:
1376         tcg_out_opc_div_wu(s, a0, a1, a2);
1377         break;
1378     case INDEX_op_divu_i64:
1379         tcg_out_opc_div_du(s, a0, a1, a2);
1380         break;
1382     case INDEX_op_rem_i32:
1383         tcg_out_opc_mod_w(s, a0, a1, a2);
1384         break;
1385     case INDEX_op_rem_i64:
1386         tcg_out_opc_mod_d(s, a0, a1, a2);
1387         break;
1389     case INDEX_op_remu_i32:
1390         tcg_out_opc_mod_wu(s, a0, a1, a2);
1391         break;
1392     case INDEX_op_remu_i64:
1393         tcg_out_opc_mod_du(s, a0, a1, a2);
1394         break;
1396     case INDEX_op_setcond_i32:
1397     case INDEX_op_setcond_i64:
1398         tcg_out_setcond(s, args[3], a0, a1, a2, c2);
1399         break;
1401     case INDEX_op_movcond_i32:
1402     case INDEX_op_movcond_i64:
1403         tcg_out_movcond(s, args[5], a0, a1, a2, c2, args[3], args[4]);
1404         break;
1406     case INDEX_op_ld8s_i32:
1407     case INDEX_op_ld8s_i64:
1408         tcg_out_ldst(s, OPC_LD_B, a0, a1, a2);
1409         break;
1410     case INDEX_op_ld8u_i32:
1411     case INDEX_op_ld8u_i64:
1412         tcg_out_ldst(s, OPC_LD_BU, a0, a1, a2);
1413         break;
1414     case INDEX_op_ld16s_i32:
1415     case INDEX_op_ld16s_i64:
1416         tcg_out_ldst(s, OPC_LD_H, a0, a1, a2);
1417         break;
1418     case INDEX_op_ld16u_i32:
1419     case INDEX_op_ld16u_i64:
1420         tcg_out_ldst(s, OPC_LD_HU, a0, a1, a2);
1421         break;
1422     case INDEX_op_ld_i32:
1423     case INDEX_op_ld32s_i64:
1424         tcg_out_ldst(s, OPC_LD_W, a0, a1, a2);
1425         break;
1426     case INDEX_op_ld32u_i64:
1427         tcg_out_ldst(s, OPC_LD_WU, a0, a1, a2);
1428         break;
1429     case INDEX_op_ld_i64:
1430         tcg_out_ldst(s, OPC_LD_D, a0, a1, a2);
1431         break;
1433     case INDEX_op_st8_i32:
1434     case INDEX_op_st8_i64:
1435         tcg_out_ldst(s, OPC_ST_B, a0, a1, a2);
1436         break;
1437     case INDEX_op_st16_i32:
1438     case INDEX_op_st16_i64:
1439         tcg_out_ldst(s, OPC_ST_H, a0, a1, a2);
1440         break;
1441     case INDEX_op_st_i32:
1442     case INDEX_op_st32_i64:
1443         tcg_out_ldst(s, OPC_ST_W, a0, a1, a2);
1444         break;
1445     case INDEX_op_st_i64:
1446         tcg_out_ldst(s, OPC_ST_D, a0, a1, a2);
1447         break;
1449     case INDEX_op_qemu_ld_a32_i32:
1450     case INDEX_op_qemu_ld_a64_i32:
1451         tcg_out_qemu_ld(s, a0, a1, a2, TCG_TYPE_I32);
1452         break;
1453     case INDEX_op_qemu_ld_a32_i64:
1454     case INDEX_op_qemu_ld_a64_i64:
1455         tcg_out_qemu_ld(s, a0, a1, a2, TCG_TYPE_I64);
1456         break;
1457     case INDEX_op_qemu_st_a32_i32:
1458     case INDEX_op_qemu_st_a64_i32:
1459         tcg_out_qemu_st(s, a0, a1, a2, TCG_TYPE_I32);
1460         break;
1461     case INDEX_op_qemu_st_a32_i64:
1462     case INDEX_op_qemu_st_a64_i64:
1463         tcg_out_qemu_st(s, a0, a1, a2, TCG_TYPE_I64);
1464         break;
1466     case INDEX_op_mov_i32:  /* Always emitted via tcg_out_mov.  */
1467     case INDEX_op_mov_i64:
1468     case INDEX_op_call:     /* Always emitted via tcg_out_call.  */
1469     case INDEX_op_exit_tb:  /* Always emitted via tcg_out_exit_tb.  */
1470     case INDEX_op_goto_tb:  /* Always emitted via tcg_out_goto_tb.  */
1471     case INDEX_op_ext8s_i32:  /* Always emitted via tcg_reg_alloc_op.  */
1472     case INDEX_op_ext8s_i64:
1473     case INDEX_op_ext8u_i32:
1474     case INDEX_op_ext8u_i64:
1475     case INDEX_op_ext16s_i32:
1476     case INDEX_op_ext16s_i64:
1477     case INDEX_op_ext16u_i32:
1478     case INDEX_op_ext16u_i64:
1479     case INDEX_op_ext32s_i64:
1480     case INDEX_op_ext32u_i64:
1481     case INDEX_op_ext_i32_i64:
1482     case INDEX_op_extu_i32_i64:
1483     case INDEX_op_extrl_i64_i32:
1484     default:
1485         g_assert_not_reached();
1486     }
1489 static TCGConstraintSetIndex tcg_target_op_def(TCGOpcode op)
1491     switch (op) {
1492     case INDEX_op_goto_ptr:
1493         return C_O0_I1(r);
1495     case INDEX_op_st8_i32:
1496     case INDEX_op_st8_i64:
1497     case INDEX_op_st16_i32:
1498     case INDEX_op_st16_i64:
1499     case INDEX_op_st32_i64:
1500     case INDEX_op_st_i32:
1501     case INDEX_op_st_i64:
1502     case INDEX_op_qemu_st_a32_i32:
1503     case INDEX_op_qemu_st_a64_i32:
1504     case INDEX_op_qemu_st_a32_i64:
1505     case INDEX_op_qemu_st_a64_i64:
1506         return C_O0_I2(rZ, r);
1508     case INDEX_op_brcond_i32:
1509     case INDEX_op_brcond_i64:
1510         return C_O0_I2(rZ, rZ);
1512     case INDEX_op_ext8s_i32:
1513     case INDEX_op_ext8s_i64:
1514     case INDEX_op_ext8u_i32:
1515     case INDEX_op_ext8u_i64:
1516     case INDEX_op_ext16s_i32:
1517     case INDEX_op_ext16s_i64:
1518     case INDEX_op_ext16u_i32:
1519     case INDEX_op_ext16u_i64:
1520     case INDEX_op_ext32s_i64:
1521     case INDEX_op_ext32u_i64:
1522     case INDEX_op_extu_i32_i64:
1523     case INDEX_op_extrl_i64_i32:
1524     case INDEX_op_extrh_i64_i32:
1525     case INDEX_op_ext_i32_i64:
1526     case INDEX_op_not_i32:
1527     case INDEX_op_not_i64:
1528     case INDEX_op_extract_i32:
1529     case INDEX_op_extract_i64:
1530     case INDEX_op_bswap16_i32:
1531     case INDEX_op_bswap16_i64:
1532     case INDEX_op_bswap32_i32:
1533     case INDEX_op_bswap32_i64:
1534     case INDEX_op_bswap64_i64:
1535     case INDEX_op_ld8s_i32:
1536     case INDEX_op_ld8s_i64:
1537     case INDEX_op_ld8u_i32:
1538     case INDEX_op_ld8u_i64:
1539     case INDEX_op_ld16s_i32:
1540     case INDEX_op_ld16s_i64:
1541     case INDEX_op_ld16u_i32:
1542     case INDEX_op_ld16u_i64:
1543     case INDEX_op_ld32s_i64:
1544     case INDEX_op_ld32u_i64:
1545     case INDEX_op_ld_i32:
1546     case INDEX_op_ld_i64:
1547     case INDEX_op_qemu_ld_a32_i32:
1548     case INDEX_op_qemu_ld_a64_i32:
1549     case INDEX_op_qemu_ld_a32_i64:
1550     case INDEX_op_qemu_ld_a64_i64:
1551         return C_O1_I1(r, r);
1553     case INDEX_op_andc_i32:
1554     case INDEX_op_andc_i64:
1555     case INDEX_op_orc_i32:
1556     case INDEX_op_orc_i64:
1557         /*
1558          * LoongArch insns for these ops don't have reg-imm forms, but we
1559          * can express using andi/ori if ~constant satisfies
1560          * TCG_CT_CONST_U12.
1561          */
1562         return C_O1_I2(r, r, rC);
1564     case INDEX_op_shl_i32:
1565     case INDEX_op_shl_i64:
1566     case INDEX_op_shr_i32:
1567     case INDEX_op_shr_i64:
1568     case INDEX_op_sar_i32:
1569     case INDEX_op_sar_i64:
1570     case INDEX_op_rotl_i32:
1571     case INDEX_op_rotl_i64:
1572     case INDEX_op_rotr_i32:
1573     case INDEX_op_rotr_i64:
1574         return C_O1_I2(r, r, ri);
1576     case INDEX_op_add_i32:
1577         return C_O1_I2(r, r, ri);
1578     case INDEX_op_add_i64:
1579         return C_O1_I2(r, r, rJ);
1581     case INDEX_op_and_i32:
1582     case INDEX_op_and_i64:
1583     case INDEX_op_nor_i32:
1584     case INDEX_op_nor_i64:
1585     case INDEX_op_or_i32:
1586     case INDEX_op_or_i64:
1587     case INDEX_op_xor_i32:
1588     case INDEX_op_xor_i64:
1589         /* LoongArch reg-imm bitops have their imms ZERO-extended */
1590         return C_O1_I2(r, r, rU);
1592     case INDEX_op_clz_i32:
1593     case INDEX_op_clz_i64:
1594     case INDEX_op_ctz_i32:
1595     case INDEX_op_ctz_i64:
1596         return C_O1_I2(r, r, rW);
1598     case INDEX_op_deposit_i32:
1599     case INDEX_op_deposit_i64:
1600         /* Must deposit into the same register as input */
1601         return C_O1_I2(r, 0, rZ);
1603     case INDEX_op_sub_i32:
1604     case INDEX_op_setcond_i32:
1605         return C_O1_I2(r, rZ, ri);
1606     case INDEX_op_sub_i64:
1607     case INDEX_op_setcond_i64:
1608         return C_O1_I2(r, rZ, rJ);
1610     case INDEX_op_mul_i32:
1611     case INDEX_op_mul_i64:
1612     case INDEX_op_mulsh_i32:
1613     case INDEX_op_mulsh_i64:
1614     case INDEX_op_muluh_i32:
1615     case INDEX_op_muluh_i64:
1616     case INDEX_op_div_i32:
1617     case INDEX_op_div_i64:
1618     case INDEX_op_divu_i32:
1619     case INDEX_op_divu_i64:
1620     case INDEX_op_rem_i32:
1621     case INDEX_op_rem_i64:
1622     case INDEX_op_remu_i32:
1623     case INDEX_op_remu_i64:
1624         return C_O1_I2(r, rZ, rZ);
1626     case INDEX_op_movcond_i32:
1627     case INDEX_op_movcond_i64:
1628         return C_O1_I4(r, rZ, rJ, rZ, rZ);
1630     default:
1631         g_assert_not_reached();
1632     }
1635 static const int tcg_target_callee_save_regs[] = {
1636     TCG_REG_S0,     /* used for the global env (TCG_AREG0) */
1637     TCG_REG_S1,
1638     TCG_REG_S2,
1639     TCG_REG_S3,
1640     TCG_REG_S4,
1641     TCG_REG_S5,
1642     TCG_REG_S6,
1643     TCG_REG_S7,
1644     TCG_REG_S8,
1645     TCG_REG_S9,
1646     TCG_REG_RA,     /* should be last for ABI compliance */
1649 /* Stack frame parameters.  */
1650 #define REG_SIZE   (TCG_TARGET_REG_BITS / 8)
1651 #define SAVE_SIZE  ((int)ARRAY_SIZE(tcg_target_callee_save_regs) * REG_SIZE)
1652 #define TEMP_SIZE  (CPU_TEMP_BUF_NLONGS * (int)sizeof(long))
1653 #define FRAME_SIZE ((TCG_STATIC_CALL_ARGS_SIZE + TEMP_SIZE + SAVE_SIZE \
1654                      + TCG_TARGET_STACK_ALIGN - 1) \
1655                     & -TCG_TARGET_STACK_ALIGN)
1656 #define SAVE_OFS   (TCG_STATIC_CALL_ARGS_SIZE + TEMP_SIZE)
1658 /* We're expecting to be able to use an immediate for frame allocation.  */
1659 QEMU_BUILD_BUG_ON(FRAME_SIZE > 0x7ff);
1661 /* Generate global QEMU prologue and epilogue code */
1662 static void tcg_target_qemu_prologue(TCGContext *s)
1664     int i;
1666     tcg_set_frame(s, TCG_REG_SP, TCG_STATIC_CALL_ARGS_SIZE, TEMP_SIZE);
1668     /* TB prologue */
1669     tcg_out_opc_addi_d(s, TCG_REG_SP, TCG_REG_SP, -FRAME_SIZE);
1670     for (i = 0; i < ARRAY_SIZE(tcg_target_callee_save_regs); i++) {
1671         tcg_out_st(s, TCG_TYPE_REG, tcg_target_callee_save_regs[i],
1672                    TCG_REG_SP, SAVE_OFS + i * REG_SIZE);
1673     }
1675 #if !defined(CONFIG_SOFTMMU)
1676     if (USE_GUEST_BASE) {
1677         tcg_out_movi(s, TCG_TYPE_PTR, TCG_GUEST_BASE_REG, guest_base);
1678         tcg_regset_set_reg(s->reserved_regs, TCG_GUEST_BASE_REG);
1679     }
1680 #endif
1682     /* Call generated code */
1683     tcg_out_mov(s, TCG_TYPE_PTR, TCG_AREG0, tcg_target_call_iarg_regs[0]);
1684     tcg_out_opc_jirl(s, TCG_REG_ZERO, tcg_target_call_iarg_regs[1], 0);
1686     /* Return path for goto_ptr. Set return value to 0 */
1687     tcg_code_gen_epilogue = tcg_splitwx_to_rx(s->code_ptr);
1688     tcg_out_mov(s, TCG_TYPE_REG, TCG_REG_A0, TCG_REG_ZERO);
1690     /* TB epilogue */
1691     tb_ret_addr = tcg_splitwx_to_rx(s->code_ptr);
1692     for (i = 0; i < ARRAY_SIZE(tcg_target_callee_save_regs); i++) {
1693         tcg_out_ld(s, TCG_TYPE_REG, tcg_target_callee_save_regs[i],
1694                    TCG_REG_SP, SAVE_OFS + i * REG_SIZE);
1695     }
1697     tcg_out_opc_addi_d(s, TCG_REG_SP, TCG_REG_SP, FRAME_SIZE);
1698     tcg_out_opc_jirl(s, TCG_REG_ZERO, TCG_REG_RA, 0);
1701 static void tcg_target_init(TCGContext *s)
1703     unsigned long hwcap = qemu_getauxval(AT_HWCAP);
1705     /* Server and desktop class cpus have UAL; embedded cpus do not. */
1706     if (!(hwcap & HWCAP_LOONGARCH_UAL)) {
1707         error_report("TCG: unaligned access support required; exiting");
1708         exit(EXIT_FAILURE);
1709     }
1711     tcg_target_available_regs[TCG_TYPE_I32] = ALL_GENERAL_REGS;
1712     tcg_target_available_regs[TCG_TYPE_I64] = ALL_GENERAL_REGS;
1714     tcg_target_call_clobber_regs = ALL_GENERAL_REGS;
1715     tcg_regset_reset_reg(tcg_target_call_clobber_regs, TCG_REG_S0);
1716     tcg_regset_reset_reg(tcg_target_call_clobber_regs, TCG_REG_S1);
1717     tcg_regset_reset_reg(tcg_target_call_clobber_regs, TCG_REG_S2);
1718     tcg_regset_reset_reg(tcg_target_call_clobber_regs, TCG_REG_S3);
1719     tcg_regset_reset_reg(tcg_target_call_clobber_regs, TCG_REG_S4);
1720     tcg_regset_reset_reg(tcg_target_call_clobber_regs, TCG_REG_S5);
1721     tcg_regset_reset_reg(tcg_target_call_clobber_regs, TCG_REG_S6);
1722     tcg_regset_reset_reg(tcg_target_call_clobber_regs, TCG_REG_S7);
1723     tcg_regset_reset_reg(tcg_target_call_clobber_regs, TCG_REG_S8);
1724     tcg_regset_reset_reg(tcg_target_call_clobber_regs, TCG_REG_S9);
1726     s->reserved_regs = 0;
1727     tcg_regset_set_reg(s->reserved_regs, TCG_REG_ZERO);
1728     tcg_regset_set_reg(s->reserved_regs, TCG_REG_TMP0);
1729     tcg_regset_set_reg(s->reserved_regs, TCG_REG_TMP1);
1730     tcg_regset_set_reg(s->reserved_regs, TCG_REG_TMP2);
1731     tcg_regset_set_reg(s->reserved_regs, TCG_REG_SP);
1732     tcg_regset_set_reg(s->reserved_regs, TCG_REG_TP);
1733     tcg_regset_set_reg(s->reserved_regs, TCG_REG_RESERVED);
1736 typedef struct {
1737     DebugFrameHeader h;
1738     uint8_t fde_def_cfa[4];
1739     uint8_t fde_reg_ofs[ARRAY_SIZE(tcg_target_callee_save_regs) * 2];
1740 } DebugFrame;
1742 #define ELF_HOST_MACHINE EM_LOONGARCH
1744 static const DebugFrame debug_frame = {
1745     .h.cie.len = sizeof(DebugFrameCIE) - 4, /* length after .len member */
1746     .h.cie.id = -1,
1747     .h.cie.version = 1,
1748     .h.cie.code_align = 1,
1749     .h.cie.data_align = -(TCG_TARGET_REG_BITS / 8) & 0x7f, /* sleb128 */
1750     .h.cie.return_column = TCG_REG_RA,
1752     /* Total FDE size does not include the "len" member.  */
1753     .h.fde.len = sizeof(DebugFrame) - offsetof(DebugFrame, h.fde.cie_offset),
1755     .fde_def_cfa = {
1756         12, TCG_REG_SP,                 /* DW_CFA_def_cfa sp, ...  */
1757         (FRAME_SIZE & 0x7f) | 0x80,     /* ... uleb128 FRAME_SIZE */
1758         (FRAME_SIZE >> 7)
1759     },
1760     .fde_reg_ofs = {
1761         0x80 + 23, 11,                  /* DW_CFA_offset, s0, -88 */
1762         0x80 + 24, 10,                  /* DW_CFA_offset, s1, -80 */
1763         0x80 + 25, 9,                   /* DW_CFA_offset, s2, -72 */
1764         0x80 + 26, 8,                   /* DW_CFA_offset, s3, -64 */
1765         0x80 + 27, 7,                   /* DW_CFA_offset, s4, -56 */
1766         0x80 + 28, 6,                   /* DW_CFA_offset, s5, -48 */
1767         0x80 + 29, 5,                   /* DW_CFA_offset, s6, -40 */
1768         0x80 + 30, 4,                   /* DW_CFA_offset, s7, -32 */
1769         0x80 + 31, 3,                   /* DW_CFA_offset, s8, -24 */
1770         0x80 + 22, 2,                   /* DW_CFA_offset, s9, -16 */
1771         0x80 + 1 , 1,                   /* DW_CFA_offset, ra, -8 */
1772     }
1775 void tcg_register_jit(const void *buf, size_t buf_size)
1777     tcg_register_jit_int(buf, buf_size, &debug_frame, sizeof(debug_frame));