xref: /openbmc/qemu/tcg/riscv/tcg-target.c.inc (revision 101c1ef56221926718eb70d33ac2844d139d55e0)
1139c1837SPaolo Bonzini/*
2139c1837SPaolo Bonzini * Tiny Code Generator for QEMU
3139c1837SPaolo Bonzini *
4139c1837SPaolo Bonzini * Copyright (c) 2018 SiFive, Inc
5139c1837SPaolo Bonzini * Copyright (c) 2008-2009 Arnaud Patard <arnaud.patard@rtp-net.org>
6139c1837SPaolo Bonzini * Copyright (c) 2009 Aurelien Jarno <aurelien@aurel32.net>
7139c1837SPaolo Bonzini * Copyright (c) 2008 Fabrice Bellard
8139c1837SPaolo Bonzini *
9139c1837SPaolo Bonzini * Based on i386/tcg-target.c and mips/tcg-target.c
10139c1837SPaolo Bonzini *
11139c1837SPaolo Bonzini * Permission is hereby granted, free of charge, to any person obtaining a copy
12139c1837SPaolo Bonzini * of this software and associated documentation files (the "Software"), to deal
13139c1837SPaolo Bonzini * in the Software without restriction, including without limitation the rights
14139c1837SPaolo Bonzini * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
15139c1837SPaolo Bonzini * copies of the Software, and to permit persons to whom the Software is
16139c1837SPaolo Bonzini * furnished to do so, subject to the following conditions:
17139c1837SPaolo Bonzini *
18139c1837SPaolo Bonzini * The above copyright notice and this permission notice shall be included in
19139c1837SPaolo Bonzini * all copies or substantial portions of the Software.
20139c1837SPaolo Bonzini *
21139c1837SPaolo Bonzini * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
22139c1837SPaolo Bonzini * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
23139c1837SPaolo Bonzini * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
24139c1837SPaolo Bonzini * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
25139c1837SPaolo Bonzini * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
26139c1837SPaolo Bonzini * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
27139c1837SPaolo Bonzini * THE SOFTWARE.
28139c1837SPaolo Bonzini */
29139c1837SPaolo Bonzini
30a3fb7c99SRichard Henderson#include "../tcg-ldst.c.inc"
31139c1837SPaolo Bonzini#include "../tcg-pool.c.inc"
32139c1837SPaolo Bonzini
33139c1837SPaolo Bonzini#ifdef CONFIG_DEBUG_TCG
34139c1837SPaolo Bonzinistatic const char * const tcg_target_reg_names[TCG_TARGET_NB_REGS] = {
35f63e7089SHuang Shiyuan    "zero", "ra",  "sp",  "gp",  "tp",  "t0",  "t1",  "t2",
36f63e7089SHuang Shiyuan    "s0",   "s1",  "a0",  "a1",  "a2",  "a3",  "a4",  "a5",
37f63e7089SHuang Shiyuan    "a6",   "a7",  "s2",  "s3",  "s4",  "s5",  "s6",  "s7",
38f63e7089SHuang Shiyuan    "s8",   "s9",  "s10", "s11", "t3",  "t4",  "t5",  "t6",
39f63e7089SHuang Shiyuan    "v0",   "v1",  "v2",  "v3",  "v4",  "v5",  "v6",  "v7",
40f63e7089SHuang Shiyuan    "v8",   "v9",  "v10", "v11", "v12", "v13", "v14", "v15",
41f63e7089SHuang Shiyuan    "v16",  "v17", "v18", "v19", "v20", "v21", "v22", "v23",
42f63e7089SHuang Shiyuan    "v24",  "v25", "v26", "v27", "v28", "v29", "v30", "v31",
43139c1837SPaolo Bonzini};
44139c1837SPaolo Bonzini#endif
45139c1837SPaolo Bonzini
46139c1837SPaolo Bonzinistatic const int tcg_target_reg_alloc_order[] = {
47139c1837SPaolo Bonzini    /* Call saved registers */
484daad8d9SMichael Tokarev    /* TCG_REG_S0 reserved for TCG_AREG0 */
49139c1837SPaolo Bonzini    TCG_REG_S1,
50139c1837SPaolo Bonzini    TCG_REG_S2,
51139c1837SPaolo Bonzini    TCG_REG_S3,
52139c1837SPaolo Bonzini    TCG_REG_S4,
53139c1837SPaolo Bonzini    TCG_REG_S5,
54139c1837SPaolo Bonzini    TCG_REG_S6,
55139c1837SPaolo Bonzini    TCG_REG_S7,
56139c1837SPaolo Bonzini    TCG_REG_S8,
57139c1837SPaolo Bonzini    TCG_REG_S9,
58139c1837SPaolo Bonzini    TCG_REG_S10,
59139c1837SPaolo Bonzini    TCG_REG_S11,
60139c1837SPaolo Bonzini
61139c1837SPaolo Bonzini    /* Call clobbered registers */
62139c1837SPaolo Bonzini    TCG_REG_T0,
63139c1837SPaolo Bonzini    TCG_REG_T1,
64139c1837SPaolo Bonzini    TCG_REG_T2,
65139c1837SPaolo Bonzini    TCG_REG_T3,
66139c1837SPaolo Bonzini    TCG_REG_T4,
67139c1837SPaolo Bonzini    TCG_REG_T5,
68139c1837SPaolo Bonzini    TCG_REG_T6,
69139c1837SPaolo Bonzini
70139c1837SPaolo Bonzini    /* Argument registers */
71139c1837SPaolo Bonzini    TCG_REG_A0,
72139c1837SPaolo Bonzini    TCG_REG_A1,
73139c1837SPaolo Bonzini    TCG_REG_A2,
74139c1837SPaolo Bonzini    TCG_REG_A3,
75139c1837SPaolo Bonzini    TCG_REG_A4,
76139c1837SPaolo Bonzini    TCG_REG_A5,
77139c1837SPaolo Bonzini    TCG_REG_A6,
78139c1837SPaolo Bonzini    TCG_REG_A7,
79f63e7089SHuang Shiyuan
80f63e7089SHuang Shiyuan    /* Vector registers and TCG_REG_V0 reserved for mask. */
81f63e7089SHuang Shiyuan    TCG_REG_V1,  TCG_REG_V2,  TCG_REG_V3,  TCG_REG_V4,
82f63e7089SHuang Shiyuan    TCG_REG_V5,  TCG_REG_V6,  TCG_REG_V7,  TCG_REG_V8,
83f63e7089SHuang Shiyuan    TCG_REG_V9,  TCG_REG_V10, TCG_REG_V11, TCG_REG_V12,
84f63e7089SHuang Shiyuan    TCG_REG_V13, TCG_REG_V14, TCG_REG_V15, TCG_REG_V16,
85f63e7089SHuang Shiyuan    TCG_REG_V17, TCG_REG_V18, TCG_REG_V19, TCG_REG_V20,
86f63e7089SHuang Shiyuan    TCG_REG_V21, TCG_REG_V22, TCG_REG_V23, TCG_REG_V24,
87f63e7089SHuang Shiyuan    TCG_REG_V25, TCG_REG_V26, TCG_REG_V27, TCG_REG_V28,
88f63e7089SHuang Shiyuan    TCG_REG_V29, TCG_REG_V30, TCG_REG_V31,
89139c1837SPaolo Bonzini};
90139c1837SPaolo Bonzini
91139c1837SPaolo Bonzinistatic const int tcg_target_call_iarg_regs[] = {
92139c1837SPaolo Bonzini    TCG_REG_A0,
93139c1837SPaolo Bonzini    TCG_REG_A1,
94139c1837SPaolo Bonzini    TCG_REG_A2,
95139c1837SPaolo Bonzini    TCG_REG_A3,
96139c1837SPaolo Bonzini    TCG_REG_A4,
97139c1837SPaolo Bonzini    TCG_REG_A5,
98139c1837SPaolo Bonzini    TCG_REG_A6,
99139c1837SPaolo Bonzini    TCG_REG_A7,
100139c1837SPaolo Bonzini};
101139c1837SPaolo Bonzini
1025e3d0c19SRichard Hendersonstatic TCGReg tcg_target_call_oarg_reg(TCGCallReturnKind kind, int slot)
1035e3d0c19SRichard Henderson{
1045e3d0c19SRichard Henderson    tcg_debug_assert(kind == TCG_CALL_RET_NORMAL);
1055e3d0c19SRichard Henderson    tcg_debug_assert(slot >= 0 && slot <= 1);
1065e3d0c19SRichard Henderson    return TCG_REG_A0 + slot;
1075e3d0c19SRichard Henderson}
108139c1837SPaolo Bonzini
109139c1837SPaolo Bonzini#define TCG_CT_CONST_ZERO    0x100
110139c1837SPaolo Bonzini#define TCG_CT_CONST_S12     0x200
111139c1837SPaolo Bonzini#define TCG_CT_CONST_N12     0x400
112139c1837SPaolo Bonzini#define TCG_CT_CONST_M12     0x800
11399f4ec6eSRichard Henderson#define TCG_CT_CONST_J12    0x1000
1145a63f599STANG Tiancheng#define TCG_CT_CONST_S5     0x2000
115a31768c0STANG Tiancheng#define TCG_CT_CONST_CMP_VI 0x4000
116139c1837SPaolo Bonzini
117fc63a4c5SRichard Henderson#define ALL_GENERAL_REGS   MAKE_64BIT_MASK(0, 32)
118f63e7089SHuang Shiyuan#define ALL_VECTOR_REGS    MAKE_64BIT_MASK(32, 32)
119f63e7089SHuang Shiyuan#define ALL_DVECTOR_REG_GROUPS 0x5555555500000000
120f63e7089SHuang Shiyuan#define ALL_QVECTOR_REG_GROUPS 0x1111111100000000
121fc63a4c5SRichard Henderson
122aeb6326eSRichard Henderson#define sextreg  sextract64
123139c1837SPaolo Bonzini
124139c1837SPaolo Bonzini/*
125139c1837SPaolo Bonzini * RISC-V Base ISA opcodes (IM)
126139c1837SPaolo Bonzini */
127139c1837SPaolo Bonzini
128f63e7089SHuang Shiyuan#define V_OPIVV (0x0 << 12)
129f63e7089SHuang Shiyuan#define V_OPFVV (0x1 << 12)
130f63e7089SHuang Shiyuan#define V_OPMVV (0x2 << 12)
131f63e7089SHuang Shiyuan#define V_OPIVI (0x3 << 12)
132f63e7089SHuang Shiyuan#define V_OPIVX (0x4 << 12)
133f63e7089SHuang Shiyuan#define V_OPFVF (0x5 << 12)
134f63e7089SHuang Shiyuan#define V_OPMVX (0x6 << 12)
135f63e7089SHuang Shiyuan#define V_OPCFG (0x7 << 12)
136f63e7089SHuang Shiyuan
137f63e7089SHuang Shiyuan/* NF <= 7 && NF >= 0 */
138f63e7089SHuang Shiyuan#define V_NF(x) (x << 29)
139f63e7089SHuang Shiyuan#define V_UNIT_STRIDE (0x0 << 20)
140f63e7089SHuang Shiyuan#define V_UNIT_STRIDE_WHOLE_REG (0x8 << 20)
141f63e7089SHuang Shiyuan
142f63e7089SHuang Shiyuantypedef enum {
143f63e7089SHuang Shiyuan    VLMUL_M1 = 0, /* LMUL=1 */
144f63e7089SHuang Shiyuan    VLMUL_M2,     /* LMUL=2 */
145f63e7089SHuang Shiyuan    VLMUL_M4,     /* LMUL=4 */
146f63e7089SHuang Shiyuan    VLMUL_M8,     /* LMUL=8 */
147f63e7089SHuang Shiyuan    VLMUL_RESERVED,
148f63e7089SHuang Shiyuan    VLMUL_MF8,    /* LMUL=1/8 */
149f63e7089SHuang Shiyuan    VLMUL_MF4,    /* LMUL=1/4 */
150f63e7089SHuang Shiyuan    VLMUL_MF2,    /* LMUL=1/2 */
151f63e7089SHuang Shiyuan} RISCVVlmul;
152f63e7089SHuang Shiyuan
153139c1837SPaolo Bonzinitypedef enum {
154139c1837SPaolo Bonzini    OPC_ADD = 0x33,
155139c1837SPaolo Bonzini    OPC_ADDI = 0x13,
156139c1837SPaolo Bonzini    OPC_AND = 0x7033,
157139c1837SPaolo Bonzini    OPC_ANDI = 0x7013,
158139c1837SPaolo Bonzini    OPC_AUIPC = 0x17,
159139c1837SPaolo Bonzini    OPC_BEQ = 0x63,
160139c1837SPaolo Bonzini    OPC_BGE = 0x5063,
161139c1837SPaolo Bonzini    OPC_BGEU = 0x7063,
162139c1837SPaolo Bonzini    OPC_BLT = 0x4063,
163139c1837SPaolo Bonzini    OPC_BLTU = 0x6063,
164139c1837SPaolo Bonzini    OPC_BNE = 0x1063,
165139c1837SPaolo Bonzini    OPC_DIV = 0x2004033,
166139c1837SPaolo Bonzini    OPC_DIVU = 0x2005033,
167139c1837SPaolo Bonzini    OPC_JAL = 0x6f,
168139c1837SPaolo Bonzini    OPC_JALR = 0x67,
169139c1837SPaolo Bonzini    OPC_LB = 0x3,
170139c1837SPaolo Bonzini    OPC_LBU = 0x4003,
171139c1837SPaolo Bonzini    OPC_LD = 0x3003,
172139c1837SPaolo Bonzini    OPC_LH = 0x1003,
173139c1837SPaolo Bonzini    OPC_LHU = 0x5003,
174139c1837SPaolo Bonzini    OPC_LUI = 0x37,
175139c1837SPaolo Bonzini    OPC_LW = 0x2003,
176139c1837SPaolo Bonzini    OPC_LWU = 0x6003,
177139c1837SPaolo Bonzini    OPC_MUL = 0x2000033,
178139c1837SPaolo Bonzini    OPC_MULH = 0x2001033,
179139c1837SPaolo Bonzini    OPC_MULHSU = 0x2002033,
180139c1837SPaolo Bonzini    OPC_MULHU = 0x2003033,
181139c1837SPaolo Bonzini    OPC_OR = 0x6033,
182139c1837SPaolo Bonzini    OPC_ORI = 0x6013,
183139c1837SPaolo Bonzini    OPC_REM = 0x2006033,
184139c1837SPaolo Bonzini    OPC_REMU = 0x2007033,
185139c1837SPaolo Bonzini    OPC_SB = 0x23,
186139c1837SPaolo Bonzini    OPC_SD = 0x3023,
187139c1837SPaolo Bonzini    OPC_SH = 0x1023,
188139c1837SPaolo Bonzini    OPC_SLL = 0x1033,
189139c1837SPaolo Bonzini    OPC_SLLI = 0x1013,
190139c1837SPaolo Bonzini    OPC_SLT = 0x2033,
191139c1837SPaolo Bonzini    OPC_SLTI = 0x2013,
192139c1837SPaolo Bonzini    OPC_SLTIU = 0x3013,
193139c1837SPaolo Bonzini    OPC_SLTU = 0x3033,
194139c1837SPaolo Bonzini    OPC_SRA = 0x40005033,
195139c1837SPaolo Bonzini    OPC_SRAI = 0x40005013,
196139c1837SPaolo Bonzini    OPC_SRL = 0x5033,
197139c1837SPaolo Bonzini    OPC_SRLI = 0x5013,
198139c1837SPaolo Bonzini    OPC_SUB = 0x40000033,
199139c1837SPaolo Bonzini    OPC_SW = 0x2023,
200139c1837SPaolo Bonzini    OPC_XOR = 0x4033,
201139c1837SPaolo Bonzini    OPC_XORI = 0x4013,
202139c1837SPaolo Bonzini
203139c1837SPaolo Bonzini    OPC_ADDIW = 0x1b,
204139c1837SPaolo Bonzini    OPC_ADDW = 0x3b,
205139c1837SPaolo Bonzini    OPC_DIVUW = 0x200503b,
206139c1837SPaolo Bonzini    OPC_DIVW = 0x200403b,
207139c1837SPaolo Bonzini    OPC_MULW = 0x200003b,
208139c1837SPaolo Bonzini    OPC_REMUW = 0x200703b,
209139c1837SPaolo Bonzini    OPC_REMW = 0x200603b,
210139c1837SPaolo Bonzini    OPC_SLLIW = 0x101b,
211139c1837SPaolo Bonzini    OPC_SLLW = 0x103b,
212139c1837SPaolo Bonzini    OPC_SRAIW = 0x4000501b,
213139c1837SPaolo Bonzini    OPC_SRAW = 0x4000503b,
214139c1837SPaolo Bonzini    OPC_SRLIW = 0x501b,
215139c1837SPaolo Bonzini    OPC_SRLW = 0x503b,
216139c1837SPaolo Bonzini    OPC_SUBW = 0x4000003b,
217139c1837SPaolo Bonzini
218139c1837SPaolo Bonzini    OPC_FENCE = 0x0000000f,
2199ae958e4SRichard Henderson    OPC_NOP   = OPC_ADDI,   /* nop = addi r0,r0,0 */
2209e3e0bc6SRichard Henderson
2219e3e0bc6SRichard Henderson    /* Zba: Bit manipulation extension, address generation */
2229e3e0bc6SRichard Henderson    OPC_ADD_UW = 0x0800003b,
2239e3e0bc6SRichard Henderson
2244daad8d9SMichael Tokarev    /* Zbb: Bit manipulation extension, basic bit manipulation */
2259e3e0bc6SRichard Henderson    OPC_ANDN   = 0x40007033,
2269e3e0bc6SRichard Henderson    OPC_CLZ    = 0x60001013,
2279e3e0bc6SRichard Henderson    OPC_CLZW   = 0x6000101b,
2289e3e0bc6SRichard Henderson    OPC_CPOP   = 0x60201013,
2299e3e0bc6SRichard Henderson    OPC_CPOPW  = 0x6020101b,
2309e3e0bc6SRichard Henderson    OPC_CTZ    = 0x60101013,
2319e3e0bc6SRichard Henderson    OPC_CTZW   = 0x6010101b,
2329e3e0bc6SRichard Henderson    OPC_ORN    = 0x40006033,
2339e3e0bc6SRichard Henderson    OPC_REV8   = 0x6b805013,
2349e3e0bc6SRichard Henderson    OPC_ROL    = 0x60001033,
2359e3e0bc6SRichard Henderson    OPC_ROLW   = 0x6000103b,
2369e3e0bc6SRichard Henderson    OPC_ROR    = 0x60005033,
2379e3e0bc6SRichard Henderson    OPC_RORW   = 0x6000503b,
2389e3e0bc6SRichard Henderson    OPC_RORI   = 0x60005013,
2399e3e0bc6SRichard Henderson    OPC_RORIW  = 0x6000501b,
2409e3e0bc6SRichard Henderson    OPC_SEXT_B = 0x60401013,
2419e3e0bc6SRichard Henderson    OPC_SEXT_H = 0x60501013,
2429e3e0bc6SRichard Henderson    OPC_XNOR   = 0x40004033,
2439e3e0bc6SRichard Henderson    OPC_ZEXT_H = 0x0800403b,
2449e3e0bc6SRichard Henderson
2459e3e0bc6SRichard Henderson    /* Zicond: integer conditional operations */
2469e3e0bc6SRichard Henderson    OPC_CZERO_EQZ = 0x0e005033,
2479e3e0bc6SRichard Henderson    OPC_CZERO_NEZ = 0x0e007033,
248f63e7089SHuang Shiyuan
249f63e7089SHuang Shiyuan    /* V: Vector extension 1.0 */
250f63e7089SHuang Shiyuan    OPC_VSETVLI  = 0x57 | V_OPCFG,
251f63e7089SHuang Shiyuan    OPC_VSETIVLI = 0xc0000057 | V_OPCFG,
252f63e7089SHuang Shiyuan    OPC_VSETVL   = 0x80000057 | V_OPCFG,
253f63e7089SHuang Shiyuan
254f63e7089SHuang Shiyuan    OPC_VLE8_V  = 0x7 | V_UNIT_STRIDE,
255f63e7089SHuang Shiyuan    OPC_VLE16_V = 0x5007 | V_UNIT_STRIDE,
256f63e7089SHuang Shiyuan    OPC_VLE32_V = 0x6007 | V_UNIT_STRIDE,
257f63e7089SHuang Shiyuan    OPC_VLE64_V = 0x7007 | V_UNIT_STRIDE,
258f63e7089SHuang Shiyuan    OPC_VSE8_V  = 0x27 | V_UNIT_STRIDE,
259f63e7089SHuang Shiyuan    OPC_VSE16_V = 0x5027 | V_UNIT_STRIDE,
260f63e7089SHuang Shiyuan    OPC_VSE32_V = 0x6027 | V_UNIT_STRIDE,
261f63e7089SHuang Shiyuan    OPC_VSE64_V = 0x7027 | V_UNIT_STRIDE,
262f63e7089SHuang Shiyuan
263f63e7089SHuang Shiyuan    OPC_VL1RE64_V = 0x2007007 | V_UNIT_STRIDE_WHOLE_REG | V_NF(0),
264f63e7089SHuang Shiyuan    OPC_VL2RE64_V = 0x2007007 | V_UNIT_STRIDE_WHOLE_REG | V_NF(1),
265f63e7089SHuang Shiyuan    OPC_VL4RE64_V = 0x2007007 | V_UNIT_STRIDE_WHOLE_REG | V_NF(3),
266f63e7089SHuang Shiyuan    OPC_VL8RE64_V = 0x2007007 | V_UNIT_STRIDE_WHOLE_REG | V_NF(7),
267f63e7089SHuang Shiyuan
268f63e7089SHuang Shiyuan    OPC_VS1R_V = 0x2000027 | V_UNIT_STRIDE_WHOLE_REG | V_NF(0),
269f63e7089SHuang Shiyuan    OPC_VS2R_V = 0x2000027 | V_UNIT_STRIDE_WHOLE_REG | V_NF(1),
270f63e7089SHuang Shiyuan    OPC_VS4R_V = 0x2000027 | V_UNIT_STRIDE_WHOLE_REG | V_NF(3),
271f63e7089SHuang Shiyuan    OPC_VS8R_V = 0x2000027 | V_UNIT_STRIDE_WHOLE_REG | V_NF(7),
272d4be6ee1STANG Tiancheng
273a31768c0STANG Tiancheng    OPC_VMERGE_VIM = 0x5c000057 | V_OPIVI,
274a31768c0STANG Tiancheng    OPC_VMERGE_VVM = 0x5c000057 | V_OPIVV,
275a31768c0STANG Tiancheng
2765a63f599STANG Tiancheng    OPC_VADD_VV = 0x57 | V_OPIVV,
2775a63f599STANG Tiancheng    OPC_VADD_VI = 0x57 | V_OPIVI,
2785a63f599STANG Tiancheng    OPC_VSUB_VV = 0x8000057 | V_OPIVV,
279c283c074STANG Tiancheng    OPC_VRSUB_VI = 0xc000057 | V_OPIVI,
2805a63f599STANG Tiancheng    OPC_VAND_VV = 0x24000057 | V_OPIVV,
2815a63f599STANG Tiancheng    OPC_VAND_VI = 0x24000057 | V_OPIVI,
2825a63f599STANG Tiancheng    OPC_VOR_VV = 0x28000057 | V_OPIVV,
2835a63f599STANG Tiancheng    OPC_VOR_VI = 0x28000057 | V_OPIVI,
2845a63f599STANG Tiancheng    OPC_VXOR_VV = 0x2c000057 | V_OPIVV,
2855a63f599STANG Tiancheng    OPC_VXOR_VI = 0x2c000057 | V_OPIVI,
2865a63f599STANG Tiancheng
287*101c1ef5STANG Tiancheng    OPC_VMUL_VV = 0x94000057 | V_OPMVV,
288*101c1ef5STANG Tiancheng    OPC_VSADD_VV = 0x84000057 | V_OPIVV,
289*101c1ef5STANG Tiancheng    OPC_VSADD_VI = 0x84000057 | V_OPIVI,
290*101c1ef5STANG Tiancheng    OPC_VSSUB_VV = 0x8c000057 | V_OPIVV,
291*101c1ef5STANG Tiancheng    OPC_VSSUB_VI = 0x8c000057 | V_OPIVI,
292*101c1ef5STANG Tiancheng    OPC_VSADDU_VV = 0x80000057 | V_OPIVV,
293*101c1ef5STANG Tiancheng    OPC_VSADDU_VI = 0x80000057 | V_OPIVI,
294*101c1ef5STANG Tiancheng    OPC_VSSUBU_VV = 0x88000057 | V_OPIVV,
295*101c1ef5STANG Tiancheng    OPC_VSSUBU_VI = 0x88000057 | V_OPIVI,
296*101c1ef5STANG Tiancheng
297a31768c0STANG Tiancheng    OPC_VMSEQ_VV = 0x60000057 | V_OPIVV,
298a31768c0STANG Tiancheng    OPC_VMSEQ_VI = 0x60000057 | V_OPIVI,
299a31768c0STANG Tiancheng    OPC_VMSEQ_VX = 0x60000057 | V_OPIVX,
300a31768c0STANG Tiancheng    OPC_VMSNE_VV = 0x64000057 | V_OPIVV,
301a31768c0STANG Tiancheng    OPC_VMSNE_VI = 0x64000057 | V_OPIVI,
302a31768c0STANG Tiancheng    OPC_VMSNE_VX = 0x64000057 | V_OPIVX,
303a31768c0STANG Tiancheng
304a31768c0STANG Tiancheng    OPC_VMSLTU_VV = 0x68000057 | V_OPIVV,
305a31768c0STANG Tiancheng    OPC_VMSLTU_VX = 0x68000057 | V_OPIVX,
306a31768c0STANG Tiancheng    OPC_VMSLT_VV = 0x6c000057 | V_OPIVV,
307a31768c0STANG Tiancheng    OPC_VMSLT_VX = 0x6c000057 | V_OPIVX,
308a31768c0STANG Tiancheng    OPC_VMSLEU_VV = 0x70000057 | V_OPIVV,
309a31768c0STANG Tiancheng    OPC_VMSLEU_VX = 0x70000057 | V_OPIVX,
310a31768c0STANG Tiancheng    OPC_VMSLE_VV = 0x74000057 | V_OPIVV,
311a31768c0STANG Tiancheng    OPC_VMSLE_VX = 0x74000057 | V_OPIVX,
312a31768c0STANG Tiancheng
313a31768c0STANG Tiancheng    OPC_VMSLEU_VI = 0x70000057 | V_OPIVI,
314a31768c0STANG Tiancheng    OPC_VMSLE_VI = 0x74000057 | V_OPIVI,
315a31768c0STANG Tiancheng    OPC_VMSGTU_VI = 0x78000057 | V_OPIVI,
316a31768c0STANG Tiancheng    OPC_VMSGTU_VX = 0x78000057 | V_OPIVX,
317a31768c0STANG Tiancheng    OPC_VMSGT_VI = 0x7c000057 | V_OPIVI,
318a31768c0STANG Tiancheng    OPC_VMSGT_VX = 0x7c000057 | V_OPIVX,
319a31768c0STANG Tiancheng
320d4be6ee1STANG Tiancheng    OPC_VMV_V_V = 0x5e000057 | V_OPIVV,
321d4be6ee1STANG Tiancheng    OPC_VMV_V_I = 0x5e000057 | V_OPIVI,
322d4be6ee1STANG Tiancheng    OPC_VMV_V_X = 0x5e000057 | V_OPIVX,
323d4be6ee1STANG Tiancheng
324d4be6ee1STANG Tiancheng    OPC_VMVNR_V = 0x9e000057 | V_OPIVI,
325139c1837SPaolo Bonzini} RISCVInsn;
326139c1837SPaolo Bonzini
327a31768c0STANG Tianchengstatic const struct {
328a31768c0STANG Tiancheng    RISCVInsn op;
329a31768c0STANG Tiancheng    bool swap;
330a31768c0STANG Tiancheng} tcg_cmpcond_to_rvv_vv[] = {
331a31768c0STANG Tiancheng    [TCG_COND_EQ] =  { OPC_VMSEQ_VV,  false },
332a31768c0STANG Tiancheng    [TCG_COND_NE] =  { OPC_VMSNE_VV,  false },
333a31768c0STANG Tiancheng    [TCG_COND_LT] =  { OPC_VMSLT_VV,  false },
334a31768c0STANG Tiancheng    [TCG_COND_GE] =  { OPC_VMSLE_VV,  true  },
335a31768c0STANG Tiancheng    [TCG_COND_GT] =  { OPC_VMSLT_VV,  true  },
336a31768c0STANG Tiancheng    [TCG_COND_LE] =  { OPC_VMSLE_VV,  false },
337a31768c0STANG Tiancheng    [TCG_COND_LTU] = { OPC_VMSLTU_VV, false },
338a31768c0STANG Tiancheng    [TCG_COND_GEU] = { OPC_VMSLEU_VV, true  },
339a31768c0STANG Tiancheng    [TCG_COND_GTU] = { OPC_VMSLTU_VV, true  },
340a31768c0STANG Tiancheng    [TCG_COND_LEU] = { OPC_VMSLEU_VV, false }
341a31768c0STANG Tiancheng};
342a31768c0STANG Tiancheng
343a31768c0STANG Tianchengstatic const struct {
344a31768c0STANG Tiancheng    RISCVInsn op;
345a31768c0STANG Tiancheng    int min;
346a31768c0STANG Tiancheng    int max;
347a31768c0STANG Tiancheng    bool adjust;
348a31768c0STANG Tiancheng}  tcg_cmpcond_to_rvv_vi[] = {
349a31768c0STANG Tiancheng    [TCG_COND_EQ]  = { OPC_VMSEQ_VI,  -16, 15, false },
350a31768c0STANG Tiancheng    [TCG_COND_NE]  = { OPC_VMSNE_VI,  -16, 15, false },
351a31768c0STANG Tiancheng    [TCG_COND_GT]  = { OPC_VMSGT_VI,  -16, 15, false },
352a31768c0STANG Tiancheng    [TCG_COND_LE]  = { OPC_VMSLE_VI,  -16, 15, false },
353a31768c0STANG Tiancheng    [TCG_COND_LT]  = { OPC_VMSLE_VI,  -15, 16, true  },
354a31768c0STANG Tiancheng    [TCG_COND_GE]  = { OPC_VMSGT_VI,  -15, 16, true  },
355a31768c0STANG Tiancheng    [TCG_COND_LEU] = { OPC_VMSLEU_VI,   0, 15, false },
356a31768c0STANG Tiancheng    [TCG_COND_GTU] = { OPC_VMSGTU_VI,   0, 15, false },
357a31768c0STANG Tiancheng    [TCG_COND_LTU] = { OPC_VMSLEU_VI,   1, 16, true  },
358a31768c0STANG Tiancheng    [TCG_COND_GEU] = { OPC_VMSGTU_VI,   1, 16, true  },
359a31768c0STANG Tiancheng};
360a31768c0STANG Tiancheng
361a31768c0STANG Tiancheng/* test if a constant matches the constraint */
362a31768c0STANG Tianchengstatic bool tcg_target_const_match(int64_t val, int ct,
363a31768c0STANG Tiancheng                                   TCGType type, TCGCond cond, int vece)
364a31768c0STANG Tiancheng{
365a31768c0STANG Tiancheng    if (ct & TCG_CT_CONST) {
366a31768c0STANG Tiancheng        return 1;
367a31768c0STANG Tiancheng    }
368a31768c0STANG Tiancheng    if ((ct & TCG_CT_CONST_ZERO) && val == 0) {
369a31768c0STANG Tiancheng        return 1;
370a31768c0STANG Tiancheng    }
371a31768c0STANG Tiancheng    if (type >= TCG_TYPE_V64) {
372a31768c0STANG Tiancheng        /* Val is replicated by VECE; extract the highest element. */
373a31768c0STANG Tiancheng        val >>= (-8 << vece) & 63;
374a31768c0STANG Tiancheng    }
375a31768c0STANG Tiancheng    /*
376a31768c0STANG Tiancheng     * Sign extended from 12 bits: [-0x800, 0x7ff].
377a31768c0STANG Tiancheng     * Used for most arithmetic, as this is the isa field.
378a31768c0STANG Tiancheng     */
379a31768c0STANG Tiancheng    if ((ct & TCG_CT_CONST_S12) && val >= -0x800 && val <= 0x7ff) {
380a31768c0STANG Tiancheng        return 1;
381a31768c0STANG Tiancheng    }
382a31768c0STANG Tiancheng    /*
383a31768c0STANG Tiancheng     * Sign extended from 12 bits, negated: [-0x7ff, 0x800].
384a31768c0STANG Tiancheng     * Used for subtraction, where a constant must be handled by ADDI.
385a31768c0STANG Tiancheng     */
386a31768c0STANG Tiancheng    if ((ct & TCG_CT_CONST_N12) && val >= -0x7ff && val <= 0x800) {
387a31768c0STANG Tiancheng        return 1;
388a31768c0STANG Tiancheng    }
389a31768c0STANG Tiancheng    /*
390a31768c0STANG Tiancheng     * Sign extended from 12 bits, +/- matching: [-0x7ff, 0x7ff].
391a31768c0STANG Tiancheng     * Used by addsub2 and movcond, which may need the negative value,
392a31768c0STANG Tiancheng     * and requires the modified constant to be representable.
393a31768c0STANG Tiancheng     */
394a31768c0STANG Tiancheng    if ((ct & TCG_CT_CONST_M12) && val >= -0x7ff && val <= 0x7ff) {
395a31768c0STANG Tiancheng        return 1;
396a31768c0STANG Tiancheng    }
397a31768c0STANG Tiancheng    /*
398a31768c0STANG Tiancheng     * Inverse of sign extended from 12 bits: ~[-0x800, 0x7ff].
399a31768c0STANG Tiancheng     * Used to map ANDN back to ANDI, etc.
400a31768c0STANG Tiancheng     */
401a31768c0STANG Tiancheng    if ((ct & TCG_CT_CONST_J12) && ~val >= -0x800 && ~val <= 0x7ff) {
402a31768c0STANG Tiancheng        return 1;
403a31768c0STANG Tiancheng    }
404a31768c0STANG Tiancheng    /*
405a31768c0STANG Tiancheng     * Sign extended from 5 bits: [-0x10, 0x0f].
406a31768c0STANG Tiancheng     * Used for vector-immediate.
407a31768c0STANG Tiancheng     */
408a31768c0STANG Tiancheng    if ((ct & TCG_CT_CONST_S5) && val >= -0x10 && val <= 0x0f) {
409a31768c0STANG Tiancheng        return 1;
410a31768c0STANG Tiancheng    }
411a31768c0STANG Tiancheng    /*
412a31768c0STANG Tiancheng     * Used for vector compare OPIVI instructions.
413a31768c0STANG Tiancheng     */
414a31768c0STANG Tiancheng    if ((ct & TCG_CT_CONST_CMP_VI) &&
415a31768c0STANG Tiancheng        val >= tcg_cmpcond_to_rvv_vi[cond].min &&
416a31768c0STANG Tiancheng        val <= tcg_cmpcond_to_rvv_vi[cond].max) {
417a31768c0STANG Tiancheng        return true;
418a31768c0STANG Tiancheng     }
419a31768c0STANG Tiancheng    return 0;
420a31768c0STANG Tiancheng}
421a31768c0STANG Tiancheng
422139c1837SPaolo Bonzini/*
423139c1837SPaolo Bonzini * RISC-V immediate and instruction encoders (excludes 16-bit RVC)
424139c1837SPaolo Bonzini */
425139c1837SPaolo Bonzini
426139c1837SPaolo Bonzini/* Type-R */
427139c1837SPaolo Bonzini
428139c1837SPaolo Bonzinistatic int32_t encode_r(RISCVInsn opc, TCGReg rd, TCGReg rs1, TCGReg rs2)
429139c1837SPaolo Bonzini{
430139c1837SPaolo Bonzini    return opc | (rd & 0x1f) << 7 | (rs1 & 0x1f) << 15 | (rs2 & 0x1f) << 20;
431139c1837SPaolo Bonzini}
432139c1837SPaolo Bonzini
433139c1837SPaolo Bonzini/* Type-I */
434139c1837SPaolo Bonzini
435139c1837SPaolo Bonzinistatic int32_t encode_imm12(uint32_t imm)
436139c1837SPaolo Bonzini{
437139c1837SPaolo Bonzini    return (imm & 0xfff) << 20;
438139c1837SPaolo Bonzini}
439139c1837SPaolo Bonzini
440139c1837SPaolo Bonzinistatic int32_t encode_i(RISCVInsn opc, TCGReg rd, TCGReg rs1, uint32_t imm)
441139c1837SPaolo Bonzini{
442139c1837SPaolo Bonzini    return opc | (rd & 0x1f) << 7 | (rs1 & 0x1f) << 15 | encode_imm12(imm);
443139c1837SPaolo Bonzini}
444139c1837SPaolo Bonzini
445139c1837SPaolo Bonzini/* Type-S */
446139c1837SPaolo Bonzini
447139c1837SPaolo Bonzinistatic int32_t encode_simm12(uint32_t imm)
448139c1837SPaolo Bonzini{
449139c1837SPaolo Bonzini    int32_t ret = 0;
450139c1837SPaolo Bonzini
451139c1837SPaolo Bonzini    ret |= (imm & 0xFE0) << 20;
452139c1837SPaolo Bonzini    ret |= (imm & 0x1F) << 7;
453139c1837SPaolo Bonzini
454139c1837SPaolo Bonzini    return ret;
455139c1837SPaolo Bonzini}
456139c1837SPaolo Bonzini
457139c1837SPaolo Bonzinistatic int32_t encode_s(RISCVInsn opc, TCGReg rs1, TCGReg rs2, uint32_t imm)
458139c1837SPaolo Bonzini{
459139c1837SPaolo Bonzini    return opc | (rs1 & 0x1f) << 15 | (rs2 & 0x1f) << 20 | encode_simm12(imm);
460139c1837SPaolo Bonzini}
461139c1837SPaolo Bonzini
462139c1837SPaolo Bonzini/* Type-SB */
463139c1837SPaolo Bonzini
464139c1837SPaolo Bonzinistatic int32_t encode_sbimm12(uint32_t imm)
465139c1837SPaolo Bonzini{
466139c1837SPaolo Bonzini    int32_t ret = 0;
467139c1837SPaolo Bonzini
468139c1837SPaolo Bonzini    ret |= (imm & 0x1000) << 19;
469139c1837SPaolo Bonzini    ret |= (imm & 0x7e0) << 20;
470139c1837SPaolo Bonzini    ret |= (imm & 0x1e) << 7;
471139c1837SPaolo Bonzini    ret |= (imm & 0x800) >> 4;
472139c1837SPaolo Bonzini
473139c1837SPaolo Bonzini    return ret;
474139c1837SPaolo Bonzini}
475139c1837SPaolo Bonzini
476139c1837SPaolo Bonzinistatic int32_t encode_sb(RISCVInsn opc, TCGReg rs1, TCGReg rs2, uint32_t imm)
477139c1837SPaolo Bonzini{
478139c1837SPaolo Bonzini    return opc | (rs1 & 0x1f) << 15 | (rs2 & 0x1f) << 20 | encode_sbimm12(imm);
479139c1837SPaolo Bonzini}
480139c1837SPaolo Bonzini
481139c1837SPaolo Bonzini/* Type-U */
482139c1837SPaolo Bonzini
483139c1837SPaolo Bonzinistatic int32_t encode_uimm20(uint32_t imm)
484139c1837SPaolo Bonzini{
485139c1837SPaolo Bonzini    return imm & 0xfffff000;
486139c1837SPaolo Bonzini}
487139c1837SPaolo Bonzini
488139c1837SPaolo Bonzinistatic int32_t encode_u(RISCVInsn opc, TCGReg rd, uint32_t imm)
489139c1837SPaolo Bonzini{
490139c1837SPaolo Bonzini    return opc | (rd & 0x1f) << 7 | encode_uimm20(imm);
491139c1837SPaolo Bonzini}
492139c1837SPaolo Bonzini
493139c1837SPaolo Bonzini/* Type-UJ */
494139c1837SPaolo Bonzini
495139c1837SPaolo Bonzinistatic int32_t encode_ujimm20(uint32_t imm)
496139c1837SPaolo Bonzini{
497139c1837SPaolo Bonzini    int32_t ret = 0;
498139c1837SPaolo Bonzini
499139c1837SPaolo Bonzini    ret |= (imm & 0x0007fe) << (21 - 1);
500139c1837SPaolo Bonzini    ret |= (imm & 0x000800) << (20 - 11);
501139c1837SPaolo Bonzini    ret |= (imm & 0x0ff000) << (12 - 12);
502139c1837SPaolo Bonzini    ret |= (imm & 0x100000) << (31 - 20);
503139c1837SPaolo Bonzini
504139c1837SPaolo Bonzini    return ret;
505139c1837SPaolo Bonzini}
506139c1837SPaolo Bonzini
507139c1837SPaolo Bonzinistatic int32_t encode_uj(RISCVInsn opc, TCGReg rd, uint32_t imm)
508139c1837SPaolo Bonzini{
509139c1837SPaolo Bonzini    return opc | (rd & 0x1f) << 7 | encode_ujimm20(imm);
510139c1837SPaolo Bonzini}
511139c1837SPaolo Bonzini
512d4be6ee1STANG Tiancheng
513d4be6ee1STANG Tiancheng/* Type-OPIVI */
514d4be6ee1STANG Tiancheng
515d4be6ee1STANG Tianchengstatic int32_t encode_vi(RISCVInsn opc, TCGReg rd, int32_t imm,
516d4be6ee1STANG Tiancheng                         TCGReg vs2, bool vm)
517d4be6ee1STANG Tiancheng{
518d4be6ee1STANG Tiancheng    return opc | (rd & 0x1f) << 7 | (imm & 0x1f) << 15 |
519d4be6ee1STANG Tiancheng           (vs2 & 0x1f) << 20 | (vm << 25);
520d4be6ee1STANG Tiancheng}
521d4be6ee1STANG Tiancheng
522f63e7089SHuang Shiyuan/* Type-OPIVV/OPMVV/OPIVX/OPMVX, Vector load and store */
523f63e7089SHuang Shiyuan
524f63e7089SHuang Shiyuanstatic int32_t encode_v(RISCVInsn opc, TCGReg d, TCGReg s1,
525f63e7089SHuang Shiyuan                        TCGReg s2, bool vm)
526f63e7089SHuang Shiyuan{
527f63e7089SHuang Shiyuan    return opc | (d & 0x1f) << 7 | (s1 & 0x1f) << 15 |
528f63e7089SHuang Shiyuan           (s2 & 0x1f) << 20 | (vm << 25);
529f63e7089SHuang Shiyuan}
530f63e7089SHuang Shiyuan
531f63e7089SHuang Shiyuan/* Vector vtype */
532f63e7089SHuang Shiyuan
533f63e7089SHuang Shiyuanstatic uint32_t encode_vtype(bool vta, bool vma,
534f63e7089SHuang Shiyuan                            MemOp vsew, RISCVVlmul vlmul)
535f63e7089SHuang Shiyuan{
536f63e7089SHuang Shiyuan    return vma << 7 | vta << 6 | vsew << 3 | vlmul;
537f63e7089SHuang Shiyuan}
538f63e7089SHuang Shiyuan
539f63e7089SHuang Shiyuanstatic int32_t encode_vset(RISCVInsn opc, TCGReg rd,
540f63e7089SHuang Shiyuan                           TCGArg rs1, uint32_t vtype)
541f63e7089SHuang Shiyuan{
542f63e7089SHuang Shiyuan    return opc | (rd & 0x1f) << 7 | (rs1 & 0x1f) << 15 | (vtype & 0x7ff) << 20;
543f63e7089SHuang Shiyuan}
544f63e7089SHuang Shiyuan
545f63e7089SHuang Shiyuanstatic int32_t encode_vseti(RISCVInsn opc, TCGReg rd,
546f63e7089SHuang Shiyuan                            uint32_t uimm, uint32_t vtype)
547f63e7089SHuang Shiyuan{
548f63e7089SHuang Shiyuan    return opc | (rd & 0x1f) << 7 | (uimm & 0x1f) << 15 | (vtype & 0x3ff) << 20;
549f63e7089SHuang Shiyuan}
550f63e7089SHuang Shiyuan
551139c1837SPaolo Bonzini/*
552139c1837SPaolo Bonzini * RISC-V instruction emitters
553139c1837SPaolo Bonzini */
554139c1837SPaolo Bonzini
555139c1837SPaolo Bonzinistatic void tcg_out_opc_reg(TCGContext *s, RISCVInsn opc,
556139c1837SPaolo Bonzini                            TCGReg rd, TCGReg rs1, TCGReg rs2)
557139c1837SPaolo Bonzini{
558139c1837SPaolo Bonzini    tcg_out32(s, encode_r(opc, rd, rs1, rs2));
559139c1837SPaolo Bonzini}
560139c1837SPaolo Bonzini
561139c1837SPaolo Bonzinistatic void tcg_out_opc_imm(TCGContext *s, RISCVInsn opc,
562139c1837SPaolo Bonzini                            TCGReg rd, TCGReg rs1, TCGArg imm)
563139c1837SPaolo Bonzini{
564139c1837SPaolo Bonzini    tcg_out32(s, encode_i(opc, rd, rs1, imm));
565139c1837SPaolo Bonzini}
566139c1837SPaolo Bonzini
567139c1837SPaolo Bonzinistatic void tcg_out_opc_store(TCGContext *s, RISCVInsn opc,
568139c1837SPaolo Bonzini                              TCGReg rs1, TCGReg rs2, uint32_t imm)
569139c1837SPaolo Bonzini{
570139c1837SPaolo Bonzini    tcg_out32(s, encode_s(opc, rs1, rs2, imm));
571139c1837SPaolo Bonzini}
572139c1837SPaolo Bonzini
573139c1837SPaolo Bonzinistatic void tcg_out_opc_branch(TCGContext *s, RISCVInsn opc,
574139c1837SPaolo Bonzini                               TCGReg rs1, TCGReg rs2, uint32_t imm)
575139c1837SPaolo Bonzini{
576139c1837SPaolo Bonzini    tcg_out32(s, encode_sb(opc, rs1, rs2, imm));
577139c1837SPaolo Bonzini}
578139c1837SPaolo Bonzini
579139c1837SPaolo Bonzinistatic void tcg_out_opc_upper(TCGContext *s, RISCVInsn opc,
580139c1837SPaolo Bonzini                              TCGReg rd, uint32_t imm)
581139c1837SPaolo Bonzini{
582139c1837SPaolo Bonzini    tcg_out32(s, encode_u(opc, rd, imm));
583139c1837SPaolo Bonzini}
584139c1837SPaolo Bonzini
585139c1837SPaolo Bonzinistatic void tcg_out_opc_jump(TCGContext *s, RISCVInsn opc,
586139c1837SPaolo Bonzini                             TCGReg rd, uint32_t imm)
587139c1837SPaolo Bonzini{
588139c1837SPaolo Bonzini    tcg_out32(s, encode_uj(opc, rd, imm));
589139c1837SPaolo Bonzini}
590139c1837SPaolo Bonzini
591139c1837SPaolo Bonzinistatic void tcg_out_nop_fill(tcg_insn_unit *p, int count)
592139c1837SPaolo Bonzini{
593139c1837SPaolo Bonzini    int i;
594139c1837SPaolo Bonzini    for (i = 0; i < count; ++i) {
5959ae958e4SRichard Henderson        p[i] = OPC_NOP;
596139c1837SPaolo Bonzini    }
597139c1837SPaolo Bonzini}
598139c1837SPaolo Bonzini
599139c1837SPaolo Bonzini/*
600139c1837SPaolo Bonzini * Relocations
601139c1837SPaolo Bonzini */
602139c1837SPaolo Bonzini
603793f7381SRichard Hendersonstatic bool reloc_sbimm12(tcg_insn_unit *src_rw, const tcg_insn_unit *target)
604139c1837SPaolo Bonzini{
605793f7381SRichard Henderson    const tcg_insn_unit *src_rx = tcg_splitwx_to_rx(src_rw);
606793f7381SRichard Henderson    intptr_t offset = (intptr_t)target - (intptr_t)src_rx;
607139c1837SPaolo Bonzini
608844d0442SRichard Henderson    tcg_debug_assert((offset & 1) == 0);
609844d0442SRichard Henderson    if (offset == sextreg(offset, 0, 12)) {
610793f7381SRichard Henderson        *src_rw |= encode_sbimm12(offset);
611139c1837SPaolo Bonzini        return true;
612139c1837SPaolo Bonzini    }
613139c1837SPaolo Bonzini
614139c1837SPaolo Bonzini    return false;
615139c1837SPaolo Bonzini}
616139c1837SPaolo Bonzini
617793f7381SRichard Hendersonstatic bool reloc_jimm20(tcg_insn_unit *src_rw, const tcg_insn_unit *target)
618139c1837SPaolo Bonzini{
619793f7381SRichard Henderson    const tcg_insn_unit *src_rx = tcg_splitwx_to_rx(src_rw);
620793f7381SRichard Henderson    intptr_t offset = (intptr_t)target - (intptr_t)src_rx;
621139c1837SPaolo Bonzini
622844d0442SRichard Henderson    tcg_debug_assert((offset & 1) == 0);
623844d0442SRichard Henderson    if (offset == sextreg(offset, 0, 20)) {
624793f7381SRichard Henderson        *src_rw |= encode_ujimm20(offset);
625139c1837SPaolo Bonzini        return true;
626139c1837SPaolo Bonzini    }
627139c1837SPaolo Bonzini
628139c1837SPaolo Bonzini    return false;
629139c1837SPaolo Bonzini}
630139c1837SPaolo Bonzini
631793f7381SRichard Hendersonstatic bool reloc_call(tcg_insn_unit *src_rw, const tcg_insn_unit *target)
632139c1837SPaolo Bonzini{
633793f7381SRichard Henderson    const tcg_insn_unit *src_rx = tcg_splitwx_to_rx(src_rw);
634793f7381SRichard Henderson    intptr_t offset = (intptr_t)target - (intptr_t)src_rx;
635139c1837SPaolo Bonzini    int32_t lo = sextreg(offset, 0, 12);
636139c1837SPaolo Bonzini    int32_t hi = offset - lo;
637139c1837SPaolo Bonzini
638139c1837SPaolo Bonzini    if (offset == hi + lo) {
639793f7381SRichard Henderson        src_rw[0] |= encode_uimm20(hi);
640793f7381SRichard Henderson        src_rw[1] |= encode_imm12(lo);
641139c1837SPaolo Bonzini        return true;
642139c1837SPaolo Bonzini    }
643139c1837SPaolo Bonzini
644139c1837SPaolo Bonzini    return false;
645139c1837SPaolo Bonzini}
646139c1837SPaolo Bonzini
647139c1837SPaolo Bonzinistatic bool patch_reloc(tcg_insn_unit *code_ptr, int type,
648139c1837SPaolo Bonzini                        intptr_t value, intptr_t addend)
649139c1837SPaolo Bonzini{
650139c1837SPaolo Bonzini    tcg_debug_assert(addend == 0);
651139c1837SPaolo Bonzini    switch (type) {
652139c1837SPaolo Bonzini    case R_RISCV_BRANCH:
653139c1837SPaolo Bonzini        return reloc_sbimm12(code_ptr, (tcg_insn_unit *)value);
654139c1837SPaolo Bonzini    case R_RISCV_JAL:
655139c1837SPaolo Bonzini        return reloc_jimm20(code_ptr, (tcg_insn_unit *)value);
656139c1837SPaolo Bonzini    case R_RISCV_CALL:
657139c1837SPaolo Bonzini        return reloc_call(code_ptr, (tcg_insn_unit *)value);
658139c1837SPaolo Bonzini    default:
6594b6a52d0SRichard Henderson        g_assert_not_reached();
660139c1837SPaolo Bonzini    }
661139c1837SPaolo Bonzini}
662139c1837SPaolo Bonzini
663139c1837SPaolo Bonzini/*
664f63e7089SHuang Shiyuan * RISC-V vector instruction emitters
665f63e7089SHuang Shiyuan */
666f63e7089SHuang Shiyuan
667d4be6ee1STANG Tiancheng/*
668d4be6ee1STANG Tiancheng * Vector registers uses the same 5 lower bits as GPR registers,
669d4be6ee1STANG Tiancheng * and vm=0 (vm = false) means vector masking ENABLED.
670d4be6ee1STANG Tiancheng * With RVV 1.0, vs2 is the first operand, while rs1/imm is the
671d4be6ee1STANG Tiancheng * second operand.
672d4be6ee1STANG Tiancheng */
6735a63f599STANG Tianchengstatic void tcg_out_opc_vv(TCGContext *s, RISCVInsn opc,
6745a63f599STANG Tiancheng                           TCGReg vd, TCGReg vs2, TCGReg vs1)
6755a63f599STANG Tiancheng{
6765a63f599STANG Tiancheng    tcg_out32(s, encode_v(opc, vd, vs1, vs2, true));
6775a63f599STANG Tiancheng}
6785a63f599STANG Tiancheng
679d4be6ee1STANG Tianchengstatic void tcg_out_opc_vx(TCGContext *s, RISCVInsn opc,
680d4be6ee1STANG Tiancheng                           TCGReg vd, TCGReg vs2, TCGReg rs1)
681d4be6ee1STANG Tiancheng{
682d4be6ee1STANG Tiancheng    tcg_out32(s, encode_v(opc, vd, rs1, vs2, true));
683d4be6ee1STANG Tiancheng}
684d4be6ee1STANG Tiancheng
685d4be6ee1STANG Tianchengstatic void tcg_out_opc_vi(TCGContext *s, RISCVInsn opc,
686d4be6ee1STANG Tiancheng                           TCGReg vd, TCGReg vs2, int32_t imm)
687d4be6ee1STANG Tiancheng{
688d4be6ee1STANG Tiancheng    tcg_out32(s, encode_vi(opc, vd, imm, vs2, true));
689d4be6ee1STANG Tiancheng}
690d4be6ee1STANG Tiancheng
6915a63f599STANG Tianchengstatic void tcg_out_opc_vv_vi(TCGContext *s, RISCVInsn o_vv, RISCVInsn o_vi,
6925a63f599STANG Tiancheng                              TCGReg vd, TCGReg vs2, TCGArg vi1, int c_vi1)
6935a63f599STANG Tiancheng{
6945a63f599STANG Tiancheng    if (c_vi1) {
6955a63f599STANG Tiancheng        tcg_out_opc_vi(s, o_vi, vd, vs2, vi1);
6965a63f599STANG Tiancheng    } else {
6975a63f599STANG Tiancheng        tcg_out_opc_vv(s, o_vv, vd, vs2, vi1);
6985a63f599STANG Tiancheng    }
6995a63f599STANG Tiancheng}
7005a63f599STANG Tiancheng
701a31768c0STANG Tianchengstatic void tcg_out_opc_vim_mask(TCGContext *s, RISCVInsn opc, TCGReg vd,
702a31768c0STANG Tiancheng                                 TCGReg vs2, int32_t imm)
703a31768c0STANG Tiancheng{
704a31768c0STANG Tiancheng    tcg_out32(s, encode_vi(opc, vd, imm, vs2, false));
705a31768c0STANG Tiancheng}
706a31768c0STANG Tiancheng
707a31768c0STANG Tianchengstatic void tcg_out_opc_vvm_mask(TCGContext *s, RISCVInsn opc, TCGReg vd,
708a31768c0STANG Tiancheng                                 TCGReg vs2, TCGReg vs1)
709a31768c0STANG Tiancheng{
710a31768c0STANG Tiancheng    tcg_out32(s, encode_v(opc, vd, vs1, vs2, false));
711a31768c0STANG Tiancheng}
712a31768c0STANG Tiancheng
713f63e7089SHuang Shiyuantypedef struct VsetCache {
714f63e7089SHuang Shiyuan    uint32_t movi_insn;
715f63e7089SHuang Shiyuan    uint32_t vset_insn;
716f63e7089SHuang Shiyuan} VsetCache;
717f63e7089SHuang Shiyuan
718f63e7089SHuang Shiyuanstatic VsetCache riscv_vset_cache[3][4];
719f63e7089SHuang Shiyuan
720f63e7089SHuang Shiyuanstatic void set_vtype(TCGContext *s, TCGType type, MemOp vsew)
721f63e7089SHuang Shiyuan{
722f63e7089SHuang Shiyuan    const VsetCache *p = &riscv_vset_cache[type - TCG_TYPE_V64][vsew];
723f63e7089SHuang Shiyuan
724f63e7089SHuang Shiyuan    s->riscv_cur_type = type;
725f63e7089SHuang Shiyuan    s->riscv_cur_vsew = vsew;
726f63e7089SHuang Shiyuan
727f63e7089SHuang Shiyuan    if (p->movi_insn) {
728f63e7089SHuang Shiyuan        tcg_out32(s, p->movi_insn);
729f63e7089SHuang Shiyuan    }
730f63e7089SHuang Shiyuan    tcg_out32(s, p->vset_insn);
731f63e7089SHuang Shiyuan}
732f63e7089SHuang Shiyuan
733f63e7089SHuang Shiyuanstatic MemOp set_vtype_len(TCGContext *s, TCGType type)
734f63e7089SHuang Shiyuan{
735f63e7089SHuang Shiyuan    if (type != s->riscv_cur_type) {
736f63e7089SHuang Shiyuan        set_vtype(s, type, MO_64);
737f63e7089SHuang Shiyuan    }
738f63e7089SHuang Shiyuan    return s->riscv_cur_vsew;
739f63e7089SHuang Shiyuan}
740f63e7089SHuang Shiyuan
741d4be6ee1STANG Tianchengstatic void set_vtype_len_sew(TCGContext *s, TCGType type, MemOp vsew)
742d4be6ee1STANG Tiancheng{
743d4be6ee1STANG Tiancheng    if (type != s->riscv_cur_type || vsew != s->riscv_cur_vsew) {
744d4be6ee1STANG Tiancheng        set_vtype(s, type, vsew);
745d4be6ee1STANG Tiancheng    }
746d4be6ee1STANG Tiancheng}
747d4be6ee1STANG Tiancheng
748f63e7089SHuang Shiyuan/*
749139c1837SPaolo Bonzini * TCG intrinsics
750139c1837SPaolo Bonzini */
751139c1837SPaolo Bonzini
752139c1837SPaolo Bonzinistatic bool tcg_out_mov(TCGContext *s, TCGType type, TCGReg ret, TCGReg arg)
753139c1837SPaolo Bonzini{
754139c1837SPaolo Bonzini    if (ret == arg) {
755139c1837SPaolo Bonzini        return true;
756139c1837SPaolo Bonzini    }
757139c1837SPaolo Bonzini    switch (type) {
758139c1837SPaolo Bonzini    case TCG_TYPE_I32:
759139c1837SPaolo Bonzini    case TCG_TYPE_I64:
760139c1837SPaolo Bonzini        tcg_out_opc_imm(s, OPC_ADDI, ret, arg, 0);
761139c1837SPaolo Bonzini        break;
762d4be6ee1STANG Tiancheng    case TCG_TYPE_V64:
763d4be6ee1STANG Tiancheng    case TCG_TYPE_V128:
764d4be6ee1STANG Tiancheng    case TCG_TYPE_V256:
765d4be6ee1STANG Tiancheng        {
766d4be6ee1STANG Tiancheng            int lmul = type - riscv_lg2_vlenb;
767d4be6ee1STANG Tiancheng            int nf = 1 << MAX(lmul, 0);
768d4be6ee1STANG Tiancheng            tcg_out_opc_vi(s, OPC_VMVNR_V, ret, arg, nf - 1);
769d4be6ee1STANG Tiancheng        }
770d4be6ee1STANG Tiancheng        break;
771139c1837SPaolo Bonzini    default:
772139c1837SPaolo Bonzini        g_assert_not_reached();
773139c1837SPaolo Bonzini    }
774139c1837SPaolo Bonzini    return true;
775139c1837SPaolo Bonzini}
776139c1837SPaolo Bonzini
777139c1837SPaolo Bonzinistatic void tcg_out_movi(TCGContext *s, TCGType type, TCGReg rd,
778139c1837SPaolo Bonzini                         tcg_target_long val)
779139c1837SPaolo Bonzini{
780139c1837SPaolo Bonzini    tcg_target_long lo, hi, tmp;
781139c1837SPaolo Bonzini    int shift, ret;
782139c1837SPaolo Bonzini
783aeb6326eSRichard Henderson    if (type == TCG_TYPE_I32) {
784139c1837SPaolo Bonzini        val = (int32_t)val;
785139c1837SPaolo Bonzini    }
786139c1837SPaolo Bonzini
787139c1837SPaolo Bonzini    lo = sextreg(val, 0, 12);
788139c1837SPaolo Bonzini    if (val == lo) {
789139c1837SPaolo Bonzini        tcg_out_opc_imm(s, OPC_ADDI, rd, TCG_REG_ZERO, lo);
790139c1837SPaolo Bonzini        return;
791139c1837SPaolo Bonzini    }
792139c1837SPaolo Bonzini
793139c1837SPaolo Bonzini    hi = val - lo;
794aeb6326eSRichard Henderson    if (val == (int32_t)val) {
795139c1837SPaolo Bonzini        tcg_out_opc_upper(s, OPC_LUI, rd, hi);
796139c1837SPaolo Bonzini        if (lo != 0) {
797139c1837SPaolo Bonzini            tcg_out_opc_imm(s, OPC_ADDIW, rd, rd, lo);
798139c1837SPaolo Bonzini        }
799139c1837SPaolo Bonzini        return;
800139c1837SPaolo Bonzini    }
801139c1837SPaolo Bonzini
802139c1837SPaolo Bonzini    tmp = tcg_pcrel_diff(s, (void *)val);
803139c1837SPaolo Bonzini    if (tmp == (int32_t)tmp) {
804139c1837SPaolo Bonzini        tcg_out_opc_upper(s, OPC_AUIPC, rd, 0);
805139c1837SPaolo Bonzini        tcg_out_opc_imm(s, OPC_ADDI, rd, rd, 0);
806793f7381SRichard Henderson        ret = reloc_call(s->code_ptr - 2, (const tcg_insn_unit *)val);
807139c1837SPaolo Bonzini        tcg_debug_assert(ret == true);
808139c1837SPaolo Bonzini        return;
809139c1837SPaolo Bonzini    }
810139c1837SPaolo Bonzini
811139c1837SPaolo Bonzini    /* Look for a single 20-bit section.  */
812139c1837SPaolo Bonzini    shift = ctz64(val);
813139c1837SPaolo Bonzini    tmp = val >> shift;
814139c1837SPaolo Bonzini    if (tmp == sextreg(tmp, 0, 20)) {
815139c1837SPaolo Bonzini        tcg_out_opc_upper(s, OPC_LUI, rd, tmp << 12);
816139c1837SPaolo Bonzini        if (shift > 12) {
817139c1837SPaolo Bonzini            tcg_out_opc_imm(s, OPC_SLLI, rd, rd, shift - 12);
818139c1837SPaolo Bonzini        } else {
819139c1837SPaolo Bonzini            tcg_out_opc_imm(s, OPC_SRAI, rd, rd, 12 - shift);
820139c1837SPaolo Bonzini        }
821139c1837SPaolo Bonzini        return;
822139c1837SPaolo Bonzini    }
823139c1837SPaolo Bonzini
824139c1837SPaolo Bonzini    /* Look for a few high zero bits, with lots of bits set in the middle.  */
825139c1837SPaolo Bonzini    shift = clz64(val);
826139c1837SPaolo Bonzini    tmp = val << shift;
827139c1837SPaolo Bonzini    if (tmp == sextreg(tmp, 12, 20) << 12) {
828139c1837SPaolo Bonzini        tcg_out_opc_upper(s, OPC_LUI, rd, tmp);
829139c1837SPaolo Bonzini        tcg_out_opc_imm(s, OPC_SRLI, rd, rd, shift);
830139c1837SPaolo Bonzini        return;
831139c1837SPaolo Bonzini    } else if (tmp == sextreg(tmp, 0, 12)) {
832139c1837SPaolo Bonzini        tcg_out_opc_imm(s, OPC_ADDI, rd, TCG_REG_ZERO, tmp);
833139c1837SPaolo Bonzini        tcg_out_opc_imm(s, OPC_SRLI, rd, rd, shift);
834139c1837SPaolo Bonzini        return;
835139c1837SPaolo Bonzini    }
836139c1837SPaolo Bonzini
837139c1837SPaolo Bonzini    /* Drop into the constant pool.  */
838139c1837SPaolo Bonzini    new_pool_label(s, val, R_RISCV_CALL, s->code_ptr, 0);
839139c1837SPaolo Bonzini    tcg_out_opc_upper(s, OPC_AUIPC, rd, 0);
840139c1837SPaolo Bonzini    tcg_out_opc_imm(s, OPC_LD, rd, rd, 0);
841139c1837SPaolo Bonzini}
842139c1837SPaolo Bonzini
843767c2503SRichard Hendersonstatic bool tcg_out_xchg(TCGContext *s, TCGType type, TCGReg r1, TCGReg r2)
844767c2503SRichard Henderson{
845767c2503SRichard Henderson    return false;
846767c2503SRichard Henderson}
847767c2503SRichard Henderson
8486a6d772eSRichard Hendersonstatic void tcg_out_addi_ptr(TCGContext *s, TCGReg rd, TCGReg rs,
8496a6d772eSRichard Henderson                             tcg_target_long imm)
8506a6d772eSRichard Henderson{
8516a6d772eSRichard Henderson    /* This function is only used for passing structs by reference. */
8526a6d772eSRichard Henderson    g_assert_not_reached();
8536a6d772eSRichard Henderson}
8546a6d772eSRichard Henderson
855139c1837SPaolo Bonzinistatic void tcg_out_ext8u(TCGContext *s, TCGReg ret, TCGReg arg)
856139c1837SPaolo Bonzini{
857139c1837SPaolo Bonzini    tcg_out_opc_imm(s, OPC_ANDI, ret, arg, 0xff);
858139c1837SPaolo Bonzini}
859139c1837SPaolo Bonzini
860139c1837SPaolo Bonzinistatic void tcg_out_ext16u(TCGContext *s, TCGReg ret, TCGReg arg)
861139c1837SPaolo Bonzini{
862b86c6ba6SRichard Henderson    if (cpuinfo & CPUINFO_ZBB) {
863d1c3f4e9SRichard Henderson        tcg_out_opc_reg(s, OPC_ZEXT_H, ret, arg, TCG_REG_ZERO);
864d1c3f4e9SRichard Henderson    } else {
865139c1837SPaolo Bonzini        tcg_out_opc_imm(s, OPC_SLLIW, ret, arg, 16);
866139c1837SPaolo Bonzini        tcg_out_opc_imm(s, OPC_SRLIW, ret, ret, 16);
867139c1837SPaolo Bonzini    }
868d1c3f4e9SRichard Henderson}
869139c1837SPaolo Bonzini
870139c1837SPaolo Bonzinistatic void tcg_out_ext32u(TCGContext *s, TCGReg ret, TCGReg arg)
871139c1837SPaolo Bonzini{
872b86c6ba6SRichard Henderson    if (cpuinfo & CPUINFO_ZBA) {
873d1c3f4e9SRichard Henderson        tcg_out_opc_reg(s, OPC_ADD_UW, ret, arg, TCG_REG_ZERO);
874d1c3f4e9SRichard Henderson    } else {
875139c1837SPaolo Bonzini        tcg_out_opc_imm(s, OPC_SLLI, ret, arg, 32);
876139c1837SPaolo Bonzini        tcg_out_opc_imm(s, OPC_SRLI, ret, ret, 32);
877139c1837SPaolo Bonzini    }
878d1c3f4e9SRichard Henderson}
879139c1837SPaolo Bonzini
880678155b2SRichard Hendersonstatic void tcg_out_ext8s(TCGContext *s, TCGType type, TCGReg ret, TCGReg arg)
881139c1837SPaolo Bonzini{
882b86c6ba6SRichard Henderson    if (cpuinfo & CPUINFO_ZBB) {
883d1c3f4e9SRichard Henderson        tcg_out_opc_imm(s, OPC_SEXT_B, ret, arg, 0);
884d1c3f4e9SRichard Henderson    } else {
885139c1837SPaolo Bonzini        tcg_out_opc_imm(s, OPC_SLLIW, ret, arg, 24);
886139c1837SPaolo Bonzini        tcg_out_opc_imm(s, OPC_SRAIW, ret, ret, 24);
887139c1837SPaolo Bonzini    }
888d1c3f4e9SRichard Henderson}
889139c1837SPaolo Bonzini
890753e42eaSRichard Hendersonstatic void tcg_out_ext16s(TCGContext *s, TCGType type, TCGReg ret, TCGReg arg)
891139c1837SPaolo Bonzini{
892b86c6ba6SRichard Henderson    if (cpuinfo & CPUINFO_ZBB) {
893d1c3f4e9SRichard Henderson        tcg_out_opc_imm(s, OPC_SEXT_H, ret, arg, 0);
894d1c3f4e9SRichard Henderson    } else {
895139c1837SPaolo Bonzini        tcg_out_opc_imm(s, OPC_SLLIW, ret, arg, 16);
896139c1837SPaolo Bonzini        tcg_out_opc_imm(s, OPC_SRAIW, ret, ret, 16);
897139c1837SPaolo Bonzini    }
898d1c3f4e9SRichard Henderson}
899139c1837SPaolo Bonzini
900139c1837SPaolo Bonzinistatic void tcg_out_ext32s(TCGContext *s, TCGReg ret, TCGReg arg)
901139c1837SPaolo Bonzini{
902139c1837SPaolo Bonzini    tcg_out_opc_imm(s, OPC_ADDIW, ret, arg, 0);
903139c1837SPaolo Bonzini}
904139c1837SPaolo Bonzini
9059c6aa274SRichard Hendersonstatic void tcg_out_exts_i32_i64(TCGContext *s, TCGReg ret, TCGReg arg)
9069c6aa274SRichard Henderson{
9073ea9be33SRichard Henderson    if (ret != arg) {
9089c6aa274SRichard Henderson        tcg_out_ext32s(s, ret, arg);
9099c6aa274SRichard Henderson    }
9103ea9be33SRichard Henderson}
9119c6aa274SRichard Henderson
912b9bfe000SRichard Hendersonstatic void tcg_out_extu_i32_i64(TCGContext *s, TCGReg ret, TCGReg arg)
913b9bfe000SRichard Henderson{
914b9bfe000SRichard Henderson    tcg_out_ext32u(s, ret, arg);
915b9bfe000SRichard Henderson}
916b9bfe000SRichard Henderson
917b8b94ac6SRichard Hendersonstatic void tcg_out_extrl_i64_i32(TCGContext *s, TCGReg ret, TCGReg arg)
918b8b94ac6SRichard Henderson{
919b8b94ac6SRichard Henderson    tcg_out_ext32s(s, ret, arg);
920b8b94ac6SRichard Henderson}
921b8b94ac6SRichard Henderson
922139c1837SPaolo Bonzinistatic void tcg_out_ldst(TCGContext *s, RISCVInsn opc, TCGReg data,
923139c1837SPaolo Bonzini                         TCGReg addr, intptr_t offset)
924139c1837SPaolo Bonzini{
925139c1837SPaolo Bonzini    intptr_t imm12 = sextreg(offset, 0, 12);
926139c1837SPaolo Bonzini
927139c1837SPaolo Bonzini    if (offset != imm12) {
9289d9db413SRichard Henderson        intptr_t diff = tcg_pcrel_diff(s, (void *)offset);
929139c1837SPaolo Bonzini
930139c1837SPaolo Bonzini        if (addr == TCG_REG_ZERO && diff == (int32_t)diff) {
931139c1837SPaolo Bonzini            imm12 = sextreg(diff, 0, 12);
932139c1837SPaolo Bonzini            tcg_out_opc_upper(s, OPC_AUIPC, TCG_REG_TMP2, diff - imm12);
933139c1837SPaolo Bonzini        } else {
934139c1837SPaolo Bonzini            tcg_out_movi(s, TCG_TYPE_PTR, TCG_REG_TMP2, offset - imm12);
935139c1837SPaolo Bonzini            if (addr != TCG_REG_ZERO) {
936139c1837SPaolo Bonzini                tcg_out_opc_reg(s, OPC_ADD, TCG_REG_TMP2, TCG_REG_TMP2, addr);
937139c1837SPaolo Bonzini            }
938139c1837SPaolo Bonzini        }
939139c1837SPaolo Bonzini        addr = TCG_REG_TMP2;
940139c1837SPaolo Bonzini    }
941139c1837SPaolo Bonzini
942139c1837SPaolo Bonzini    switch (opc) {
943139c1837SPaolo Bonzini    case OPC_SB:
944139c1837SPaolo Bonzini    case OPC_SH:
945139c1837SPaolo Bonzini    case OPC_SW:
946139c1837SPaolo Bonzini    case OPC_SD:
947139c1837SPaolo Bonzini        tcg_out_opc_store(s, opc, addr, data, imm12);
948139c1837SPaolo Bonzini        break;
949139c1837SPaolo Bonzini    case OPC_LB:
950139c1837SPaolo Bonzini    case OPC_LBU:
951139c1837SPaolo Bonzini    case OPC_LH:
952139c1837SPaolo Bonzini    case OPC_LHU:
953139c1837SPaolo Bonzini    case OPC_LW:
954139c1837SPaolo Bonzini    case OPC_LWU:
955139c1837SPaolo Bonzini    case OPC_LD:
956139c1837SPaolo Bonzini        tcg_out_opc_imm(s, opc, data, addr, imm12);
957139c1837SPaolo Bonzini        break;
958139c1837SPaolo Bonzini    default:
959139c1837SPaolo Bonzini        g_assert_not_reached();
960139c1837SPaolo Bonzini    }
961139c1837SPaolo Bonzini}
962139c1837SPaolo Bonzini
963f63e7089SHuang Shiyuanstatic void tcg_out_vec_ldst(TCGContext *s, RISCVInsn opc, TCGReg data,
964f63e7089SHuang Shiyuan                             TCGReg addr, intptr_t offset)
965f63e7089SHuang Shiyuan{
966f63e7089SHuang Shiyuan    tcg_debug_assert(data >= TCG_REG_V0);
967f63e7089SHuang Shiyuan    tcg_debug_assert(addr < TCG_REG_V0);
968f63e7089SHuang Shiyuan
969f63e7089SHuang Shiyuan    if (offset) {
970f63e7089SHuang Shiyuan        tcg_debug_assert(addr != TCG_REG_ZERO);
971f63e7089SHuang Shiyuan        if (offset == sextreg(offset, 0, 12)) {
972f63e7089SHuang Shiyuan            tcg_out_opc_imm(s, OPC_ADDI, TCG_REG_TMP0, addr, offset);
973f63e7089SHuang Shiyuan        } else {
974f63e7089SHuang Shiyuan            tcg_out_movi(s, TCG_TYPE_PTR, TCG_REG_TMP0, offset);
975f63e7089SHuang Shiyuan            tcg_out_opc_reg(s, OPC_ADD, TCG_REG_TMP0, TCG_REG_TMP0, addr);
976f63e7089SHuang Shiyuan        }
977f63e7089SHuang Shiyuan        addr = TCG_REG_TMP0;
978f63e7089SHuang Shiyuan    }
979f63e7089SHuang Shiyuan    tcg_out32(s, encode_v(opc, data, addr, 0, true));
980f63e7089SHuang Shiyuan}
981f63e7089SHuang Shiyuan
982139c1837SPaolo Bonzinistatic void tcg_out_ld(TCGContext *s, TCGType type, TCGReg arg,
983139c1837SPaolo Bonzini                       TCGReg arg1, intptr_t arg2)
984139c1837SPaolo Bonzini{
985f63e7089SHuang Shiyuan    RISCVInsn insn;
986f63e7089SHuang Shiyuan
987f63e7089SHuang Shiyuan    switch (type) {
988f63e7089SHuang Shiyuan    case TCG_TYPE_I32:
989f63e7089SHuang Shiyuan        tcg_out_ldst(s, OPC_LW, arg, arg1, arg2);
990f63e7089SHuang Shiyuan        break;
991f63e7089SHuang Shiyuan    case TCG_TYPE_I64:
992f63e7089SHuang Shiyuan        tcg_out_ldst(s, OPC_LD, arg, arg1, arg2);
993f63e7089SHuang Shiyuan        break;
994f63e7089SHuang Shiyuan    case TCG_TYPE_V64:
995f63e7089SHuang Shiyuan    case TCG_TYPE_V128:
996f63e7089SHuang Shiyuan    case TCG_TYPE_V256:
997f63e7089SHuang Shiyuan        if (type >= riscv_lg2_vlenb) {
998f63e7089SHuang Shiyuan            static const RISCVInsn whole_reg_ld[] = {
999f63e7089SHuang Shiyuan                OPC_VL1RE64_V, OPC_VL2RE64_V, OPC_VL4RE64_V, OPC_VL8RE64_V
1000f63e7089SHuang Shiyuan            };
1001f63e7089SHuang Shiyuan            unsigned idx = type - riscv_lg2_vlenb;
1002f63e7089SHuang Shiyuan
1003f63e7089SHuang Shiyuan            tcg_debug_assert(idx < ARRAY_SIZE(whole_reg_ld));
1004f63e7089SHuang Shiyuan            insn = whole_reg_ld[idx];
1005f63e7089SHuang Shiyuan        } else {
1006f63e7089SHuang Shiyuan            static const RISCVInsn unit_stride_ld[] = {
1007f63e7089SHuang Shiyuan                OPC_VLE8_V, OPC_VLE16_V, OPC_VLE32_V, OPC_VLE64_V
1008f63e7089SHuang Shiyuan            };
1009f63e7089SHuang Shiyuan            MemOp prev_vsew = set_vtype_len(s, type);
1010f63e7089SHuang Shiyuan
1011f63e7089SHuang Shiyuan            tcg_debug_assert(prev_vsew < ARRAY_SIZE(unit_stride_ld));
1012f63e7089SHuang Shiyuan            insn = unit_stride_ld[prev_vsew];
1013f63e7089SHuang Shiyuan        }
1014f63e7089SHuang Shiyuan        tcg_out_vec_ldst(s, insn, arg, arg1, arg2);
1015f63e7089SHuang Shiyuan        break;
1016f63e7089SHuang Shiyuan    default:
1017f63e7089SHuang Shiyuan        g_assert_not_reached();
1018f63e7089SHuang Shiyuan    }
1019139c1837SPaolo Bonzini}
1020139c1837SPaolo Bonzini
1021139c1837SPaolo Bonzinistatic void tcg_out_st(TCGContext *s, TCGType type, TCGReg arg,
1022139c1837SPaolo Bonzini                       TCGReg arg1, intptr_t arg2)
1023139c1837SPaolo Bonzini{
1024f63e7089SHuang Shiyuan    RISCVInsn insn;
1025f63e7089SHuang Shiyuan
1026f63e7089SHuang Shiyuan    switch (type) {
1027f63e7089SHuang Shiyuan    case TCG_TYPE_I32:
1028f63e7089SHuang Shiyuan        tcg_out_ldst(s, OPC_SW, arg, arg1, arg2);
1029f63e7089SHuang Shiyuan        break;
1030f63e7089SHuang Shiyuan    case TCG_TYPE_I64:
1031f63e7089SHuang Shiyuan        tcg_out_ldst(s, OPC_SD, arg, arg1, arg2);
1032f63e7089SHuang Shiyuan        break;
1033f63e7089SHuang Shiyuan    case TCG_TYPE_V64:
1034f63e7089SHuang Shiyuan    case TCG_TYPE_V128:
1035f63e7089SHuang Shiyuan    case TCG_TYPE_V256:
1036f63e7089SHuang Shiyuan        if (type >= riscv_lg2_vlenb) {
1037f63e7089SHuang Shiyuan            static const RISCVInsn whole_reg_st[] = {
1038f63e7089SHuang Shiyuan                OPC_VS1R_V, OPC_VS2R_V, OPC_VS4R_V, OPC_VS8R_V
1039f63e7089SHuang Shiyuan            };
1040f63e7089SHuang Shiyuan            unsigned idx = type - riscv_lg2_vlenb;
1041f63e7089SHuang Shiyuan
1042f63e7089SHuang Shiyuan            tcg_debug_assert(idx < ARRAY_SIZE(whole_reg_st));
1043f63e7089SHuang Shiyuan            insn = whole_reg_st[idx];
1044f63e7089SHuang Shiyuan        } else {
1045f63e7089SHuang Shiyuan            static const RISCVInsn unit_stride_st[] = {
1046f63e7089SHuang Shiyuan                OPC_VSE8_V, OPC_VSE16_V, OPC_VSE32_V, OPC_VSE64_V
1047f63e7089SHuang Shiyuan            };
1048f63e7089SHuang Shiyuan            MemOp prev_vsew = set_vtype_len(s, type);
1049f63e7089SHuang Shiyuan
1050f63e7089SHuang Shiyuan            tcg_debug_assert(prev_vsew < ARRAY_SIZE(unit_stride_st));
1051f63e7089SHuang Shiyuan            insn = unit_stride_st[prev_vsew];
1052f63e7089SHuang Shiyuan        }
1053f63e7089SHuang Shiyuan        tcg_out_vec_ldst(s, insn, arg, arg1, arg2);
1054f63e7089SHuang Shiyuan        break;
1055f63e7089SHuang Shiyuan    default:
1056f63e7089SHuang Shiyuan        g_assert_not_reached();
1057f63e7089SHuang Shiyuan    }
1058139c1837SPaolo Bonzini}
1059139c1837SPaolo Bonzini
1060139c1837SPaolo Bonzinistatic bool tcg_out_sti(TCGContext *s, TCGType type, TCGArg val,
1061139c1837SPaolo Bonzini                        TCGReg base, intptr_t ofs)
1062139c1837SPaolo Bonzini{
1063139c1837SPaolo Bonzini    if (val == 0) {
1064139c1837SPaolo Bonzini        tcg_out_st(s, type, TCG_REG_ZERO, base, ofs);
1065139c1837SPaolo Bonzini        return true;
1066139c1837SPaolo Bonzini    }
1067139c1837SPaolo Bonzini    return false;
1068139c1837SPaolo Bonzini}
1069139c1837SPaolo Bonzini
1070139c1837SPaolo Bonzinistatic void tcg_out_addsub2(TCGContext *s,
1071139c1837SPaolo Bonzini                            TCGReg rl, TCGReg rh,
1072139c1837SPaolo Bonzini                            TCGReg al, TCGReg ah,
1073139c1837SPaolo Bonzini                            TCGArg bl, TCGArg bh,
1074139c1837SPaolo Bonzini                            bool cbl, bool cbh, bool is_sub, bool is32bit)
1075139c1837SPaolo Bonzini{
1076139c1837SPaolo Bonzini    const RISCVInsn opc_add = is32bit ? OPC_ADDW : OPC_ADD;
1077139c1837SPaolo Bonzini    const RISCVInsn opc_addi = is32bit ? OPC_ADDIW : OPC_ADDI;
1078139c1837SPaolo Bonzini    const RISCVInsn opc_sub = is32bit ? OPC_SUBW : OPC_SUB;
1079139c1837SPaolo Bonzini    TCGReg th = TCG_REG_TMP1;
1080139c1837SPaolo Bonzini
1081139c1837SPaolo Bonzini    /* If we have a negative constant such that negating it would
1082139c1837SPaolo Bonzini       make the high part zero, we can (usually) eliminate one insn.  */
1083139c1837SPaolo Bonzini    if (cbl && cbh && bh == -1 && bl != 0) {
1084139c1837SPaolo Bonzini        bl = -bl;
1085139c1837SPaolo Bonzini        bh = 0;
1086139c1837SPaolo Bonzini        is_sub = !is_sub;
1087139c1837SPaolo Bonzini    }
1088139c1837SPaolo Bonzini
1089139c1837SPaolo Bonzini    /* By operating on the high part first, we get to use the final
1090139c1837SPaolo Bonzini       carry operation to move back from the temporary.  */
1091139c1837SPaolo Bonzini    if (!cbh) {
1092139c1837SPaolo Bonzini        tcg_out_opc_reg(s, (is_sub ? opc_sub : opc_add), th, ah, bh);
1093139c1837SPaolo Bonzini    } else if (bh != 0 || ah == rl) {
1094139c1837SPaolo Bonzini        tcg_out_opc_imm(s, opc_addi, th, ah, (is_sub ? -bh : bh));
1095139c1837SPaolo Bonzini    } else {
1096139c1837SPaolo Bonzini        th = ah;
1097139c1837SPaolo Bonzini    }
1098139c1837SPaolo Bonzini
1099139c1837SPaolo Bonzini    /* Note that tcg optimization should eliminate the bl == 0 case.  */
1100139c1837SPaolo Bonzini    if (is_sub) {
1101139c1837SPaolo Bonzini        if (cbl) {
1102139c1837SPaolo Bonzini            tcg_out_opc_imm(s, OPC_SLTIU, TCG_REG_TMP0, al, bl);
1103139c1837SPaolo Bonzini            tcg_out_opc_imm(s, opc_addi, rl, al, -bl);
1104139c1837SPaolo Bonzini        } else {
1105139c1837SPaolo Bonzini            tcg_out_opc_reg(s, OPC_SLTU, TCG_REG_TMP0, al, bl);
1106139c1837SPaolo Bonzini            tcg_out_opc_reg(s, opc_sub, rl, al, bl);
1107139c1837SPaolo Bonzini        }
1108139c1837SPaolo Bonzini        tcg_out_opc_reg(s, opc_sub, rh, th, TCG_REG_TMP0);
1109139c1837SPaolo Bonzini    } else {
1110139c1837SPaolo Bonzini        if (cbl) {
1111139c1837SPaolo Bonzini            tcg_out_opc_imm(s, opc_addi, rl, al, bl);
1112139c1837SPaolo Bonzini            tcg_out_opc_imm(s, OPC_SLTIU, TCG_REG_TMP0, rl, bl);
11139b246685SRichard Henderson        } else if (al == bl) {
11149b246685SRichard Henderson            /*
11159b246685SRichard Henderson             * If the input regs overlap, this is a simple doubling
11169b246685SRichard Henderson             * and carry-out is the input msb.  This special case is
11179b246685SRichard Henderson             * required when the output reg overlaps the input,
11189b246685SRichard Henderson             * but we might as well use it always.
11199b246685SRichard Henderson             */
1120139c1837SPaolo Bonzini            tcg_out_opc_imm(s, OPC_SLTI, TCG_REG_TMP0, al, 0);
11219b246685SRichard Henderson            tcg_out_opc_reg(s, opc_add, rl, al, al);
1122139c1837SPaolo Bonzini        } else {
1123139c1837SPaolo Bonzini            tcg_out_opc_reg(s, opc_add, rl, al, bl);
1124139c1837SPaolo Bonzini            tcg_out_opc_reg(s, OPC_SLTU, TCG_REG_TMP0,
1125139c1837SPaolo Bonzini                            rl, (rl == bl ? al : bl));
1126139c1837SPaolo Bonzini        }
1127139c1837SPaolo Bonzini        tcg_out_opc_reg(s, opc_add, rh, th, TCG_REG_TMP0);
1128139c1837SPaolo Bonzini    }
1129139c1837SPaolo Bonzini}
1130139c1837SPaolo Bonzini
1131f63e7089SHuang Shiyuanstatic bool tcg_out_dup_vec(TCGContext *s, TCGType type, unsigned vece,
1132f63e7089SHuang Shiyuan                                   TCGReg dst, TCGReg src)
1133f63e7089SHuang Shiyuan{
1134d4be6ee1STANG Tiancheng    set_vtype_len_sew(s, type, vece);
1135d4be6ee1STANG Tiancheng    tcg_out_opc_vx(s, OPC_VMV_V_X, dst, 0, src);
1136d4be6ee1STANG Tiancheng    return true;
1137f63e7089SHuang Shiyuan}
1138f63e7089SHuang Shiyuan
1139f63e7089SHuang Shiyuanstatic bool tcg_out_dupm_vec(TCGContext *s, TCGType type, unsigned vece,
1140f63e7089SHuang Shiyuan                                    TCGReg dst, TCGReg base, intptr_t offset)
1141f63e7089SHuang Shiyuan{
1142d4be6ee1STANG Tiancheng    tcg_out_ld(s, TCG_TYPE_REG, TCG_REG_TMP0, base, offset);
1143d4be6ee1STANG Tiancheng    return tcg_out_dup_vec(s, type, vece, dst, TCG_REG_TMP0);
1144f63e7089SHuang Shiyuan}
1145f63e7089SHuang Shiyuan
1146f63e7089SHuang Shiyuanstatic void tcg_out_dupi_vec(TCGContext *s, TCGType type, unsigned vece,
1147f63e7089SHuang Shiyuan                                    TCGReg dst, int64_t arg)
1148f63e7089SHuang Shiyuan{
1149d4be6ee1STANG Tiancheng    /* Arg is replicated by VECE; extract the highest element. */
1150d4be6ee1STANG Tiancheng    arg >>= (-8 << vece) & 63;
1151d4be6ee1STANG Tiancheng
1152d4be6ee1STANG Tiancheng    if (arg >= -16 && arg < 16) {
1153d4be6ee1STANG Tiancheng        if (arg == 0 || arg == -1) {
1154d4be6ee1STANG Tiancheng            set_vtype_len(s, type);
1155d4be6ee1STANG Tiancheng        } else {
1156d4be6ee1STANG Tiancheng            set_vtype_len_sew(s, type, vece);
1157d4be6ee1STANG Tiancheng        }
1158d4be6ee1STANG Tiancheng        tcg_out_opc_vi(s, OPC_VMV_V_I, dst, 0, arg);
1159d4be6ee1STANG Tiancheng        return;
1160d4be6ee1STANG Tiancheng    }
1161d4be6ee1STANG Tiancheng    tcg_out_movi(s, TCG_TYPE_I64, TCG_REG_TMP0, arg);
1162d4be6ee1STANG Tiancheng    tcg_out_dup_vec(s, type, vece, dst, TCG_REG_TMP0);
1163f63e7089SHuang Shiyuan}
1164f63e7089SHuang Shiyuan
1165139c1837SPaolo Bonzinistatic const struct {
1166139c1837SPaolo Bonzini    RISCVInsn op;
1167139c1837SPaolo Bonzini    bool swap;
1168139c1837SPaolo Bonzini} tcg_brcond_to_riscv[] = {
1169139c1837SPaolo Bonzini    [TCG_COND_EQ] =  { OPC_BEQ,  false },
1170139c1837SPaolo Bonzini    [TCG_COND_NE] =  { OPC_BNE,  false },
1171139c1837SPaolo Bonzini    [TCG_COND_LT] =  { OPC_BLT,  false },
1172139c1837SPaolo Bonzini    [TCG_COND_GE] =  { OPC_BGE,  false },
1173139c1837SPaolo Bonzini    [TCG_COND_LE] =  { OPC_BGE,  true  },
1174139c1837SPaolo Bonzini    [TCG_COND_GT] =  { OPC_BLT,  true  },
1175139c1837SPaolo Bonzini    [TCG_COND_LTU] = { OPC_BLTU, false },
1176139c1837SPaolo Bonzini    [TCG_COND_GEU] = { OPC_BGEU, false },
1177139c1837SPaolo Bonzini    [TCG_COND_LEU] = { OPC_BGEU, true  },
1178139c1837SPaolo Bonzini    [TCG_COND_GTU] = { OPC_BLTU, true  }
1179139c1837SPaolo Bonzini};
1180139c1837SPaolo Bonzini
1181139c1837SPaolo Bonzinistatic void tcg_out_brcond(TCGContext *s, TCGCond cond, TCGReg arg1,
1182139c1837SPaolo Bonzini                           TCGReg arg2, TCGLabel *l)
1183139c1837SPaolo Bonzini{
1184139c1837SPaolo Bonzini    RISCVInsn op = tcg_brcond_to_riscv[cond].op;
1185139c1837SPaolo Bonzini
1186139c1837SPaolo Bonzini    tcg_debug_assert(op != 0);
1187139c1837SPaolo Bonzini
1188139c1837SPaolo Bonzini    if (tcg_brcond_to_riscv[cond].swap) {
1189139c1837SPaolo Bonzini        TCGReg t = arg1;
1190139c1837SPaolo Bonzini        arg1 = arg2;
1191139c1837SPaolo Bonzini        arg2 = t;
1192139c1837SPaolo Bonzini    }
1193139c1837SPaolo Bonzini
1194139c1837SPaolo Bonzini    tcg_out_reloc(s, s->code_ptr, R_RISCV_BRANCH, l, 0);
1195139c1837SPaolo Bonzini    tcg_out_opc_branch(s, op, arg1, arg2, 0);
1196139c1837SPaolo Bonzini}
1197139c1837SPaolo Bonzini
1198f6453695SRichard Henderson#define SETCOND_INV    TCG_TARGET_NB_REGS
1199f6453695SRichard Henderson#define SETCOND_NEZ    (SETCOND_INV << 1)
1200f6453695SRichard Henderson#define SETCOND_FLAGS  (SETCOND_INV | SETCOND_NEZ)
1201f6453695SRichard Henderson
1202f6453695SRichard Hendersonstatic int tcg_out_setcond_int(TCGContext *s, TCGCond cond, TCGReg ret,
1203f6453695SRichard Henderson                               TCGReg arg1, tcg_target_long arg2, bool c2)
1204139c1837SPaolo Bonzini{
1205f6453695SRichard Henderson    int flags = 0;
1206f6453695SRichard Henderson
1207139c1837SPaolo Bonzini    switch (cond) {
1208f6453695SRichard Henderson    case TCG_COND_EQ:    /* -> NE  */
1209f6453695SRichard Henderson    case TCG_COND_GE:    /* -> LT  */
1210f6453695SRichard Henderson    case TCG_COND_GEU:   /* -> LTU */
1211f6453695SRichard Henderson    case TCG_COND_GT:    /* -> LE  */
1212f6453695SRichard Henderson    case TCG_COND_GTU:   /* -> LEU */
1213f6453695SRichard Henderson        cond = tcg_invert_cond(cond);
1214f6453695SRichard Henderson        flags ^= SETCOND_INV;
1215139c1837SPaolo Bonzini        break;
1216f6453695SRichard Henderson    default:
1217139c1837SPaolo Bonzini        break;
1218f6453695SRichard Henderson    }
1219f6453695SRichard Henderson
1220f6453695SRichard Henderson    switch (cond) {
1221139c1837SPaolo Bonzini    case TCG_COND_LE:
1222139c1837SPaolo Bonzini    case TCG_COND_LEU:
1223f6453695SRichard Henderson        /*
1224f6453695SRichard Henderson         * If we have a constant input, the most efficient way to implement
1225f6453695SRichard Henderson         * LE is by adding 1 and using LT.  Watch out for wrap around for LEU.
1226f6453695SRichard Henderson         * We don't need to care for this for LE because the constant input
1227f6453695SRichard Henderson         * is constrained to signed 12-bit, and 0x800 is representable in the
1228f6453695SRichard Henderson         * temporary register.
1229f6453695SRichard Henderson         */
1230f6453695SRichard Henderson        if (c2) {
1231f6453695SRichard Henderson            if (cond == TCG_COND_LEU) {
1232f6453695SRichard Henderson                /* unsigned <= -1 is true */
1233f6453695SRichard Henderson                if (arg2 == -1) {
1234f6453695SRichard Henderson                    tcg_out_movi(s, TCG_TYPE_REG, ret, !(flags & SETCOND_INV));
1235f6453695SRichard Henderson                    return ret;
1236f6453695SRichard Henderson                }
1237f6453695SRichard Henderson                cond = TCG_COND_LTU;
1238f6453695SRichard Henderson            } else {
1239f6453695SRichard Henderson                cond = TCG_COND_LT;
1240f6453695SRichard Henderson            }
1241f6453695SRichard Henderson            tcg_debug_assert(arg2 <= 0x7ff);
1242f6453695SRichard Henderson            if (++arg2 == 0x800) {
1243f6453695SRichard Henderson                tcg_out_movi(s, TCG_TYPE_REG, TCG_REG_TMP0, arg2);
1244f6453695SRichard Henderson                arg2 = TCG_REG_TMP0;
1245f6453695SRichard Henderson                c2 = false;
1246f6453695SRichard Henderson            }
1247f6453695SRichard Henderson        } else {
1248f6453695SRichard Henderson            TCGReg tmp = arg2;
1249f6453695SRichard Henderson            arg2 = arg1;
1250f6453695SRichard Henderson            arg1 = tmp;
1251f6453695SRichard Henderson            cond = tcg_swap_cond(cond);    /* LE -> GE */
1252f6453695SRichard Henderson            cond = tcg_invert_cond(cond);  /* GE -> LT */
1253f6453695SRichard Henderson            flags ^= SETCOND_INV;
1254f6453695SRichard Henderson        }
1255139c1837SPaolo Bonzini        break;
1256f6453695SRichard Henderson    default:
1257f6453695SRichard Henderson        break;
1258f6453695SRichard Henderson    }
1259f6453695SRichard Henderson
1260f6453695SRichard Henderson    switch (cond) {
1261f6453695SRichard Henderson    case TCG_COND_NE:
1262f6453695SRichard Henderson        flags |= SETCOND_NEZ;
1263f6453695SRichard Henderson        if (!c2) {
1264f6453695SRichard Henderson            tcg_out_opc_reg(s, OPC_XOR, ret, arg1, arg2);
1265f6453695SRichard Henderson        } else if (arg2 == 0) {
1266f6453695SRichard Henderson            ret = arg1;
1267f6453695SRichard Henderson        } else {
1268f6453695SRichard Henderson            tcg_out_opc_imm(s, OPC_XORI, ret, arg1, arg2);
1269f6453695SRichard Henderson        }
1270f6453695SRichard Henderson        break;
1271f6453695SRichard Henderson
1272f6453695SRichard Henderson    case TCG_COND_LT:
1273f6453695SRichard Henderson        if (c2) {
1274f6453695SRichard Henderson            tcg_out_opc_imm(s, OPC_SLTI, ret, arg1, arg2);
1275f6453695SRichard Henderson        } else {
1276f6453695SRichard Henderson            tcg_out_opc_reg(s, OPC_SLT, ret, arg1, arg2);
1277f6453695SRichard Henderson        }
1278f6453695SRichard Henderson        break;
1279f6453695SRichard Henderson
1280f6453695SRichard Henderson    case TCG_COND_LTU:
1281f6453695SRichard Henderson        if (c2) {
1282f6453695SRichard Henderson            tcg_out_opc_imm(s, OPC_SLTIU, ret, arg1, arg2);
1283f6453695SRichard Henderson        } else {
1284f6453695SRichard Henderson            tcg_out_opc_reg(s, OPC_SLTU, ret, arg1, arg2);
1285f6453695SRichard Henderson        }
1286f6453695SRichard Henderson        break;
1287f6453695SRichard Henderson
1288f6453695SRichard Henderson    default:
1289f6453695SRichard Henderson        g_assert_not_reached();
1290f6453695SRichard Henderson    }
1291f6453695SRichard Henderson
1292f6453695SRichard Henderson    return ret | flags;
1293f6453695SRichard Henderson}
1294f6453695SRichard Henderson
1295f6453695SRichard Hendersonstatic void tcg_out_setcond(TCGContext *s, TCGCond cond, TCGReg ret,
1296f6453695SRichard Henderson                            TCGReg arg1, tcg_target_long arg2, bool c2)
1297f6453695SRichard Henderson{
1298f6453695SRichard Henderson    int tmpflags = tcg_out_setcond_int(s, cond, ret, arg1, arg2, c2);
1299f6453695SRichard Henderson
1300f6453695SRichard Henderson    if (tmpflags != ret) {
1301f6453695SRichard Henderson        TCGReg tmp = tmpflags & ~SETCOND_FLAGS;
1302f6453695SRichard Henderson
1303f6453695SRichard Henderson        switch (tmpflags & SETCOND_FLAGS) {
1304f6453695SRichard Henderson        case SETCOND_INV:
1305f6453695SRichard Henderson            /* Intermediate result is boolean: simply invert. */
1306f6453695SRichard Henderson            tcg_out_opc_imm(s, OPC_XORI, ret, tmp, 1);
1307f6453695SRichard Henderson            break;
1308f6453695SRichard Henderson        case SETCOND_NEZ:
1309f6453695SRichard Henderson            /* Intermediate result is zero/non-zero: test != 0. */
1310f6453695SRichard Henderson            tcg_out_opc_reg(s, OPC_SLTU, ret, TCG_REG_ZERO, tmp);
1311f6453695SRichard Henderson            break;
1312f6453695SRichard Henderson        case SETCOND_NEZ | SETCOND_INV:
1313f6453695SRichard Henderson            /* Intermediate result is zero/non-zero: test == 0. */
1314f6453695SRichard Henderson            tcg_out_opc_imm(s, OPC_SLTIU, ret, tmp, 1);
1315139c1837SPaolo Bonzini            break;
1316139c1837SPaolo Bonzini        default:
1317139c1837SPaolo Bonzini            g_assert_not_reached();
1318f6453695SRichard Henderson        }
1319139c1837SPaolo Bonzini    }
1320139c1837SPaolo Bonzini}
1321139c1837SPaolo Bonzini
132241e4c0a9SRichard Hendersonstatic void tcg_out_negsetcond(TCGContext *s, TCGCond cond, TCGReg ret,
132341e4c0a9SRichard Henderson                               TCGReg arg1, tcg_target_long arg2, bool c2)
132441e4c0a9SRichard Henderson{
132541e4c0a9SRichard Henderson    int tmpflags;
132641e4c0a9SRichard Henderson    TCGReg tmp;
132741e4c0a9SRichard Henderson
132841e4c0a9SRichard Henderson    /* For LT/GE comparison against 0, replicate the sign bit. */
132941e4c0a9SRichard Henderson    if (c2 && arg2 == 0) {
133041e4c0a9SRichard Henderson        switch (cond) {
133141e4c0a9SRichard Henderson        case TCG_COND_GE:
133241e4c0a9SRichard Henderson            tcg_out_opc_imm(s, OPC_XORI, ret, arg1, -1);
133341e4c0a9SRichard Henderson            arg1 = ret;
133441e4c0a9SRichard Henderson            /* fall through */
133541e4c0a9SRichard Henderson        case TCG_COND_LT:
133641e4c0a9SRichard Henderson            tcg_out_opc_imm(s, OPC_SRAI, ret, arg1, TCG_TARGET_REG_BITS - 1);
133741e4c0a9SRichard Henderson            return;
133841e4c0a9SRichard Henderson        default:
133941e4c0a9SRichard Henderson            break;
134041e4c0a9SRichard Henderson        }
134141e4c0a9SRichard Henderson    }
134241e4c0a9SRichard Henderson
134341e4c0a9SRichard Henderson    tmpflags = tcg_out_setcond_int(s, cond, ret, arg1, arg2, c2);
134441e4c0a9SRichard Henderson    tmp = tmpflags & ~SETCOND_FLAGS;
134541e4c0a9SRichard Henderson
134641e4c0a9SRichard Henderson    /* If intermediate result is zero/non-zero: test != 0. */
134741e4c0a9SRichard Henderson    if (tmpflags & SETCOND_NEZ) {
134841e4c0a9SRichard Henderson        tcg_out_opc_reg(s, OPC_SLTU, ret, TCG_REG_ZERO, tmp);
134941e4c0a9SRichard Henderson        tmp = ret;
135041e4c0a9SRichard Henderson    }
135141e4c0a9SRichard Henderson
135241e4c0a9SRichard Henderson    /* Produce the 0/-1 result. */
135341e4c0a9SRichard Henderson    if (tmpflags & SETCOND_INV) {
135441e4c0a9SRichard Henderson        tcg_out_opc_imm(s, OPC_ADDI, ret, tmp, -1);
135541e4c0a9SRichard Henderson    } else {
135641e4c0a9SRichard Henderson        tcg_out_opc_reg(s, OPC_SUB, ret, TCG_REG_ZERO, tmp);
135741e4c0a9SRichard Henderson    }
135841e4c0a9SRichard Henderson}
135941e4c0a9SRichard Henderson
1360a18d783eSRichard Hendersonstatic void tcg_out_movcond_zicond(TCGContext *s, TCGReg ret, TCGReg test_ne,
1361a18d783eSRichard Henderson                                   int val1, bool c_val1,
1362a18d783eSRichard Henderson                                   int val2, bool c_val2)
1363a18d783eSRichard Henderson{
1364a18d783eSRichard Henderson    if (val1 == 0) {
1365a18d783eSRichard Henderson        if (c_val2) {
1366a18d783eSRichard Henderson            tcg_out_movi(s, TCG_TYPE_REG, TCG_REG_TMP1, val2);
1367a18d783eSRichard Henderson            val2 = TCG_REG_TMP1;
1368a18d783eSRichard Henderson        }
1369a18d783eSRichard Henderson        tcg_out_opc_reg(s, OPC_CZERO_NEZ, ret, val2, test_ne);
1370a18d783eSRichard Henderson        return;
1371a18d783eSRichard Henderson    }
1372a18d783eSRichard Henderson
1373a18d783eSRichard Henderson    if (val2 == 0) {
1374a18d783eSRichard Henderson        if (c_val1) {
1375a18d783eSRichard Henderson            tcg_out_movi(s, TCG_TYPE_REG, TCG_REG_TMP1, val1);
1376a18d783eSRichard Henderson            val1 = TCG_REG_TMP1;
1377a18d783eSRichard Henderson        }
1378a18d783eSRichard Henderson        tcg_out_opc_reg(s, OPC_CZERO_EQZ, ret, val1, test_ne);
1379a18d783eSRichard Henderson        return;
1380a18d783eSRichard Henderson    }
1381a18d783eSRichard Henderson
1382a18d783eSRichard Henderson    if (c_val2) {
1383a18d783eSRichard Henderson        if (c_val1) {
1384a18d783eSRichard Henderson            tcg_out_movi(s, TCG_TYPE_REG, TCG_REG_TMP1, val1 - val2);
1385a18d783eSRichard Henderson        } else {
1386a18d783eSRichard Henderson            tcg_out_opc_imm(s, OPC_ADDI, TCG_REG_TMP1, val1, -val2);
1387a18d783eSRichard Henderson        }
1388a18d783eSRichard Henderson        tcg_out_opc_reg(s, OPC_CZERO_EQZ, ret, TCG_REG_TMP1, test_ne);
1389a18d783eSRichard Henderson        tcg_out_opc_imm(s, OPC_ADDI, ret, ret, val2);
1390a18d783eSRichard Henderson        return;
1391a18d783eSRichard Henderson    }
1392a18d783eSRichard Henderson
1393a18d783eSRichard Henderson    if (c_val1) {
1394a18d783eSRichard Henderson        tcg_out_opc_imm(s, OPC_ADDI, TCG_REG_TMP1, val2, -val1);
1395a18d783eSRichard Henderson        tcg_out_opc_reg(s, OPC_CZERO_NEZ, ret, TCG_REG_TMP1, test_ne);
1396a18d783eSRichard Henderson        tcg_out_opc_imm(s, OPC_ADDI, ret, ret, val1);
1397a18d783eSRichard Henderson        return;
1398a18d783eSRichard Henderson    }
1399a18d783eSRichard Henderson
1400a18d783eSRichard Henderson    tcg_out_opc_reg(s, OPC_CZERO_NEZ, TCG_REG_TMP1, val2, test_ne);
1401a18d783eSRichard Henderson    tcg_out_opc_reg(s, OPC_CZERO_EQZ, TCG_REG_TMP0, val1, test_ne);
1402a18d783eSRichard Henderson    tcg_out_opc_reg(s, OPC_OR, ret, TCG_REG_TMP0, TCG_REG_TMP1);
1403a18d783eSRichard Henderson}
1404a18d783eSRichard Henderson
1405a18d783eSRichard Hendersonstatic void tcg_out_movcond_br1(TCGContext *s, TCGCond cond, TCGReg ret,
1406a18d783eSRichard Henderson                                TCGReg cmp1, TCGReg cmp2,
1407a18d783eSRichard Henderson                                int val, bool c_val)
1408a18d783eSRichard Henderson{
1409a18d783eSRichard Henderson    RISCVInsn op;
1410a18d783eSRichard Henderson    int disp = 8;
1411a18d783eSRichard Henderson
1412a18d783eSRichard Henderson    tcg_debug_assert((unsigned)cond < ARRAY_SIZE(tcg_brcond_to_riscv));
1413a18d783eSRichard Henderson    op = tcg_brcond_to_riscv[cond].op;
1414a18d783eSRichard Henderson    tcg_debug_assert(op != 0);
1415a18d783eSRichard Henderson
1416a18d783eSRichard Henderson    if (tcg_brcond_to_riscv[cond].swap) {
1417a18d783eSRichard Henderson        tcg_out_opc_branch(s, op, cmp2, cmp1, disp);
1418a18d783eSRichard Henderson    } else {
1419a18d783eSRichard Henderson        tcg_out_opc_branch(s, op, cmp1, cmp2, disp);
1420a18d783eSRichard Henderson    }
1421a18d783eSRichard Henderson    if (c_val) {
1422a18d783eSRichard Henderson        tcg_out_opc_imm(s, OPC_ADDI, ret, TCG_REG_ZERO, val);
1423a18d783eSRichard Henderson    } else {
1424a18d783eSRichard Henderson        tcg_out_opc_imm(s, OPC_ADDI, ret, val, 0);
1425a18d783eSRichard Henderson    }
1426a18d783eSRichard Henderson}
1427a18d783eSRichard Henderson
1428a18d783eSRichard Hendersonstatic void tcg_out_movcond_br2(TCGContext *s, TCGCond cond, TCGReg ret,
1429a18d783eSRichard Henderson                                TCGReg cmp1, TCGReg cmp2,
1430a18d783eSRichard Henderson                                int val1, bool c_val1,
1431a18d783eSRichard Henderson                                int val2, bool c_val2)
1432a18d783eSRichard Henderson{
1433a18d783eSRichard Henderson    TCGReg tmp;
1434a18d783eSRichard Henderson
1435a18d783eSRichard Henderson    /* TCG optimizer reorders to prefer ret matching val2. */
1436a18d783eSRichard Henderson    if (!c_val2 && ret == val2) {
1437a18d783eSRichard Henderson        cond = tcg_invert_cond(cond);
1438a18d783eSRichard Henderson        tcg_out_movcond_br1(s, cond, ret, cmp1, cmp2, val1, c_val1);
1439a18d783eSRichard Henderson        return;
1440a18d783eSRichard Henderson    }
1441a18d783eSRichard Henderson
1442a18d783eSRichard Henderson    if (!c_val1 && ret == val1) {
1443a18d783eSRichard Henderson        tcg_out_movcond_br1(s, cond, ret, cmp1, cmp2, val2, c_val2);
1444a18d783eSRichard Henderson        return;
1445a18d783eSRichard Henderson    }
1446a18d783eSRichard Henderson
1447a18d783eSRichard Henderson    tmp = (ret == cmp1 || ret == cmp2 ? TCG_REG_TMP1 : ret);
1448a18d783eSRichard Henderson    if (c_val1) {
1449a18d783eSRichard Henderson        tcg_out_movi(s, TCG_TYPE_REG, tmp, val1);
1450a18d783eSRichard Henderson    } else {
1451a18d783eSRichard Henderson        tcg_out_mov(s, TCG_TYPE_REG, tmp, val1);
1452a18d783eSRichard Henderson    }
1453a18d783eSRichard Henderson    tcg_out_movcond_br1(s, cond, tmp, cmp1, cmp2, val2, c_val2);
1454a18d783eSRichard Henderson    tcg_out_mov(s, TCG_TYPE_REG, ret, tmp);
1455a18d783eSRichard Henderson}
1456a18d783eSRichard Henderson
1457a18d783eSRichard Hendersonstatic void tcg_out_movcond(TCGContext *s, TCGCond cond, TCGReg ret,
1458a18d783eSRichard Henderson                            TCGReg cmp1, int cmp2, bool c_cmp2,
1459a18d783eSRichard Henderson                            TCGReg val1, bool c_val1,
1460a18d783eSRichard Henderson                            TCGReg val2, bool c_val2)
1461a18d783eSRichard Henderson{
1462a18d783eSRichard Henderson    int tmpflags;
1463a18d783eSRichard Henderson    TCGReg t;
1464a18d783eSRichard Henderson
1465b86c6ba6SRichard Henderson    if (!(cpuinfo & CPUINFO_ZICOND) && (!c_cmp2 || cmp2 == 0)) {
1466a18d783eSRichard Henderson        tcg_out_movcond_br2(s, cond, ret, cmp1, cmp2,
1467a18d783eSRichard Henderson                            val1, c_val1, val2, c_val2);
1468a18d783eSRichard Henderson        return;
1469a18d783eSRichard Henderson    }
1470a18d783eSRichard Henderson
1471a18d783eSRichard Henderson    tmpflags = tcg_out_setcond_int(s, cond, TCG_REG_TMP0, cmp1, cmp2, c_cmp2);
1472a18d783eSRichard Henderson    t = tmpflags & ~SETCOND_FLAGS;
1473a18d783eSRichard Henderson
1474b86c6ba6SRichard Henderson    if (cpuinfo & CPUINFO_ZICOND) {
1475a18d783eSRichard Henderson        if (tmpflags & SETCOND_INV) {
1476a18d783eSRichard Henderson            tcg_out_movcond_zicond(s, ret, t, val2, c_val2, val1, c_val1);
1477a18d783eSRichard Henderson        } else {
1478a18d783eSRichard Henderson            tcg_out_movcond_zicond(s, ret, t, val1, c_val1, val2, c_val2);
1479a18d783eSRichard Henderson        }
1480a18d783eSRichard Henderson    } else {
1481a18d783eSRichard Henderson        cond = tmpflags & SETCOND_INV ? TCG_COND_EQ : TCG_COND_NE;
1482a18d783eSRichard Henderson        tcg_out_movcond_br2(s, cond, ret, t, TCG_REG_ZERO,
1483a18d783eSRichard Henderson                            val1, c_val1, val2, c_val2);
1484a18d783eSRichard Henderson    }
1485a18d783eSRichard Henderson}
1486a18d783eSRichard Henderson
1487a30498fcSRichard Hendersonstatic void tcg_out_cltz(TCGContext *s, TCGType type, RISCVInsn insn,
1488a30498fcSRichard Henderson                         TCGReg ret, TCGReg src1, int src2, bool c_src2)
1489a30498fcSRichard Henderson{
1490a30498fcSRichard Henderson    tcg_out_opc_imm(s, insn, ret, src1, 0);
1491a30498fcSRichard Henderson
1492a30498fcSRichard Henderson    if (!c_src2 || src2 != (type == TCG_TYPE_I32 ? 32 : 64)) {
1493a30498fcSRichard Henderson        /*
1494a30498fcSRichard Henderson         * The requested zero result does not match the insn, so adjust.
1495a30498fcSRichard Henderson         * Note that constraints put 'ret' in a new register, so the
1496a30498fcSRichard Henderson         * computation above did not clobber either 'src1' or 'src2'.
1497a30498fcSRichard Henderson         */
1498a30498fcSRichard Henderson        tcg_out_movcond(s, TCG_COND_EQ, ret, src1, 0, true,
1499a30498fcSRichard Henderson                        src2, c_src2, ret, false);
1500a30498fcSRichard Henderson    }
1501a30498fcSRichard Henderson}
1502a30498fcSRichard Henderson
1503a31768c0STANG Tianchengstatic void tcg_out_cmpsel(TCGContext *s, TCGType type, unsigned vece,
1504a31768c0STANG Tiancheng                           TCGCond cond, TCGReg ret,
1505a31768c0STANG Tiancheng                           TCGReg cmp1, TCGReg cmp2, bool c_cmp2,
1506a31768c0STANG Tiancheng                           TCGReg val1, bool c_val1,
1507a31768c0STANG Tiancheng                           TCGReg val2, bool c_val2)
1508a31768c0STANG Tiancheng{
1509a31768c0STANG Tiancheng    set_vtype_len_sew(s, type, vece);
1510a31768c0STANG Tiancheng
1511a31768c0STANG Tiancheng    /* Use only vmerge_vim if possible, by inverting the test. */
1512a31768c0STANG Tiancheng    if (c_val2 && !c_val1) {
1513a31768c0STANG Tiancheng        TCGArg temp = val1;
1514a31768c0STANG Tiancheng        cond = tcg_invert_cond(cond);
1515a31768c0STANG Tiancheng        val1 = val2;
1516a31768c0STANG Tiancheng        val2 = temp;
1517a31768c0STANG Tiancheng        c_val1 = true;
1518a31768c0STANG Tiancheng        c_val2 = false;
1519a31768c0STANG Tiancheng    }
1520a31768c0STANG Tiancheng
1521a31768c0STANG Tiancheng    /* Perform the comparison into V0 mask. */
1522a31768c0STANG Tiancheng    if (c_cmp2) {
1523a31768c0STANG Tiancheng        tcg_out_opc_vi(s, tcg_cmpcond_to_rvv_vi[cond].op, TCG_REG_V0, cmp1,
1524a31768c0STANG Tiancheng                       cmp2 - tcg_cmpcond_to_rvv_vi[cond].adjust);
1525a31768c0STANG Tiancheng    } else if (tcg_cmpcond_to_rvv_vv[cond].swap) {
1526a31768c0STANG Tiancheng        tcg_out_opc_vv(s, tcg_cmpcond_to_rvv_vv[cond].op,
1527a31768c0STANG Tiancheng                       TCG_REG_V0, cmp2, cmp1);
1528a31768c0STANG Tiancheng    } else {
1529a31768c0STANG Tiancheng        tcg_out_opc_vv(s, tcg_cmpcond_to_rvv_vv[cond].op,
1530a31768c0STANG Tiancheng                       TCG_REG_V0, cmp1, cmp2);
1531a31768c0STANG Tiancheng    }
1532a31768c0STANG Tiancheng    if (c_val1) {
1533a31768c0STANG Tiancheng        if (c_val2) {
1534a31768c0STANG Tiancheng            tcg_out_opc_vi(s, OPC_VMV_V_I, ret, 0, val2);
1535a31768c0STANG Tiancheng            val2 = ret;
1536a31768c0STANG Tiancheng        }
1537a31768c0STANG Tiancheng        /* vd[i] == v0.mask[i] ? imm : vs2[i] */
1538a31768c0STANG Tiancheng        tcg_out_opc_vim_mask(s, OPC_VMERGE_VIM, ret, val2, val1);
1539a31768c0STANG Tiancheng    } else {
1540a31768c0STANG Tiancheng        /* vd[i] == v0.mask[i] ? vs1[i] : vs2[i] */
1541a31768c0STANG Tiancheng        tcg_out_opc_vvm_mask(s, OPC_VMERGE_VVM, ret, val2, val1);
1542a31768c0STANG Tiancheng    }
1543a31768c0STANG Tiancheng}
1544a31768c0STANG Tiancheng
1545f63e7089SHuang Shiyuanstatic void init_setting_vtype(TCGContext *s)
1546f63e7089SHuang Shiyuan{
1547f63e7089SHuang Shiyuan    s->riscv_cur_type = TCG_TYPE_COUNT;
1548f63e7089SHuang Shiyuan}
1549f63e7089SHuang Shiyuan
15502be7d76bSRichard Hendersonstatic void tcg_out_call_int(TCGContext *s, const tcg_insn_unit *arg, bool tail)
1551139c1837SPaolo Bonzini{
1552139c1837SPaolo Bonzini    TCGReg link = tail ? TCG_REG_ZERO : TCG_REG_RA;
1553139c1837SPaolo Bonzini    ptrdiff_t offset = tcg_pcrel_diff(s, arg);
1554139c1837SPaolo Bonzini    int ret;
1555139c1837SPaolo Bonzini
1556f63e7089SHuang Shiyuan    init_setting_vtype(s);
1557f63e7089SHuang Shiyuan
1558844d0442SRichard Henderson    tcg_debug_assert((offset & 1) == 0);
1559844d0442SRichard Henderson    if (offset == sextreg(offset, 0, 20)) {
1560139c1837SPaolo Bonzini        /* short jump: -2097150 to 2097152 */
1561139c1837SPaolo Bonzini        tcg_out_opc_jump(s, OPC_JAL, link, offset);
1562aeb6326eSRichard Henderson    } else if (offset == (int32_t)offset) {
1563139c1837SPaolo Bonzini        /* long jump: -2147483646 to 2147483648 */
1564139c1837SPaolo Bonzini        tcg_out_opc_upper(s, OPC_AUIPC, TCG_REG_TMP0, 0);
1565139c1837SPaolo Bonzini        tcg_out_opc_imm(s, OPC_JALR, link, TCG_REG_TMP0, 0);
1566844d0442SRichard Henderson        ret = reloc_call(s->code_ptr - 2, arg);
1567139c1837SPaolo Bonzini        tcg_debug_assert(ret == true);
1568aeb6326eSRichard Henderson    } else {
1569139c1837SPaolo Bonzini        /* far jump: 64-bit */
1570139c1837SPaolo Bonzini        tcg_target_long imm = sextreg((tcg_target_long)arg, 0, 12);
1571139c1837SPaolo Bonzini        tcg_target_long base = (tcg_target_long)arg - imm;
1572139c1837SPaolo Bonzini        tcg_out_movi(s, TCG_TYPE_PTR, TCG_REG_TMP0, base);
1573139c1837SPaolo Bonzini        tcg_out_opc_imm(s, OPC_JALR, link, TCG_REG_TMP0, imm);
1574139c1837SPaolo Bonzini    }
1575139c1837SPaolo Bonzini}
1576139c1837SPaolo Bonzini
1577cee44b03SRichard Hendersonstatic void tcg_out_call(TCGContext *s, const tcg_insn_unit *arg,
1578cee44b03SRichard Henderson                         const TCGHelperInfo *info)
1579139c1837SPaolo Bonzini{
1580139c1837SPaolo Bonzini    tcg_out_call_int(s, arg, false);
1581139c1837SPaolo Bonzini}
1582139c1837SPaolo Bonzini
1583139c1837SPaolo Bonzinistatic void tcg_out_mb(TCGContext *s, TCGArg a0)
1584139c1837SPaolo Bonzini{
1585139c1837SPaolo Bonzini    tcg_insn_unit insn = OPC_FENCE;
1586139c1837SPaolo Bonzini
1587139c1837SPaolo Bonzini    if (a0 & TCG_MO_LD_LD) {
1588139c1837SPaolo Bonzini        insn |= 0x02200000;
1589139c1837SPaolo Bonzini    }
1590139c1837SPaolo Bonzini    if (a0 & TCG_MO_ST_LD) {
1591139c1837SPaolo Bonzini        insn |= 0x01200000;
1592139c1837SPaolo Bonzini    }
1593139c1837SPaolo Bonzini    if (a0 & TCG_MO_LD_ST) {
1594139c1837SPaolo Bonzini        insn |= 0x02100000;
1595139c1837SPaolo Bonzini    }
1596139c1837SPaolo Bonzini    if (a0 & TCG_MO_ST_ST) {
1597139c1837SPaolo Bonzini        insn |= 0x02200000;
1598139c1837SPaolo Bonzini    }
1599139c1837SPaolo Bonzini    tcg_out32(s, insn);
1600139c1837SPaolo Bonzini}
1601139c1837SPaolo Bonzini
1602139c1837SPaolo Bonzini/*
1603139c1837SPaolo Bonzini * Load/store and TLB
1604139c1837SPaolo Bonzini */
1605139c1837SPaolo Bonzini
1606793f7381SRichard Hendersonstatic void tcg_out_goto(TCGContext *s, const tcg_insn_unit *target)
1607844d0442SRichard Henderson{
1608844d0442SRichard Henderson    tcg_out_opc_jump(s, OPC_JAL, TCG_REG_ZERO, 0);
1609844d0442SRichard Henderson    bool ok = reloc_jimm20(s->code_ptr - 1, target);
1610844d0442SRichard Henderson    tcg_debug_assert(ok);
1611844d0442SRichard Henderson}
1612844d0442SRichard Henderson
16137b880107SRichard Hendersonbool tcg_target_has_memory_bswap(MemOp memop)
16147b880107SRichard Henderson{
16157b880107SRichard Henderson    return false;
16167b880107SRichard Henderson}
16177b880107SRichard Henderson
161861b6daafSRichard Henderson/* We have three temps, we might as well expose them. */
161961b6daafSRichard Hendersonstatic const TCGLdstHelperParam ldst_helper_param = {
162061b6daafSRichard Henderson    .ntmp = 3, .tmp = { TCG_REG_TMP0, TCG_REG_TMP1, TCG_REG_TMP2 }
162161b6daafSRichard Henderson};
162261b6daafSRichard Henderson
1623139c1837SPaolo Bonzinistatic bool tcg_out_qemu_ld_slow_path(TCGContext *s, TCGLabelQemuLdst *l)
1624139c1837SPaolo Bonzini{
162561b6daafSRichard Henderson    MemOp opc = get_memop(l->oi);
1626139c1837SPaolo Bonzini
1627139c1837SPaolo Bonzini    /* resolve label address */
1628793f7381SRichard Henderson    if (!reloc_sbimm12(l->label_ptr[0], tcg_splitwx_to_rx(s->code_ptr))) {
1629139c1837SPaolo Bonzini        return false;
1630139c1837SPaolo Bonzini    }
1631139c1837SPaolo Bonzini
1632139c1837SPaolo Bonzini    /* call load helper */
163361b6daafSRichard Henderson    tcg_out_ld_helper_args(s, l, &ldst_helper_param);
1634cee44b03SRichard Henderson    tcg_out_call_int(s, qemu_ld_helpers[opc & MO_SSIZE], false);
163561b6daafSRichard Henderson    tcg_out_ld_helper_ret(s, l, true, &ldst_helper_param);
1636139c1837SPaolo Bonzini
1637139c1837SPaolo Bonzini    tcg_out_goto(s, l->raddr);
1638139c1837SPaolo Bonzini    return true;
1639139c1837SPaolo Bonzini}
1640139c1837SPaolo Bonzini
1641139c1837SPaolo Bonzinistatic bool tcg_out_qemu_st_slow_path(TCGContext *s, TCGLabelQemuLdst *l)
1642139c1837SPaolo Bonzini{
164361b6daafSRichard Henderson    MemOp opc = get_memop(l->oi);
1644139c1837SPaolo Bonzini
1645139c1837SPaolo Bonzini    /* resolve label address */
1646793f7381SRichard Henderson    if (!reloc_sbimm12(l->label_ptr[0], tcg_splitwx_to_rx(s->code_ptr))) {
1647139c1837SPaolo Bonzini        return false;
1648139c1837SPaolo Bonzini    }
1649139c1837SPaolo Bonzini
1650139c1837SPaolo Bonzini    /* call store helper */
165161b6daafSRichard Henderson    tcg_out_st_helper_args(s, l, &ldst_helper_param);
1652cee44b03SRichard Henderson    tcg_out_call_int(s, qemu_st_helpers[opc & MO_SIZE], false);
1653139c1837SPaolo Bonzini
1654139c1837SPaolo Bonzini    tcg_out_goto(s, l->raddr);
1655139c1837SPaolo Bonzini    return true;
1656139c1837SPaolo Bonzini}
1657139c1837SPaolo Bonzini
1658d0a9bb5eSRichard Henderson/* We expect to use a 12-bit negative offset from ENV.  */
1659d0a9bb5eSRichard Henderson#define MIN_TLB_MASK_TABLE_OFS  -(1 << 11)
1660d0a9bb5eSRichard Henderson
1661001dddfeSRichard Henderson/*
16627893e42dSPhilippe Mathieu-Daudé * For system-mode, perform the TLB load and compare.
16637893e42dSPhilippe Mathieu-Daudé * For user-mode, perform any required alignment tests.
1664001dddfeSRichard Henderson * In both cases, return a TCGLabelQemuLdst structure if the slow path
1665001dddfeSRichard Henderson * is required and fill in @h with the host address for the fast path.
1666001dddfeSRichard Henderson */
1667001dddfeSRichard Hendersonstatic TCGLabelQemuLdst *prepare_host_addr(TCGContext *s, TCGReg *pbase,
1668001dddfeSRichard Henderson                                           TCGReg addr_reg, MemOpIdx oi,
1669001dddfeSRichard Henderson                                           bool is_ld)
1670001dddfeSRichard Henderson{
16718aefe1fbSRichard Henderson    TCGType addr_type = s->addr_type;
1672001dddfeSRichard Henderson    TCGLabelQemuLdst *ldst = NULL;
1673001dddfeSRichard Henderson    MemOp opc = get_memop(oi);
167437e523f0SRichard Henderson    TCGAtomAlign aa;
167537e523f0SRichard Henderson    unsigned a_mask;
167637e523f0SRichard Henderson
167737e523f0SRichard Henderson    aa = atom_and_align_for_opc(s, opc, MO_ATOM_IFALIGN, false);
167837e523f0SRichard Henderson    a_mask = (1u << aa.align) - 1;
1679001dddfeSRichard Henderson
16804944d359SRichard Henderson    if (tcg_use_softmmu) {
1681001dddfeSRichard Henderson        unsigned s_bits = opc & MO_SIZE;
1682933b331bSRichard Henderson        unsigned s_mask = (1u << s_bits) - 1;
1683001dddfeSRichard Henderson        int mem_index = get_mmuidx(oi);
1684d0a9bb5eSRichard Henderson        int fast_ofs = tlb_mask_table_ofs(s, mem_index);
1685001dddfeSRichard Henderson        int mask_ofs = fast_ofs + offsetof(CPUTLBDescFast, mask);
1686001dddfeSRichard Henderson        int table_ofs = fast_ofs + offsetof(CPUTLBDescFast, table);
1687933b331bSRichard Henderson        int compare_mask;
1688933b331bSRichard Henderson        TCGReg addr_adj;
1689001dddfeSRichard Henderson
1690001dddfeSRichard Henderson        ldst = new_ldst_label(s);
1691001dddfeSRichard Henderson        ldst->is_ld = is_ld;
1692001dddfeSRichard Henderson        ldst->oi = oi;
1693001dddfeSRichard Henderson        ldst->addrlo_reg = addr_reg;
1694001dddfeSRichard Henderson
1695f63e7089SHuang Shiyuan        init_setting_vtype(s);
1696f63e7089SHuang Shiyuan
1697933b331bSRichard Henderson        tcg_out_ld(s, TCG_TYPE_PTR, TCG_REG_TMP0, TCG_AREG0, mask_ofs);
1698933b331bSRichard Henderson        tcg_out_ld(s, TCG_TYPE_PTR, TCG_REG_TMP1, TCG_AREG0, table_ofs);
1699001dddfeSRichard Henderson
1700001dddfeSRichard Henderson        tcg_out_opc_imm(s, OPC_SRLI, TCG_REG_TMP2, addr_reg,
1701aece72b7SRichard Henderson                        s->page_bits - CPU_TLB_ENTRY_BITS);
1702001dddfeSRichard Henderson        tcg_out_opc_reg(s, OPC_AND, TCG_REG_TMP2, TCG_REG_TMP2, TCG_REG_TMP0);
1703001dddfeSRichard Henderson        tcg_out_opc_reg(s, OPC_ADD, TCG_REG_TMP2, TCG_REG_TMP2, TCG_REG_TMP1);
1704001dddfeSRichard Henderson
1705933b331bSRichard Henderson        /*
17064944d359SRichard Henderson         * For aligned accesses, we check the first byte and include the
17074944d359SRichard Henderson         * alignment bits within the address.  For unaligned access, we
17084944d359SRichard Henderson         * check that we don't cross pages using the address of the last
17094944d359SRichard Henderson         * byte of the access.
1710933b331bSRichard Henderson         */
1711933b331bSRichard Henderson        addr_adj = addr_reg;
171237e523f0SRichard Henderson        if (a_mask < s_mask) {
1713933b331bSRichard Henderson            addr_adj = TCG_REG_TMP0;
17148aefe1fbSRichard Henderson            tcg_out_opc_imm(s, addr_type == TCG_TYPE_I32 ? OPC_ADDIW : OPC_ADDI,
1715933b331bSRichard Henderson                            addr_adj, addr_reg, s_mask - a_mask);
1716933b331bSRichard Henderson        }
1717aece72b7SRichard Henderson        compare_mask = s->page_mask | a_mask;
1718933b331bSRichard Henderson        if (compare_mask == sextreg(compare_mask, 0, 12)) {
1719933b331bSRichard Henderson            tcg_out_opc_imm(s, OPC_ANDI, TCG_REG_TMP1, addr_adj, compare_mask);
1720933b331bSRichard Henderson        } else {
17218aefe1fbSRichard Henderson            tcg_out_movi(s, addr_type, TCG_REG_TMP1, compare_mask);
1722933b331bSRichard Henderson            tcg_out_opc_reg(s, OPC_AND, TCG_REG_TMP1, TCG_REG_TMP1, addr_adj);
1723933b331bSRichard Henderson        }
1724933b331bSRichard Henderson
1725001dddfeSRichard Henderson        /* Load the tlb comparator and the addend.  */
1726238f4380SRichard Henderson        QEMU_BUILD_BUG_ON(HOST_BIG_ENDIAN);
17278aefe1fbSRichard Henderson        tcg_out_ld(s, addr_type, TCG_REG_TMP0, TCG_REG_TMP2,
1728001dddfeSRichard Henderson                   is_ld ? offsetof(CPUTLBEntry, addr_read)
1729001dddfeSRichard Henderson                         : offsetof(CPUTLBEntry, addr_write));
1730001dddfeSRichard Henderson        tcg_out_ld(s, TCG_TYPE_PTR, TCG_REG_TMP2, TCG_REG_TMP2,
1731001dddfeSRichard Henderson                   offsetof(CPUTLBEntry, addend));
1732001dddfeSRichard Henderson
1733001dddfeSRichard Henderson        /* Compare masked address with the TLB entry. */
1734001dddfeSRichard Henderson        ldst->label_ptr[0] = s->code_ptr;
1735001dddfeSRichard Henderson        tcg_out_opc_branch(s, OPC_BNE, TCG_REG_TMP0, TCG_REG_TMP1, 0);
1736001dddfeSRichard Henderson
1737001dddfeSRichard Henderson        /* TLB Hit - translate address using addend.  */
17388aefe1fbSRichard Henderson        if (addr_type != TCG_TYPE_I32) {
1739eda15159SRichard Henderson            tcg_out_opc_reg(s, OPC_ADD, TCG_REG_TMP0, addr_reg, TCG_REG_TMP2);
1740b86c6ba6SRichard Henderson        } else if (cpuinfo & CPUINFO_ZBA) {
17414944d359SRichard Henderson            tcg_out_opc_reg(s, OPC_ADD_UW, TCG_REG_TMP0,
17424944d359SRichard Henderson                            addr_reg, TCG_REG_TMP2);
1743eda15159SRichard Henderson        } else {
1744eda15159SRichard Henderson            tcg_out_ext32u(s, TCG_REG_TMP0, addr_reg);
17454944d359SRichard Henderson            tcg_out_opc_reg(s, OPC_ADD, TCG_REG_TMP0,
17464944d359SRichard Henderson                            TCG_REG_TMP0, TCG_REG_TMP2);
1747001dddfeSRichard Henderson        }
1748001dddfeSRichard Henderson        *pbase = TCG_REG_TMP0;
17494944d359SRichard Henderson    } else {
1750eda15159SRichard Henderson        TCGReg base;
1751eda15159SRichard Henderson
1752001dddfeSRichard Henderson        if (a_mask) {
1753001dddfeSRichard Henderson            ldst = new_ldst_label(s);
1754001dddfeSRichard Henderson            ldst->is_ld = is_ld;
1755001dddfeSRichard Henderson            ldst->oi = oi;
1756001dddfeSRichard Henderson            ldst->addrlo_reg = addr_reg;
1757001dddfeSRichard Henderson
1758f63e7089SHuang Shiyuan            init_setting_vtype(s);
1759f63e7089SHuang Shiyuan
176037e523f0SRichard Henderson            /* We are expecting alignment max 7, so we can always use andi. */
176137e523f0SRichard Henderson            tcg_debug_assert(a_mask == sextreg(a_mask, 0, 12));
1762001dddfeSRichard Henderson            tcg_out_opc_imm(s, OPC_ANDI, TCG_REG_TMP1, addr_reg, a_mask);
1763001dddfeSRichard Henderson
1764001dddfeSRichard Henderson            ldst->label_ptr[0] = s->code_ptr;
1765001dddfeSRichard Henderson            tcg_out_opc_branch(s, OPC_BNE, TCG_REG_TMP1, TCG_REG_ZERO, 0);
1766001dddfeSRichard Henderson        }
1767001dddfeSRichard Henderson
1768001dddfeSRichard Henderson        if (guest_base != 0) {
1769001dddfeSRichard Henderson            base = TCG_REG_TMP0;
17708aefe1fbSRichard Henderson            if (addr_type != TCG_TYPE_I32) {
17714944d359SRichard Henderson                tcg_out_opc_reg(s, OPC_ADD, base, addr_reg,
17724944d359SRichard Henderson                                TCG_GUEST_BASE_REG);
1773b86c6ba6SRichard Henderson            } else if (cpuinfo & CPUINFO_ZBA) {
17744944d359SRichard Henderson                tcg_out_opc_reg(s, OPC_ADD_UW, base, addr_reg,
17754944d359SRichard Henderson                                TCG_GUEST_BASE_REG);
1776eda15159SRichard Henderson            } else {
1777eda15159SRichard Henderson                tcg_out_ext32u(s, base, addr_reg);
1778eda15159SRichard Henderson                tcg_out_opc_reg(s, OPC_ADD, base, base, TCG_GUEST_BASE_REG);
1779eda15159SRichard Henderson            }
17808aefe1fbSRichard Henderson        } else if (addr_type != TCG_TYPE_I32) {
1781eda15159SRichard Henderson            base = addr_reg;
1782eda15159SRichard Henderson        } else {
1783eda15159SRichard Henderson            base = TCG_REG_TMP0;
1784eda15159SRichard Henderson            tcg_out_ext32u(s, base, addr_reg);
1785001dddfeSRichard Henderson        }
1786001dddfeSRichard Henderson        *pbase = base;
17874944d359SRichard Henderson    }
1788001dddfeSRichard Henderson
1789001dddfeSRichard Henderson    return ldst;
1790001dddfeSRichard Henderson}
1791001dddfeSRichard Henderson
1792aeb6326eSRichard Hendersonstatic void tcg_out_qemu_ld_direct(TCGContext *s, TCGReg val,
1793f7041977SRichard Henderson                                   TCGReg base, MemOp opc, TCGType type)
1794139c1837SPaolo Bonzini{
1795c86bd2dcSRichard Henderson    /* Byte swapping is left to middle-end expansion. */
1796c86bd2dcSRichard Henderson    tcg_debug_assert((opc & MO_BSWAP) == 0);
1797139c1837SPaolo Bonzini
1798139c1837SPaolo Bonzini    switch (opc & (MO_SSIZE)) {
1799139c1837SPaolo Bonzini    case MO_UB:
1800aeb6326eSRichard Henderson        tcg_out_opc_imm(s, OPC_LBU, val, base, 0);
1801139c1837SPaolo Bonzini        break;
1802139c1837SPaolo Bonzini    case MO_SB:
1803aeb6326eSRichard Henderson        tcg_out_opc_imm(s, OPC_LB, val, base, 0);
1804139c1837SPaolo Bonzini        break;
1805139c1837SPaolo Bonzini    case MO_UW:
1806aeb6326eSRichard Henderson        tcg_out_opc_imm(s, OPC_LHU, val, base, 0);
1807139c1837SPaolo Bonzini        break;
1808139c1837SPaolo Bonzini    case MO_SW:
1809aeb6326eSRichard Henderson        tcg_out_opc_imm(s, OPC_LH, val, base, 0);
1810139c1837SPaolo Bonzini        break;
1811139c1837SPaolo Bonzini    case MO_UL:
1812f7041977SRichard Henderson        if (type == TCG_TYPE_I64) {
1813aeb6326eSRichard Henderson            tcg_out_opc_imm(s, OPC_LWU, val, base, 0);
1814139c1837SPaolo Bonzini            break;
1815139c1837SPaolo Bonzini        }
1816139c1837SPaolo Bonzini        /* FALLTHRU */
1817139c1837SPaolo Bonzini    case MO_SL:
1818aeb6326eSRichard Henderson        tcg_out_opc_imm(s, OPC_LW, val, base, 0);
1819139c1837SPaolo Bonzini        break;
1820fc313c64SFrédéric Pétrot    case MO_UQ:
1821aeb6326eSRichard Henderson        tcg_out_opc_imm(s, OPC_LD, val, base, 0);
1822139c1837SPaolo Bonzini        break;
1823139c1837SPaolo Bonzini    default:
1824139c1837SPaolo Bonzini        g_assert_not_reached();
1825139c1837SPaolo Bonzini    }
1826139c1837SPaolo Bonzini}
1827139c1837SPaolo Bonzini
1828f7041977SRichard Hendersonstatic void tcg_out_qemu_ld(TCGContext *s, TCGReg data_reg, TCGReg addr_reg,
1829f7041977SRichard Henderson                            MemOpIdx oi, TCGType data_type)
1830139c1837SPaolo Bonzini{
1831001dddfeSRichard Henderson    TCGLabelQemuLdst *ldst;
18322e3a933aSRichard Henderson    TCGReg base;
1833139c1837SPaolo Bonzini
1834001dddfeSRichard Henderson    ldst = prepare_host_addr(s, &base, addr_reg, oi, true);
1835001dddfeSRichard Henderson    tcg_out_qemu_ld_direct(s, data_reg, base, get_memop(oi), data_type);
1836f7041977SRichard Henderson
1837001dddfeSRichard Henderson    if (ldst) {
1838001dddfeSRichard Henderson        ldst->type = data_type;
1839001dddfeSRichard Henderson        ldst->datalo_reg = data_reg;
1840001dddfeSRichard Henderson        ldst->raddr = tcg_splitwx_to_rx(s->code_ptr);
1841a3fb7c99SRichard Henderson    }
1842139c1837SPaolo Bonzini}
1843139c1837SPaolo Bonzini
1844aeb6326eSRichard Hendersonstatic void tcg_out_qemu_st_direct(TCGContext *s, TCGReg val,
1845139c1837SPaolo Bonzini                                   TCGReg base, MemOp opc)
1846139c1837SPaolo Bonzini{
1847c86bd2dcSRichard Henderson    /* Byte swapping is left to middle-end expansion. */
1848c86bd2dcSRichard Henderson    tcg_debug_assert((opc & MO_BSWAP) == 0);
1849139c1837SPaolo Bonzini
1850139c1837SPaolo Bonzini    switch (opc & (MO_SSIZE)) {
1851139c1837SPaolo Bonzini    case MO_8:
1852aeb6326eSRichard Henderson        tcg_out_opc_store(s, OPC_SB, base, val, 0);
1853139c1837SPaolo Bonzini        break;
1854139c1837SPaolo Bonzini    case MO_16:
1855aeb6326eSRichard Henderson        tcg_out_opc_store(s, OPC_SH, base, val, 0);
1856139c1837SPaolo Bonzini        break;
1857139c1837SPaolo Bonzini    case MO_32:
1858aeb6326eSRichard Henderson        tcg_out_opc_store(s, OPC_SW, base, val, 0);
1859139c1837SPaolo Bonzini        break;
1860139c1837SPaolo Bonzini    case MO_64:
1861aeb6326eSRichard Henderson        tcg_out_opc_store(s, OPC_SD, base, val, 0);
1862139c1837SPaolo Bonzini        break;
1863139c1837SPaolo Bonzini    default:
1864139c1837SPaolo Bonzini        g_assert_not_reached();
1865139c1837SPaolo Bonzini    }
1866139c1837SPaolo Bonzini}
1867139c1837SPaolo Bonzini
1868f7041977SRichard Hendersonstatic void tcg_out_qemu_st(TCGContext *s, TCGReg data_reg, TCGReg addr_reg,
1869f7041977SRichard Henderson                            MemOpIdx oi, TCGType data_type)
1870139c1837SPaolo Bonzini{
1871001dddfeSRichard Henderson    TCGLabelQemuLdst *ldst;
18722e3a933aSRichard Henderson    TCGReg base;
1873139c1837SPaolo Bonzini
1874001dddfeSRichard Henderson    ldst = prepare_host_addr(s, &base, addr_reg, oi, false);
1875001dddfeSRichard Henderson    tcg_out_qemu_st_direct(s, data_reg, base, get_memop(oi));
1876f7041977SRichard Henderson
1877001dddfeSRichard Henderson    if (ldst) {
1878001dddfeSRichard Henderson        ldst->type = data_type;
1879001dddfeSRichard Henderson        ldst->datalo_reg = data_reg;
1880001dddfeSRichard Henderson        ldst->raddr = tcg_splitwx_to_rx(s->code_ptr);
1881a3fb7c99SRichard Henderson    }
1882139c1837SPaolo Bonzini}
1883139c1837SPaolo Bonzini
1884793f7381SRichard Hendersonstatic const tcg_insn_unit *tb_ret_addr;
1885139c1837SPaolo Bonzini
1886b55a8d9dSRichard Hendersonstatic void tcg_out_exit_tb(TCGContext *s, uintptr_t a0)
1887b55a8d9dSRichard Henderson{
1888b55a8d9dSRichard Henderson    /* Reuse the zeroing that exists for goto_ptr.  */
1889b55a8d9dSRichard Henderson    if (a0 == 0) {
1890b55a8d9dSRichard Henderson        tcg_out_call_int(s, tcg_code_gen_epilogue, true);
1891b55a8d9dSRichard Henderson    } else {
1892b55a8d9dSRichard Henderson        tcg_out_movi(s, TCG_TYPE_PTR, TCG_REG_A0, a0);
1893b55a8d9dSRichard Henderson        tcg_out_call_int(s, tb_ret_addr, true);
1894b55a8d9dSRichard Henderson    }
1895b55a8d9dSRichard Henderson}
1896b55a8d9dSRichard Henderson
1897cf7d6b8eSRichard Hendersonstatic void tcg_out_goto_tb(TCGContext *s, int which)
1898cf7d6b8eSRichard Henderson{
1899493c9b19SRichard Henderson    /* Direct branch will be patched by tb_target_set_jmp_target. */
1900493c9b19SRichard Henderson    set_jmp_insn_offset(s, which);
1901493c9b19SRichard Henderson    tcg_out32(s, OPC_JAL);
1902493c9b19SRichard Henderson
1903493c9b19SRichard Henderson    /* When branch is out of range, fall through to indirect. */
1904cf7d6b8eSRichard Henderson    tcg_out_ld(s, TCG_TYPE_PTR, TCG_REG_TMP0, TCG_REG_ZERO,
1905cf7d6b8eSRichard Henderson               get_jmp_target_addr(s, which));
1906cf7d6b8eSRichard Henderson    tcg_out_opc_imm(s, OPC_JALR, TCG_REG_ZERO, TCG_REG_TMP0, 0);
1907cf7d6b8eSRichard Henderson    set_jmp_reset_offset(s, which);
1908cf7d6b8eSRichard Henderson}
1909cf7d6b8eSRichard Henderson
191090c0fee3SRichard Hendersonvoid tb_target_set_jmp_target(const TranslationBlock *tb, int n,
191190c0fee3SRichard Henderson                              uintptr_t jmp_rx, uintptr_t jmp_rw)
191290c0fee3SRichard Henderson{
1913493c9b19SRichard Henderson    uintptr_t addr = tb->jmp_target_addr[n];
1914493c9b19SRichard Henderson    ptrdiff_t offset = addr - jmp_rx;
1915493c9b19SRichard Henderson    tcg_insn_unit insn;
1916493c9b19SRichard Henderson
1917493c9b19SRichard Henderson    /* Either directly branch, or fall through to indirect branch. */
1918493c9b19SRichard Henderson    if (offset == sextreg(offset, 0, 20)) {
1919493c9b19SRichard Henderson        insn = encode_uj(OPC_JAL, TCG_REG_ZERO, offset);
1920493c9b19SRichard Henderson    } else {
1921493c9b19SRichard Henderson        insn = OPC_NOP;
1922493c9b19SRichard Henderson    }
1923493c9b19SRichard Henderson    qatomic_set((uint32_t *)jmp_rw, insn);
1924493c9b19SRichard Henderson    flush_idcache_range(jmp_rx, jmp_rw, 4);
192590c0fee3SRichard Henderson}
192690c0fee3SRichard Henderson
1927139c1837SPaolo Bonzinistatic void tcg_out_op(TCGContext *s, TCGOpcode opc,
19285e8892dbSMiroslav Rezanina                       const TCGArg args[TCG_MAX_OP_ARGS],
19295e8892dbSMiroslav Rezanina                       const int const_args[TCG_MAX_OP_ARGS])
1930139c1837SPaolo Bonzini{
1931139c1837SPaolo Bonzini    TCGArg a0 = args[0];
1932139c1837SPaolo Bonzini    TCGArg a1 = args[1];
1933139c1837SPaolo Bonzini    TCGArg a2 = args[2];
1934139c1837SPaolo Bonzini    int c2 = const_args[2];
1935139c1837SPaolo Bonzini
1936139c1837SPaolo Bonzini    switch (opc) {
1937139c1837SPaolo Bonzini    case INDEX_op_goto_ptr:
1938139c1837SPaolo Bonzini        tcg_out_opc_imm(s, OPC_JALR, TCG_REG_ZERO, a0, 0);
1939139c1837SPaolo Bonzini        break;
1940139c1837SPaolo Bonzini
1941139c1837SPaolo Bonzini    case INDEX_op_br:
1942139c1837SPaolo Bonzini        tcg_out_reloc(s, s->code_ptr, R_RISCV_JAL, arg_label(a0), 0);
1943139c1837SPaolo Bonzini        tcg_out_opc_jump(s, OPC_JAL, TCG_REG_ZERO, 0);
1944139c1837SPaolo Bonzini        break;
1945139c1837SPaolo Bonzini
1946139c1837SPaolo Bonzini    case INDEX_op_ld8u_i32:
1947139c1837SPaolo Bonzini    case INDEX_op_ld8u_i64:
1948139c1837SPaolo Bonzini        tcg_out_ldst(s, OPC_LBU, a0, a1, a2);
1949139c1837SPaolo Bonzini        break;
1950139c1837SPaolo Bonzini    case INDEX_op_ld8s_i32:
1951139c1837SPaolo Bonzini    case INDEX_op_ld8s_i64:
1952139c1837SPaolo Bonzini        tcg_out_ldst(s, OPC_LB, a0, a1, a2);
1953139c1837SPaolo Bonzini        break;
1954139c1837SPaolo Bonzini    case INDEX_op_ld16u_i32:
1955139c1837SPaolo Bonzini    case INDEX_op_ld16u_i64:
1956139c1837SPaolo Bonzini        tcg_out_ldst(s, OPC_LHU, a0, a1, a2);
1957139c1837SPaolo Bonzini        break;
1958139c1837SPaolo Bonzini    case INDEX_op_ld16s_i32:
1959139c1837SPaolo Bonzini    case INDEX_op_ld16s_i64:
1960139c1837SPaolo Bonzini        tcg_out_ldst(s, OPC_LH, a0, a1, a2);
1961139c1837SPaolo Bonzini        break;
1962139c1837SPaolo Bonzini    case INDEX_op_ld32u_i64:
1963139c1837SPaolo Bonzini        tcg_out_ldst(s, OPC_LWU, a0, a1, a2);
1964139c1837SPaolo Bonzini        break;
1965139c1837SPaolo Bonzini    case INDEX_op_ld_i32:
1966139c1837SPaolo Bonzini    case INDEX_op_ld32s_i64:
1967139c1837SPaolo Bonzini        tcg_out_ldst(s, OPC_LW, a0, a1, a2);
1968139c1837SPaolo Bonzini        break;
1969139c1837SPaolo Bonzini    case INDEX_op_ld_i64:
1970139c1837SPaolo Bonzini        tcg_out_ldst(s, OPC_LD, a0, a1, a2);
1971139c1837SPaolo Bonzini        break;
1972139c1837SPaolo Bonzini
1973139c1837SPaolo Bonzini    case INDEX_op_st8_i32:
1974139c1837SPaolo Bonzini    case INDEX_op_st8_i64:
1975139c1837SPaolo Bonzini        tcg_out_ldst(s, OPC_SB, a0, a1, a2);
1976139c1837SPaolo Bonzini        break;
1977139c1837SPaolo Bonzini    case INDEX_op_st16_i32:
1978139c1837SPaolo Bonzini    case INDEX_op_st16_i64:
1979139c1837SPaolo Bonzini        tcg_out_ldst(s, OPC_SH, a0, a1, a2);
1980139c1837SPaolo Bonzini        break;
1981139c1837SPaolo Bonzini    case INDEX_op_st_i32:
1982139c1837SPaolo Bonzini    case INDEX_op_st32_i64:
1983139c1837SPaolo Bonzini        tcg_out_ldst(s, OPC_SW, a0, a1, a2);
1984139c1837SPaolo Bonzini        break;
1985139c1837SPaolo Bonzini    case INDEX_op_st_i64:
1986139c1837SPaolo Bonzini        tcg_out_ldst(s, OPC_SD, a0, a1, a2);
1987139c1837SPaolo Bonzini        break;
1988139c1837SPaolo Bonzini
1989139c1837SPaolo Bonzini    case INDEX_op_add_i32:
1990139c1837SPaolo Bonzini        if (c2) {
1991139c1837SPaolo Bonzini            tcg_out_opc_imm(s, OPC_ADDIW, a0, a1, a2);
1992139c1837SPaolo Bonzini        } else {
1993139c1837SPaolo Bonzini            tcg_out_opc_reg(s, OPC_ADDW, a0, a1, a2);
1994139c1837SPaolo Bonzini        }
1995139c1837SPaolo Bonzini        break;
1996139c1837SPaolo Bonzini    case INDEX_op_add_i64:
1997139c1837SPaolo Bonzini        if (c2) {
1998139c1837SPaolo Bonzini            tcg_out_opc_imm(s, OPC_ADDI, a0, a1, a2);
1999139c1837SPaolo Bonzini        } else {
2000139c1837SPaolo Bonzini            tcg_out_opc_reg(s, OPC_ADD, a0, a1, a2);
2001139c1837SPaolo Bonzini        }
2002139c1837SPaolo Bonzini        break;
2003139c1837SPaolo Bonzini
2004139c1837SPaolo Bonzini    case INDEX_op_sub_i32:
2005139c1837SPaolo Bonzini        if (c2) {
2006139c1837SPaolo Bonzini            tcg_out_opc_imm(s, OPC_ADDIW, a0, a1, -a2);
2007139c1837SPaolo Bonzini        } else {
2008139c1837SPaolo Bonzini            tcg_out_opc_reg(s, OPC_SUBW, a0, a1, a2);
2009139c1837SPaolo Bonzini        }
2010139c1837SPaolo Bonzini        break;
2011139c1837SPaolo Bonzini    case INDEX_op_sub_i64:
2012139c1837SPaolo Bonzini        if (c2) {
2013139c1837SPaolo Bonzini            tcg_out_opc_imm(s, OPC_ADDI, a0, a1, -a2);
2014139c1837SPaolo Bonzini        } else {
2015139c1837SPaolo Bonzini            tcg_out_opc_reg(s, OPC_SUB, a0, a1, a2);
2016139c1837SPaolo Bonzini        }
2017139c1837SPaolo Bonzini        break;
2018139c1837SPaolo Bonzini
2019139c1837SPaolo Bonzini    case INDEX_op_and_i32:
2020139c1837SPaolo Bonzini    case INDEX_op_and_i64:
2021139c1837SPaolo Bonzini        if (c2) {
2022139c1837SPaolo Bonzini            tcg_out_opc_imm(s, OPC_ANDI, a0, a1, a2);
2023139c1837SPaolo Bonzini        } else {
2024139c1837SPaolo Bonzini            tcg_out_opc_reg(s, OPC_AND, a0, a1, a2);
2025139c1837SPaolo Bonzini        }
2026139c1837SPaolo Bonzini        break;
2027139c1837SPaolo Bonzini
2028139c1837SPaolo Bonzini    case INDEX_op_or_i32:
2029139c1837SPaolo Bonzini    case INDEX_op_or_i64:
2030139c1837SPaolo Bonzini        if (c2) {
2031139c1837SPaolo Bonzini            tcg_out_opc_imm(s, OPC_ORI, a0, a1, a2);
2032139c1837SPaolo Bonzini        } else {
2033139c1837SPaolo Bonzini            tcg_out_opc_reg(s, OPC_OR, a0, a1, a2);
2034139c1837SPaolo Bonzini        }
2035139c1837SPaolo Bonzini        break;
2036139c1837SPaolo Bonzini
2037139c1837SPaolo Bonzini    case INDEX_op_xor_i32:
2038139c1837SPaolo Bonzini    case INDEX_op_xor_i64:
2039139c1837SPaolo Bonzini        if (c2) {
2040139c1837SPaolo Bonzini            tcg_out_opc_imm(s, OPC_XORI, a0, a1, a2);
2041139c1837SPaolo Bonzini        } else {
2042139c1837SPaolo Bonzini            tcg_out_opc_reg(s, OPC_XOR, a0, a1, a2);
2043139c1837SPaolo Bonzini        }
2044139c1837SPaolo Bonzini        break;
2045139c1837SPaolo Bonzini
204699f4ec6eSRichard Henderson    case INDEX_op_andc_i32:
204799f4ec6eSRichard Henderson    case INDEX_op_andc_i64:
204899f4ec6eSRichard Henderson        if (c2) {
204999f4ec6eSRichard Henderson            tcg_out_opc_imm(s, OPC_ANDI, a0, a1, ~a2);
205099f4ec6eSRichard Henderson        } else {
205199f4ec6eSRichard Henderson            tcg_out_opc_reg(s, OPC_ANDN, a0, a1, a2);
205299f4ec6eSRichard Henderson        }
205399f4ec6eSRichard Henderson        break;
205499f4ec6eSRichard Henderson    case INDEX_op_orc_i32:
205599f4ec6eSRichard Henderson    case INDEX_op_orc_i64:
205699f4ec6eSRichard Henderson        if (c2) {
205799f4ec6eSRichard Henderson            tcg_out_opc_imm(s, OPC_ORI, a0, a1, ~a2);
205899f4ec6eSRichard Henderson        } else {
205999f4ec6eSRichard Henderson            tcg_out_opc_reg(s, OPC_ORN, a0, a1, a2);
206099f4ec6eSRichard Henderson        }
206199f4ec6eSRichard Henderson        break;
206299f4ec6eSRichard Henderson    case INDEX_op_eqv_i32:
206399f4ec6eSRichard Henderson    case INDEX_op_eqv_i64:
206499f4ec6eSRichard Henderson        if (c2) {
206599f4ec6eSRichard Henderson            tcg_out_opc_imm(s, OPC_XORI, a0, a1, ~a2);
206699f4ec6eSRichard Henderson        } else {
206799f4ec6eSRichard Henderson            tcg_out_opc_reg(s, OPC_XNOR, a0, a1, a2);
206899f4ec6eSRichard Henderson        }
206999f4ec6eSRichard Henderson        break;
207099f4ec6eSRichard Henderson
2071139c1837SPaolo Bonzini    case INDEX_op_not_i32:
2072139c1837SPaolo Bonzini    case INDEX_op_not_i64:
2073139c1837SPaolo Bonzini        tcg_out_opc_imm(s, OPC_XORI, a0, a1, -1);
2074139c1837SPaolo Bonzini        break;
2075139c1837SPaolo Bonzini
2076139c1837SPaolo Bonzini    case INDEX_op_neg_i32:
2077139c1837SPaolo Bonzini        tcg_out_opc_reg(s, OPC_SUBW, a0, TCG_REG_ZERO, a1);
2078139c1837SPaolo Bonzini        break;
2079139c1837SPaolo Bonzini    case INDEX_op_neg_i64:
2080139c1837SPaolo Bonzini        tcg_out_opc_reg(s, OPC_SUB, a0, TCG_REG_ZERO, a1);
2081139c1837SPaolo Bonzini        break;
2082139c1837SPaolo Bonzini
2083139c1837SPaolo Bonzini    case INDEX_op_mul_i32:
2084139c1837SPaolo Bonzini        tcg_out_opc_reg(s, OPC_MULW, a0, a1, a2);
2085139c1837SPaolo Bonzini        break;
2086139c1837SPaolo Bonzini    case INDEX_op_mul_i64:
2087139c1837SPaolo Bonzini        tcg_out_opc_reg(s, OPC_MUL, a0, a1, a2);
2088139c1837SPaolo Bonzini        break;
2089139c1837SPaolo Bonzini
2090139c1837SPaolo Bonzini    case INDEX_op_div_i32:
2091139c1837SPaolo Bonzini        tcg_out_opc_reg(s, OPC_DIVW, a0, a1, a2);
2092139c1837SPaolo Bonzini        break;
2093139c1837SPaolo Bonzini    case INDEX_op_div_i64:
2094139c1837SPaolo Bonzini        tcg_out_opc_reg(s, OPC_DIV, a0, a1, a2);
2095139c1837SPaolo Bonzini        break;
2096139c1837SPaolo Bonzini
2097139c1837SPaolo Bonzini    case INDEX_op_divu_i32:
2098139c1837SPaolo Bonzini        tcg_out_opc_reg(s, OPC_DIVUW, a0, a1, a2);
2099139c1837SPaolo Bonzini        break;
2100139c1837SPaolo Bonzini    case INDEX_op_divu_i64:
2101139c1837SPaolo Bonzini        tcg_out_opc_reg(s, OPC_DIVU, a0, a1, a2);
2102139c1837SPaolo Bonzini        break;
2103139c1837SPaolo Bonzini
2104139c1837SPaolo Bonzini    case INDEX_op_rem_i32:
2105139c1837SPaolo Bonzini        tcg_out_opc_reg(s, OPC_REMW, a0, a1, a2);
2106139c1837SPaolo Bonzini        break;
2107139c1837SPaolo Bonzini    case INDEX_op_rem_i64:
2108139c1837SPaolo Bonzini        tcg_out_opc_reg(s, OPC_REM, a0, a1, a2);
2109139c1837SPaolo Bonzini        break;
2110139c1837SPaolo Bonzini
2111139c1837SPaolo Bonzini    case INDEX_op_remu_i32:
2112139c1837SPaolo Bonzini        tcg_out_opc_reg(s, OPC_REMUW, a0, a1, a2);
2113139c1837SPaolo Bonzini        break;
2114139c1837SPaolo Bonzini    case INDEX_op_remu_i64:
2115139c1837SPaolo Bonzini        tcg_out_opc_reg(s, OPC_REMU, a0, a1, a2);
2116139c1837SPaolo Bonzini        break;
2117139c1837SPaolo Bonzini
2118139c1837SPaolo Bonzini    case INDEX_op_shl_i32:
2119139c1837SPaolo Bonzini        if (c2) {
2120d2f3066eSZihao Yu            tcg_out_opc_imm(s, OPC_SLLIW, a0, a1, a2 & 0x1f);
2121139c1837SPaolo Bonzini        } else {
2122139c1837SPaolo Bonzini            tcg_out_opc_reg(s, OPC_SLLW, a0, a1, a2);
2123139c1837SPaolo Bonzini        }
2124139c1837SPaolo Bonzini        break;
2125139c1837SPaolo Bonzini    case INDEX_op_shl_i64:
2126139c1837SPaolo Bonzini        if (c2) {
2127d2f3066eSZihao Yu            tcg_out_opc_imm(s, OPC_SLLI, a0, a1, a2 & 0x3f);
2128139c1837SPaolo Bonzini        } else {
2129139c1837SPaolo Bonzini            tcg_out_opc_reg(s, OPC_SLL, a0, a1, a2);
2130139c1837SPaolo Bonzini        }
2131139c1837SPaolo Bonzini        break;
2132139c1837SPaolo Bonzini
2133139c1837SPaolo Bonzini    case INDEX_op_shr_i32:
2134139c1837SPaolo Bonzini        if (c2) {
2135d2f3066eSZihao Yu            tcg_out_opc_imm(s, OPC_SRLIW, a0, a1, a2 & 0x1f);
2136139c1837SPaolo Bonzini        } else {
2137139c1837SPaolo Bonzini            tcg_out_opc_reg(s, OPC_SRLW, a0, a1, a2);
2138139c1837SPaolo Bonzini        }
2139139c1837SPaolo Bonzini        break;
2140139c1837SPaolo Bonzini    case INDEX_op_shr_i64:
2141139c1837SPaolo Bonzini        if (c2) {
2142d2f3066eSZihao Yu            tcg_out_opc_imm(s, OPC_SRLI, a0, a1, a2 & 0x3f);
2143139c1837SPaolo Bonzini        } else {
2144139c1837SPaolo Bonzini            tcg_out_opc_reg(s, OPC_SRL, a0, a1, a2);
2145139c1837SPaolo Bonzini        }
2146139c1837SPaolo Bonzini        break;
2147139c1837SPaolo Bonzini
2148139c1837SPaolo Bonzini    case INDEX_op_sar_i32:
2149139c1837SPaolo Bonzini        if (c2) {
2150d2f3066eSZihao Yu            tcg_out_opc_imm(s, OPC_SRAIW, a0, a1, a2 & 0x1f);
2151139c1837SPaolo Bonzini        } else {
2152139c1837SPaolo Bonzini            tcg_out_opc_reg(s, OPC_SRAW, a0, a1, a2);
2153139c1837SPaolo Bonzini        }
2154139c1837SPaolo Bonzini        break;
2155139c1837SPaolo Bonzini    case INDEX_op_sar_i64:
2156139c1837SPaolo Bonzini        if (c2) {
2157d2f3066eSZihao Yu            tcg_out_opc_imm(s, OPC_SRAI, a0, a1, a2 & 0x3f);
2158139c1837SPaolo Bonzini        } else {
2159139c1837SPaolo Bonzini            tcg_out_opc_reg(s, OPC_SRA, a0, a1, a2);
2160139c1837SPaolo Bonzini        }
2161139c1837SPaolo Bonzini        break;
2162139c1837SPaolo Bonzini
216319d016adSRichard Henderson    case INDEX_op_rotl_i32:
216419d016adSRichard Henderson        if (c2) {
216519d016adSRichard Henderson            tcg_out_opc_imm(s, OPC_RORIW, a0, a1, -a2 & 0x1f);
216619d016adSRichard Henderson        } else {
216719d016adSRichard Henderson            tcg_out_opc_reg(s, OPC_ROLW, a0, a1, a2);
216819d016adSRichard Henderson        }
216919d016adSRichard Henderson        break;
217019d016adSRichard Henderson    case INDEX_op_rotl_i64:
217119d016adSRichard Henderson        if (c2) {
217219d016adSRichard Henderson            tcg_out_opc_imm(s, OPC_RORI, a0, a1, -a2 & 0x3f);
217319d016adSRichard Henderson        } else {
217419d016adSRichard Henderson            tcg_out_opc_reg(s, OPC_ROL, a0, a1, a2);
217519d016adSRichard Henderson        }
217619d016adSRichard Henderson        break;
217719d016adSRichard Henderson
217819d016adSRichard Henderson    case INDEX_op_rotr_i32:
217919d016adSRichard Henderson        if (c2) {
218019d016adSRichard Henderson            tcg_out_opc_imm(s, OPC_RORIW, a0, a1, a2 & 0x1f);
218119d016adSRichard Henderson        } else {
218219d016adSRichard Henderson            tcg_out_opc_reg(s, OPC_RORW, a0, a1, a2);
218319d016adSRichard Henderson        }
218419d016adSRichard Henderson        break;
218519d016adSRichard Henderson    case INDEX_op_rotr_i64:
218619d016adSRichard Henderson        if (c2) {
218719d016adSRichard Henderson            tcg_out_opc_imm(s, OPC_RORI, a0, a1, a2 & 0x3f);
218819d016adSRichard Henderson        } else {
218919d016adSRichard Henderson            tcg_out_opc_reg(s, OPC_ROR, a0, a1, a2);
219019d016adSRichard Henderson        }
219119d016adSRichard Henderson        break;
219219d016adSRichard Henderson
21937b4d5274SRichard Henderson    case INDEX_op_bswap64_i64:
21947b4d5274SRichard Henderson        tcg_out_opc_imm(s, OPC_REV8, a0, a1, 0);
21957b4d5274SRichard Henderson        break;
21967b4d5274SRichard Henderson    case INDEX_op_bswap32_i32:
21977b4d5274SRichard Henderson        a2 = 0;
21987b4d5274SRichard Henderson        /* fall through */
21997b4d5274SRichard Henderson    case INDEX_op_bswap32_i64:
22007b4d5274SRichard Henderson        tcg_out_opc_imm(s, OPC_REV8, a0, a1, 0);
22017b4d5274SRichard Henderson        if (a2 & TCG_BSWAP_OZ) {
22027b4d5274SRichard Henderson            tcg_out_opc_imm(s, OPC_SRLI, a0, a0, 32);
22037b4d5274SRichard Henderson        } else {
22047b4d5274SRichard Henderson            tcg_out_opc_imm(s, OPC_SRAI, a0, a0, 32);
22057b4d5274SRichard Henderson        }
22067b4d5274SRichard Henderson        break;
22077b4d5274SRichard Henderson    case INDEX_op_bswap16_i64:
22087b4d5274SRichard Henderson    case INDEX_op_bswap16_i32:
22097b4d5274SRichard Henderson        tcg_out_opc_imm(s, OPC_REV8, a0, a1, 0);
22107b4d5274SRichard Henderson        if (a2 & TCG_BSWAP_OZ) {
22117b4d5274SRichard Henderson            tcg_out_opc_imm(s, OPC_SRLI, a0, a0, 48);
22127b4d5274SRichard Henderson        } else {
22137b4d5274SRichard Henderson            tcg_out_opc_imm(s, OPC_SRAI, a0, a0, 48);
22147b4d5274SRichard Henderson        }
22157b4d5274SRichard Henderson        break;
22167b4d5274SRichard Henderson
22170956ecdaSRichard Henderson    case INDEX_op_ctpop_i32:
22180956ecdaSRichard Henderson        tcg_out_opc_imm(s, OPC_CPOPW, a0, a1, 0);
22190956ecdaSRichard Henderson        break;
22200956ecdaSRichard Henderson    case INDEX_op_ctpop_i64:
22210956ecdaSRichard Henderson        tcg_out_opc_imm(s, OPC_CPOP, a0, a1, 0);
22220956ecdaSRichard Henderson        break;
22230956ecdaSRichard Henderson
2224a30498fcSRichard Henderson    case INDEX_op_clz_i32:
2225a30498fcSRichard Henderson        tcg_out_cltz(s, TCG_TYPE_I32, OPC_CLZW, a0, a1, a2, c2);
2226a30498fcSRichard Henderson        break;
2227a30498fcSRichard Henderson    case INDEX_op_clz_i64:
2228a30498fcSRichard Henderson        tcg_out_cltz(s, TCG_TYPE_I64, OPC_CLZ, a0, a1, a2, c2);
2229a30498fcSRichard Henderson        break;
2230a30498fcSRichard Henderson    case INDEX_op_ctz_i32:
2231a30498fcSRichard Henderson        tcg_out_cltz(s, TCG_TYPE_I32, OPC_CTZW, a0, a1, a2, c2);
2232a30498fcSRichard Henderson        break;
2233a30498fcSRichard Henderson    case INDEX_op_ctz_i64:
2234a30498fcSRichard Henderson        tcg_out_cltz(s, TCG_TYPE_I64, OPC_CTZ, a0, a1, a2, c2);
2235a30498fcSRichard Henderson        break;
2236a30498fcSRichard Henderson
2237139c1837SPaolo Bonzini    case INDEX_op_add2_i32:
2238139c1837SPaolo Bonzini        tcg_out_addsub2(s, a0, a1, a2, args[3], args[4], args[5],
2239139c1837SPaolo Bonzini                        const_args[4], const_args[5], false, true);
2240139c1837SPaolo Bonzini        break;
2241139c1837SPaolo Bonzini    case INDEX_op_add2_i64:
2242139c1837SPaolo Bonzini        tcg_out_addsub2(s, a0, a1, a2, args[3], args[4], args[5],
2243139c1837SPaolo Bonzini                        const_args[4], const_args[5], false, false);
2244139c1837SPaolo Bonzini        break;
2245139c1837SPaolo Bonzini    case INDEX_op_sub2_i32:
2246139c1837SPaolo Bonzini        tcg_out_addsub2(s, a0, a1, a2, args[3], args[4], args[5],
2247139c1837SPaolo Bonzini                        const_args[4], const_args[5], true, true);
2248139c1837SPaolo Bonzini        break;
2249139c1837SPaolo Bonzini    case INDEX_op_sub2_i64:
2250139c1837SPaolo Bonzini        tcg_out_addsub2(s, a0, a1, a2, args[3], args[4], args[5],
2251139c1837SPaolo Bonzini                        const_args[4], const_args[5], true, false);
2252139c1837SPaolo Bonzini        break;
2253139c1837SPaolo Bonzini
2254139c1837SPaolo Bonzini    case INDEX_op_brcond_i32:
2255139c1837SPaolo Bonzini    case INDEX_op_brcond_i64:
2256139c1837SPaolo Bonzini        tcg_out_brcond(s, a2, a0, a1, arg_label(args[3]));
2257139c1837SPaolo Bonzini        break;
2258139c1837SPaolo Bonzini
2259139c1837SPaolo Bonzini    case INDEX_op_setcond_i32:
2260139c1837SPaolo Bonzini    case INDEX_op_setcond_i64:
2261f6453695SRichard Henderson        tcg_out_setcond(s, args[3], a0, a1, a2, c2);
2262139c1837SPaolo Bonzini        break;
2263139c1837SPaolo Bonzini
226441e4c0a9SRichard Henderson    case INDEX_op_negsetcond_i32:
226541e4c0a9SRichard Henderson    case INDEX_op_negsetcond_i64:
226641e4c0a9SRichard Henderson        tcg_out_negsetcond(s, args[3], a0, a1, a2, c2);
226741e4c0a9SRichard Henderson        break;
226841e4c0a9SRichard Henderson
2269a18d783eSRichard Henderson    case INDEX_op_movcond_i32:
2270a18d783eSRichard Henderson    case INDEX_op_movcond_i64:
2271a18d783eSRichard Henderson        tcg_out_movcond(s, args[5], a0, a1, a2, c2,
2272a18d783eSRichard Henderson                        args[3], const_args[3], args[4], const_args[4]);
2273a18d783eSRichard Henderson        break;
2274a18d783eSRichard Henderson
2275fecccfccSRichard Henderson    case INDEX_op_qemu_ld_a32_i32:
2276fecccfccSRichard Henderson    case INDEX_op_qemu_ld_a64_i32:
2277f7041977SRichard Henderson        tcg_out_qemu_ld(s, a0, a1, a2, TCG_TYPE_I32);
2278139c1837SPaolo Bonzini        break;
2279fecccfccSRichard Henderson    case INDEX_op_qemu_ld_a32_i64:
2280fecccfccSRichard Henderson    case INDEX_op_qemu_ld_a64_i64:
2281f7041977SRichard Henderson        tcg_out_qemu_ld(s, a0, a1, a2, TCG_TYPE_I64);
2282139c1837SPaolo Bonzini        break;
2283fecccfccSRichard Henderson    case INDEX_op_qemu_st_a32_i32:
2284fecccfccSRichard Henderson    case INDEX_op_qemu_st_a64_i32:
2285f7041977SRichard Henderson        tcg_out_qemu_st(s, a0, a1, a2, TCG_TYPE_I32);
2286139c1837SPaolo Bonzini        break;
2287fecccfccSRichard Henderson    case INDEX_op_qemu_st_a32_i64:
2288fecccfccSRichard Henderson    case INDEX_op_qemu_st_a64_i64:
2289f7041977SRichard Henderson        tcg_out_qemu_st(s, a0, a1, a2, TCG_TYPE_I64);
2290139c1837SPaolo Bonzini        break;
2291139c1837SPaolo Bonzini
2292139c1837SPaolo Bonzini    case INDEX_op_extrh_i64_i32:
2293139c1837SPaolo Bonzini        tcg_out_opc_imm(s, OPC_SRAI, a0, a1, 32);
2294139c1837SPaolo Bonzini        break;
2295139c1837SPaolo Bonzini
2296139c1837SPaolo Bonzini    case INDEX_op_mulsh_i32:
2297139c1837SPaolo Bonzini    case INDEX_op_mulsh_i64:
2298139c1837SPaolo Bonzini        tcg_out_opc_reg(s, OPC_MULH, a0, a1, a2);
2299139c1837SPaolo Bonzini        break;
2300139c1837SPaolo Bonzini
2301139c1837SPaolo Bonzini    case INDEX_op_muluh_i32:
2302139c1837SPaolo Bonzini    case INDEX_op_muluh_i64:
2303139c1837SPaolo Bonzini        tcg_out_opc_reg(s, OPC_MULHU, a0, a1, a2);
2304139c1837SPaolo Bonzini        break;
2305139c1837SPaolo Bonzini
2306139c1837SPaolo Bonzini    case INDEX_op_mb:
2307139c1837SPaolo Bonzini        tcg_out_mb(s, a0);
2308139c1837SPaolo Bonzini        break;
2309139c1837SPaolo Bonzini
2310139c1837SPaolo Bonzini    case INDEX_op_mov_i32:  /* Always emitted via tcg_out_mov.  */
2311139c1837SPaolo Bonzini    case INDEX_op_mov_i64:
2312139c1837SPaolo Bonzini    case INDEX_op_call:     /* Always emitted via tcg_out_call.  */
2313b55a8d9dSRichard Henderson    case INDEX_op_exit_tb:  /* Always emitted via tcg_out_exit_tb.  */
2314cf7d6b8eSRichard Henderson    case INDEX_op_goto_tb:  /* Always emitted via tcg_out_goto_tb.  */
2315678155b2SRichard Henderson    case INDEX_op_ext8s_i32:  /* Always emitted via tcg_reg_alloc_op.  */
2316678155b2SRichard Henderson    case INDEX_op_ext8s_i64:
2317d0e66c89SRichard Henderson    case INDEX_op_ext8u_i32:
2318d0e66c89SRichard Henderson    case INDEX_op_ext8u_i64:
2319753e42eaSRichard Henderson    case INDEX_op_ext16s_i32:
2320753e42eaSRichard Henderson    case INDEX_op_ext16s_i64:
2321379afdffSRichard Henderson    case INDEX_op_ext16u_i32:
2322379afdffSRichard Henderson    case INDEX_op_ext16u_i64:
232352bf3398SRichard Henderson    case INDEX_op_ext32s_i64:
23249ecf5f61SRichard Henderson    case INDEX_op_ext32u_i64:
23259c6aa274SRichard Henderson    case INDEX_op_ext_i32_i64:
2326b9bfe000SRichard Henderson    case INDEX_op_extu_i32_i64:
2327b8b94ac6SRichard Henderson    case INDEX_op_extrl_i64_i32:
2328139c1837SPaolo Bonzini    default:
2329139c1837SPaolo Bonzini        g_assert_not_reached();
2330139c1837SPaolo Bonzini    }
2331139c1837SPaolo Bonzini}
2332139c1837SPaolo Bonzini
2333f63e7089SHuang Shiyuanstatic void tcg_out_vec_op(TCGContext *s, TCGOpcode opc,
2334f63e7089SHuang Shiyuan                           unsigned vecl, unsigned vece,
2335f63e7089SHuang Shiyuan                           const TCGArg args[TCG_MAX_OP_ARGS],
2336f63e7089SHuang Shiyuan                           const int const_args[TCG_MAX_OP_ARGS])
2337f63e7089SHuang Shiyuan{
2338f63e7089SHuang Shiyuan    TCGType type = vecl + TCG_TYPE_V64;
2339f63e7089SHuang Shiyuan    TCGArg a0, a1, a2;
23405a63f599STANG Tiancheng    int c2;
2341f63e7089SHuang Shiyuan
2342f63e7089SHuang Shiyuan    a0 = args[0];
2343f63e7089SHuang Shiyuan    a1 = args[1];
2344f63e7089SHuang Shiyuan    a2 = args[2];
23455a63f599STANG Tiancheng    c2 = const_args[2];
2346f63e7089SHuang Shiyuan
2347f63e7089SHuang Shiyuan    switch (opc) {
2348d4be6ee1STANG Tiancheng    case INDEX_op_dupm_vec:
2349d4be6ee1STANG Tiancheng        tcg_out_dupm_vec(s, type, vece, a0, a1, a2);
2350d4be6ee1STANG Tiancheng        break;
2351f63e7089SHuang Shiyuan    case INDEX_op_ld_vec:
2352f63e7089SHuang Shiyuan        tcg_out_ld(s, type, a0, a1, a2);
2353f63e7089SHuang Shiyuan        break;
2354f63e7089SHuang Shiyuan    case INDEX_op_st_vec:
2355f63e7089SHuang Shiyuan        tcg_out_st(s, type, a0, a1, a2);
2356f63e7089SHuang Shiyuan        break;
23575a63f599STANG Tiancheng    case INDEX_op_add_vec:
23585a63f599STANG Tiancheng        set_vtype_len_sew(s, type, vece);
23595a63f599STANG Tiancheng        tcg_out_opc_vv_vi(s, OPC_VADD_VV, OPC_VADD_VI, a0, a1, a2, c2);
23605a63f599STANG Tiancheng        break;
23615a63f599STANG Tiancheng    case INDEX_op_sub_vec:
23625a63f599STANG Tiancheng        set_vtype_len_sew(s, type, vece);
2363dc9cd4ecSRichard Henderson        if (const_args[1]) {
2364dc9cd4ecSRichard Henderson            tcg_out_opc_vi(s, OPC_VRSUB_VI, a0, a2, a1);
2365dc9cd4ecSRichard Henderson        } else {
23665a63f599STANG Tiancheng            tcg_out_opc_vv(s, OPC_VSUB_VV, a0, a1, a2);
2367dc9cd4ecSRichard Henderson        }
23685a63f599STANG Tiancheng        break;
23695a63f599STANG Tiancheng    case INDEX_op_and_vec:
23705a63f599STANG Tiancheng        set_vtype_len(s, type);
23715a63f599STANG Tiancheng        tcg_out_opc_vv_vi(s, OPC_VAND_VV, OPC_VAND_VI, a0, a1, a2, c2);
23725a63f599STANG Tiancheng        break;
23735a63f599STANG Tiancheng    case INDEX_op_or_vec:
23745a63f599STANG Tiancheng        set_vtype_len(s, type);
23755a63f599STANG Tiancheng        tcg_out_opc_vv_vi(s, OPC_VOR_VV, OPC_VOR_VI, a0, a1, a2, c2);
23765a63f599STANG Tiancheng        break;
23775a63f599STANG Tiancheng    case INDEX_op_xor_vec:
23785a63f599STANG Tiancheng        set_vtype_len(s, type);
23795a63f599STANG Tiancheng        tcg_out_opc_vv_vi(s, OPC_VXOR_VV, OPC_VXOR_VI, a0, a1, a2, c2);
23805a63f599STANG Tiancheng        break;
23815a63f599STANG Tiancheng    case INDEX_op_not_vec:
23825a63f599STANG Tiancheng        set_vtype_len(s, type);
23835a63f599STANG Tiancheng        tcg_out_opc_vi(s, OPC_VXOR_VI, a0, a1, -1);
23845a63f599STANG Tiancheng        break;
2385c283c074STANG Tiancheng    case INDEX_op_neg_vec:
2386c283c074STANG Tiancheng        set_vtype_len_sew(s, type, vece);
2387c283c074STANG Tiancheng        tcg_out_opc_vi(s, OPC_VRSUB_VI, a0, a1, 0);
2388c283c074STANG Tiancheng        break;
2389*101c1ef5STANG Tiancheng    case INDEX_op_mul_vec:
2390*101c1ef5STANG Tiancheng        set_vtype_len_sew(s, type, vece);
2391*101c1ef5STANG Tiancheng        tcg_out_opc_vv(s, OPC_VMUL_VV, a0, a1, a2);
2392*101c1ef5STANG Tiancheng        break;
2393*101c1ef5STANG Tiancheng    case INDEX_op_ssadd_vec:
2394*101c1ef5STANG Tiancheng        set_vtype_len_sew(s, type, vece);
2395*101c1ef5STANG Tiancheng        tcg_out_opc_vv_vi(s, OPC_VSADD_VV, OPC_VSADD_VI, a0, a1, a2, c2);
2396*101c1ef5STANG Tiancheng        break;
2397*101c1ef5STANG Tiancheng    case INDEX_op_sssub_vec:
2398*101c1ef5STANG Tiancheng        set_vtype_len_sew(s, type, vece);
2399*101c1ef5STANG Tiancheng        tcg_out_opc_vv_vi(s, OPC_VSSUB_VV, OPC_VSSUB_VI, a0, a1, a2, c2);
2400*101c1ef5STANG Tiancheng        break;
2401*101c1ef5STANG Tiancheng    case INDEX_op_usadd_vec:
2402*101c1ef5STANG Tiancheng        set_vtype_len_sew(s, type, vece);
2403*101c1ef5STANG Tiancheng        tcg_out_opc_vv_vi(s, OPC_VSADDU_VV, OPC_VSADDU_VI, a0, a1, a2, c2);
2404*101c1ef5STANG Tiancheng        break;
2405*101c1ef5STANG Tiancheng    case INDEX_op_ussub_vec:
2406*101c1ef5STANG Tiancheng        set_vtype_len_sew(s, type, vece);
2407*101c1ef5STANG Tiancheng        tcg_out_opc_vv_vi(s, OPC_VSSUBU_VV, OPC_VSSUBU_VI, a0, a1, a2, c2);
2408*101c1ef5STANG Tiancheng        break;
2409a31768c0STANG Tiancheng    case INDEX_op_cmp_vec:
2410a31768c0STANG Tiancheng        tcg_out_cmpsel(s, type, vece, args[3], a0, a1, a2, c2,
2411a31768c0STANG Tiancheng                       -1, true, 0, true);
2412a31768c0STANG Tiancheng        break;
2413a31768c0STANG Tiancheng    case INDEX_op_cmpsel_vec:
2414a31768c0STANG Tiancheng        tcg_out_cmpsel(s, type, vece, args[5], a0, a1, a2, c2,
2415a31768c0STANG Tiancheng                       args[3], const_args[3], args[4], const_args[4]);
2416a31768c0STANG Tiancheng        break;
2417f63e7089SHuang Shiyuan    case INDEX_op_mov_vec: /* Always emitted via tcg_out_mov.  */
2418f63e7089SHuang Shiyuan    case INDEX_op_dup_vec: /* Always emitted via tcg_out_dup_vec.  */
2419f63e7089SHuang Shiyuan    default:
2420f63e7089SHuang Shiyuan        g_assert_not_reached();
2421f63e7089SHuang Shiyuan    }
2422f63e7089SHuang Shiyuan}
2423f63e7089SHuang Shiyuan
2424f63e7089SHuang Shiyuanvoid tcg_expand_vec_op(TCGOpcode opc, TCGType type, unsigned vece,
2425f63e7089SHuang Shiyuan                       TCGArg a0, ...)
2426f63e7089SHuang Shiyuan{
2427f63e7089SHuang Shiyuan    g_assert_not_reached();
2428f63e7089SHuang Shiyuan}
2429f63e7089SHuang Shiyuan
2430f63e7089SHuang Shiyuanint tcg_can_emit_vec_op(TCGOpcode opc, TCGType type, unsigned vece)
2431f63e7089SHuang Shiyuan{
2432f63e7089SHuang Shiyuan    switch (opc) {
24335a63f599STANG Tiancheng    case INDEX_op_add_vec:
24345a63f599STANG Tiancheng    case INDEX_op_sub_vec:
24355a63f599STANG Tiancheng    case INDEX_op_and_vec:
24365a63f599STANG Tiancheng    case INDEX_op_or_vec:
24375a63f599STANG Tiancheng    case INDEX_op_xor_vec:
24385a63f599STANG Tiancheng    case INDEX_op_not_vec:
2439c283c074STANG Tiancheng    case INDEX_op_neg_vec:
2440*101c1ef5STANG Tiancheng    case INDEX_op_mul_vec:
2441*101c1ef5STANG Tiancheng    case INDEX_op_ssadd_vec:
2442*101c1ef5STANG Tiancheng    case INDEX_op_sssub_vec:
2443*101c1ef5STANG Tiancheng    case INDEX_op_usadd_vec:
2444*101c1ef5STANG Tiancheng    case INDEX_op_ussub_vec:
2445a31768c0STANG Tiancheng    case INDEX_op_cmp_vec:
2446a31768c0STANG Tiancheng    case INDEX_op_cmpsel_vec:
24475a63f599STANG Tiancheng        return 1;
2448f63e7089SHuang Shiyuan    default:
2449f63e7089SHuang Shiyuan        return 0;
2450f63e7089SHuang Shiyuan    }
2451f63e7089SHuang Shiyuan}
2452f63e7089SHuang Shiyuan
2453665be288SRichard Hendersonstatic TCGConstraintSetIndex tcg_target_op_def(TCGOpcode op)
2454139c1837SPaolo Bonzini{
2455139c1837SPaolo Bonzini    switch (op) {
2456139c1837SPaolo Bonzini    case INDEX_op_goto_ptr:
2457665be288SRichard Henderson        return C_O0_I1(r);
2458139c1837SPaolo Bonzini
2459139c1837SPaolo Bonzini    case INDEX_op_ld8u_i32:
2460139c1837SPaolo Bonzini    case INDEX_op_ld8s_i32:
2461139c1837SPaolo Bonzini    case INDEX_op_ld16u_i32:
2462139c1837SPaolo Bonzini    case INDEX_op_ld16s_i32:
2463139c1837SPaolo Bonzini    case INDEX_op_ld_i32:
2464139c1837SPaolo Bonzini    case INDEX_op_not_i32:
2465139c1837SPaolo Bonzini    case INDEX_op_neg_i32:
2466139c1837SPaolo Bonzini    case INDEX_op_ld8u_i64:
2467139c1837SPaolo Bonzini    case INDEX_op_ld8s_i64:
2468139c1837SPaolo Bonzini    case INDEX_op_ld16u_i64:
2469139c1837SPaolo Bonzini    case INDEX_op_ld16s_i64:
2470139c1837SPaolo Bonzini    case INDEX_op_ld32s_i64:
2471139c1837SPaolo Bonzini    case INDEX_op_ld32u_i64:
2472139c1837SPaolo Bonzini    case INDEX_op_ld_i64:
2473139c1837SPaolo Bonzini    case INDEX_op_not_i64:
2474139c1837SPaolo Bonzini    case INDEX_op_neg_i64:
2475139c1837SPaolo Bonzini    case INDEX_op_ext8u_i32:
2476139c1837SPaolo Bonzini    case INDEX_op_ext8u_i64:
2477139c1837SPaolo Bonzini    case INDEX_op_ext16u_i32:
2478139c1837SPaolo Bonzini    case INDEX_op_ext16u_i64:
2479139c1837SPaolo Bonzini    case INDEX_op_ext32u_i64:
2480139c1837SPaolo Bonzini    case INDEX_op_extu_i32_i64:
2481139c1837SPaolo Bonzini    case INDEX_op_ext8s_i32:
2482139c1837SPaolo Bonzini    case INDEX_op_ext8s_i64:
2483139c1837SPaolo Bonzini    case INDEX_op_ext16s_i32:
2484139c1837SPaolo Bonzini    case INDEX_op_ext16s_i64:
2485139c1837SPaolo Bonzini    case INDEX_op_ext32s_i64:
2486139c1837SPaolo Bonzini    case INDEX_op_extrl_i64_i32:
2487139c1837SPaolo Bonzini    case INDEX_op_extrh_i64_i32:
2488139c1837SPaolo Bonzini    case INDEX_op_ext_i32_i64:
24897b4d5274SRichard Henderson    case INDEX_op_bswap16_i32:
24907b4d5274SRichard Henderson    case INDEX_op_bswap32_i32:
24917b4d5274SRichard Henderson    case INDEX_op_bswap16_i64:
24927b4d5274SRichard Henderson    case INDEX_op_bswap32_i64:
24937b4d5274SRichard Henderson    case INDEX_op_bswap64_i64:
24940956ecdaSRichard Henderson    case INDEX_op_ctpop_i32:
24950956ecdaSRichard Henderson    case INDEX_op_ctpop_i64:
2496665be288SRichard Henderson        return C_O1_I1(r, r);
2497139c1837SPaolo Bonzini
2498139c1837SPaolo Bonzini    case INDEX_op_st8_i32:
2499139c1837SPaolo Bonzini    case INDEX_op_st16_i32:
2500139c1837SPaolo Bonzini    case INDEX_op_st_i32:
2501139c1837SPaolo Bonzini    case INDEX_op_st8_i64:
2502139c1837SPaolo Bonzini    case INDEX_op_st16_i64:
2503139c1837SPaolo Bonzini    case INDEX_op_st32_i64:
2504139c1837SPaolo Bonzini    case INDEX_op_st_i64:
2505665be288SRichard Henderson        return C_O0_I2(rZ, r);
2506139c1837SPaolo Bonzini
2507139c1837SPaolo Bonzini    case INDEX_op_add_i32:
2508139c1837SPaolo Bonzini    case INDEX_op_and_i32:
2509139c1837SPaolo Bonzini    case INDEX_op_or_i32:
2510139c1837SPaolo Bonzini    case INDEX_op_xor_i32:
2511139c1837SPaolo Bonzini    case INDEX_op_add_i64:
2512139c1837SPaolo Bonzini    case INDEX_op_and_i64:
2513139c1837SPaolo Bonzini    case INDEX_op_or_i64:
2514139c1837SPaolo Bonzini    case INDEX_op_xor_i64:
2515f6453695SRichard Henderson    case INDEX_op_setcond_i32:
2516f6453695SRichard Henderson    case INDEX_op_setcond_i64:
251741e4c0a9SRichard Henderson    case INDEX_op_negsetcond_i32:
251841e4c0a9SRichard Henderson    case INDEX_op_negsetcond_i64:
2519665be288SRichard Henderson        return C_O1_I2(r, r, rI);
2520139c1837SPaolo Bonzini
252199f4ec6eSRichard Henderson    case INDEX_op_andc_i32:
252299f4ec6eSRichard Henderson    case INDEX_op_andc_i64:
252399f4ec6eSRichard Henderson    case INDEX_op_orc_i32:
252499f4ec6eSRichard Henderson    case INDEX_op_orc_i64:
252599f4ec6eSRichard Henderson    case INDEX_op_eqv_i32:
252699f4ec6eSRichard Henderson    case INDEX_op_eqv_i64:
252799f4ec6eSRichard Henderson        return C_O1_I2(r, r, rJ);
252899f4ec6eSRichard Henderson
2529139c1837SPaolo Bonzini    case INDEX_op_sub_i32:
2530139c1837SPaolo Bonzini    case INDEX_op_sub_i64:
2531665be288SRichard Henderson        return C_O1_I2(r, rZ, rN);
2532139c1837SPaolo Bonzini
2533139c1837SPaolo Bonzini    case INDEX_op_mul_i32:
2534139c1837SPaolo Bonzini    case INDEX_op_mulsh_i32:
2535139c1837SPaolo Bonzini    case INDEX_op_muluh_i32:
2536139c1837SPaolo Bonzini    case INDEX_op_div_i32:
2537139c1837SPaolo Bonzini    case INDEX_op_divu_i32:
2538139c1837SPaolo Bonzini    case INDEX_op_rem_i32:
2539139c1837SPaolo Bonzini    case INDEX_op_remu_i32:
2540139c1837SPaolo Bonzini    case INDEX_op_mul_i64:
2541139c1837SPaolo Bonzini    case INDEX_op_mulsh_i64:
2542139c1837SPaolo Bonzini    case INDEX_op_muluh_i64:
2543139c1837SPaolo Bonzini    case INDEX_op_div_i64:
2544139c1837SPaolo Bonzini    case INDEX_op_divu_i64:
2545139c1837SPaolo Bonzini    case INDEX_op_rem_i64:
2546139c1837SPaolo Bonzini    case INDEX_op_remu_i64:
2547665be288SRichard Henderson        return C_O1_I2(r, rZ, rZ);
2548139c1837SPaolo Bonzini
2549139c1837SPaolo Bonzini    case INDEX_op_shl_i32:
2550139c1837SPaolo Bonzini    case INDEX_op_shr_i32:
2551139c1837SPaolo Bonzini    case INDEX_op_sar_i32:
255219d016adSRichard Henderson    case INDEX_op_rotl_i32:
255319d016adSRichard Henderson    case INDEX_op_rotr_i32:
2554139c1837SPaolo Bonzini    case INDEX_op_shl_i64:
2555139c1837SPaolo Bonzini    case INDEX_op_shr_i64:
2556139c1837SPaolo Bonzini    case INDEX_op_sar_i64:
255719d016adSRichard Henderson    case INDEX_op_rotl_i64:
255819d016adSRichard Henderson    case INDEX_op_rotr_i64:
2559665be288SRichard Henderson        return C_O1_I2(r, r, ri);
2560139c1837SPaolo Bonzini
2561a30498fcSRichard Henderson    case INDEX_op_clz_i32:
2562a30498fcSRichard Henderson    case INDEX_op_clz_i64:
2563a30498fcSRichard Henderson    case INDEX_op_ctz_i32:
2564a30498fcSRichard Henderson    case INDEX_op_ctz_i64:
2565a30498fcSRichard Henderson        return C_N1_I2(r, r, rM);
2566a30498fcSRichard Henderson
2567139c1837SPaolo Bonzini    case INDEX_op_brcond_i32:
2568139c1837SPaolo Bonzini    case INDEX_op_brcond_i64:
2569665be288SRichard Henderson        return C_O0_I2(rZ, rZ);
2570139c1837SPaolo Bonzini
2571a18d783eSRichard Henderson    case INDEX_op_movcond_i32:
2572a18d783eSRichard Henderson    case INDEX_op_movcond_i64:
2573a18d783eSRichard Henderson        return C_O1_I4(r, r, rI, rM, rM);
2574a18d783eSRichard Henderson
2575139c1837SPaolo Bonzini    case INDEX_op_add2_i32:
2576139c1837SPaolo Bonzini    case INDEX_op_add2_i64:
2577139c1837SPaolo Bonzini    case INDEX_op_sub2_i32:
2578139c1837SPaolo Bonzini    case INDEX_op_sub2_i64:
2579665be288SRichard Henderson        return C_O2_I4(r, r, rZ, rZ, rM, rM);
2580139c1837SPaolo Bonzini
2581fecccfccSRichard Henderson    case INDEX_op_qemu_ld_a32_i32:
2582fecccfccSRichard Henderson    case INDEX_op_qemu_ld_a64_i32:
2583fecccfccSRichard Henderson    case INDEX_op_qemu_ld_a32_i64:
2584fecccfccSRichard Henderson    case INDEX_op_qemu_ld_a64_i64:
2585f0f43534SRichard Henderson        return C_O1_I1(r, r);
2586fecccfccSRichard Henderson    case INDEX_op_qemu_st_a32_i32:
2587fecccfccSRichard Henderson    case INDEX_op_qemu_st_a64_i32:
2588fecccfccSRichard Henderson    case INDEX_op_qemu_st_a32_i64:
2589fecccfccSRichard Henderson    case INDEX_op_qemu_st_a64_i64:
2590f0f43534SRichard Henderson        return C_O0_I2(rZ, r);
2591139c1837SPaolo Bonzini
2592f63e7089SHuang Shiyuan    case INDEX_op_st_vec:
2593f63e7089SHuang Shiyuan        return C_O0_I2(v, r);
2594d4be6ee1STANG Tiancheng    case INDEX_op_dup_vec:
2595d4be6ee1STANG Tiancheng    case INDEX_op_dupm_vec:
2596f63e7089SHuang Shiyuan    case INDEX_op_ld_vec:
2597f63e7089SHuang Shiyuan        return C_O1_I1(v, r);
2598c283c074STANG Tiancheng    case INDEX_op_neg_vec:
25995a63f599STANG Tiancheng    case INDEX_op_not_vec:
26005a63f599STANG Tiancheng        return C_O1_I1(v, v);
26015a63f599STANG Tiancheng    case INDEX_op_add_vec:
26025a63f599STANG Tiancheng    case INDEX_op_and_vec:
26035a63f599STANG Tiancheng    case INDEX_op_or_vec:
26045a63f599STANG Tiancheng    case INDEX_op_xor_vec:
2605*101c1ef5STANG Tiancheng    case INDEX_op_ssadd_vec:
2606*101c1ef5STANG Tiancheng    case INDEX_op_sssub_vec:
2607*101c1ef5STANG Tiancheng    case INDEX_op_usadd_vec:
2608*101c1ef5STANG Tiancheng    case INDEX_op_ussub_vec:
26095a63f599STANG Tiancheng        return C_O1_I2(v, v, vK);
26105a63f599STANG Tiancheng    case INDEX_op_sub_vec:
2611dc9cd4ecSRichard Henderson        return C_O1_I2(v, vK, v);
2612*101c1ef5STANG Tiancheng    case INDEX_op_mul_vec:
2613*101c1ef5STANG Tiancheng        return C_O1_I2(v, v, v);
2614a31768c0STANG Tiancheng    case INDEX_op_cmp_vec:
2615a31768c0STANG Tiancheng        return C_O1_I2(v, v, vL);
2616a31768c0STANG Tiancheng    case INDEX_op_cmpsel_vec:
2617a31768c0STANG Tiancheng        return C_O1_I4(v, v, vL, vK, vK);
2618139c1837SPaolo Bonzini    default:
2619665be288SRichard Henderson        g_assert_not_reached();
2620139c1837SPaolo Bonzini    }
2621139c1837SPaolo Bonzini}
2622139c1837SPaolo Bonzini
2623139c1837SPaolo Bonzinistatic const int tcg_target_callee_save_regs[] = {
2624139c1837SPaolo Bonzini    TCG_REG_S0,       /* used for the global env (TCG_AREG0) */
2625139c1837SPaolo Bonzini    TCG_REG_S1,
2626139c1837SPaolo Bonzini    TCG_REG_S2,
2627139c1837SPaolo Bonzini    TCG_REG_S3,
2628139c1837SPaolo Bonzini    TCG_REG_S4,
2629139c1837SPaolo Bonzini    TCG_REG_S5,
2630139c1837SPaolo Bonzini    TCG_REG_S6,
2631139c1837SPaolo Bonzini    TCG_REG_S7,
2632139c1837SPaolo Bonzini    TCG_REG_S8,
2633139c1837SPaolo Bonzini    TCG_REG_S9,
2634139c1837SPaolo Bonzini    TCG_REG_S10,
2635139c1837SPaolo Bonzini    TCG_REG_S11,
2636139c1837SPaolo Bonzini    TCG_REG_RA,       /* should be last for ABI compliance */
2637139c1837SPaolo Bonzini};
2638139c1837SPaolo Bonzini
2639139c1837SPaolo Bonzini/* Stack frame parameters.  */
2640139c1837SPaolo Bonzini#define REG_SIZE   (TCG_TARGET_REG_BITS / 8)
2641139c1837SPaolo Bonzini#define SAVE_SIZE  ((int)ARRAY_SIZE(tcg_target_callee_save_regs) * REG_SIZE)
2642139c1837SPaolo Bonzini#define TEMP_SIZE  (CPU_TEMP_BUF_NLONGS * (int)sizeof(long))
2643139c1837SPaolo Bonzini#define FRAME_SIZE ((TCG_STATIC_CALL_ARGS_SIZE + TEMP_SIZE + SAVE_SIZE \
2644139c1837SPaolo Bonzini                     + TCG_TARGET_STACK_ALIGN - 1) \
2645139c1837SPaolo Bonzini                    & -TCG_TARGET_STACK_ALIGN)
2646139c1837SPaolo Bonzini#define SAVE_OFS   (TCG_STATIC_CALL_ARGS_SIZE + TEMP_SIZE)
2647139c1837SPaolo Bonzini
2648139c1837SPaolo Bonzini/* We're expecting to be able to use an immediate for frame allocation.  */
2649139c1837SPaolo BonziniQEMU_BUILD_BUG_ON(FRAME_SIZE > 0x7ff);
2650139c1837SPaolo Bonzini
2651139c1837SPaolo Bonzini/* Generate global QEMU prologue and epilogue code */
2652139c1837SPaolo Bonzinistatic void tcg_target_qemu_prologue(TCGContext *s)
2653139c1837SPaolo Bonzini{
2654139c1837SPaolo Bonzini    int i;
2655139c1837SPaolo Bonzini
2656139c1837SPaolo Bonzini    tcg_set_frame(s, TCG_REG_SP, TCG_STATIC_CALL_ARGS_SIZE, TEMP_SIZE);
2657139c1837SPaolo Bonzini
2658139c1837SPaolo Bonzini    /* TB prologue */
2659139c1837SPaolo Bonzini    tcg_out_opc_imm(s, OPC_ADDI, TCG_REG_SP, TCG_REG_SP, -FRAME_SIZE);
2660139c1837SPaolo Bonzini    for (i = 0; i < ARRAY_SIZE(tcg_target_callee_save_regs); i++) {
2661139c1837SPaolo Bonzini        tcg_out_st(s, TCG_TYPE_REG, tcg_target_callee_save_regs[i],
2662139c1837SPaolo Bonzini                   TCG_REG_SP, SAVE_OFS + i * REG_SIZE);
2663139c1837SPaolo Bonzini    }
2664139c1837SPaolo Bonzini
26654944d359SRichard Henderson    if (!tcg_use_softmmu && guest_base) {
2666139c1837SPaolo Bonzini        tcg_out_movi(s, TCG_TYPE_PTR, TCG_GUEST_BASE_REG, guest_base);
2667139c1837SPaolo Bonzini        tcg_regset_set_reg(s->reserved_regs, TCG_GUEST_BASE_REG);
2668cf0ed30eSRichard Henderson    }
2669139c1837SPaolo Bonzini
2670139c1837SPaolo Bonzini    /* Call generated code */
2671139c1837SPaolo Bonzini    tcg_out_mov(s, TCG_TYPE_PTR, TCG_AREG0, tcg_target_call_iarg_regs[0]);
2672139c1837SPaolo Bonzini    tcg_out_opc_imm(s, OPC_JALR, TCG_REG_ZERO, tcg_target_call_iarg_regs[1], 0);
2673139c1837SPaolo Bonzini
2674139c1837SPaolo Bonzini    /* Return path for goto_ptr. Set return value to 0 */
2675c8bc1168SRichard Henderson    tcg_code_gen_epilogue = tcg_splitwx_to_rx(s->code_ptr);
2676139c1837SPaolo Bonzini    tcg_out_mov(s, TCG_TYPE_REG, TCG_REG_A0, TCG_REG_ZERO);
2677139c1837SPaolo Bonzini
2678139c1837SPaolo Bonzini    /* TB epilogue */
2679793f7381SRichard Henderson    tb_ret_addr = tcg_splitwx_to_rx(s->code_ptr);
2680139c1837SPaolo Bonzini    for (i = 0; i < ARRAY_SIZE(tcg_target_callee_save_regs); i++) {
2681139c1837SPaolo Bonzini        tcg_out_ld(s, TCG_TYPE_REG, tcg_target_callee_save_regs[i],
2682139c1837SPaolo Bonzini                   TCG_REG_SP, SAVE_OFS + i * REG_SIZE);
2683139c1837SPaolo Bonzini    }
2684139c1837SPaolo Bonzini
2685139c1837SPaolo Bonzini    tcg_out_opc_imm(s, OPC_ADDI, TCG_REG_SP, TCG_REG_SP, FRAME_SIZE);
2686139c1837SPaolo Bonzini    tcg_out_opc_imm(s, OPC_JALR, TCG_REG_ZERO, TCG_REG_RA, 0);
2687139c1837SPaolo Bonzini}
2688139c1837SPaolo Bonzini
26899358fbbfSRichard Hendersonstatic void tcg_out_tb_start(TCGContext *s)
26909358fbbfSRichard Henderson{
2691f63e7089SHuang Shiyuan    init_setting_vtype(s);
2692f63e7089SHuang Shiyuan}
2693f63e7089SHuang Shiyuan
2694f63e7089SHuang Shiyuanstatic bool vtype_check(unsigned vtype)
2695f63e7089SHuang Shiyuan{
2696f63e7089SHuang Shiyuan    unsigned long tmp;
2697f63e7089SHuang Shiyuan
2698f63e7089SHuang Shiyuan    /* vsetvl tmp, zero, vtype */
2699f63e7089SHuang Shiyuan    asm(".insn r 0x57, 7, 0x40, %0, zero, %1" : "=r"(tmp) : "r"(vtype));
2700f63e7089SHuang Shiyuan    return tmp != 0;
2701f63e7089SHuang Shiyuan}
2702f63e7089SHuang Shiyuan
2703f63e7089SHuang Shiyuanstatic void probe_frac_lmul_1(TCGType type, MemOp vsew)
2704f63e7089SHuang Shiyuan{
2705f63e7089SHuang Shiyuan    VsetCache *p = &riscv_vset_cache[type - TCG_TYPE_V64][vsew];
2706f63e7089SHuang Shiyuan    unsigned avl = tcg_type_size(type) >> vsew;
2707f63e7089SHuang Shiyuan    int lmul = type - riscv_lg2_vlenb;
2708f63e7089SHuang Shiyuan    unsigned vtype = encode_vtype(true, true, vsew, lmul & 7);
2709f63e7089SHuang Shiyuan    bool lmul_eq_avl = true;
2710f63e7089SHuang Shiyuan
2711f63e7089SHuang Shiyuan    /* Guaranteed by Zve64x. */
2712f63e7089SHuang Shiyuan    assert(lmul < 3);
2713f63e7089SHuang Shiyuan
2714f63e7089SHuang Shiyuan    /*
2715f63e7089SHuang Shiyuan     * For LMUL < -3, the host vector size is so large that TYPE
2716f63e7089SHuang Shiyuan     * is smaller than the minimum 1/8 fraction.
2717f63e7089SHuang Shiyuan     *
2718f63e7089SHuang Shiyuan     * For other fractional LMUL settings, implementations must
2719f63e7089SHuang Shiyuan     * support SEW settings between SEW_MIN and LMUL * ELEN, inclusive.
2720f63e7089SHuang Shiyuan     * So if ELEN = 64, LMUL = 1/2, then SEW will support e8, e16, e32,
2721f63e7089SHuang Shiyuan     * but e64 may not be supported. In other words, the hardware only
2722f63e7089SHuang Shiyuan     * guarantees SEW_MIN <= SEW <= LMUL * ELEN.  Check.
2723f63e7089SHuang Shiyuan     */
2724f63e7089SHuang Shiyuan    if (lmul < 0 && (lmul < -3 || !vtype_check(vtype))) {
2725f63e7089SHuang Shiyuan        vtype = encode_vtype(true, true, vsew, VLMUL_M1);
2726f63e7089SHuang Shiyuan        lmul_eq_avl = false;
2727f63e7089SHuang Shiyuan    }
2728f63e7089SHuang Shiyuan
2729f63e7089SHuang Shiyuan    if (avl < 32) {
2730f63e7089SHuang Shiyuan        p->vset_insn = encode_vseti(OPC_VSETIVLI, TCG_REG_ZERO, avl, vtype);
2731f63e7089SHuang Shiyuan    } else if (lmul_eq_avl) {
2732f63e7089SHuang Shiyuan        /* rd != 0 and rs1 == 0 uses vlmax */
2733f63e7089SHuang Shiyuan        p->vset_insn = encode_vset(OPC_VSETVLI, TCG_REG_TMP0, TCG_REG_ZERO, vtype);
2734f63e7089SHuang Shiyuan    } else {
2735f63e7089SHuang Shiyuan        p->movi_insn = encode_i(OPC_ADDI, TCG_REG_TMP0, TCG_REG_ZERO, avl);
2736f63e7089SHuang Shiyuan        p->vset_insn = encode_vset(OPC_VSETVLI, TCG_REG_ZERO, TCG_REG_TMP0, vtype);
2737f63e7089SHuang Shiyuan    }
2738f63e7089SHuang Shiyuan}
2739f63e7089SHuang Shiyuan
2740f63e7089SHuang Shiyuanstatic void probe_frac_lmul(void)
2741f63e7089SHuang Shiyuan{
2742f63e7089SHuang Shiyuan    /* Match riscv_lg2_vlenb to TCG_TYPE_V64. */
2743f63e7089SHuang Shiyuan    QEMU_BUILD_BUG_ON(TCG_TYPE_V64 != 3);
2744f63e7089SHuang Shiyuan
2745f63e7089SHuang Shiyuan    for (TCGType t = TCG_TYPE_V64; t <= TCG_TYPE_V256; t++) {
2746f63e7089SHuang Shiyuan        for (MemOp e = MO_8; e <= MO_64; e++) {
2747f63e7089SHuang Shiyuan            probe_frac_lmul_1(t, e);
2748f63e7089SHuang Shiyuan        }
2749f63e7089SHuang Shiyuan    }
27509358fbbfSRichard Henderson}
27519358fbbfSRichard Henderson
2752139c1837SPaolo Bonzinistatic void tcg_target_init(TCGContext *s)
2753139c1837SPaolo Bonzini{
2754139c1837SPaolo Bonzini    tcg_target_available_regs[TCG_TYPE_I32] = 0xffffffff;
2755139c1837SPaolo Bonzini    tcg_target_available_regs[TCG_TYPE_I64] = 0xffffffff;
2756139c1837SPaolo Bonzini
2757f63e7089SHuang Shiyuan    tcg_target_call_clobber_regs = -1;
2758139c1837SPaolo Bonzini    tcg_regset_reset_reg(tcg_target_call_clobber_regs, TCG_REG_S0);
2759139c1837SPaolo Bonzini    tcg_regset_reset_reg(tcg_target_call_clobber_regs, TCG_REG_S1);
2760139c1837SPaolo Bonzini    tcg_regset_reset_reg(tcg_target_call_clobber_regs, TCG_REG_S2);
2761139c1837SPaolo Bonzini    tcg_regset_reset_reg(tcg_target_call_clobber_regs, TCG_REG_S3);
2762139c1837SPaolo Bonzini    tcg_regset_reset_reg(tcg_target_call_clobber_regs, TCG_REG_S4);
2763139c1837SPaolo Bonzini    tcg_regset_reset_reg(tcg_target_call_clobber_regs, TCG_REG_S5);
2764139c1837SPaolo Bonzini    tcg_regset_reset_reg(tcg_target_call_clobber_regs, TCG_REG_S6);
2765139c1837SPaolo Bonzini    tcg_regset_reset_reg(tcg_target_call_clobber_regs, TCG_REG_S7);
2766139c1837SPaolo Bonzini    tcg_regset_reset_reg(tcg_target_call_clobber_regs, TCG_REG_S8);
2767139c1837SPaolo Bonzini    tcg_regset_reset_reg(tcg_target_call_clobber_regs, TCG_REG_S9);
2768139c1837SPaolo Bonzini    tcg_regset_reset_reg(tcg_target_call_clobber_regs, TCG_REG_S10);
2769139c1837SPaolo Bonzini    tcg_regset_reset_reg(tcg_target_call_clobber_regs, TCG_REG_S11);
2770139c1837SPaolo Bonzini
2771139c1837SPaolo Bonzini    s->reserved_regs = 0;
2772139c1837SPaolo Bonzini    tcg_regset_set_reg(s->reserved_regs, TCG_REG_ZERO);
2773139c1837SPaolo Bonzini    tcg_regset_set_reg(s->reserved_regs, TCG_REG_TMP0);
2774139c1837SPaolo Bonzini    tcg_regset_set_reg(s->reserved_regs, TCG_REG_TMP1);
2775139c1837SPaolo Bonzini    tcg_regset_set_reg(s->reserved_regs, TCG_REG_TMP2);
2776139c1837SPaolo Bonzini    tcg_regset_set_reg(s->reserved_regs, TCG_REG_SP);
2777139c1837SPaolo Bonzini    tcg_regset_set_reg(s->reserved_regs, TCG_REG_GP);
2778139c1837SPaolo Bonzini    tcg_regset_set_reg(s->reserved_regs, TCG_REG_TP);
2779f63e7089SHuang Shiyuan
2780f63e7089SHuang Shiyuan    if (cpuinfo & CPUINFO_ZVE64X) {
2781f63e7089SHuang Shiyuan        switch (riscv_lg2_vlenb) {
2782f63e7089SHuang Shiyuan        case TCG_TYPE_V64:
2783f63e7089SHuang Shiyuan            tcg_target_available_regs[TCG_TYPE_V64] = ALL_VECTOR_REGS;
2784f63e7089SHuang Shiyuan            tcg_target_available_regs[TCG_TYPE_V128] = ALL_DVECTOR_REG_GROUPS;
2785f63e7089SHuang Shiyuan            tcg_target_available_regs[TCG_TYPE_V256] = ALL_QVECTOR_REG_GROUPS;
2786f63e7089SHuang Shiyuan            s->reserved_regs |= (~ALL_QVECTOR_REG_GROUPS & ALL_VECTOR_REGS);
2787f63e7089SHuang Shiyuan            break;
2788f63e7089SHuang Shiyuan        case TCG_TYPE_V128:
2789f63e7089SHuang Shiyuan            tcg_target_available_regs[TCG_TYPE_V64] = ALL_VECTOR_REGS;
2790f63e7089SHuang Shiyuan            tcg_target_available_regs[TCG_TYPE_V128] = ALL_VECTOR_REGS;
2791f63e7089SHuang Shiyuan            tcg_target_available_regs[TCG_TYPE_V256] = ALL_DVECTOR_REG_GROUPS;
2792f63e7089SHuang Shiyuan            s->reserved_regs |= (~ALL_DVECTOR_REG_GROUPS & ALL_VECTOR_REGS);
2793f63e7089SHuang Shiyuan            break;
2794f63e7089SHuang Shiyuan        default:
2795f63e7089SHuang Shiyuan            /* Guaranteed by Zve64x. */
2796f63e7089SHuang Shiyuan            tcg_debug_assert(riscv_lg2_vlenb >= TCG_TYPE_V256);
2797f63e7089SHuang Shiyuan            tcg_target_available_regs[TCG_TYPE_V64] = ALL_VECTOR_REGS;
2798f63e7089SHuang Shiyuan            tcg_target_available_regs[TCG_TYPE_V128] = ALL_VECTOR_REGS;
2799f63e7089SHuang Shiyuan            tcg_target_available_regs[TCG_TYPE_V256] = ALL_VECTOR_REGS;
2800f63e7089SHuang Shiyuan            break;
2801f63e7089SHuang Shiyuan        }
2802f63e7089SHuang Shiyuan        tcg_regset_set_reg(s->reserved_regs, TCG_REG_V0);
2803f63e7089SHuang Shiyuan        probe_frac_lmul();
2804f63e7089SHuang Shiyuan    }
2805139c1837SPaolo Bonzini}
2806139c1837SPaolo Bonzini
2807139c1837SPaolo Bonzinitypedef struct {
2808139c1837SPaolo Bonzini    DebugFrameHeader h;
2809139c1837SPaolo Bonzini    uint8_t fde_def_cfa[4];
2810139c1837SPaolo Bonzini    uint8_t fde_reg_ofs[ARRAY_SIZE(tcg_target_callee_save_regs) * 2];
2811139c1837SPaolo Bonzini} DebugFrame;
2812139c1837SPaolo Bonzini
2813139c1837SPaolo Bonzini#define ELF_HOST_MACHINE EM_RISCV
2814139c1837SPaolo Bonzini
2815139c1837SPaolo Bonzinistatic const DebugFrame debug_frame = {
2816139c1837SPaolo Bonzini    .h.cie.len = sizeof(DebugFrameCIE) - 4, /* length after .len member */
2817139c1837SPaolo Bonzini    .h.cie.id = -1,
2818139c1837SPaolo Bonzini    .h.cie.version = 1,
2819139c1837SPaolo Bonzini    .h.cie.code_align = 1,
2820139c1837SPaolo Bonzini    .h.cie.data_align = -(TCG_TARGET_REG_BITS / 8) & 0x7f, /* sleb128 */
2821139c1837SPaolo Bonzini    .h.cie.return_column = TCG_REG_RA,
2822139c1837SPaolo Bonzini
2823139c1837SPaolo Bonzini    /* Total FDE size does not include the "len" member.  */
2824139c1837SPaolo Bonzini    .h.fde.len = sizeof(DebugFrame) - offsetof(DebugFrame, h.fde.cie_offset),
2825139c1837SPaolo Bonzini
2826139c1837SPaolo Bonzini    .fde_def_cfa = {
2827139c1837SPaolo Bonzini        12, TCG_REG_SP,                 /* DW_CFA_def_cfa sp, ... */
2828139c1837SPaolo Bonzini        (FRAME_SIZE & 0x7f) | 0x80,     /* ... uleb128 FRAME_SIZE */
2829139c1837SPaolo Bonzini        (FRAME_SIZE >> 7)
2830139c1837SPaolo Bonzini    },
2831139c1837SPaolo Bonzini    .fde_reg_ofs = {
2832139c1837SPaolo Bonzini        0x80 + 9,  12,                  /* DW_CFA_offset, s1,  -96 */
2833139c1837SPaolo Bonzini        0x80 + 18, 11,                  /* DW_CFA_offset, s2,  -88 */
2834139c1837SPaolo Bonzini        0x80 + 19, 10,                  /* DW_CFA_offset, s3,  -80 */
2835139c1837SPaolo Bonzini        0x80 + 20, 9,                   /* DW_CFA_offset, s4,  -72 */
2836139c1837SPaolo Bonzini        0x80 + 21, 8,                   /* DW_CFA_offset, s5,  -64 */
2837139c1837SPaolo Bonzini        0x80 + 22, 7,                   /* DW_CFA_offset, s6,  -56 */
2838139c1837SPaolo Bonzini        0x80 + 23, 6,                   /* DW_CFA_offset, s7,  -48 */
2839139c1837SPaolo Bonzini        0x80 + 24, 5,                   /* DW_CFA_offset, s8,  -40 */
2840139c1837SPaolo Bonzini        0x80 + 25, 4,                   /* DW_CFA_offset, s9,  -32 */
2841139c1837SPaolo Bonzini        0x80 + 26, 3,                   /* DW_CFA_offset, s10, -24 */
2842139c1837SPaolo Bonzini        0x80 + 27, 2,                   /* DW_CFA_offset, s11, -16 */
2843139c1837SPaolo Bonzini        0x80 + 1 , 1,                   /* DW_CFA_offset, ra,  -8 */
2844139c1837SPaolo Bonzini    }
2845139c1837SPaolo Bonzini};
2846139c1837SPaolo Bonzini
2847755bf9e5SRichard Hendersonvoid tcg_register_jit(const void *buf, size_t buf_size)
2848139c1837SPaolo Bonzini{
2849139c1837SPaolo Bonzini    tcg_register_jit_int(buf, buf_size, &debug_frame, sizeof(debug_frame));
2850139c1837SPaolo Bonzini}
2851