xref: /openbmc/qemu/tcg/riscv/tcg-target.c.inc (revision 1631f19b04fe29ba6c3c75a8c6decd3856da4853)
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
287101c1ef5STANG Tiancheng    OPC_VMUL_VV = 0x94000057 | V_OPMVV,
288101c1ef5STANG Tiancheng    OPC_VSADD_VV = 0x84000057 | V_OPIVV,
289101c1ef5STANG Tiancheng    OPC_VSADD_VI = 0x84000057 | V_OPIVI,
290101c1ef5STANG Tiancheng    OPC_VSSUB_VV = 0x8c000057 | V_OPIVV,
291101c1ef5STANG Tiancheng    OPC_VSSUB_VI = 0x8c000057 | V_OPIVI,
292101c1ef5STANG Tiancheng    OPC_VSADDU_VV = 0x80000057 | V_OPIVV,
293101c1ef5STANG Tiancheng    OPC_VSADDU_VI = 0x80000057 | V_OPIVI,
294101c1ef5STANG Tiancheng    OPC_VSSUBU_VV = 0x88000057 | V_OPIVV,
295101c1ef5STANG Tiancheng    OPC_VSSUBU_VI = 0x88000057 | V_OPIVI,
296101c1ef5STANG Tiancheng
297*1631f19bSTANG Tiancheng    OPC_VMAX_VV = 0x1c000057 | V_OPIVV,
298*1631f19bSTANG Tiancheng    OPC_VMAX_VI = 0x1c000057 | V_OPIVI,
299*1631f19bSTANG Tiancheng    OPC_VMAXU_VV = 0x18000057 | V_OPIVV,
300*1631f19bSTANG Tiancheng    OPC_VMAXU_VI = 0x18000057 | V_OPIVI,
301*1631f19bSTANG Tiancheng    OPC_VMIN_VV = 0x14000057 | V_OPIVV,
302*1631f19bSTANG Tiancheng    OPC_VMIN_VI = 0x14000057 | V_OPIVI,
303*1631f19bSTANG Tiancheng    OPC_VMINU_VV = 0x10000057 | V_OPIVV,
304*1631f19bSTANG Tiancheng    OPC_VMINU_VI = 0x10000057 | V_OPIVI,
305*1631f19bSTANG Tiancheng
306a31768c0STANG Tiancheng    OPC_VMSEQ_VV = 0x60000057 | V_OPIVV,
307a31768c0STANG Tiancheng    OPC_VMSEQ_VI = 0x60000057 | V_OPIVI,
308a31768c0STANG Tiancheng    OPC_VMSEQ_VX = 0x60000057 | V_OPIVX,
309a31768c0STANG Tiancheng    OPC_VMSNE_VV = 0x64000057 | V_OPIVV,
310a31768c0STANG Tiancheng    OPC_VMSNE_VI = 0x64000057 | V_OPIVI,
311a31768c0STANG Tiancheng    OPC_VMSNE_VX = 0x64000057 | V_OPIVX,
312a31768c0STANG Tiancheng
313a31768c0STANG Tiancheng    OPC_VMSLTU_VV = 0x68000057 | V_OPIVV,
314a31768c0STANG Tiancheng    OPC_VMSLTU_VX = 0x68000057 | V_OPIVX,
315a31768c0STANG Tiancheng    OPC_VMSLT_VV = 0x6c000057 | V_OPIVV,
316a31768c0STANG Tiancheng    OPC_VMSLT_VX = 0x6c000057 | V_OPIVX,
317a31768c0STANG Tiancheng    OPC_VMSLEU_VV = 0x70000057 | V_OPIVV,
318a31768c0STANG Tiancheng    OPC_VMSLEU_VX = 0x70000057 | V_OPIVX,
319a31768c0STANG Tiancheng    OPC_VMSLE_VV = 0x74000057 | V_OPIVV,
320a31768c0STANG Tiancheng    OPC_VMSLE_VX = 0x74000057 | V_OPIVX,
321a31768c0STANG Tiancheng
322a31768c0STANG Tiancheng    OPC_VMSLEU_VI = 0x70000057 | V_OPIVI,
323a31768c0STANG Tiancheng    OPC_VMSLE_VI = 0x74000057 | V_OPIVI,
324a31768c0STANG Tiancheng    OPC_VMSGTU_VI = 0x78000057 | V_OPIVI,
325a31768c0STANG Tiancheng    OPC_VMSGTU_VX = 0x78000057 | V_OPIVX,
326a31768c0STANG Tiancheng    OPC_VMSGT_VI = 0x7c000057 | V_OPIVI,
327a31768c0STANG Tiancheng    OPC_VMSGT_VX = 0x7c000057 | V_OPIVX,
328a31768c0STANG Tiancheng
329d4be6ee1STANG Tiancheng    OPC_VMV_V_V = 0x5e000057 | V_OPIVV,
330d4be6ee1STANG Tiancheng    OPC_VMV_V_I = 0x5e000057 | V_OPIVI,
331d4be6ee1STANG Tiancheng    OPC_VMV_V_X = 0x5e000057 | V_OPIVX,
332d4be6ee1STANG Tiancheng
333d4be6ee1STANG Tiancheng    OPC_VMVNR_V = 0x9e000057 | V_OPIVI,
334139c1837SPaolo Bonzini} RISCVInsn;
335139c1837SPaolo Bonzini
336a31768c0STANG Tianchengstatic const struct {
337a31768c0STANG Tiancheng    RISCVInsn op;
338a31768c0STANG Tiancheng    bool swap;
339a31768c0STANG Tiancheng} tcg_cmpcond_to_rvv_vv[] = {
340a31768c0STANG Tiancheng    [TCG_COND_EQ] =  { OPC_VMSEQ_VV,  false },
341a31768c0STANG Tiancheng    [TCG_COND_NE] =  { OPC_VMSNE_VV,  false },
342a31768c0STANG Tiancheng    [TCG_COND_LT] =  { OPC_VMSLT_VV,  false },
343a31768c0STANG Tiancheng    [TCG_COND_GE] =  { OPC_VMSLE_VV,  true  },
344a31768c0STANG Tiancheng    [TCG_COND_GT] =  { OPC_VMSLT_VV,  true  },
345a31768c0STANG Tiancheng    [TCG_COND_LE] =  { OPC_VMSLE_VV,  false },
346a31768c0STANG Tiancheng    [TCG_COND_LTU] = { OPC_VMSLTU_VV, false },
347a31768c0STANG Tiancheng    [TCG_COND_GEU] = { OPC_VMSLEU_VV, true  },
348a31768c0STANG Tiancheng    [TCG_COND_GTU] = { OPC_VMSLTU_VV, true  },
349a31768c0STANG Tiancheng    [TCG_COND_LEU] = { OPC_VMSLEU_VV, false }
350a31768c0STANG Tiancheng};
351a31768c0STANG Tiancheng
352a31768c0STANG Tianchengstatic const struct {
353a31768c0STANG Tiancheng    RISCVInsn op;
354a31768c0STANG Tiancheng    int min;
355a31768c0STANG Tiancheng    int max;
356a31768c0STANG Tiancheng    bool adjust;
357a31768c0STANG Tiancheng}  tcg_cmpcond_to_rvv_vi[] = {
358a31768c0STANG Tiancheng    [TCG_COND_EQ]  = { OPC_VMSEQ_VI,  -16, 15, false },
359a31768c0STANG Tiancheng    [TCG_COND_NE]  = { OPC_VMSNE_VI,  -16, 15, false },
360a31768c0STANG Tiancheng    [TCG_COND_GT]  = { OPC_VMSGT_VI,  -16, 15, false },
361a31768c0STANG Tiancheng    [TCG_COND_LE]  = { OPC_VMSLE_VI,  -16, 15, false },
362a31768c0STANG Tiancheng    [TCG_COND_LT]  = { OPC_VMSLE_VI,  -15, 16, true  },
363a31768c0STANG Tiancheng    [TCG_COND_GE]  = { OPC_VMSGT_VI,  -15, 16, true  },
364a31768c0STANG Tiancheng    [TCG_COND_LEU] = { OPC_VMSLEU_VI,   0, 15, false },
365a31768c0STANG Tiancheng    [TCG_COND_GTU] = { OPC_VMSGTU_VI,   0, 15, false },
366a31768c0STANG Tiancheng    [TCG_COND_LTU] = { OPC_VMSLEU_VI,   1, 16, true  },
367a31768c0STANG Tiancheng    [TCG_COND_GEU] = { OPC_VMSGTU_VI,   1, 16, true  },
368a31768c0STANG Tiancheng};
369a31768c0STANG Tiancheng
370a31768c0STANG Tiancheng/* test if a constant matches the constraint */
371a31768c0STANG Tianchengstatic bool tcg_target_const_match(int64_t val, int ct,
372a31768c0STANG Tiancheng                                   TCGType type, TCGCond cond, int vece)
373a31768c0STANG Tiancheng{
374a31768c0STANG Tiancheng    if (ct & TCG_CT_CONST) {
375a31768c0STANG Tiancheng        return 1;
376a31768c0STANG Tiancheng    }
377a31768c0STANG Tiancheng    if ((ct & TCG_CT_CONST_ZERO) && val == 0) {
378a31768c0STANG Tiancheng        return 1;
379a31768c0STANG Tiancheng    }
380a31768c0STANG Tiancheng    if (type >= TCG_TYPE_V64) {
381a31768c0STANG Tiancheng        /* Val is replicated by VECE; extract the highest element. */
382a31768c0STANG Tiancheng        val >>= (-8 << vece) & 63;
383a31768c0STANG Tiancheng    }
384a31768c0STANG Tiancheng    /*
385a31768c0STANG Tiancheng     * Sign extended from 12 bits: [-0x800, 0x7ff].
386a31768c0STANG Tiancheng     * Used for most arithmetic, as this is the isa field.
387a31768c0STANG Tiancheng     */
388a31768c0STANG Tiancheng    if ((ct & TCG_CT_CONST_S12) && val >= -0x800 && val <= 0x7ff) {
389a31768c0STANG Tiancheng        return 1;
390a31768c0STANG Tiancheng    }
391a31768c0STANG Tiancheng    /*
392a31768c0STANG Tiancheng     * Sign extended from 12 bits, negated: [-0x7ff, 0x800].
393a31768c0STANG Tiancheng     * Used for subtraction, where a constant must be handled by ADDI.
394a31768c0STANG Tiancheng     */
395a31768c0STANG Tiancheng    if ((ct & TCG_CT_CONST_N12) && val >= -0x7ff && val <= 0x800) {
396a31768c0STANG Tiancheng        return 1;
397a31768c0STANG Tiancheng    }
398a31768c0STANG Tiancheng    /*
399a31768c0STANG Tiancheng     * Sign extended from 12 bits, +/- matching: [-0x7ff, 0x7ff].
400a31768c0STANG Tiancheng     * Used by addsub2 and movcond, which may need the negative value,
401a31768c0STANG Tiancheng     * and requires the modified constant to be representable.
402a31768c0STANG Tiancheng     */
403a31768c0STANG Tiancheng    if ((ct & TCG_CT_CONST_M12) && val >= -0x7ff && val <= 0x7ff) {
404a31768c0STANG Tiancheng        return 1;
405a31768c0STANG Tiancheng    }
406a31768c0STANG Tiancheng    /*
407a31768c0STANG Tiancheng     * Inverse of sign extended from 12 bits: ~[-0x800, 0x7ff].
408a31768c0STANG Tiancheng     * Used to map ANDN back to ANDI, etc.
409a31768c0STANG Tiancheng     */
410a31768c0STANG Tiancheng    if ((ct & TCG_CT_CONST_J12) && ~val >= -0x800 && ~val <= 0x7ff) {
411a31768c0STANG Tiancheng        return 1;
412a31768c0STANG Tiancheng    }
413a31768c0STANG Tiancheng    /*
414a31768c0STANG Tiancheng     * Sign extended from 5 bits: [-0x10, 0x0f].
415a31768c0STANG Tiancheng     * Used for vector-immediate.
416a31768c0STANG Tiancheng     */
417a31768c0STANG Tiancheng    if ((ct & TCG_CT_CONST_S5) && val >= -0x10 && val <= 0x0f) {
418a31768c0STANG Tiancheng        return 1;
419a31768c0STANG Tiancheng    }
420a31768c0STANG Tiancheng    /*
421a31768c0STANG Tiancheng     * Used for vector compare OPIVI instructions.
422a31768c0STANG Tiancheng     */
423a31768c0STANG Tiancheng    if ((ct & TCG_CT_CONST_CMP_VI) &&
424a31768c0STANG Tiancheng        val >= tcg_cmpcond_to_rvv_vi[cond].min &&
425a31768c0STANG Tiancheng        val <= tcg_cmpcond_to_rvv_vi[cond].max) {
426a31768c0STANG Tiancheng        return true;
427a31768c0STANG Tiancheng     }
428a31768c0STANG Tiancheng    return 0;
429a31768c0STANG Tiancheng}
430a31768c0STANG Tiancheng
431139c1837SPaolo Bonzini/*
432139c1837SPaolo Bonzini * RISC-V immediate and instruction encoders (excludes 16-bit RVC)
433139c1837SPaolo Bonzini */
434139c1837SPaolo Bonzini
435139c1837SPaolo Bonzini/* Type-R */
436139c1837SPaolo Bonzini
437139c1837SPaolo Bonzinistatic int32_t encode_r(RISCVInsn opc, TCGReg rd, TCGReg rs1, TCGReg rs2)
438139c1837SPaolo Bonzini{
439139c1837SPaolo Bonzini    return opc | (rd & 0x1f) << 7 | (rs1 & 0x1f) << 15 | (rs2 & 0x1f) << 20;
440139c1837SPaolo Bonzini}
441139c1837SPaolo Bonzini
442139c1837SPaolo Bonzini/* Type-I */
443139c1837SPaolo Bonzini
444139c1837SPaolo Bonzinistatic int32_t encode_imm12(uint32_t imm)
445139c1837SPaolo Bonzini{
446139c1837SPaolo Bonzini    return (imm & 0xfff) << 20;
447139c1837SPaolo Bonzini}
448139c1837SPaolo Bonzini
449139c1837SPaolo Bonzinistatic int32_t encode_i(RISCVInsn opc, TCGReg rd, TCGReg rs1, uint32_t imm)
450139c1837SPaolo Bonzini{
451139c1837SPaolo Bonzini    return opc | (rd & 0x1f) << 7 | (rs1 & 0x1f) << 15 | encode_imm12(imm);
452139c1837SPaolo Bonzini}
453139c1837SPaolo Bonzini
454139c1837SPaolo Bonzini/* Type-S */
455139c1837SPaolo Bonzini
456139c1837SPaolo Bonzinistatic int32_t encode_simm12(uint32_t imm)
457139c1837SPaolo Bonzini{
458139c1837SPaolo Bonzini    int32_t ret = 0;
459139c1837SPaolo Bonzini
460139c1837SPaolo Bonzini    ret |= (imm & 0xFE0) << 20;
461139c1837SPaolo Bonzini    ret |= (imm & 0x1F) << 7;
462139c1837SPaolo Bonzini
463139c1837SPaolo Bonzini    return ret;
464139c1837SPaolo Bonzini}
465139c1837SPaolo Bonzini
466139c1837SPaolo Bonzinistatic int32_t encode_s(RISCVInsn opc, TCGReg rs1, TCGReg rs2, uint32_t imm)
467139c1837SPaolo Bonzini{
468139c1837SPaolo Bonzini    return opc | (rs1 & 0x1f) << 15 | (rs2 & 0x1f) << 20 | encode_simm12(imm);
469139c1837SPaolo Bonzini}
470139c1837SPaolo Bonzini
471139c1837SPaolo Bonzini/* Type-SB */
472139c1837SPaolo Bonzini
473139c1837SPaolo Bonzinistatic int32_t encode_sbimm12(uint32_t imm)
474139c1837SPaolo Bonzini{
475139c1837SPaolo Bonzini    int32_t ret = 0;
476139c1837SPaolo Bonzini
477139c1837SPaolo Bonzini    ret |= (imm & 0x1000) << 19;
478139c1837SPaolo Bonzini    ret |= (imm & 0x7e0) << 20;
479139c1837SPaolo Bonzini    ret |= (imm & 0x1e) << 7;
480139c1837SPaolo Bonzini    ret |= (imm & 0x800) >> 4;
481139c1837SPaolo Bonzini
482139c1837SPaolo Bonzini    return ret;
483139c1837SPaolo Bonzini}
484139c1837SPaolo Bonzini
485139c1837SPaolo Bonzinistatic int32_t encode_sb(RISCVInsn opc, TCGReg rs1, TCGReg rs2, uint32_t imm)
486139c1837SPaolo Bonzini{
487139c1837SPaolo Bonzini    return opc | (rs1 & 0x1f) << 15 | (rs2 & 0x1f) << 20 | encode_sbimm12(imm);
488139c1837SPaolo Bonzini}
489139c1837SPaolo Bonzini
490139c1837SPaolo Bonzini/* Type-U */
491139c1837SPaolo Bonzini
492139c1837SPaolo Bonzinistatic int32_t encode_uimm20(uint32_t imm)
493139c1837SPaolo Bonzini{
494139c1837SPaolo Bonzini    return imm & 0xfffff000;
495139c1837SPaolo Bonzini}
496139c1837SPaolo Bonzini
497139c1837SPaolo Bonzinistatic int32_t encode_u(RISCVInsn opc, TCGReg rd, uint32_t imm)
498139c1837SPaolo Bonzini{
499139c1837SPaolo Bonzini    return opc | (rd & 0x1f) << 7 | encode_uimm20(imm);
500139c1837SPaolo Bonzini}
501139c1837SPaolo Bonzini
502139c1837SPaolo Bonzini/* Type-UJ */
503139c1837SPaolo Bonzini
504139c1837SPaolo Bonzinistatic int32_t encode_ujimm20(uint32_t imm)
505139c1837SPaolo Bonzini{
506139c1837SPaolo Bonzini    int32_t ret = 0;
507139c1837SPaolo Bonzini
508139c1837SPaolo Bonzini    ret |= (imm & 0x0007fe) << (21 - 1);
509139c1837SPaolo Bonzini    ret |= (imm & 0x000800) << (20 - 11);
510139c1837SPaolo Bonzini    ret |= (imm & 0x0ff000) << (12 - 12);
511139c1837SPaolo Bonzini    ret |= (imm & 0x100000) << (31 - 20);
512139c1837SPaolo Bonzini
513139c1837SPaolo Bonzini    return ret;
514139c1837SPaolo Bonzini}
515139c1837SPaolo Bonzini
516139c1837SPaolo Bonzinistatic int32_t encode_uj(RISCVInsn opc, TCGReg rd, uint32_t imm)
517139c1837SPaolo Bonzini{
518139c1837SPaolo Bonzini    return opc | (rd & 0x1f) << 7 | encode_ujimm20(imm);
519139c1837SPaolo Bonzini}
520139c1837SPaolo Bonzini
521d4be6ee1STANG Tiancheng
522d4be6ee1STANG Tiancheng/* Type-OPIVI */
523d4be6ee1STANG Tiancheng
524d4be6ee1STANG Tianchengstatic int32_t encode_vi(RISCVInsn opc, TCGReg rd, int32_t imm,
525d4be6ee1STANG Tiancheng                         TCGReg vs2, bool vm)
526d4be6ee1STANG Tiancheng{
527d4be6ee1STANG Tiancheng    return opc | (rd & 0x1f) << 7 | (imm & 0x1f) << 15 |
528d4be6ee1STANG Tiancheng           (vs2 & 0x1f) << 20 | (vm << 25);
529d4be6ee1STANG Tiancheng}
530d4be6ee1STANG Tiancheng
531f63e7089SHuang Shiyuan/* Type-OPIVV/OPMVV/OPIVX/OPMVX, Vector load and store */
532f63e7089SHuang Shiyuan
533f63e7089SHuang Shiyuanstatic int32_t encode_v(RISCVInsn opc, TCGReg d, TCGReg s1,
534f63e7089SHuang Shiyuan                        TCGReg s2, bool vm)
535f63e7089SHuang Shiyuan{
536f63e7089SHuang Shiyuan    return opc | (d & 0x1f) << 7 | (s1 & 0x1f) << 15 |
537f63e7089SHuang Shiyuan           (s2 & 0x1f) << 20 | (vm << 25);
538f63e7089SHuang Shiyuan}
539f63e7089SHuang Shiyuan
540f63e7089SHuang Shiyuan/* Vector vtype */
541f63e7089SHuang Shiyuan
542f63e7089SHuang Shiyuanstatic uint32_t encode_vtype(bool vta, bool vma,
543f63e7089SHuang Shiyuan                            MemOp vsew, RISCVVlmul vlmul)
544f63e7089SHuang Shiyuan{
545f63e7089SHuang Shiyuan    return vma << 7 | vta << 6 | vsew << 3 | vlmul;
546f63e7089SHuang Shiyuan}
547f63e7089SHuang Shiyuan
548f63e7089SHuang Shiyuanstatic int32_t encode_vset(RISCVInsn opc, TCGReg rd,
549f63e7089SHuang Shiyuan                           TCGArg rs1, uint32_t vtype)
550f63e7089SHuang Shiyuan{
551f63e7089SHuang Shiyuan    return opc | (rd & 0x1f) << 7 | (rs1 & 0x1f) << 15 | (vtype & 0x7ff) << 20;
552f63e7089SHuang Shiyuan}
553f63e7089SHuang Shiyuan
554f63e7089SHuang Shiyuanstatic int32_t encode_vseti(RISCVInsn opc, TCGReg rd,
555f63e7089SHuang Shiyuan                            uint32_t uimm, uint32_t vtype)
556f63e7089SHuang Shiyuan{
557f63e7089SHuang Shiyuan    return opc | (rd & 0x1f) << 7 | (uimm & 0x1f) << 15 | (vtype & 0x3ff) << 20;
558f63e7089SHuang Shiyuan}
559f63e7089SHuang Shiyuan
560139c1837SPaolo Bonzini/*
561139c1837SPaolo Bonzini * RISC-V instruction emitters
562139c1837SPaolo Bonzini */
563139c1837SPaolo Bonzini
564139c1837SPaolo Bonzinistatic void tcg_out_opc_reg(TCGContext *s, RISCVInsn opc,
565139c1837SPaolo Bonzini                            TCGReg rd, TCGReg rs1, TCGReg rs2)
566139c1837SPaolo Bonzini{
567139c1837SPaolo Bonzini    tcg_out32(s, encode_r(opc, rd, rs1, rs2));
568139c1837SPaolo Bonzini}
569139c1837SPaolo Bonzini
570139c1837SPaolo Bonzinistatic void tcg_out_opc_imm(TCGContext *s, RISCVInsn opc,
571139c1837SPaolo Bonzini                            TCGReg rd, TCGReg rs1, TCGArg imm)
572139c1837SPaolo Bonzini{
573139c1837SPaolo Bonzini    tcg_out32(s, encode_i(opc, rd, rs1, imm));
574139c1837SPaolo Bonzini}
575139c1837SPaolo Bonzini
576139c1837SPaolo Bonzinistatic void tcg_out_opc_store(TCGContext *s, RISCVInsn opc,
577139c1837SPaolo Bonzini                              TCGReg rs1, TCGReg rs2, uint32_t imm)
578139c1837SPaolo Bonzini{
579139c1837SPaolo Bonzini    tcg_out32(s, encode_s(opc, rs1, rs2, imm));
580139c1837SPaolo Bonzini}
581139c1837SPaolo Bonzini
582139c1837SPaolo Bonzinistatic void tcg_out_opc_branch(TCGContext *s, RISCVInsn opc,
583139c1837SPaolo Bonzini                               TCGReg rs1, TCGReg rs2, uint32_t imm)
584139c1837SPaolo Bonzini{
585139c1837SPaolo Bonzini    tcg_out32(s, encode_sb(opc, rs1, rs2, imm));
586139c1837SPaolo Bonzini}
587139c1837SPaolo Bonzini
588139c1837SPaolo Bonzinistatic void tcg_out_opc_upper(TCGContext *s, RISCVInsn opc,
589139c1837SPaolo Bonzini                              TCGReg rd, uint32_t imm)
590139c1837SPaolo Bonzini{
591139c1837SPaolo Bonzini    tcg_out32(s, encode_u(opc, rd, imm));
592139c1837SPaolo Bonzini}
593139c1837SPaolo Bonzini
594139c1837SPaolo Bonzinistatic void tcg_out_opc_jump(TCGContext *s, RISCVInsn opc,
595139c1837SPaolo Bonzini                             TCGReg rd, uint32_t imm)
596139c1837SPaolo Bonzini{
597139c1837SPaolo Bonzini    tcg_out32(s, encode_uj(opc, rd, imm));
598139c1837SPaolo Bonzini}
599139c1837SPaolo Bonzini
600139c1837SPaolo Bonzinistatic void tcg_out_nop_fill(tcg_insn_unit *p, int count)
601139c1837SPaolo Bonzini{
602139c1837SPaolo Bonzini    int i;
603139c1837SPaolo Bonzini    for (i = 0; i < count; ++i) {
6049ae958e4SRichard Henderson        p[i] = OPC_NOP;
605139c1837SPaolo Bonzini    }
606139c1837SPaolo Bonzini}
607139c1837SPaolo Bonzini
608139c1837SPaolo Bonzini/*
609139c1837SPaolo Bonzini * Relocations
610139c1837SPaolo Bonzini */
611139c1837SPaolo Bonzini
612793f7381SRichard Hendersonstatic bool reloc_sbimm12(tcg_insn_unit *src_rw, const tcg_insn_unit *target)
613139c1837SPaolo Bonzini{
614793f7381SRichard Henderson    const tcg_insn_unit *src_rx = tcg_splitwx_to_rx(src_rw);
615793f7381SRichard Henderson    intptr_t offset = (intptr_t)target - (intptr_t)src_rx;
616139c1837SPaolo Bonzini
617844d0442SRichard Henderson    tcg_debug_assert((offset & 1) == 0);
618844d0442SRichard Henderson    if (offset == sextreg(offset, 0, 12)) {
619793f7381SRichard Henderson        *src_rw |= encode_sbimm12(offset);
620139c1837SPaolo Bonzini        return true;
621139c1837SPaolo Bonzini    }
622139c1837SPaolo Bonzini
623139c1837SPaolo Bonzini    return false;
624139c1837SPaolo Bonzini}
625139c1837SPaolo Bonzini
626793f7381SRichard Hendersonstatic bool reloc_jimm20(tcg_insn_unit *src_rw, const tcg_insn_unit *target)
627139c1837SPaolo Bonzini{
628793f7381SRichard Henderson    const tcg_insn_unit *src_rx = tcg_splitwx_to_rx(src_rw);
629793f7381SRichard Henderson    intptr_t offset = (intptr_t)target - (intptr_t)src_rx;
630139c1837SPaolo Bonzini
631844d0442SRichard Henderson    tcg_debug_assert((offset & 1) == 0);
632844d0442SRichard Henderson    if (offset == sextreg(offset, 0, 20)) {
633793f7381SRichard Henderson        *src_rw |= encode_ujimm20(offset);
634139c1837SPaolo Bonzini        return true;
635139c1837SPaolo Bonzini    }
636139c1837SPaolo Bonzini
637139c1837SPaolo Bonzini    return false;
638139c1837SPaolo Bonzini}
639139c1837SPaolo Bonzini
640793f7381SRichard Hendersonstatic bool reloc_call(tcg_insn_unit *src_rw, const tcg_insn_unit *target)
641139c1837SPaolo Bonzini{
642793f7381SRichard Henderson    const tcg_insn_unit *src_rx = tcg_splitwx_to_rx(src_rw);
643793f7381SRichard Henderson    intptr_t offset = (intptr_t)target - (intptr_t)src_rx;
644139c1837SPaolo Bonzini    int32_t lo = sextreg(offset, 0, 12);
645139c1837SPaolo Bonzini    int32_t hi = offset - lo;
646139c1837SPaolo Bonzini
647139c1837SPaolo Bonzini    if (offset == hi + lo) {
648793f7381SRichard Henderson        src_rw[0] |= encode_uimm20(hi);
649793f7381SRichard Henderson        src_rw[1] |= encode_imm12(lo);
650139c1837SPaolo Bonzini        return true;
651139c1837SPaolo Bonzini    }
652139c1837SPaolo Bonzini
653139c1837SPaolo Bonzini    return false;
654139c1837SPaolo Bonzini}
655139c1837SPaolo Bonzini
656139c1837SPaolo Bonzinistatic bool patch_reloc(tcg_insn_unit *code_ptr, int type,
657139c1837SPaolo Bonzini                        intptr_t value, intptr_t addend)
658139c1837SPaolo Bonzini{
659139c1837SPaolo Bonzini    tcg_debug_assert(addend == 0);
660139c1837SPaolo Bonzini    switch (type) {
661139c1837SPaolo Bonzini    case R_RISCV_BRANCH:
662139c1837SPaolo Bonzini        return reloc_sbimm12(code_ptr, (tcg_insn_unit *)value);
663139c1837SPaolo Bonzini    case R_RISCV_JAL:
664139c1837SPaolo Bonzini        return reloc_jimm20(code_ptr, (tcg_insn_unit *)value);
665139c1837SPaolo Bonzini    case R_RISCV_CALL:
666139c1837SPaolo Bonzini        return reloc_call(code_ptr, (tcg_insn_unit *)value);
667139c1837SPaolo Bonzini    default:
6684b6a52d0SRichard Henderson        g_assert_not_reached();
669139c1837SPaolo Bonzini    }
670139c1837SPaolo Bonzini}
671139c1837SPaolo Bonzini
672139c1837SPaolo Bonzini/*
673f63e7089SHuang Shiyuan * RISC-V vector instruction emitters
674f63e7089SHuang Shiyuan */
675f63e7089SHuang Shiyuan
676d4be6ee1STANG Tiancheng/*
677d4be6ee1STANG Tiancheng * Vector registers uses the same 5 lower bits as GPR registers,
678d4be6ee1STANG Tiancheng * and vm=0 (vm = false) means vector masking ENABLED.
679d4be6ee1STANG Tiancheng * With RVV 1.0, vs2 is the first operand, while rs1/imm is the
680d4be6ee1STANG Tiancheng * second operand.
681d4be6ee1STANG Tiancheng */
6825a63f599STANG Tianchengstatic void tcg_out_opc_vv(TCGContext *s, RISCVInsn opc,
6835a63f599STANG Tiancheng                           TCGReg vd, TCGReg vs2, TCGReg vs1)
6845a63f599STANG Tiancheng{
6855a63f599STANG Tiancheng    tcg_out32(s, encode_v(opc, vd, vs1, vs2, true));
6865a63f599STANG Tiancheng}
6875a63f599STANG Tiancheng
688d4be6ee1STANG Tianchengstatic void tcg_out_opc_vx(TCGContext *s, RISCVInsn opc,
689d4be6ee1STANG Tiancheng                           TCGReg vd, TCGReg vs2, TCGReg rs1)
690d4be6ee1STANG Tiancheng{
691d4be6ee1STANG Tiancheng    tcg_out32(s, encode_v(opc, vd, rs1, vs2, true));
692d4be6ee1STANG Tiancheng}
693d4be6ee1STANG Tiancheng
694d4be6ee1STANG Tianchengstatic void tcg_out_opc_vi(TCGContext *s, RISCVInsn opc,
695d4be6ee1STANG Tiancheng                           TCGReg vd, TCGReg vs2, int32_t imm)
696d4be6ee1STANG Tiancheng{
697d4be6ee1STANG Tiancheng    tcg_out32(s, encode_vi(opc, vd, imm, vs2, true));
698d4be6ee1STANG Tiancheng}
699d4be6ee1STANG Tiancheng
7005a63f599STANG Tianchengstatic void tcg_out_opc_vv_vi(TCGContext *s, RISCVInsn o_vv, RISCVInsn o_vi,
7015a63f599STANG Tiancheng                              TCGReg vd, TCGReg vs2, TCGArg vi1, int c_vi1)
7025a63f599STANG Tiancheng{
7035a63f599STANG Tiancheng    if (c_vi1) {
7045a63f599STANG Tiancheng        tcg_out_opc_vi(s, o_vi, vd, vs2, vi1);
7055a63f599STANG Tiancheng    } else {
7065a63f599STANG Tiancheng        tcg_out_opc_vv(s, o_vv, vd, vs2, vi1);
7075a63f599STANG Tiancheng    }
7085a63f599STANG Tiancheng}
7095a63f599STANG Tiancheng
710a31768c0STANG Tianchengstatic void tcg_out_opc_vim_mask(TCGContext *s, RISCVInsn opc, TCGReg vd,
711a31768c0STANG Tiancheng                                 TCGReg vs2, int32_t imm)
712a31768c0STANG Tiancheng{
713a31768c0STANG Tiancheng    tcg_out32(s, encode_vi(opc, vd, imm, vs2, false));
714a31768c0STANG Tiancheng}
715a31768c0STANG Tiancheng
716a31768c0STANG Tianchengstatic void tcg_out_opc_vvm_mask(TCGContext *s, RISCVInsn opc, TCGReg vd,
717a31768c0STANG Tiancheng                                 TCGReg vs2, TCGReg vs1)
718a31768c0STANG Tiancheng{
719a31768c0STANG Tiancheng    tcg_out32(s, encode_v(opc, vd, vs1, vs2, false));
720a31768c0STANG Tiancheng}
721a31768c0STANG Tiancheng
722f63e7089SHuang Shiyuantypedef struct VsetCache {
723f63e7089SHuang Shiyuan    uint32_t movi_insn;
724f63e7089SHuang Shiyuan    uint32_t vset_insn;
725f63e7089SHuang Shiyuan} VsetCache;
726f63e7089SHuang Shiyuan
727f63e7089SHuang Shiyuanstatic VsetCache riscv_vset_cache[3][4];
728f63e7089SHuang Shiyuan
729f63e7089SHuang Shiyuanstatic void set_vtype(TCGContext *s, TCGType type, MemOp vsew)
730f63e7089SHuang Shiyuan{
731f63e7089SHuang Shiyuan    const VsetCache *p = &riscv_vset_cache[type - TCG_TYPE_V64][vsew];
732f63e7089SHuang Shiyuan
733f63e7089SHuang Shiyuan    s->riscv_cur_type = type;
734f63e7089SHuang Shiyuan    s->riscv_cur_vsew = vsew;
735f63e7089SHuang Shiyuan
736f63e7089SHuang Shiyuan    if (p->movi_insn) {
737f63e7089SHuang Shiyuan        tcg_out32(s, p->movi_insn);
738f63e7089SHuang Shiyuan    }
739f63e7089SHuang Shiyuan    tcg_out32(s, p->vset_insn);
740f63e7089SHuang Shiyuan}
741f63e7089SHuang Shiyuan
742f63e7089SHuang Shiyuanstatic MemOp set_vtype_len(TCGContext *s, TCGType type)
743f63e7089SHuang Shiyuan{
744f63e7089SHuang Shiyuan    if (type != s->riscv_cur_type) {
745f63e7089SHuang Shiyuan        set_vtype(s, type, MO_64);
746f63e7089SHuang Shiyuan    }
747f63e7089SHuang Shiyuan    return s->riscv_cur_vsew;
748f63e7089SHuang Shiyuan}
749f63e7089SHuang Shiyuan
750d4be6ee1STANG Tianchengstatic void set_vtype_len_sew(TCGContext *s, TCGType type, MemOp vsew)
751d4be6ee1STANG Tiancheng{
752d4be6ee1STANG Tiancheng    if (type != s->riscv_cur_type || vsew != s->riscv_cur_vsew) {
753d4be6ee1STANG Tiancheng        set_vtype(s, type, vsew);
754d4be6ee1STANG Tiancheng    }
755d4be6ee1STANG Tiancheng}
756d4be6ee1STANG Tiancheng
757f63e7089SHuang Shiyuan/*
758139c1837SPaolo Bonzini * TCG intrinsics
759139c1837SPaolo Bonzini */
760139c1837SPaolo Bonzini
761139c1837SPaolo Bonzinistatic bool tcg_out_mov(TCGContext *s, TCGType type, TCGReg ret, TCGReg arg)
762139c1837SPaolo Bonzini{
763139c1837SPaolo Bonzini    if (ret == arg) {
764139c1837SPaolo Bonzini        return true;
765139c1837SPaolo Bonzini    }
766139c1837SPaolo Bonzini    switch (type) {
767139c1837SPaolo Bonzini    case TCG_TYPE_I32:
768139c1837SPaolo Bonzini    case TCG_TYPE_I64:
769139c1837SPaolo Bonzini        tcg_out_opc_imm(s, OPC_ADDI, ret, arg, 0);
770139c1837SPaolo Bonzini        break;
771d4be6ee1STANG Tiancheng    case TCG_TYPE_V64:
772d4be6ee1STANG Tiancheng    case TCG_TYPE_V128:
773d4be6ee1STANG Tiancheng    case TCG_TYPE_V256:
774d4be6ee1STANG Tiancheng        {
775d4be6ee1STANG Tiancheng            int lmul = type - riscv_lg2_vlenb;
776d4be6ee1STANG Tiancheng            int nf = 1 << MAX(lmul, 0);
777d4be6ee1STANG Tiancheng            tcg_out_opc_vi(s, OPC_VMVNR_V, ret, arg, nf - 1);
778d4be6ee1STANG Tiancheng        }
779d4be6ee1STANG Tiancheng        break;
780139c1837SPaolo Bonzini    default:
781139c1837SPaolo Bonzini        g_assert_not_reached();
782139c1837SPaolo Bonzini    }
783139c1837SPaolo Bonzini    return true;
784139c1837SPaolo Bonzini}
785139c1837SPaolo Bonzini
786139c1837SPaolo Bonzinistatic void tcg_out_movi(TCGContext *s, TCGType type, TCGReg rd,
787139c1837SPaolo Bonzini                         tcg_target_long val)
788139c1837SPaolo Bonzini{
789139c1837SPaolo Bonzini    tcg_target_long lo, hi, tmp;
790139c1837SPaolo Bonzini    int shift, ret;
791139c1837SPaolo Bonzini
792aeb6326eSRichard Henderson    if (type == TCG_TYPE_I32) {
793139c1837SPaolo Bonzini        val = (int32_t)val;
794139c1837SPaolo Bonzini    }
795139c1837SPaolo Bonzini
796139c1837SPaolo Bonzini    lo = sextreg(val, 0, 12);
797139c1837SPaolo Bonzini    if (val == lo) {
798139c1837SPaolo Bonzini        tcg_out_opc_imm(s, OPC_ADDI, rd, TCG_REG_ZERO, lo);
799139c1837SPaolo Bonzini        return;
800139c1837SPaolo Bonzini    }
801139c1837SPaolo Bonzini
802139c1837SPaolo Bonzini    hi = val - lo;
803aeb6326eSRichard Henderson    if (val == (int32_t)val) {
804139c1837SPaolo Bonzini        tcg_out_opc_upper(s, OPC_LUI, rd, hi);
805139c1837SPaolo Bonzini        if (lo != 0) {
806139c1837SPaolo Bonzini            tcg_out_opc_imm(s, OPC_ADDIW, rd, rd, lo);
807139c1837SPaolo Bonzini        }
808139c1837SPaolo Bonzini        return;
809139c1837SPaolo Bonzini    }
810139c1837SPaolo Bonzini
811139c1837SPaolo Bonzini    tmp = tcg_pcrel_diff(s, (void *)val);
812139c1837SPaolo Bonzini    if (tmp == (int32_t)tmp) {
813139c1837SPaolo Bonzini        tcg_out_opc_upper(s, OPC_AUIPC, rd, 0);
814139c1837SPaolo Bonzini        tcg_out_opc_imm(s, OPC_ADDI, rd, rd, 0);
815793f7381SRichard Henderson        ret = reloc_call(s->code_ptr - 2, (const tcg_insn_unit *)val);
816139c1837SPaolo Bonzini        tcg_debug_assert(ret == true);
817139c1837SPaolo Bonzini        return;
818139c1837SPaolo Bonzini    }
819139c1837SPaolo Bonzini
820139c1837SPaolo Bonzini    /* Look for a single 20-bit section.  */
821139c1837SPaolo Bonzini    shift = ctz64(val);
822139c1837SPaolo Bonzini    tmp = val >> shift;
823139c1837SPaolo Bonzini    if (tmp == sextreg(tmp, 0, 20)) {
824139c1837SPaolo Bonzini        tcg_out_opc_upper(s, OPC_LUI, rd, tmp << 12);
825139c1837SPaolo Bonzini        if (shift > 12) {
826139c1837SPaolo Bonzini            tcg_out_opc_imm(s, OPC_SLLI, rd, rd, shift - 12);
827139c1837SPaolo Bonzini        } else {
828139c1837SPaolo Bonzini            tcg_out_opc_imm(s, OPC_SRAI, rd, rd, 12 - shift);
829139c1837SPaolo Bonzini        }
830139c1837SPaolo Bonzini        return;
831139c1837SPaolo Bonzini    }
832139c1837SPaolo Bonzini
833139c1837SPaolo Bonzini    /* Look for a few high zero bits, with lots of bits set in the middle.  */
834139c1837SPaolo Bonzini    shift = clz64(val);
835139c1837SPaolo Bonzini    tmp = val << shift;
836139c1837SPaolo Bonzini    if (tmp == sextreg(tmp, 12, 20) << 12) {
837139c1837SPaolo Bonzini        tcg_out_opc_upper(s, OPC_LUI, rd, tmp);
838139c1837SPaolo Bonzini        tcg_out_opc_imm(s, OPC_SRLI, rd, rd, shift);
839139c1837SPaolo Bonzini        return;
840139c1837SPaolo Bonzini    } else if (tmp == sextreg(tmp, 0, 12)) {
841139c1837SPaolo Bonzini        tcg_out_opc_imm(s, OPC_ADDI, rd, TCG_REG_ZERO, tmp);
842139c1837SPaolo Bonzini        tcg_out_opc_imm(s, OPC_SRLI, rd, rd, shift);
843139c1837SPaolo Bonzini        return;
844139c1837SPaolo Bonzini    }
845139c1837SPaolo Bonzini
846139c1837SPaolo Bonzini    /* Drop into the constant pool.  */
847139c1837SPaolo Bonzini    new_pool_label(s, val, R_RISCV_CALL, s->code_ptr, 0);
848139c1837SPaolo Bonzini    tcg_out_opc_upper(s, OPC_AUIPC, rd, 0);
849139c1837SPaolo Bonzini    tcg_out_opc_imm(s, OPC_LD, rd, rd, 0);
850139c1837SPaolo Bonzini}
851139c1837SPaolo Bonzini
852767c2503SRichard Hendersonstatic bool tcg_out_xchg(TCGContext *s, TCGType type, TCGReg r1, TCGReg r2)
853767c2503SRichard Henderson{
854767c2503SRichard Henderson    return false;
855767c2503SRichard Henderson}
856767c2503SRichard Henderson
8576a6d772eSRichard Hendersonstatic void tcg_out_addi_ptr(TCGContext *s, TCGReg rd, TCGReg rs,
8586a6d772eSRichard Henderson                             tcg_target_long imm)
8596a6d772eSRichard Henderson{
8606a6d772eSRichard Henderson    /* This function is only used for passing structs by reference. */
8616a6d772eSRichard Henderson    g_assert_not_reached();
8626a6d772eSRichard Henderson}
8636a6d772eSRichard Henderson
864139c1837SPaolo Bonzinistatic void tcg_out_ext8u(TCGContext *s, TCGReg ret, TCGReg arg)
865139c1837SPaolo Bonzini{
866139c1837SPaolo Bonzini    tcg_out_opc_imm(s, OPC_ANDI, ret, arg, 0xff);
867139c1837SPaolo Bonzini}
868139c1837SPaolo Bonzini
869139c1837SPaolo Bonzinistatic void tcg_out_ext16u(TCGContext *s, TCGReg ret, TCGReg arg)
870139c1837SPaolo Bonzini{
871b86c6ba6SRichard Henderson    if (cpuinfo & CPUINFO_ZBB) {
872d1c3f4e9SRichard Henderson        tcg_out_opc_reg(s, OPC_ZEXT_H, ret, arg, TCG_REG_ZERO);
873d1c3f4e9SRichard Henderson    } else {
874139c1837SPaolo Bonzini        tcg_out_opc_imm(s, OPC_SLLIW, ret, arg, 16);
875139c1837SPaolo Bonzini        tcg_out_opc_imm(s, OPC_SRLIW, ret, ret, 16);
876139c1837SPaolo Bonzini    }
877d1c3f4e9SRichard Henderson}
878139c1837SPaolo Bonzini
879139c1837SPaolo Bonzinistatic void tcg_out_ext32u(TCGContext *s, TCGReg ret, TCGReg arg)
880139c1837SPaolo Bonzini{
881b86c6ba6SRichard Henderson    if (cpuinfo & CPUINFO_ZBA) {
882d1c3f4e9SRichard Henderson        tcg_out_opc_reg(s, OPC_ADD_UW, ret, arg, TCG_REG_ZERO);
883d1c3f4e9SRichard Henderson    } else {
884139c1837SPaolo Bonzini        tcg_out_opc_imm(s, OPC_SLLI, ret, arg, 32);
885139c1837SPaolo Bonzini        tcg_out_opc_imm(s, OPC_SRLI, ret, ret, 32);
886139c1837SPaolo Bonzini    }
887d1c3f4e9SRichard Henderson}
888139c1837SPaolo Bonzini
889678155b2SRichard Hendersonstatic void tcg_out_ext8s(TCGContext *s, TCGType type, TCGReg ret, TCGReg arg)
890139c1837SPaolo Bonzini{
891b86c6ba6SRichard Henderson    if (cpuinfo & CPUINFO_ZBB) {
892d1c3f4e9SRichard Henderson        tcg_out_opc_imm(s, OPC_SEXT_B, ret, arg, 0);
893d1c3f4e9SRichard Henderson    } else {
894139c1837SPaolo Bonzini        tcg_out_opc_imm(s, OPC_SLLIW, ret, arg, 24);
895139c1837SPaolo Bonzini        tcg_out_opc_imm(s, OPC_SRAIW, ret, ret, 24);
896139c1837SPaolo Bonzini    }
897d1c3f4e9SRichard Henderson}
898139c1837SPaolo Bonzini
899753e42eaSRichard Hendersonstatic void tcg_out_ext16s(TCGContext *s, TCGType type, TCGReg ret, TCGReg arg)
900139c1837SPaolo Bonzini{
901b86c6ba6SRichard Henderson    if (cpuinfo & CPUINFO_ZBB) {
902d1c3f4e9SRichard Henderson        tcg_out_opc_imm(s, OPC_SEXT_H, ret, arg, 0);
903d1c3f4e9SRichard Henderson    } else {
904139c1837SPaolo Bonzini        tcg_out_opc_imm(s, OPC_SLLIW, ret, arg, 16);
905139c1837SPaolo Bonzini        tcg_out_opc_imm(s, OPC_SRAIW, ret, ret, 16);
906139c1837SPaolo Bonzini    }
907d1c3f4e9SRichard Henderson}
908139c1837SPaolo Bonzini
909139c1837SPaolo Bonzinistatic void tcg_out_ext32s(TCGContext *s, TCGReg ret, TCGReg arg)
910139c1837SPaolo Bonzini{
911139c1837SPaolo Bonzini    tcg_out_opc_imm(s, OPC_ADDIW, ret, arg, 0);
912139c1837SPaolo Bonzini}
913139c1837SPaolo Bonzini
9149c6aa274SRichard Hendersonstatic void tcg_out_exts_i32_i64(TCGContext *s, TCGReg ret, TCGReg arg)
9159c6aa274SRichard Henderson{
9163ea9be33SRichard Henderson    if (ret != arg) {
9179c6aa274SRichard Henderson        tcg_out_ext32s(s, ret, arg);
9189c6aa274SRichard Henderson    }
9193ea9be33SRichard Henderson}
9209c6aa274SRichard Henderson
921b9bfe000SRichard Hendersonstatic void tcg_out_extu_i32_i64(TCGContext *s, TCGReg ret, TCGReg arg)
922b9bfe000SRichard Henderson{
923b9bfe000SRichard Henderson    tcg_out_ext32u(s, ret, arg);
924b9bfe000SRichard Henderson}
925b9bfe000SRichard Henderson
926b8b94ac6SRichard Hendersonstatic void tcg_out_extrl_i64_i32(TCGContext *s, TCGReg ret, TCGReg arg)
927b8b94ac6SRichard Henderson{
928b8b94ac6SRichard Henderson    tcg_out_ext32s(s, ret, arg);
929b8b94ac6SRichard Henderson}
930b8b94ac6SRichard Henderson
931139c1837SPaolo Bonzinistatic void tcg_out_ldst(TCGContext *s, RISCVInsn opc, TCGReg data,
932139c1837SPaolo Bonzini                         TCGReg addr, intptr_t offset)
933139c1837SPaolo Bonzini{
934139c1837SPaolo Bonzini    intptr_t imm12 = sextreg(offset, 0, 12);
935139c1837SPaolo Bonzini
936139c1837SPaolo Bonzini    if (offset != imm12) {
9379d9db413SRichard Henderson        intptr_t diff = tcg_pcrel_diff(s, (void *)offset);
938139c1837SPaolo Bonzini
939139c1837SPaolo Bonzini        if (addr == TCG_REG_ZERO && diff == (int32_t)diff) {
940139c1837SPaolo Bonzini            imm12 = sextreg(diff, 0, 12);
941139c1837SPaolo Bonzini            tcg_out_opc_upper(s, OPC_AUIPC, TCG_REG_TMP2, diff - imm12);
942139c1837SPaolo Bonzini        } else {
943139c1837SPaolo Bonzini            tcg_out_movi(s, TCG_TYPE_PTR, TCG_REG_TMP2, offset - imm12);
944139c1837SPaolo Bonzini            if (addr != TCG_REG_ZERO) {
945139c1837SPaolo Bonzini                tcg_out_opc_reg(s, OPC_ADD, TCG_REG_TMP2, TCG_REG_TMP2, addr);
946139c1837SPaolo Bonzini            }
947139c1837SPaolo Bonzini        }
948139c1837SPaolo Bonzini        addr = TCG_REG_TMP2;
949139c1837SPaolo Bonzini    }
950139c1837SPaolo Bonzini
951139c1837SPaolo Bonzini    switch (opc) {
952139c1837SPaolo Bonzini    case OPC_SB:
953139c1837SPaolo Bonzini    case OPC_SH:
954139c1837SPaolo Bonzini    case OPC_SW:
955139c1837SPaolo Bonzini    case OPC_SD:
956139c1837SPaolo Bonzini        tcg_out_opc_store(s, opc, addr, data, imm12);
957139c1837SPaolo Bonzini        break;
958139c1837SPaolo Bonzini    case OPC_LB:
959139c1837SPaolo Bonzini    case OPC_LBU:
960139c1837SPaolo Bonzini    case OPC_LH:
961139c1837SPaolo Bonzini    case OPC_LHU:
962139c1837SPaolo Bonzini    case OPC_LW:
963139c1837SPaolo Bonzini    case OPC_LWU:
964139c1837SPaolo Bonzini    case OPC_LD:
965139c1837SPaolo Bonzini        tcg_out_opc_imm(s, opc, data, addr, imm12);
966139c1837SPaolo Bonzini        break;
967139c1837SPaolo Bonzini    default:
968139c1837SPaolo Bonzini        g_assert_not_reached();
969139c1837SPaolo Bonzini    }
970139c1837SPaolo Bonzini}
971139c1837SPaolo Bonzini
972f63e7089SHuang Shiyuanstatic void tcg_out_vec_ldst(TCGContext *s, RISCVInsn opc, TCGReg data,
973f63e7089SHuang Shiyuan                             TCGReg addr, intptr_t offset)
974f63e7089SHuang Shiyuan{
975f63e7089SHuang Shiyuan    tcg_debug_assert(data >= TCG_REG_V0);
976f63e7089SHuang Shiyuan    tcg_debug_assert(addr < TCG_REG_V0);
977f63e7089SHuang Shiyuan
978f63e7089SHuang Shiyuan    if (offset) {
979f63e7089SHuang Shiyuan        tcg_debug_assert(addr != TCG_REG_ZERO);
980f63e7089SHuang Shiyuan        if (offset == sextreg(offset, 0, 12)) {
981f63e7089SHuang Shiyuan            tcg_out_opc_imm(s, OPC_ADDI, TCG_REG_TMP0, addr, offset);
982f63e7089SHuang Shiyuan        } else {
983f63e7089SHuang Shiyuan            tcg_out_movi(s, TCG_TYPE_PTR, TCG_REG_TMP0, offset);
984f63e7089SHuang Shiyuan            tcg_out_opc_reg(s, OPC_ADD, TCG_REG_TMP0, TCG_REG_TMP0, addr);
985f63e7089SHuang Shiyuan        }
986f63e7089SHuang Shiyuan        addr = TCG_REG_TMP0;
987f63e7089SHuang Shiyuan    }
988f63e7089SHuang Shiyuan    tcg_out32(s, encode_v(opc, data, addr, 0, true));
989f63e7089SHuang Shiyuan}
990f63e7089SHuang Shiyuan
991139c1837SPaolo Bonzinistatic void tcg_out_ld(TCGContext *s, TCGType type, TCGReg arg,
992139c1837SPaolo Bonzini                       TCGReg arg1, intptr_t arg2)
993139c1837SPaolo Bonzini{
994f63e7089SHuang Shiyuan    RISCVInsn insn;
995f63e7089SHuang Shiyuan
996f63e7089SHuang Shiyuan    switch (type) {
997f63e7089SHuang Shiyuan    case TCG_TYPE_I32:
998f63e7089SHuang Shiyuan        tcg_out_ldst(s, OPC_LW, arg, arg1, arg2);
999f63e7089SHuang Shiyuan        break;
1000f63e7089SHuang Shiyuan    case TCG_TYPE_I64:
1001f63e7089SHuang Shiyuan        tcg_out_ldst(s, OPC_LD, arg, arg1, arg2);
1002f63e7089SHuang Shiyuan        break;
1003f63e7089SHuang Shiyuan    case TCG_TYPE_V64:
1004f63e7089SHuang Shiyuan    case TCG_TYPE_V128:
1005f63e7089SHuang Shiyuan    case TCG_TYPE_V256:
1006f63e7089SHuang Shiyuan        if (type >= riscv_lg2_vlenb) {
1007f63e7089SHuang Shiyuan            static const RISCVInsn whole_reg_ld[] = {
1008f63e7089SHuang Shiyuan                OPC_VL1RE64_V, OPC_VL2RE64_V, OPC_VL4RE64_V, OPC_VL8RE64_V
1009f63e7089SHuang Shiyuan            };
1010f63e7089SHuang Shiyuan            unsigned idx = type - riscv_lg2_vlenb;
1011f63e7089SHuang Shiyuan
1012f63e7089SHuang Shiyuan            tcg_debug_assert(idx < ARRAY_SIZE(whole_reg_ld));
1013f63e7089SHuang Shiyuan            insn = whole_reg_ld[idx];
1014f63e7089SHuang Shiyuan        } else {
1015f63e7089SHuang Shiyuan            static const RISCVInsn unit_stride_ld[] = {
1016f63e7089SHuang Shiyuan                OPC_VLE8_V, OPC_VLE16_V, OPC_VLE32_V, OPC_VLE64_V
1017f63e7089SHuang Shiyuan            };
1018f63e7089SHuang Shiyuan            MemOp prev_vsew = set_vtype_len(s, type);
1019f63e7089SHuang Shiyuan
1020f63e7089SHuang Shiyuan            tcg_debug_assert(prev_vsew < ARRAY_SIZE(unit_stride_ld));
1021f63e7089SHuang Shiyuan            insn = unit_stride_ld[prev_vsew];
1022f63e7089SHuang Shiyuan        }
1023f63e7089SHuang Shiyuan        tcg_out_vec_ldst(s, insn, arg, arg1, arg2);
1024f63e7089SHuang Shiyuan        break;
1025f63e7089SHuang Shiyuan    default:
1026f63e7089SHuang Shiyuan        g_assert_not_reached();
1027f63e7089SHuang Shiyuan    }
1028139c1837SPaolo Bonzini}
1029139c1837SPaolo Bonzini
1030139c1837SPaolo Bonzinistatic void tcg_out_st(TCGContext *s, TCGType type, TCGReg arg,
1031139c1837SPaolo Bonzini                       TCGReg arg1, intptr_t arg2)
1032139c1837SPaolo Bonzini{
1033f63e7089SHuang Shiyuan    RISCVInsn insn;
1034f63e7089SHuang Shiyuan
1035f63e7089SHuang Shiyuan    switch (type) {
1036f63e7089SHuang Shiyuan    case TCG_TYPE_I32:
1037f63e7089SHuang Shiyuan        tcg_out_ldst(s, OPC_SW, arg, arg1, arg2);
1038f63e7089SHuang Shiyuan        break;
1039f63e7089SHuang Shiyuan    case TCG_TYPE_I64:
1040f63e7089SHuang Shiyuan        tcg_out_ldst(s, OPC_SD, arg, arg1, arg2);
1041f63e7089SHuang Shiyuan        break;
1042f63e7089SHuang Shiyuan    case TCG_TYPE_V64:
1043f63e7089SHuang Shiyuan    case TCG_TYPE_V128:
1044f63e7089SHuang Shiyuan    case TCG_TYPE_V256:
1045f63e7089SHuang Shiyuan        if (type >= riscv_lg2_vlenb) {
1046f63e7089SHuang Shiyuan            static const RISCVInsn whole_reg_st[] = {
1047f63e7089SHuang Shiyuan                OPC_VS1R_V, OPC_VS2R_V, OPC_VS4R_V, OPC_VS8R_V
1048f63e7089SHuang Shiyuan            };
1049f63e7089SHuang Shiyuan            unsigned idx = type - riscv_lg2_vlenb;
1050f63e7089SHuang Shiyuan
1051f63e7089SHuang Shiyuan            tcg_debug_assert(idx < ARRAY_SIZE(whole_reg_st));
1052f63e7089SHuang Shiyuan            insn = whole_reg_st[idx];
1053f63e7089SHuang Shiyuan        } else {
1054f63e7089SHuang Shiyuan            static const RISCVInsn unit_stride_st[] = {
1055f63e7089SHuang Shiyuan                OPC_VSE8_V, OPC_VSE16_V, OPC_VSE32_V, OPC_VSE64_V
1056f63e7089SHuang Shiyuan            };
1057f63e7089SHuang Shiyuan            MemOp prev_vsew = set_vtype_len(s, type);
1058f63e7089SHuang Shiyuan
1059f63e7089SHuang Shiyuan            tcg_debug_assert(prev_vsew < ARRAY_SIZE(unit_stride_st));
1060f63e7089SHuang Shiyuan            insn = unit_stride_st[prev_vsew];
1061f63e7089SHuang Shiyuan        }
1062f63e7089SHuang Shiyuan        tcg_out_vec_ldst(s, insn, arg, arg1, arg2);
1063f63e7089SHuang Shiyuan        break;
1064f63e7089SHuang Shiyuan    default:
1065f63e7089SHuang Shiyuan        g_assert_not_reached();
1066f63e7089SHuang Shiyuan    }
1067139c1837SPaolo Bonzini}
1068139c1837SPaolo Bonzini
1069139c1837SPaolo Bonzinistatic bool tcg_out_sti(TCGContext *s, TCGType type, TCGArg val,
1070139c1837SPaolo Bonzini                        TCGReg base, intptr_t ofs)
1071139c1837SPaolo Bonzini{
1072139c1837SPaolo Bonzini    if (val == 0) {
1073139c1837SPaolo Bonzini        tcg_out_st(s, type, TCG_REG_ZERO, base, ofs);
1074139c1837SPaolo Bonzini        return true;
1075139c1837SPaolo Bonzini    }
1076139c1837SPaolo Bonzini    return false;
1077139c1837SPaolo Bonzini}
1078139c1837SPaolo Bonzini
1079139c1837SPaolo Bonzinistatic void tcg_out_addsub2(TCGContext *s,
1080139c1837SPaolo Bonzini                            TCGReg rl, TCGReg rh,
1081139c1837SPaolo Bonzini                            TCGReg al, TCGReg ah,
1082139c1837SPaolo Bonzini                            TCGArg bl, TCGArg bh,
1083139c1837SPaolo Bonzini                            bool cbl, bool cbh, bool is_sub, bool is32bit)
1084139c1837SPaolo Bonzini{
1085139c1837SPaolo Bonzini    const RISCVInsn opc_add = is32bit ? OPC_ADDW : OPC_ADD;
1086139c1837SPaolo Bonzini    const RISCVInsn opc_addi = is32bit ? OPC_ADDIW : OPC_ADDI;
1087139c1837SPaolo Bonzini    const RISCVInsn opc_sub = is32bit ? OPC_SUBW : OPC_SUB;
1088139c1837SPaolo Bonzini    TCGReg th = TCG_REG_TMP1;
1089139c1837SPaolo Bonzini
1090139c1837SPaolo Bonzini    /* If we have a negative constant such that negating it would
1091139c1837SPaolo Bonzini       make the high part zero, we can (usually) eliminate one insn.  */
1092139c1837SPaolo Bonzini    if (cbl && cbh && bh == -1 && bl != 0) {
1093139c1837SPaolo Bonzini        bl = -bl;
1094139c1837SPaolo Bonzini        bh = 0;
1095139c1837SPaolo Bonzini        is_sub = !is_sub;
1096139c1837SPaolo Bonzini    }
1097139c1837SPaolo Bonzini
1098139c1837SPaolo Bonzini    /* By operating on the high part first, we get to use the final
1099139c1837SPaolo Bonzini       carry operation to move back from the temporary.  */
1100139c1837SPaolo Bonzini    if (!cbh) {
1101139c1837SPaolo Bonzini        tcg_out_opc_reg(s, (is_sub ? opc_sub : opc_add), th, ah, bh);
1102139c1837SPaolo Bonzini    } else if (bh != 0 || ah == rl) {
1103139c1837SPaolo Bonzini        tcg_out_opc_imm(s, opc_addi, th, ah, (is_sub ? -bh : bh));
1104139c1837SPaolo Bonzini    } else {
1105139c1837SPaolo Bonzini        th = ah;
1106139c1837SPaolo Bonzini    }
1107139c1837SPaolo Bonzini
1108139c1837SPaolo Bonzini    /* Note that tcg optimization should eliminate the bl == 0 case.  */
1109139c1837SPaolo Bonzini    if (is_sub) {
1110139c1837SPaolo Bonzini        if (cbl) {
1111139c1837SPaolo Bonzini            tcg_out_opc_imm(s, OPC_SLTIU, TCG_REG_TMP0, al, bl);
1112139c1837SPaolo Bonzini            tcg_out_opc_imm(s, opc_addi, rl, al, -bl);
1113139c1837SPaolo Bonzini        } else {
1114139c1837SPaolo Bonzini            tcg_out_opc_reg(s, OPC_SLTU, TCG_REG_TMP0, al, bl);
1115139c1837SPaolo Bonzini            tcg_out_opc_reg(s, opc_sub, rl, al, bl);
1116139c1837SPaolo Bonzini        }
1117139c1837SPaolo Bonzini        tcg_out_opc_reg(s, opc_sub, rh, th, TCG_REG_TMP0);
1118139c1837SPaolo Bonzini    } else {
1119139c1837SPaolo Bonzini        if (cbl) {
1120139c1837SPaolo Bonzini            tcg_out_opc_imm(s, opc_addi, rl, al, bl);
1121139c1837SPaolo Bonzini            tcg_out_opc_imm(s, OPC_SLTIU, TCG_REG_TMP0, rl, bl);
11229b246685SRichard Henderson        } else if (al == bl) {
11239b246685SRichard Henderson            /*
11249b246685SRichard Henderson             * If the input regs overlap, this is a simple doubling
11259b246685SRichard Henderson             * and carry-out is the input msb.  This special case is
11269b246685SRichard Henderson             * required when the output reg overlaps the input,
11279b246685SRichard Henderson             * but we might as well use it always.
11289b246685SRichard Henderson             */
1129139c1837SPaolo Bonzini            tcg_out_opc_imm(s, OPC_SLTI, TCG_REG_TMP0, al, 0);
11309b246685SRichard Henderson            tcg_out_opc_reg(s, opc_add, rl, al, al);
1131139c1837SPaolo Bonzini        } else {
1132139c1837SPaolo Bonzini            tcg_out_opc_reg(s, opc_add, rl, al, bl);
1133139c1837SPaolo Bonzini            tcg_out_opc_reg(s, OPC_SLTU, TCG_REG_TMP0,
1134139c1837SPaolo Bonzini                            rl, (rl == bl ? al : bl));
1135139c1837SPaolo Bonzini        }
1136139c1837SPaolo Bonzini        tcg_out_opc_reg(s, opc_add, rh, th, TCG_REG_TMP0);
1137139c1837SPaolo Bonzini    }
1138139c1837SPaolo Bonzini}
1139139c1837SPaolo Bonzini
1140f63e7089SHuang Shiyuanstatic bool tcg_out_dup_vec(TCGContext *s, TCGType type, unsigned vece,
1141f63e7089SHuang Shiyuan                                   TCGReg dst, TCGReg src)
1142f63e7089SHuang Shiyuan{
1143d4be6ee1STANG Tiancheng    set_vtype_len_sew(s, type, vece);
1144d4be6ee1STANG Tiancheng    tcg_out_opc_vx(s, OPC_VMV_V_X, dst, 0, src);
1145d4be6ee1STANG Tiancheng    return true;
1146f63e7089SHuang Shiyuan}
1147f63e7089SHuang Shiyuan
1148f63e7089SHuang Shiyuanstatic bool tcg_out_dupm_vec(TCGContext *s, TCGType type, unsigned vece,
1149f63e7089SHuang Shiyuan                                    TCGReg dst, TCGReg base, intptr_t offset)
1150f63e7089SHuang Shiyuan{
1151d4be6ee1STANG Tiancheng    tcg_out_ld(s, TCG_TYPE_REG, TCG_REG_TMP0, base, offset);
1152d4be6ee1STANG Tiancheng    return tcg_out_dup_vec(s, type, vece, dst, TCG_REG_TMP0);
1153f63e7089SHuang Shiyuan}
1154f63e7089SHuang Shiyuan
1155f63e7089SHuang Shiyuanstatic void tcg_out_dupi_vec(TCGContext *s, TCGType type, unsigned vece,
1156f63e7089SHuang Shiyuan                                    TCGReg dst, int64_t arg)
1157f63e7089SHuang Shiyuan{
1158d4be6ee1STANG Tiancheng    /* Arg is replicated by VECE; extract the highest element. */
1159d4be6ee1STANG Tiancheng    arg >>= (-8 << vece) & 63;
1160d4be6ee1STANG Tiancheng
1161d4be6ee1STANG Tiancheng    if (arg >= -16 && arg < 16) {
1162d4be6ee1STANG Tiancheng        if (arg == 0 || arg == -1) {
1163d4be6ee1STANG Tiancheng            set_vtype_len(s, type);
1164d4be6ee1STANG Tiancheng        } else {
1165d4be6ee1STANG Tiancheng            set_vtype_len_sew(s, type, vece);
1166d4be6ee1STANG Tiancheng        }
1167d4be6ee1STANG Tiancheng        tcg_out_opc_vi(s, OPC_VMV_V_I, dst, 0, arg);
1168d4be6ee1STANG Tiancheng        return;
1169d4be6ee1STANG Tiancheng    }
1170d4be6ee1STANG Tiancheng    tcg_out_movi(s, TCG_TYPE_I64, TCG_REG_TMP0, arg);
1171d4be6ee1STANG Tiancheng    tcg_out_dup_vec(s, type, vece, dst, TCG_REG_TMP0);
1172f63e7089SHuang Shiyuan}
1173f63e7089SHuang Shiyuan
1174139c1837SPaolo Bonzinistatic const struct {
1175139c1837SPaolo Bonzini    RISCVInsn op;
1176139c1837SPaolo Bonzini    bool swap;
1177139c1837SPaolo Bonzini} tcg_brcond_to_riscv[] = {
1178139c1837SPaolo Bonzini    [TCG_COND_EQ] =  { OPC_BEQ,  false },
1179139c1837SPaolo Bonzini    [TCG_COND_NE] =  { OPC_BNE,  false },
1180139c1837SPaolo Bonzini    [TCG_COND_LT] =  { OPC_BLT,  false },
1181139c1837SPaolo Bonzini    [TCG_COND_GE] =  { OPC_BGE,  false },
1182139c1837SPaolo Bonzini    [TCG_COND_LE] =  { OPC_BGE,  true  },
1183139c1837SPaolo Bonzini    [TCG_COND_GT] =  { OPC_BLT,  true  },
1184139c1837SPaolo Bonzini    [TCG_COND_LTU] = { OPC_BLTU, false },
1185139c1837SPaolo Bonzini    [TCG_COND_GEU] = { OPC_BGEU, false },
1186139c1837SPaolo Bonzini    [TCG_COND_LEU] = { OPC_BGEU, true  },
1187139c1837SPaolo Bonzini    [TCG_COND_GTU] = { OPC_BLTU, true  }
1188139c1837SPaolo Bonzini};
1189139c1837SPaolo Bonzini
1190139c1837SPaolo Bonzinistatic void tcg_out_brcond(TCGContext *s, TCGCond cond, TCGReg arg1,
1191139c1837SPaolo Bonzini                           TCGReg arg2, TCGLabel *l)
1192139c1837SPaolo Bonzini{
1193139c1837SPaolo Bonzini    RISCVInsn op = tcg_brcond_to_riscv[cond].op;
1194139c1837SPaolo Bonzini
1195139c1837SPaolo Bonzini    tcg_debug_assert(op != 0);
1196139c1837SPaolo Bonzini
1197139c1837SPaolo Bonzini    if (tcg_brcond_to_riscv[cond].swap) {
1198139c1837SPaolo Bonzini        TCGReg t = arg1;
1199139c1837SPaolo Bonzini        arg1 = arg2;
1200139c1837SPaolo Bonzini        arg2 = t;
1201139c1837SPaolo Bonzini    }
1202139c1837SPaolo Bonzini
1203139c1837SPaolo Bonzini    tcg_out_reloc(s, s->code_ptr, R_RISCV_BRANCH, l, 0);
1204139c1837SPaolo Bonzini    tcg_out_opc_branch(s, op, arg1, arg2, 0);
1205139c1837SPaolo Bonzini}
1206139c1837SPaolo Bonzini
1207f6453695SRichard Henderson#define SETCOND_INV    TCG_TARGET_NB_REGS
1208f6453695SRichard Henderson#define SETCOND_NEZ    (SETCOND_INV << 1)
1209f6453695SRichard Henderson#define SETCOND_FLAGS  (SETCOND_INV | SETCOND_NEZ)
1210f6453695SRichard Henderson
1211f6453695SRichard Hendersonstatic int tcg_out_setcond_int(TCGContext *s, TCGCond cond, TCGReg ret,
1212f6453695SRichard Henderson                               TCGReg arg1, tcg_target_long arg2, bool c2)
1213139c1837SPaolo Bonzini{
1214f6453695SRichard Henderson    int flags = 0;
1215f6453695SRichard Henderson
1216139c1837SPaolo Bonzini    switch (cond) {
1217f6453695SRichard Henderson    case TCG_COND_EQ:    /* -> NE  */
1218f6453695SRichard Henderson    case TCG_COND_GE:    /* -> LT  */
1219f6453695SRichard Henderson    case TCG_COND_GEU:   /* -> LTU */
1220f6453695SRichard Henderson    case TCG_COND_GT:    /* -> LE  */
1221f6453695SRichard Henderson    case TCG_COND_GTU:   /* -> LEU */
1222f6453695SRichard Henderson        cond = tcg_invert_cond(cond);
1223f6453695SRichard Henderson        flags ^= SETCOND_INV;
1224139c1837SPaolo Bonzini        break;
1225f6453695SRichard Henderson    default:
1226139c1837SPaolo Bonzini        break;
1227f6453695SRichard Henderson    }
1228f6453695SRichard Henderson
1229f6453695SRichard Henderson    switch (cond) {
1230139c1837SPaolo Bonzini    case TCG_COND_LE:
1231139c1837SPaolo Bonzini    case TCG_COND_LEU:
1232f6453695SRichard Henderson        /*
1233f6453695SRichard Henderson         * If we have a constant input, the most efficient way to implement
1234f6453695SRichard Henderson         * LE is by adding 1 and using LT.  Watch out for wrap around for LEU.
1235f6453695SRichard Henderson         * We don't need to care for this for LE because the constant input
1236f6453695SRichard Henderson         * is constrained to signed 12-bit, and 0x800 is representable in the
1237f6453695SRichard Henderson         * temporary register.
1238f6453695SRichard Henderson         */
1239f6453695SRichard Henderson        if (c2) {
1240f6453695SRichard Henderson            if (cond == TCG_COND_LEU) {
1241f6453695SRichard Henderson                /* unsigned <= -1 is true */
1242f6453695SRichard Henderson                if (arg2 == -1) {
1243f6453695SRichard Henderson                    tcg_out_movi(s, TCG_TYPE_REG, ret, !(flags & SETCOND_INV));
1244f6453695SRichard Henderson                    return ret;
1245f6453695SRichard Henderson                }
1246f6453695SRichard Henderson                cond = TCG_COND_LTU;
1247f6453695SRichard Henderson            } else {
1248f6453695SRichard Henderson                cond = TCG_COND_LT;
1249f6453695SRichard Henderson            }
1250f6453695SRichard Henderson            tcg_debug_assert(arg2 <= 0x7ff);
1251f6453695SRichard Henderson            if (++arg2 == 0x800) {
1252f6453695SRichard Henderson                tcg_out_movi(s, TCG_TYPE_REG, TCG_REG_TMP0, arg2);
1253f6453695SRichard Henderson                arg2 = TCG_REG_TMP0;
1254f6453695SRichard Henderson                c2 = false;
1255f6453695SRichard Henderson            }
1256f6453695SRichard Henderson        } else {
1257f6453695SRichard Henderson            TCGReg tmp = arg2;
1258f6453695SRichard Henderson            arg2 = arg1;
1259f6453695SRichard Henderson            arg1 = tmp;
1260f6453695SRichard Henderson            cond = tcg_swap_cond(cond);    /* LE -> GE */
1261f6453695SRichard Henderson            cond = tcg_invert_cond(cond);  /* GE -> LT */
1262f6453695SRichard Henderson            flags ^= SETCOND_INV;
1263f6453695SRichard Henderson        }
1264139c1837SPaolo Bonzini        break;
1265f6453695SRichard Henderson    default:
1266f6453695SRichard Henderson        break;
1267f6453695SRichard Henderson    }
1268f6453695SRichard Henderson
1269f6453695SRichard Henderson    switch (cond) {
1270f6453695SRichard Henderson    case TCG_COND_NE:
1271f6453695SRichard Henderson        flags |= SETCOND_NEZ;
1272f6453695SRichard Henderson        if (!c2) {
1273f6453695SRichard Henderson            tcg_out_opc_reg(s, OPC_XOR, ret, arg1, arg2);
1274f6453695SRichard Henderson        } else if (arg2 == 0) {
1275f6453695SRichard Henderson            ret = arg1;
1276f6453695SRichard Henderson        } else {
1277f6453695SRichard Henderson            tcg_out_opc_imm(s, OPC_XORI, ret, arg1, arg2);
1278f6453695SRichard Henderson        }
1279f6453695SRichard Henderson        break;
1280f6453695SRichard Henderson
1281f6453695SRichard Henderson    case TCG_COND_LT:
1282f6453695SRichard Henderson        if (c2) {
1283f6453695SRichard Henderson            tcg_out_opc_imm(s, OPC_SLTI, ret, arg1, arg2);
1284f6453695SRichard Henderson        } else {
1285f6453695SRichard Henderson            tcg_out_opc_reg(s, OPC_SLT, ret, arg1, arg2);
1286f6453695SRichard Henderson        }
1287f6453695SRichard Henderson        break;
1288f6453695SRichard Henderson
1289f6453695SRichard Henderson    case TCG_COND_LTU:
1290f6453695SRichard Henderson        if (c2) {
1291f6453695SRichard Henderson            tcg_out_opc_imm(s, OPC_SLTIU, ret, arg1, arg2);
1292f6453695SRichard Henderson        } else {
1293f6453695SRichard Henderson            tcg_out_opc_reg(s, OPC_SLTU, ret, arg1, arg2);
1294f6453695SRichard Henderson        }
1295f6453695SRichard Henderson        break;
1296f6453695SRichard Henderson
1297f6453695SRichard Henderson    default:
1298f6453695SRichard Henderson        g_assert_not_reached();
1299f6453695SRichard Henderson    }
1300f6453695SRichard Henderson
1301f6453695SRichard Henderson    return ret | flags;
1302f6453695SRichard Henderson}
1303f6453695SRichard Henderson
1304f6453695SRichard Hendersonstatic void tcg_out_setcond(TCGContext *s, TCGCond cond, TCGReg ret,
1305f6453695SRichard Henderson                            TCGReg arg1, tcg_target_long arg2, bool c2)
1306f6453695SRichard Henderson{
1307f6453695SRichard Henderson    int tmpflags = tcg_out_setcond_int(s, cond, ret, arg1, arg2, c2);
1308f6453695SRichard Henderson
1309f6453695SRichard Henderson    if (tmpflags != ret) {
1310f6453695SRichard Henderson        TCGReg tmp = tmpflags & ~SETCOND_FLAGS;
1311f6453695SRichard Henderson
1312f6453695SRichard Henderson        switch (tmpflags & SETCOND_FLAGS) {
1313f6453695SRichard Henderson        case SETCOND_INV:
1314f6453695SRichard Henderson            /* Intermediate result is boolean: simply invert. */
1315f6453695SRichard Henderson            tcg_out_opc_imm(s, OPC_XORI, ret, tmp, 1);
1316f6453695SRichard Henderson            break;
1317f6453695SRichard Henderson        case SETCOND_NEZ:
1318f6453695SRichard Henderson            /* Intermediate result is zero/non-zero: test != 0. */
1319f6453695SRichard Henderson            tcg_out_opc_reg(s, OPC_SLTU, ret, TCG_REG_ZERO, tmp);
1320f6453695SRichard Henderson            break;
1321f6453695SRichard Henderson        case SETCOND_NEZ | SETCOND_INV:
1322f6453695SRichard Henderson            /* Intermediate result is zero/non-zero: test == 0. */
1323f6453695SRichard Henderson            tcg_out_opc_imm(s, OPC_SLTIU, ret, tmp, 1);
1324139c1837SPaolo Bonzini            break;
1325139c1837SPaolo Bonzini        default:
1326139c1837SPaolo Bonzini            g_assert_not_reached();
1327f6453695SRichard Henderson        }
1328139c1837SPaolo Bonzini    }
1329139c1837SPaolo Bonzini}
1330139c1837SPaolo Bonzini
133141e4c0a9SRichard Hendersonstatic void tcg_out_negsetcond(TCGContext *s, TCGCond cond, TCGReg ret,
133241e4c0a9SRichard Henderson                               TCGReg arg1, tcg_target_long arg2, bool c2)
133341e4c0a9SRichard Henderson{
133441e4c0a9SRichard Henderson    int tmpflags;
133541e4c0a9SRichard Henderson    TCGReg tmp;
133641e4c0a9SRichard Henderson
133741e4c0a9SRichard Henderson    /* For LT/GE comparison against 0, replicate the sign bit. */
133841e4c0a9SRichard Henderson    if (c2 && arg2 == 0) {
133941e4c0a9SRichard Henderson        switch (cond) {
134041e4c0a9SRichard Henderson        case TCG_COND_GE:
134141e4c0a9SRichard Henderson            tcg_out_opc_imm(s, OPC_XORI, ret, arg1, -1);
134241e4c0a9SRichard Henderson            arg1 = ret;
134341e4c0a9SRichard Henderson            /* fall through */
134441e4c0a9SRichard Henderson        case TCG_COND_LT:
134541e4c0a9SRichard Henderson            tcg_out_opc_imm(s, OPC_SRAI, ret, arg1, TCG_TARGET_REG_BITS - 1);
134641e4c0a9SRichard Henderson            return;
134741e4c0a9SRichard Henderson        default:
134841e4c0a9SRichard Henderson            break;
134941e4c0a9SRichard Henderson        }
135041e4c0a9SRichard Henderson    }
135141e4c0a9SRichard Henderson
135241e4c0a9SRichard Henderson    tmpflags = tcg_out_setcond_int(s, cond, ret, arg1, arg2, c2);
135341e4c0a9SRichard Henderson    tmp = tmpflags & ~SETCOND_FLAGS;
135441e4c0a9SRichard Henderson
135541e4c0a9SRichard Henderson    /* If intermediate result is zero/non-zero: test != 0. */
135641e4c0a9SRichard Henderson    if (tmpflags & SETCOND_NEZ) {
135741e4c0a9SRichard Henderson        tcg_out_opc_reg(s, OPC_SLTU, ret, TCG_REG_ZERO, tmp);
135841e4c0a9SRichard Henderson        tmp = ret;
135941e4c0a9SRichard Henderson    }
136041e4c0a9SRichard Henderson
136141e4c0a9SRichard Henderson    /* Produce the 0/-1 result. */
136241e4c0a9SRichard Henderson    if (tmpflags & SETCOND_INV) {
136341e4c0a9SRichard Henderson        tcg_out_opc_imm(s, OPC_ADDI, ret, tmp, -1);
136441e4c0a9SRichard Henderson    } else {
136541e4c0a9SRichard Henderson        tcg_out_opc_reg(s, OPC_SUB, ret, TCG_REG_ZERO, tmp);
136641e4c0a9SRichard Henderson    }
136741e4c0a9SRichard Henderson}
136841e4c0a9SRichard Henderson
1369a18d783eSRichard Hendersonstatic void tcg_out_movcond_zicond(TCGContext *s, TCGReg ret, TCGReg test_ne,
1370a18d783eSRichard Henderson                                   int val1, bool c_val1,
1371a18d783eSRichard Henderson                                   int val2, bool c_val2)
1372a18d783eSRichard Henderson{
1373a18d783eSRichard Henderson    if (val1 == 0) {
1374a18d783eSRichard Henderson        if (c_val2) {
1375a18d783eSRichard Henderson            tcg_out_movi(s, TCG_TYPE_REG, TCG_REG_TMP1, val2);
1376a18d783eSRichard Henderson            val2 = TCG_REG_TMP1;
1377a18d783eSRichard Henderson        }
1378a18d783eSRichard Henderson        tcg_out_opc_reg(s, OPC_CZERO_NEZ, ret, val2, test_ne);
1379a18d783eSRichard Henderson        return;
1380a18d783eSRichard Henderson    }
1381a18d783eSRichard Henderson
1382a18d783eSRichard Henderson    if (val2 == 0) {
1383a18d783eSRichard Henderson        if (c_val1) {
1384a18d783eSRichard Henderson            tcg_out_movi(s, TCG_TYPE_REG, TCG_REG_TMP1, val1);
1385a18d783eSRichard Henderson            val1 = TCG_REG_TMP1;
1386a18d783eSRichard Henderson        }
1387a18d783eSRichard Henderson        tcg_out_opc_reg(s, OPC_CZERO_EQZ, ret, val1, test_ne);
1388a18d783eSRichard Henderson        return;
1389a18d783eSRichard Henderson    }
1390a18d783eSRichard Henderson
1391a18d783eSRichard Henderson    if (c_val2) {
1392a18d783eSRichard Henderson        if (c_val1) {
1393a18d783eSRichard Henderson            tcg_out_movi(s, TCG_TYPE_REG, TCG_REG_TMP1, val1 - val2);
1394a18d783eSRichard Henderson        } else {
1395a18d783eSRichard Henderson            tcg_out_opc_imm(s, OPC_ADDI, TCG_REG_TMP1, val1, -val2);
1396a18d783eSRichard Henderson        }
1397a18d783eSRichard Henderson        tcg_out_opc_reg(s, OPC_CZERO_EQZ, ret, TCG_REG_TMP1, test_ne);
1398a18d783eSRichard Henderson        tcg_out_opc_imm(s, OPC_ADDI, ret, ret, val2);
1399a18d783eSRichard Henderson        return;
1400a18d783eSRichard Henderson    }
1401a18d783eSRichard Henderson
1402a18d783eSRichard Henderson    if (c_val1) {
1403a18d783eSRichard Henderson        tcg_out_opc_imm(s, OPC_ADDI, TCG_REG_TMP1, val2, -val1);
1404a18d783eSRichard Henderson        tcg_out_opc_reg(s, OPC_CZERO_NEZ, ret, TCG_REG_TMP1, test_ne);
1405a18d783eSRichard Henderson        tcg_out_opc_imm(s, OPC_ADDI, ret, ret, val1);
1406a18d783eSRichard Henderson        return;
1407a18d783eSRichard Henderson    }
1408a18d783eSRichard Henderson
1409a18d783eSRichard Henderson    tcg_out_opc_reg(s, OPC_CZERO_NEZ, TCG_REG_TMP1, val2, test_ne);
1410a18d783eSRichard Henderson    tcg_out_opc_reg(s, OPC_CZERO_EQZ, TCG_REG_TMP0, val1, test_ne);
1411a18d783eSRichard Henderson    tcg_out_opc_reg(s, OPC_OR, ret, TCG_REG_TMP0, TCG_REG_TMP1);
1412a18d783eSRichard Henderson}
1413a18d783eSRichard Henderson
1414a18d783eSRichard Hendersonstatic void tcg_out_movcond_br1(TCGContext *s, TCGCond cond, TCGReg ret,
1415a18d783eSRichard Henderson                                TCGReg cmp1, TCGReg cmp2,
1416a18d783eSRichard Henderson                                int val, bool c_val)
1417a18d783eSRichard Henderson{
1418a18d783eSRichard Henderson    RISCVInsn op;
1419a18d783eSRichard Henderson    int disp = 8;
1420a18d783eSRichard Henderson
1421a18d783eSRichard Henderson    tcg_debug_assert((unsigned)cond < ARRAY_SIZE(tcg_brcond_to_riscv));
1422a18d783eSRichard Henderson    op = tcg_brcond_to_riscv[cond].op;
1423a18d783eSRichard Henderson    tcg_debug_assert(op != 0);
1424a18d783eSRichard Henderson
1425a18d783eSRichard Henderson    if (tcg_brcond_to_riscv[cond].swap) {
1426a18d783eSRichard Henderson        tcg_out_opc_branch(s, op, cmp2, cmp1, disp);
1427a18d783eSRichard Henderson    } else {
1428a18d783eSRichard Henderson        tcg_out_opc_branch(s, op, cmp1, cmp2, disp);
1429a18d783eSRichard Henderson    }
1430a18d783eSRichard Henderson    if (c_val) {
1431a18d783eSRichard Henderson        tcg_out_opc_imm(s, OPC_ADDI, ret, TCG_REG_ZERO, val);
1432a18d783eSRichard Henderson    } else {
1433a18d783eSRichard Henderson        tcg_out_opc_imm(s, OPC_ADDI, ret, val, 0);
1434a18d783eSRichard Henderson    }
1435a18d783eSRichard Henderson}
1436a18d783eSRichard Henderson
1437a18d783eSRichard Hendersonstatic void tcg_out_movcond_br2(TCGContext *s, TCGCond cond, TCGReg ret,
1438a18d783eSRichard Henderson                                TCGReg cmp1, TCGReg cmp2,
1439a18d783eSRichard Henderson                                int val1, bool c_val1,
1440a18d783eSRichard Henderson                                int val2, bool c_val2)
1441a18d783eSRichard Henderson{
1442a18d783eSRichard Henderson    TCGReg tmp;
1443a18d783eSRichard Henderson
1444a18d783eSRichard Henderson    /* TCG optimizer reorders to prefer ret matching val2. */
1445a18d783eSRichard Henderson    if (!c_val2 && ret == val2) {
1446a18d783eSRichard Henderson        cond = tcg_invert_cond(cond);
1447a18d783eSRichard Henderson        tcg_out_movcond_br1(s, cond, ret, cmp1, cmp2, val1, c_val1);
1448a18d783eSRichard Henderson        return;
1449a18d783eSRichard Henderson    }
1450a18d783eSRichard Henderson
1451a18d783eSRichard Henderson    if (!c_val1 && ret == val1) {
1452a18d783eSRichard Henderson        tcg_out_movcond_br1(s, cond, ret, cmp1, cmp2, val2, c_val2);
1453a18d783eSRichard Henderson        return;
1454a18d783eSRichard Henderson    }
1455a18d783eSRichard Henderson
1456a18d783eSRichard Henderson    tmp = (ret == cmp1 || ret == cmp2 ? TCG_REG_TMP1 : ret);
1457a18d783eSRichard Henderson    if (c_val1) {
1458a18d783eSRichard Henderson        tcg_out_movi(s, TCG_TYPE_REG, tmp, val1);
1459a18d783eSRichard Henderson    } else {
1460a18d783eSRichard Henderson        tcg_out_mov(s, TCG_TYPE_REG, tmp, val1);
1461a18d783eSRichard Henderson    }
1462a18d783eSRichard Henderson    tcg_out_movcond_br1(s, cond, tmp, cmp1, cmp2, val2, c_val2);
1463a18d783eSRichard Henderson    tcg_out_mov(s, TCG_TYPE_REG, ret, tmp);
1464a18d783eSRichard Henderson}
1465a18d783eSRichard Henderson
1466a18d783eSRichard Hendersonstatic void tcg_out_movcond(TCGContext *s, TCGCond cond, TCGReg ret,
1467a18d783eSRichard Henderson                            TCGReg cmp1, int cmp2, bool c_cmp2,
1468a18d783eSRichard Henderson                            TCGReg val1, bool c_val1,
1469a18d783eSRichard Henderson                            TCGReg val2, bool c_val2)
1470a18d783eSRichard Henderson{
1471a18d783eSRichard Henderson    int tmpflags;
1472a18d783eSRichard Henderson    TCGReg t;
1473a18d783eSRichard Henderson
1474b86c6ba6SRichard Henderson    if (!(cpuinfo & CPUINFO_ZICOND) && (!c_cmp2 || cmp2 == 0)) {
1475a18d783eSRichard Henderson        tcg_out_movcond_br2(s, cond, ret, cmp1, cmp2,
1476a18d783eSRichard Henderson                            val1, c_val1, val2, c_val2);
1477a18d783eSRichard Henderson        return;
1478a18d783eSRichard Henderson    }
1479a18d783eSRichard Henderson
1480a18d783eSRichard Henderson    tmpflags = tcg_out_setcond_int(s, cond, TCG_REG_TMP0, cmp1, cmp2, c_cmp2);
1481a18d783eSRichard Henderson    t = tmpflags & ~SETCOND_FLAGS;
1482a18d783eSRichard Henderson
1483b86c6ba6SRichard Henderson    if (cpuinfo & CPUINFO_ZICOND) {
1484a18d783eSRichard Henderson        if (tmpflags & SETCOND_INV) {
1485a18d783eSRichard Henderson            tcg_out_movcond_zicond(s, ret, t, val2, c_val2, val1, c_val1);
1486a18d783eSRichard Henderson        } else {
1487a18d783eSRichard Henderson            tcg_out_movcond_zicond(s, ret, t, val1, c_val1, val2, c_val2);
1488a18d783eSRichard Henderson        }
1489a18d783eSRichard Henderson    } else {
1490a18d783eSRichard Henderson        cond = tmpflags & SETCOND_INV ? TCG_COND_EQ : TCG_COND_NE;
1491a18d783eSRichard Henderson        tcg_out_movcond_br2(s, cond, ret, t, TCG_REG_ZERO,
1492a18d783eSRichard Henderson                            val1, c_val1, val2, c_val2);
1493a18d783eSRichard Henderson    }
1494a18d783eSRichard Henderson}
1495a18d783eSRichard Henderson
1496a30498fcSRichard Hendersonstatic void tcg_out_cltz(TCGContext *s, TCGType type, RISCVInsn insn,
1497a30498fcSRichard Henderson                         TCGReg ret, TCGReg src1, int src2, bool c_src2)
1498a30498fcSRichard Henderson{
1499a30498fcSRichard Henderson    tcg_out_opc_imm(s, insn, ret, src1, 0);
1500a30498fcSRichard Henderson
1501a30498fcSRichard Henderson    if (!c_src2 || src2 != (type == TCG_TYPE_I32 ? 32 : 64)) {
1502a30498fcSRichard Henderson        /*
1503a30498fcSRichard Henderson         * The requested zero result does not match the insn, so adjust.
1504a30498fcSRichard Henderson         * Note that constraints put 'ret' in a new register, so the
1505a30498fcSRichard Henderson         * computation above did not clobber either 'src1' or 'src2'.
1506a30498fcSRichard Henderson         */
1507a30498fcSRichard Henderson        tcg_out_movcond(s, TCG_COND_EQ, ret, src1, 0, true,
1508a30498fcSRichard Henderson                        src2, c_src2, ret, false);
1509a30498fcSRichard Henderson    }
1510a30498fcSRichard Henderson}
1511a30498fcSRichard Henderson
1512a31768c0STANG Tianchengstatic void tcg_out_cmpsel(TCGContext *s, TCGType type, unsigned vece,
1513a31768c0STANG Tiancheng                           TCGCond cond, TCGReg ret,
1514a31768c0STANG Tiancheng                           TCGReg cmp1, TCGReg cmp2, bool c_cmp2,
1515a31768c0STANG Tiancheng                           TCGReg val1, bool c_val1,
1516a31768c0STANG Tiancheng                           TCGReg val2, bool c_val2)
1517a31768c0STANG Tiancheng{
1518a31768c0STANG Tiancheng    set_vtype_len_sew(s, type, vece);
1519a31768c0STANG Tiancheng
1520a31768c0STANG Tiancheng    /* Use only vmerge_vim if possible, by inverting the test. */
1521a31768c0STANG Tiancheng    if (c_val2 && !c_val1) {
1522a31768c0STANG Tiancheng        TCGArg temp = val1;
1523a31768c0STANG Tiancheng        cond = tcg_invert_cond(cond);
1524a31768c0STANG Tiancheng        val1 = val2;
1525a31768c0STANG Tiancheng        val2 = temp;
1526a31768c0STANG Tiancheng        c_val1 = true;
1527a31768c0STANG Tiancheng        c_val2 = false;
1528a31768c0STANG Tiancheng    }
1529a31768c0STANG Tiancheng
1530a31768c0STANG Tiancheng    /* Perform the comparison into V0 mask. */
1531a31768c0STANG Tiancheng    if (c_cmp2) {
1532a31768c0STANG Tiancheng        tcg_out_opc_vi(s, tcg_cmpcond_to_rvv_vi[cond].op, TCG_REG_V0, cmp1,
1533a31768c0STANG Tiancheng                       cmp2 - tcg_cmpcond_to_rvv_vi[cond].adjust);
1534a31768c0STANG Tiancheng    } else if (tcg_cmpcond_to_rvv_vv[cond].swap) {
1535a31768c0STANG Tiancheng        tcg_out_opc_vv(s, tcg_cmpcond_to_rvv_vv[cond].op,
1536a31768c0STANG Tiancheng                       TCG_REG_V0, cmp2, cmp1);
1537a31768c0STANG Tiancheng    } else {
1538a31768c0STANG Tiancheng        tcg_out_opc_vv(s, tcg_cmpcond_to_rvv_vv[cond].op,
1539a31768c0STANG Tiancheng                       TCG_REG_V0, cmp1, cmp2);
1540a31768c0STANG Tiancheng    }
1541a31768c0STANG Tiancheng    if (c_val1) {
1542a31768c0STANG Tiancheng        if (c_val2) {
1543a31768c0STANG Tiancheng            tcg_out_opc_vi(s, OPC_VMV_V_I, ret, 0, val2);
1544a31768c0STANG Tiancheng            val2 = ret;
1545a31768c0STANG Tiancheng        }
1546a31768c0STANG Tiancheng        /* vd[i] == v0.mask[i] ? imm : vs2[i] */
1547a31768c0STANG Tiancheng        tcg_out_opc_vim_mask(s, OPC_VMERGE_VIM, ret, val2, val1);
1548a31768c0STANG Tiancheng    } else {
1549a31768c0STANG Tiancheng        /* vd[i] == v0.mask[i] ? vs1[i] : vs2[i] */
1550a31768c0STANG Tiancheng        tcg_out_opc_vvm_mask(s, OPC_VMERGE_VVM, ret, val2, val1);
1551a31768c0STANG Tiancheng    }
1552a31768c0STANG Tiancheng}
1553a31768c0STANG Tiancheng
1554f63e7089SHuang Shiyuanstatic void init_setting_vtype(TCGContext *s)
1555f63e7089SHuang Shiyuan{
1556f63e7089SHuang Shiyuan    s->riscv_cur_type = TCG_TYPE_COUNT;
1557f63e7089SHuang Shiyuan}
1558f63e7089SHuang Shiyuan
15592be7d76bSRichard Hendersonstatic void tcg_out_call_int(TCGContext *s, const tcg_insn_unit *arg, bool tail)
1560139c1837SPaolo Bonzini{
1561139c1837SPaolo Bonzini    TCGReg link = tail ? TCG_REG_ZERO : TCG_REG_RA;
1562139c1837SPaolo Bonzini    ptrdiff_t offset = tcg_pcrel_diff(s, arg);
1563139c1837SPaolo Bonzini    int ret;
1564139c1837SPaolo Bonzini
1565f63e7089SHuang Shiyuan    init_setting_vtype(s);
1566f63e7089SHuang Shiyuan
1567844d0442SRichard Henderson    tcg_debug_assert((offset & 1) == 0);
1568844d0442SRichard Henderson    if (offset == sextreg(offset, 0, 20)) {
1569139c1837SPaolo Bonzini        /* short jump: -2097150 to 2097152 */
1570139c1837SPaolo Bonzini        tcg_out_opc_jump(s, OPC_JAL, link, offset);
1571aeb6326eSRichard Henderson    } else if (offset == (int32_t)offset) {
1572139c1837SPaolo Bonzini        /* long jump: -2147483646 to 2147483648 */
1573139c1837SPaolo Bonzini        tcg_out_opc_upper(s, OPC_AUIPC, TCG_REG_TMP0, 0);
1574139c1837SPaolo Bonzini        tcg_out_opc_imm(s, OPC_JALR, link, TCG_REG_TMP0, 0);
1575844d0442SRichard Henderson        ret = reloc_call(s->code_ptr - 2, arg);
1576139c1837SPaolo Bonzini        tcg_debug_assert(ret == true);
1577aeb6326eSRichard Henderson    } else {
1578139c1837SPaolo Bonzini        /* far jump: 64-bit */
1579139c1837SPaolo Bonzini        tcg_target_long imm = sextreg((tcg_target_long)arg, 0, 12);
1580139c1837SPaolo Bonzini        tcg_target_long base = (tcg_target_long)arg - imm;
1581139c1837SPaolo Bonzini        tcg_out_movi(s, TCG_TYPE_PTR, TCG_REG_TMP0, base);
1582139c1837SPaolo Bonzini        tcg_out_opc_imm(s, OPC_JALR, link, TCG_REG_TMP0, imm);
1583139c1837SPaolo Bonzini    }
1584139c1837SPaolo Bonzini}
1585139c1837SPaolo Bonzini
1586cee44b03SRichard Hendersonstatic void tcg_out_call(TCGContext *s, const tcg_insn_unit *arg,
1587cee44b03SRichard Henderson                         const TCGHelperInfo *info)
1588139c1837SPaolo Bonzini{
1589139c1837SPaolo Bonzini    tcg_out_call_int(s, arg, false);
1590139c1837SPaolo Bonzini}
1591139c1837SPaolo Bonzini
1592139c1837SPaolo Bonzinistatic void tcg_out_mb(TCGContext *s, TCGArg a0)
1593139c1837SPaolo Bonzini{
1594139c1837SPaolo Bonzini    tcg_insn_unit insn = OPC_FENCE;
1595139c1837SPaolo Bonzini
1596139c1837SPaolo Bonzini    if (a0 & TCG_MO_LD_LD) {
1597139c1837SPaolo Bonzini        insn |= 0x02200000;
1598139c1837SPaolo Bonzini    }
1599139c1837SPaolo Bonzini    if (a0 & TCG_MO_ST_LD) {
1600139c1837SPaolo Bonzini        insn |= 0x01200000;
1601139c1837SPaolo Bonzini    }
1602139c1837SPaolo Bonzini    if (a0 & TCG_MO_LD_ST) {
1603139c1837SPaolo Bonzini        insn |= 0x02100000;
1604139c1837SPaolo Bonzini    }
1605139c1837SPaolo Bonzini    if (a0 & TCG_MO_ST_ST) {
1606139c1837SPaolo Bonzini        insn |= 0x02200000;
1607139c1837SPaolo Bonzini    }
1608139c1837SPaolo Bonzini    tcg_out32(s, insn);
1609139c1837SPaolo Bonzini}
1610139c1837SPaolo Bonzini
1611139c1837SPaolo Bonzini/*
1612139c1837SPaolo Bonzini * Load/store and TLB
1613139c1837SPaolo Bonzini */
1614139c1837SPaolo Bonzini
1615793f7381SRichard Hendersonstatic void tcg_out_goto(TCGContext *s, const tcg_insn_unit *target)
1616844d0442SRichard Henderson{
1617844d0442SRichard Henderson    tcg_out_opc_jump(s, OPC_JAL, TCG_REG_ZERO, 0);
1618844d0442SRichard Henderson    bool ok = reloc_jimm20(s->code_ptr - 1, target);
1619844d0442SRichard Henderson    tcg_debug_assert(ok);
1620844d0442SRichard Henderson}
1621844d0442SRichard Henderson
16227b880107SRichard Hendersonbool tcg_target_has_memory_bswap(MemOp memop)
16237b880107SRichard Henderson{
16247b880107SRichard Henderson    return false;
16257b880107SRichard Henderson}
16267b880107SRichard Henderson
162761b6daafSRichard Henderson/* We have three temps, we might as well expose them. */
162861b6daafSRichard Hendersonstatic const TCGLdstHelperParam ldst_helper_param = {
162961b6daafSRichard Henderson    .ntmp = 3, .tmp = { TCG_REG_TMP0, TCG_REG_TMP1, TCG_REG_TMP2 }
163061b6daafSRichard Henderson};
163161b6daafSRichard Henderson
1632139c1837SPaolo Bonzinistatic bool tcg_out_qemu_ld_slow_path(TCGContext *s, TCGLabelQemuLdst *l)
1633139c1837SPaolo Bonzini{
163461b6daafSRichard Henderson    MemOp opc = get_memop(l->oi);
1635139c1837SPaolo Bonzini
1636139c1837SPaolo Bonzini    /* resolve label address */
1637793f7381SRichard Henderson    if (!reloc_sbimm12(l->label_ptr[0], tcg_splitwx_to_rx(s->code_ptr))) {
1638139c1837SPaolo Bonzini        return false;
1639139c1837SPaolo Bonzini    }
1640139c1837SPaolo Bonzini
1641139c1837SPaolo Bonzini    /* call load helper */
164261b6daafSRichard Henderson    tcg_out_ld_helper_args(s, l, &ldst_helper_param);
1643cee44b03SRichard Henderson    tcg_out_call_int(s, qemu_ld_helpers[opc & MO_SSIZE], false);
164461b6daafSRichard Henderson    tcg_out_ld_helper_ret(s, l, true, &ldst_helper_param);
1645139c1837SPaolo Bonzini
1646139c1837SPaolo Bonzini    tcg_out_goto(s, l->raddr);
1647139c1837SPaolo Bonzini    return true;
1648139c1837SPaolo Bonzini}
1649139c1837SPaolo Bonzini
1650139c1837SPaolo Bonzinistatic bool tcg_out_qemu_st_slow_path(TCGContext *s, TCGLabelQemuLdst *l)
1651139c1837SPaolo Bonzini{
165261b6daafSRichard Henderson    MemOp opc = get_memop(l->oi);
1653139c1837SPaolo Bonzini
1654139c1837SPaolo Bonzini    /* resolve label address */
1655793f7381SRichard Henderson    if (!reloc_sbimm12(l->label_ptr[0], tcg_splitwx_to_rx(s->code_ptr))) {
1656139c1837SPaolo Bonzini        return false;
1657139c1837SPaolo Bonzini    }
1658139c1837SPaolo Bonzini
1659139c1837SPaolo Bonzini    /* call store helper */
166061b6daafSRichard Henderson    tcg_out_st_helper_args(s, l, &ldst_helper_param);
1661cee44b03SRichard Henderson    tcg_out_call_int(s, qemu_st_helpers[opc & MO_SIZE], false);
1662139c1837SPaolo Bonzini
1663139c1837SPaolo Bonzini    tcg_out_goto(s, l->raddr);
1664139c1837SPaolo Bonzini    return true;
1665139c1837SPaolo Bonzini}
1666139c1837SPaolo Bonzini
1667d0a9bb5eSRichard Henderson/* We expect to use a 12-bit negative offset from ENV.  */
1668d0a9bb5eSRichard Henderson#define MIN_TLB_MASK_TABLE_OFS  -(1 << 11)
1669d0a9bb5eSRichard Henderson
1670001dddfeSRichard Henderson/*
16717893e42dSPhilippe Mathieu-Daudé * For system-mode, perform the TLB load and compare.
16727893e42dSPhilippe Mathieu-Daudé * For user-mode, perform any required alignment tests.
1673001dddfeSRichard Henderson * In both cases, return a TCGLabelQemuLdst structure if the slow path
1674001dddfeSRichard Henderson * is required and fill in @h with the host address for the fast path.
1675001dddfeSRichard Henderson */
1676001dddfeSRichard Hendersonstatic TCGLabelQemuLdst *prepare_host_addr(TCGContext *s, TCGReg *pbase,
1677001dddfeSRichard Henderson                                           TCGReg addr_reg, MemOpIdx oi,
1678001dddfeSRichard Henderson                                           bool is_ld)
1679001dddfeSRichard Henderson{
16808aefe1fbSRichard Henderson    TCGType addr_type = s->addr_type;
1681001dddfeSRichard Henderson    TCGLabelQemuLdst *ldst = NULL;
1682001dddfeSRichard Henderson    MemOp opc = get_memop(oi);
168337e523f0SRichard Henderson    TCGAtomAlign aa;
168437e523f0SRichard Henderson    unsigned a_mask;
168537e523f0SRichard Henderson
168637e523f0SRichard Henderson    aa = atom_and_align_for_opc(s, opc, MO_ATOM_IFALIGN, false);
168737e523f0SRichard Henderson    a_mask = (1u << aa.align) - 1;
1688001dddfeSRichard Henderson
16894944d359SRichard Henderson    if (tcg_use_softmmu) {
1690001dddfeSRichard Henderson        unsigned s_bits = opc & MO_SIZE;
1691933b331bSRichard Henderson        unsigned s_mask = (1u << s_bits) - 1;
1692001dddfeSRichard Henderson        int mem_index = get_mmuidx(oi);
1693d0a9bb5eSRichard Henderson        int fast_ofs = tlb_mask_table_ofs(s, mem_index);
1694001dddfeSRichard Henderson        int mask_ofs = fast_ofs + offsetof(CPUTLBDescFast, mask);
1695001dddfeSRichard Henderson        int table_ofs = fast_ofs + offsetof(CPUTLBDescFast, table);
1696933b331bSRichard Henderson        int compare_mask;
1697933b331bSRichard Henderson        TCGReg addr_adj;
1698001dddfeSRichard Henderson
1699001dddfeSRichard Henderson        ldst = new_ldst_label(s);
1700001dddfeSRichard Henderson        ldst->is_ld = is_ld;
1701001dddfeSRichard Henderson        ldst->oi = oi;
1702001dddfeSRichard Henderson        ldst->addrlo_reg = addr_reg;
1703001dddfeSRichard Henderson
1704f63e7089SHuang Shiyuan        init_setting_vtype(s);
1705f63e7089SHuang Shiyuan
1706933b331bSRichard Henderson        tcg_out_ld(s, TCG_TYPE_PTR, TCG_REG_TMP0, TCG_AREG0, mask_ofs);
1707933b331bSRichard Henderson        tcg_out_ld(s, TCG_TYPE_PTR, TCG_REG_TMP1, TCG_AREG0, table_ofs);
1708001dddfeSRichard Henderson
1709001dddfeSRichard Henderson        tcg_out_opc_imm(s, OPC_SRLI, TCG_REG_TMP2, addr_reg,
1710aece72b7SRichard Henderson                        s->page_bits - CPU_TLB_ENTRY_BITS);
1711001dddfeSRichard Henderson        tcg_out_opc_reg(s, OPC_AND, TCG_REG_TMP2, TCG_REG_TMP2, TCG_REG_TMP0);
1712001dddfeSRichard Henderson        tcg_out_opc_reg(s, OPC_ADD, TCG_REG_TMP2, TCG_REG_TMP2, TCG_REG_TMP1);
1713001dddfeSRichard Henderson
1714933b331bSRichard Henderson        /*
17154944d359SRichard Henderson         * For aligned accesses, we check the first byte and include the
17164944d359SRichard Henderson         * alignment bits within the address.  For unaligned access, we
17174944d359SRichard Henderson         * check that we don't cross pages using the address of the last
17184944d359SRichard Henderson         * byte of the access.
1719933b331bSRichard Henderson         */
1720933b331bSRichard Henderson        addr_adj = addr_reg;
172137e523f0SRichard Henderson        if (a_mask < s_mask) {
1722933b331bSRichard Henderson            addr_adj = TCG_REG_TMP0;
17238aefe1fbSRichard Henderson            tcg_out_opc_imm(s, addr_type == TCG_TYPE_I32 ? OPC_ADDIW : OPC_ADDI,
1724933b331bSRichard Henderson                            addr_adj, addr_reg, s_mask - a_mask);
1725933b331bSRichard Henderson        }
1726aece72b7SRichard Henderson        compare_mask = s->page_mask | a_mask;
1727933b331bSRichard Henderson        if (compare_mask == sextreg(compare_mask, 0, 12)) {
1728933b331bSRichard Henderson            tcg_out_opc_imm(s, OPC_ANDI, TCG_REG_TMP1, addr_adj, compare_mask);
1729933b331bSRichard Henderson        } else {
17308aefe1fbSRichard Henderson            tcg_out_movi(s, addr_type, TCG_REG_TMP1, compare_mask);
1731933b331bSRichard Henderson            tcg_out_opc_reg(s, OPC_AND, TCG_REG_TMP1, TCG_REG_TMP1, addr_adj);
1732933b331bSRichard Henderson        }
1733933b331bSRichard Henderson
1734001dddfeSRichard Henderson        /* Load the tlb comparator and the addend.  */
1735238f4380SRichard Henderson        QEMU_BUILD_BUG_ON(HOST_BIG_ENDIAN);
17368aefe1fbSRichard Henderson        tcg_out_ld(s, addr_type, TCG_REG_TMP0, TCG_REG_TMP2,
1737001dddfeSRichard Henderson                   is_ld ? offsetof(CPUTLBEntry, addr_read)
1738001dddfeSRichard Henderson                         : offsetof(CPUTLBEntry, addr_write));
1739001dddfeSRichard Henderson        tcg_out_ld(s, TCG_TYPE_PTR, TCG_REG_TMP2, TCG_REG_TMP2,
1740001dddfeSRichard Henderson                   offsetof(CPUTLBEntry, addend));
1741001dddfeSRichard Henderson
1742001dddfeSRichard Henderson        /* Compare masked address with the TLB entry. */
1743001dddfeSRichard Henderson        ldst->label_ptr[0] = s->code_ptr;
1744001dddfeSRichard Henderson        tcg_out_opc_branch(s, OPC_BNE, TCG_REG_TMP0, TCG_REG_TMP1, 0);
1745001dddfeSRichard Henderson
1746001dddfeSRichard Henderson        /* TLB Hit - translate address using addend.  */
17478aefe1fbSRichard Henderson        if (addr_type != TCG_TYPE_I32) {
1748eda15159SRichard Henderson            tcg_out_opc_reg(s, OPC_ADD, TCG_REG_TMP0, addr_reg, TCG_REG_TMP2);
1749b86c6ba6SRichard Henderson        } else if (cpuinfo & CPUINFO_ZBA) {
17504944d359SRichard Henderson            tcg_out_opc_reg(s, OPC_ADD_UW, TCG_REG_TMP0,
17514944d359SRichard Henderson                            addr_reg, TCG_REG_TMP2);
1752eda15159SRichard Henderson        } else {
1753eda15159SRichard Henderson            tcg_out_ext32u(s, TCG_REG_TMP0, addr_reg);
17544944d359SRichard Henderson            tcg_out_opc_reg(s, OPC_ADD, TCG_REG_TMP0,
17554944d359SRichard Henderson                            TCG_REG_TMP0, TCG_REG_TMP2);
1756001dddfeSRichard Henderson        }
1757001dddfeSRichard Henderson        *pbase = TCG_REG_TMP0;
17584944d359SRichard Henderson    } else {
1759eda15159SRichard Henderson        TCGReg base;
1760eda15159SRichard Henderson
1761001dddfeSRichard Henderson        if (a_mask) {
1762001dddfeSRichard Henderson            ldst = new_ldst_label(s);
1763001dddfeSRichard Henderson            ldst->is_ld = is_ld;
1764001dddfeSRichard Henderson            ldst->oi = oi;
1765001dddfeSRichard Henderson            ldst->addrlo_reg = addr_reg;
1766001dddfeSRichard Henderson
1767f63e7089SHuang Shiyuan            init_setting_vtype(s);
1768f63e7089SHuang Shiyuan
176937e523f0SRichard Henderson            /* We are expecting alignment max 7, so we can always use andi. */
177037e523f0SRichard Henderson            tcg_debug_assert(a_mask == sextreg(a_mask, 0, 12));
1771001dddfeSRichard Henderson            tcg_out_opc_imm(s, OPC_ANDI, TCG_REG_TMP1, addr_reg, a_mask);
1772001dddfeSRichard Henderson
1773001dddfeSRichard Henderson            ldst->label_ptr[0] = s->code_ptr;
1774001dddfeSRichard Henderson            tcg_out_opc_branch(s, OPC_BNE, TCG_REG_TMP1, TCG_REG_ZERO, 0);
1775001dddfeSRichard Henderson        }
1776001dddfeSRichard Henderson
1777001dddfeSRichard Henderson        if (guest_base != 0) {
1778001dddfeSRichard Henderson            base = TCG_REG_TMP0;
17798aefe1fbSRichard Henderson            if (addr_type != TCG_TYPE_I32) {
17804944d359SRichard Henderson                tcg_out_opc_reg(s, OPC_ADD, base, addr_reg,
17814944d359SRichard Henderson                                TCG_GUEST_BASE_REG);
1782b86c6ba6SRichard Henderson            } else if (cpuinfo & CPUINFO_ZBA) {
17834944d359SRichard Henderson                tcg_out_opc_reg(s, OPC_ADD_UW, base, addr_reg,
17844944d359SRichard Henderson                                TCG_GUEST_BASE_REG);
1785eda15159SRichard Henderson            } else {
1786eda15159SRichard Henderson                tcg_out_ext32u(s, base, addr_reg);
1787eda15159SRichard Henderson                tcg_out_opc_reg(s, OPC_ADD, base, base, TCG_GUEST_BASE_REG);
1788eda15159SRichard Henderson            }
17898aefe1fbSRichard Henderson        } else if (addr_type != TCG_TYPE_I32) {
1790eda15159SRichard Henderson            base = addr_reg;
1791eda15159SRichard Henderson        } else {
1792eda15159SRichard Henderson            base = TCG_REG_TMP0;
1793eda15159SRichard Henderson            tcg_out_ext32u(s, base, addr_reg);
1794001dddfeSRichard Henderson        }
1795001dddfeSRichard Henderson        *pbase = base;
17964944d359SRichard Henderson    }
1797001dddfeSRichard Henderson
1798001dddfeSRichard Henderson    return ldst;
1799001dddfeSRichard Henderson}
1800001dddfeSRichard Henderson
1801aeb6326eSRichard Hendersonstatic void tcg_out_qemu_ld_direct(TCGContext *s, TCGReg val,
1802f7041977SRichard Henderson                                   TCGReg base, MemOp opc, TCGType type)
1803139c1837SPaolo Bonzini{
1804c86bd2dcSRichard Henderson    /* Byte swapping is left to middle-end expansion. */
1805c86bd2dcSRichard Henderson    tcg_debug_assert((opc & MO_BSWAP) == 0);
1806139c1837SPaolo Bonzini
1807139c1837SPaolo Bonzini    switch (opc & (MO_SSIZE)) {
1808139c1837SPaolo Bonzini    case MO_UB:
1809aeb6326eSRichard Henderson        tcg_out_opc_imm(s, OPC_LBU, val, base, 0);
1810139c1837SPaolo Bonzini        break;
1811139c1837SPaolo Bonzini    case MO_SB:
1812aeb6326eSRichard Henderson        tcg_out_opc_imm(s, OPC_LB, val, base, 0);
1813139c1837SPaolo Bonzini        break;
1814139c1837SPaolo Bonzini    case MO_UW:
1815aeb6326eSRichard Henderson        tcg_out_opc_imm(s, OPC_LHU, val, base, 0);
1816139c1837SPaolo Bonzini        break;
1817139c1837SPaolo Bonzini    case MO_SW:
1818aeb6326eSRichard Henderson        tcg_out_opc_imm(s, OPC_LH, val, base, 0);
1819139c1837SPaolo Bonzini        break;
1820139c1837SPaolo Bonzini    case MO_UL:
1821f7041977SRichard Henderson        if (type == TCG_TYPE_I64) {
1822aeb6326eSRichard Henderson            tcg_out_opc_imm(s, OPC_LWU, val, base, 0);
1823139c1837SPaolo Bonzini            break;
1824139c1837SPaolo Bonzini        }
1825139c1837SPaolo Bonzini        /* FALLTHRU */
1826139c1837SPaolo Bonzini    case MO_SL:
1827aeb6326eSRichard Henderson        tcg_out_opc_imm(s, OPC_LW, val, base, 0);
1828139c1837SPaolo Bonzini        break;
1829fc313c64SFrédéric Pétrot    case MO_UQ:
1830aeb6326eSRichard Henderson        tcg_out_opc_imm(s, OPC_LD, val, base, 0);
1831139c1837SPaolo Bonzini        break;
1832139c1837SPaolo Bonzini    default:
1833139c1837SPaolo Bonzini        g_assert_not_reached();
1834139c1837SPaolo Bonzini    }
1835139c1837SPaolo Bonzini}
1836139c1837SPaolo Bonzini
1837f7041977SRichard Hendersonstatic void tcg_out_qemu_ld(TCGContext *s, TCGReg data_reg, TCGReg addr_reg,
1838f7041977SRichard Henderson                            MemOpIdx oi, TCGType data_type)
1839139c1837SPaolo Bonzini{
1840001dddfeSRichard Henderson    TCGLabelQemuLdst *ldst;
18412e3a933aSRichard Henderson    TCGReg base;
1842139c1837SPaolo Bonzini
1843001dddfeSRichard Henderson    ldst = prepare_host_addr(s, &base, addr_reg, oi, true);
1844001dddfeSRichard Henderson    tcg_out_qemu_ld_direct(s, data_reg, base, get_memop(oi), data_type);
1845f7041977SRichard Henderson
1846001dddfeSRichard Henderson    if (ldst) {
1847001dddfeSRichard Henderson        ldst->type = data_type;
1848001dddfeSRichard Henderson        ldst->datalo_reg = data_reg;
1849001dddfeSRichard Henderson        ldst->raddr = tcg_splitwx_to_rx(s->code_ptr);
1850a3fb7c99SRichard Henderson    }
1851139c1837SPaolo Bonzini}
1852139c1837SPaolo Bonzini
1853aeb6326eSRichard Hendersonstatic void tcg_out_qemu_st_direct(TCGContext *s, TCGReg val,
1854139c1837SPaolo Bonzini                                   TCGReg base, MemOp opc)
1855139c1837SPaolo Bonzini{
1856c86bd2dcSRichard Henderson    /* Byte swapping is left to middle-end expansion. */
1857c86bd2dcSRichard Henderson    tcg_debug_assert((opc & MO_BSWAP) == 0);
1858139c1837SPaolo Bonzini
1859139c1837SPaolo Bonzini    switch (opc & (MO_SSIZE)) {
1860139c1837SPaolo Bonzini    case MO_8:
1861aeb6326eSRichard Henderson        tcg_out_opc_store(s, OPC_SB, base, val, 0);
1862139c1837SPaolo Bonzini        break;
1863139c1837SPaolo Bonzini    case MO_16:
1864aeb6326eSRichard Henderson        tcg_out_opc_store(s, OPC_SH, base, val, 0);
1865139c1837SPaolo Bonzini        break;
1866139c1837SPaolo Bonzini    case MO_32:
1867aeb6326eSRichard Henderson        tcg_out_opc_store(s, OPC_SW, base, val, 0);
1868139c1837SPaolo Bonzini        break;
1869139c1837SPaolo Bonzini    case MO_64:
1870aeb6326eSRichard Henderson        tcg_out_opc_store(s, OPC_SD, base, val, 0);
1871139c1837SPaolo Bonzini        break;
1872139c1837SPaolo Bonzini    default:
1873139c1837SPaolo Bonzini        g_assert_not_reached();
1874139c1837SPaolo Bonzini    }
1875139c1837SPaolo Bonzini}
1876139c1837SPaolo Bonzini
1877f7041977SRichard Hendersonstatic void tcg_out_qemu_st(TCGContext *s, TCGReg data_reg, TCGReg addr_reg,
1878f7041977SRichard Henderson                            MemOpIdx oi, TCGType data_type)
1879139c1837SPaolo Bonzini{
1880001dddfeSRichard Henderson    TCGLabelQemuLdst *ldst;
18812e3a933aSRichard Henderson    TCGReg base;
1882139c1837SPaolo Bonzini
1883001dddfeSRichard Henderson    ldst = prepare_host_addr(s, &base, addr_reg, oi, false);
1884001dddfeSRichard Henderson    tcg_out_qemu_st_direct(s, data_reg, base, get_memop(oi));
1885f7041977SRichard Henderson
1886001dddfeSRichard Henderson    if (ldst) {
1887001dddfeSRichard Henderson        ldst->type = data_type;
1888001dddfeSRichard Henderson        ldst->datalo_reg = data_reg;
1889001dddfeSRichard Henderson        ldst->raddr = tcg_splitwx_to_rx(s->code_ptr);
1890a3fb7c99SRichard Henderson    }
1891139c1837SPaolo Bonzini}
1892139c1837SPaolo Bonzini
1893793f7381SRichard Hendersonstatic const tcg_insn_unit *tb_ret_addr;
1894139c1837SPaolo Bonzini
1895b55a8d9dSRichard Hendersonstatic void tcg_out_exit_tb(TCGContext *s, uintptr_t a0)
1896b55a8d9dSRichard Henderson{
1897b55a8d9dSRichard Henderson    /* Reuse the zeroing that exists for goto_ptr.  */
1898b55a8d9dSRichard Henderson    if (a0 == 0) {
1899b55a8d9dSRichard Henderson        tcg_out_call_int(s, tcg_code_gen_epilogue, true);
1900b55a8d9dSRichard Henderson    } else {
1901b55a8d9dSRichard Henderson        tcg_out_movi(s, TCG_TYPE_PTR, TCG_REG_A0, a0);
1902b55a8d9dSRichard Henderson        tcg_out_call_int(s, tb_ret_addr, true);
1903b55a8d9dSRichard Henderson    }
1904b55a8d9dSRichard Henderson}
1905b55a8d9dSRichard Henderson
1906cf7d6b8eSRichard Hendersonstatic void tcg_out_goto_tb(TCGContext *s, int which)
1907cf7d6b8eSRichard Henderson{
1908493c9b19SRichard Henderson    /* Direct branch will be patched by tb_target_set_jmp_target. */
1909493c9b19SRichard Henderson    set_jmp_insn_offset(s, which);
1910493c9b19SRichard Henderson    tcg_out32(s, OPC_JAL);
1911493c9b19SRichard Henderson
1912493c9b19SRichard Henderson    /* When branch is out of range, fall through to indirect. */
1913cf7d6b8eSRichard Henderson    tcg_out_ld(s, TCG_TYPE_PTR, TCG_REG_TMP0, TCG_REG_ZERO,
1914cf7d6b8eSRichard Henderson               get_jmp_target_addr(s, which));
1915cf7d6b8eSRichard Henderson    tcg_out_opc_imm(s, OPC_JALR, TCG_REG_ZERO, TCG_REG_TMP0, 0);
1916cf7d6b8eSRichard Henderson    set_jmp_reset_offset(s, which);
1917cf7d6b8eSRichard Henderson}
1918cf7d6b8eSRichard Henderson
191990c0fee3SRichard Hendersonvoid tb_target_set_jmp_target(const TranslationBlock *tb, int n,
192090c0fee3SRichard Henderson                              uintptr_t jmp_rx, uintptr_t jmp_rw)
192190c0fee3SRichard Henderson{
1922493c9b19SRichard Henderson    uintptr_t addr = tb->jmp_target_addr[n];
1923493c9b19SRichard Henderson    ptrdiff_t offset = addr - jmp_rx;
1924493c9b19SRichard Henderson    tcg_insn_unit insn;
1925493c9b19SRichard Henderson
1926493c9b19SRichard Henderson    /* Either directly branch, or fall through to indirect branch. */
1927493c9b19SRichard Henderson    if (offset == sextreg(offset, 0, 20)) {
1928493c9b19SRichard Henderson        insn = encode_uj(OPC_JAL, TCG_REG_ZERO, offset);
1929493c9b19SRichard Henderson    } else {
1930493c9b19SRichard Henderson        insn = OPC_NOP;
1931493c9b19SRichard Henderson    }
1932493c9b19SRichard Henderson    qatomic_set((uint32_t *)jmp_rw, insn);
1933493c9b19SRichard Henderson    flush_idcache_range(jmp_rx, jmp_rw, 4);
193490c0fee3SRichard Henderson}
193590c0fee3SRichard Henderson
1936139c1837SPaolo Bonzinistatic void tcg_out_op(TCGContext *s, TCGOpcode opc,
19375e8892dbSMiroslav Rezanina                       const TCGArg args[TCG_MAX_OP_ARGS],
19385e8892dbSMiroslav Rezanina                       const int const_args[TCG_MAX_OP_ARGS])
1939139c1837SPaolo Bonzini{
1940139c1837SPaolo Bonzini    TCGArg a0 = args[0];
1941139c1837SPaolo Bonzini    TCGArg a1 = args[1];
1942139c1837SPaolo Bonzini    TCGArg a2 = args[2];
1943139c1837SPaolo Bonzini    int c2 = const_args[2];
1944139c1837SPaolo Bonzini
1945139c1837SPaolo Bonzini    switch (opc) {
1946139c1837SPaolo Bonzini    case INDEX_op_goto_ptr:
1947139c1837SPaolo Bonzini        tcg_out_opc_imm(s, OPC_JALR, TCG_REG_ZERO, a0, 0);
1948139c1837SPaolo Bonzini        break;
1949139c1837SPaolo Bonzini
1950139c1837SPaolo Bonzini    case INDEX_op_br:
1951139c1837SPaolo Bonzini        tcg_out_reloc(s, s->code_ptr, R_RISCV_JAL, arg_label(a0), 0);
1952139c1837SPaolo Bonzini        tcg_out_opc_jump(s, OPC_JAL, TCG_REG_ZERO, 0);
1953139c1837SPaolo Bonzini        break;
1954139c1837SPaolo Bonzini
1955139c1837SPaolo Bonzini    case INDEX_op_ld8u_i32:
1956139c1837SPaolo Bonzini    case INDEX_op_ld8u_i64:
1957139c1837SPaolo Bonzini        tcg_out_ldst(s, OPC_LBU, a0, a1, a2);
1958139c1837SPaolo Bonzini        break;
1959139c1837SPaolo Bonzini    case INDEX_op_ld8s_i32:
1960139c1837SPaolo Bonzini    case INDEX_op_ld8s_i64:
1961139c1837SPaolo Bonzini        tcg_out_ldst(s, OPC_LB, a0, a1, a2);
1962139c1837SPaolo Bonzini        break;
1963139c1837SPaolo Bonzini    case INDEX_op_ld16u_i32:
1964139c1837SPaolo Bonzini    case INDEX_op_ld16u_i64:
1965139c1837SPaolo Bonzini        tcg_out_ldst(s, OPC_LHU, a0, a1, a2);
1966139c1837SPaolo Bonzini        break;
1967139c1837SPaolo Bonzini    case INDEX_op_ld16s_i32:
1968139c1837SPaolo Bonzini    case INDEX_op_ld16s_i64:
1969139c1837SPaolo Bonzini        tcg_out_ldst(s, OPC_LH, a0, a1, a2);
1970139c1837SPaolo Bonzini        break;
1971139c1837SPaolo Bonzini    case INDEX_op_ld32u_i64:
1972139c1837SPaolo Bonzini        tcg_out_ldst(s, OPC_LWU, a0, a1, a2);
1973139c1837SPaolo Bonzini        break;
1974139c1837SPaolo Bonzini    case INDEX_op_ld_i32:
1975139c1837SPaolo Bonzini    case INDEX_op_ld32s_i64:
1976139c1837SPaolo Bonzini        tcg_out_ldst(s, OPC_LW, a0, a1, a2);
1977139c1837SPaolo Bonzini        break;
1978139c1837SPaolo Bonzini    case INDEX_op_ld_i64:
1979139c1837SPaolo Bonzini        tcg_out_ldst(s, OPC_LD, a0, a1, a2);
1980139c1837SPaolo Bonzini        break;
1981139c1837SPaolo Bonzini
1982139c1837SPaolo Bonzini    case INDEX_op_st8_i32:
1983139c1837SPaolo Bonzini    case INDEX_op_st8_i64:
1984139c1837SPaolo Bonzini        tcg_out_ldst(s, OPC_SB, a0, a1, a2);
1985139c1837SPaolo Bonzini        break;
1986139c1837SPaolo Bonzini    case INDEX_op_st16_i32:
1987139c1837SPaolo Bonzini    case INDEX_op_st16_i64:
1988139c1837SPaolo Bonzini        tcg_out_ldst(s, OPC_SH, a0, a1, a2);
1989139c1837SPaolo Bonzini        break;
1990139c1837SPaolo Bonzini    case INDEX_op_st_i32:
1991139c1837SPaolo Bonzini    case INDEX_op_st32_i64:
1992139c1837SPaolo Bonzini        tcg_out_ldst(s, OPC_SW, a0, a1, a2);
1993139c1837SPaolo Bonzini        break;
1994139c1837SPaolo Bonzini    case INDEX_op_st_i64:
1995139c1837SPaolo Bonzini        tcg_out_ldst(s, OPC_SD, a0, a1, a2);
1996139c1837SPaolo Bonzini        break;
1997139c1837SPaolo Bonzini
1998139c1837SPaolo Bonzini    case INDEX_op_add_i32:
1999139c1837SPaolo Bonzini        if (c2) {
2000139c1837SPaolo Bonzini            tcg_out_opc_imm(s, OPC_ADDIW, a0, a1, a2);
2001139c1837SPaolo Bonzini        } else {
2002139c1837SPaolo Bonzini            tcg_out_opc_reg(s, OPC_ADDW, a0, a1, a2);
2003139c1837SPaolo Bonzini        }
2004139c1837SPaolo Bonzini        break;
2005139c1837SPaolo Bonzini    case INDEX_op_add_i64:
2006139c1837SPaolo Bonzini        if (c2) {
2007139c1837SPaolo Bonzini            tcg_out_opc_imm(s, OPC_ADDI, a0, a1, a2);
2008139c1837SPaolo Bonzini        } else {
2009139c1837SPaolo Bonzini            tcg_out_opc_reg(s, OPC_ADD, a0, a1, a2);
2010139c1837SPaolo Bonzini        }
2011139c1837SPaolo Bonzini        break;
2012139c1837SPaolo Bonzini
2013139c1837SPaolo Bonzini    case INDEX_op_sub_i32:
2014139c1837SPaolo Bonzini        if (c2) {
2015139c1837SPaolo Bonzini            tcg_out_opc_imm(s, OPC_ADDIW, a0, a1, -a2);
2016139c1837SPaolo Bonzini        } else {
2017139c1837SPaolo Bonzini            tcg_out_opc_reg(s, OPC_SUBW, a0, a1, a2);
2018139c1837SPaolo Bonzini        }
2019139c1837SPaolo Bonzini        break;
2020139c1837SPaolo Bonzini    case INDEX_op_sub_i64:
2021139c1837SPaolo Bonzini        if (c2) {
2022139c1837SPaolo Bonzini            tcg_out_opc_imm(s, OPC_ADDI, a0, a1, -a2);
2023139c1837SPaolo Bonzini        } else {
2024139c1837SPaolo Bonzini            tcg_out_opc_reg(s, OPC_SUB, a0, a1, a2);
2025139c1837SPaolo Bonzini        }
2026139c1837SPaolo Bonzini        break;
2027139c1837SPaolo Bonzini
2028139c1837SPaolo Bonzini    case INDEX_op_and_i32:
2029139c1837SPaolo Bonzini    case INDEX_op_and_i64:
2030139c1837SPaolo Bonzini        if (c2) {
2031139c1837SPaolo Bonzini            tcg_out_opc_imm(s, OPC_ANDI, a0, a1, a2);
2032139c1837SPaolo Bonzini        } else {
2033139c1837SPaolo Bonzini            tcg_out_opc_reg(s, OPC_AND, a0, a1, a2);
2034139c1837SPaolo Bonzini        }
2035139c1837SPaolo Bonzini        break;
2036139c1837SPaolo Bonzini
2037139c1837SPaolo Bonzini    case INDEX_op_or_i32:
2038139c1837SPaolo Bonzini    case INDEX_op_or_i64:
2039139c1837SPaolo Bonzini        if (c2) {
2040139c1837SPaolo Bonzini            tcg_out_opc_imm(s, OPC_ORI, a0, a1, a2);
2041139c1837SPaolo Bonzini        } else {
2042139c1837SPaolo Bonzini            tcg_out_opc_reg(s, OPC_OR, a0, a1, a2);
2043139c1837SPaolo Bonzini        }
2044139c1837SPaolo Bonzini        break;
2045139c1837SPaolo Bonzini
2046139c1837SPaolo Bonzini    case INDEX_op_xor_i32:
2047139c1837SPaolo Bonzini    case INDEX_op_xor_i64:
2048139c1837SPaolo Bonzini        if (c2) {
2049139c1837SPaolo Bonzini            tcg_out_opc_imm(s, OPC_XORI, a0, a1, a2);
2050139c1837SPaolo Bonzini        } else {
2051139c1837SPaolo Bonzini            tcg_out_opc_reg(s, OPC_XOR, a0, a1, a2);
2052139c1837SPaolo Bonzini        }
2053139c1837SPaolo Bonzini        break;
2054139c1837SPaolo Bonzini
205599f4ec6eSRichard Henderson    case INDEX_op_andc_i32:
205699f4ec6eSRichard Henderson    case INDEX_op_andc_i64:
205799f4ec6eSRichard Henderson        if (c2) {
205899f4ec6eSRichard Henderson            tcg_out_opc_imm(s, OPC_ANDI, a0, a1, ~a2);
205999f4ec6eSRichard Henderson        } else {
206099f4ec6eSRichard Henderson            tcg_out_opc_reg(s, OPC_ANDN, a0, a1, a2);
206199f4ec6eSRichard Henderson        }
206299f4ec6eSRichard Henderson        break;
206399f4ec6eSRichard Henderson    case INDEX_op_orc_i32:
206499f4ec6eSRichard Henderson    case INDEX_op_orc_i64:
206599f4ec6eSRichard Henderson        if (c2) {
206699f4ec6eSRichard Henderson            tcg_out_opc_imm(s, OPC_ORI, a0, a1, ~a2);
206799f4ec6eSRichard Henderson        } else {
206899f4ec6eSRichard Henderson            tcg_out_opc_reg(s, OPC_ORN, a0, a1, a2);
206999f4ec6eSRichard Henderson        }
207099f4ec6eSRichard Henderson        break;
207199f4ec6eSRichard Henderson    case INDEX_op_eqv_i32:
207299f4ec6eSRichard Henderson    case INDEX_op_eqv_i64:
207399f4ec6eSRichard Henderson        if (c2) {
207499f4ec6eSRichard Henderson            tcg_out_opc_imm(s, OPC_XORI, a0, a1, ~a2);
207599f4ec6eSRichard Henderson        } else {
207699f4ec6eSRichard Henderson            tcg_out_opc_reg(s, OPC_XNOR, a0, a1, a2);
207799f4ec6eSRichard Henderson        }
207899f4ec6eSRichard Henderson        break;
207999f4ec6eSRichard Henderson
2080139c1837SPaolo Bonzini    case INDEX_op_not_i32:
2081139c1837SPaolo Bonzini    case INDEX_op_not_i64:
2082139c1837SPaolo Bonzini        tcg_out_opc_imm(s, OPC_XORI, a0, a1, -1);
2083139c1837SPaolo Bonzini        break;
2084139c1837SPaolo Bonzini
2085139c1837SPaolo Bonzini    case INDEX_op_neg_i32:
2086139c1837SPaolo Bonzini        tcg_out_opc_reg(s, OPC_SUBW, a0, TCG_REG_ZERO, a1);
2087139c1837SPaolo Bonzini        break;
2088139c1837SPaolo Bonzini    case INDEX_op_neg_i64:
2089139c1837SPaolo Bonzini        tcg_out_opc_reg(s, OPC_SUB, a0, TCG_REG_ZERO, a1);
2090139c1837SPaolo Bonzini        break;
2091139c1837SPaolo Bonzini
2092139c1837SPaolo Bonzini    case INDEX_op_mul_i32:
2093139c1837SPaolo Bonzini        tcg_out_opc_reg(s, OPC_MULW, a0, a1, a2);
2094139c1837SPaolo Bonzini        break;
2095139c1837SPaolo Bonzini    case INDEX_op_mul_i64:
2096139c1837SPaolo Bonzini        tcg_out_opc_reg(s, OPC_MUL, a0, a1, a2);
2097139c1837SPaolo Bonzini        break;
2098139c1837SPaolo Bonzini
2099139c1837SPaolo Bonzini    case INDEX_op_div_i32:
2100139c1837SPaolo Bonzini        tcg_out_opc_reg(s, OPC_DIVW, a0, a1, a2);
2101139c1837SPaolo Bonzini        break;
2102139c1837SPaolo Bonzini    case INDEX_op_div_i64:
2103139c1837SPaolo Bonzini        tcg_out_opc_reg(s, OPC_DIV, a0, a1, a2);
2104139c1837SPaolo Bonzini        break;
2105139c1837SPaolo Bonzini
2106139c1837SPaolo Bonzini    case INDEX_op_divu_i32:
2107139c1837SPaolo Bonzini        tcg_out_opc_reg(s, OPC_DIVUW, a0, a1, a2);
2108139c1837SPaolo Bonzini        break;
2109139c1837SPaolo Bonzini    case INDEX_op_divu_i64:
2110139c1837SPaolo Bonzini        tcg_out_opc_reg(s, OPC_DIVU, a0, a1, a2);
2111139c1837SPaolo Bonzini        break;
2112139c1837SPaolo Bonzini
2113139c1837SPaolo Bonzini    case INDEX_op_rem_i32:
2114139c1837SPaolo Bonzini        tcg_out_opc_reg(s, OPC_REMW, a0, a1, a2);
2115139c1837SPaolo Bonzini        break;
2116139c1837SPaolo Bonzini    case INDEX_op_rem_i64:
2117139c1837SPaolo Bonzini        tcg_out_opc_reg(s, OPC_REM, a0, a1, a2);
2118139c1837SPaolo Bonzini        break;
2119139c1837SPaolo Bonzini
2120139c1837SPaolo Bonzini    case INDEX_op_remu_i32:
2121139c1837SPaolo Bonzini        tcg_out_opc_reg(s, OPC_REMUW, a0, a1, a2);
2122139c1837SPaolo Bonzini        break;
2123139c1837SPaolo Bonzini    case INDEX_op_remu_i64:
2124139c1837SPaolo Bonzini        tcg_out_opc_reg(s, OPC_REMU, a0, a1, a2);
2125139c1837SPaolo Bonzini        break;
2126139c1837SPaolo Bonzini
2127139c1837SPaolo Bonzini    case INDEX_op_shl_i32:
2128139c1837SPaolo Bonzini        if (c2) {
2129d2f3066eSZihao Yu            tcg_out_opc_imm(s, OPC_SLLIW, a0, a1, a2 & 0x1f);
2130139c1837SPaolo Bonzini        } else {
2131139c1837SPaolo Bonzini            tcg_out_opc_reg(s, OPC_SLLW, a0, a1, a2);
2132139c1837SPaolo Bonzini        }
2133139c1837SPaolo Bonzini        break;
2134139c1837SPaolo Bonzini    case INDEX_op_shl_i64:
2135139c1837SPaolo Bonzini        if (c2) {
2136d2f3066eSZihao Yu            tcg_out_opc_imm(s, OPC_SLLI, a0, a1, a2 & 0x3f);
2137139c1837SPaolo Bonzini        } else {
2138139c1837SPaolo Bonzini            tcg_out_opc_reg(s, OPC_SLL, a0, a1, a2);
2139139c1837SPaolo Bonzini        }
2140139c1837SPaolo Bonzini        break;
2141139c1837SPaolo Bonzini
2142139c1837SPaolo Bonzini    case INDEX_op_shr_i32:
2143139c1837SPaolo Bonzini        if (c2) {
2144d2f3066eSZihao Yu            tcg_out_opc_imm(s, OPC_SRLIW, a0, a1, a2 & 0x1f);
2145139c1837SPaolo Bonzini        } else {
2146139c1837SPaolo Bonzini            tcg_out_opc_reg(s, OPC_SRLW, a0, a1, a2);
2147139c1837SPaolo Bonzini        }
2148139c1837SPaolo Bonzini        break;
2149139c1837SPaolo Bonzini    case INDEX_op_shr_i64:
2150139c1837SPaolo Bonzini        if (c2) {
2151d2f3066eSZihao Yu            tcg_out_opc_imm(s, OPC_SRLI, a0, a1, a2 & 0x3f);
2152139c1837SPaolo Bonzini        } else {
2153139c1837SPaolo Bonzini            tcg_out_opc_reg(s, OPC_SRL, a0, a1, a2);
2154139c1837SPaolo Bonzini        }
2155139c1837SPaolo Bonzini        break;
2156139c1837SPaolo Bonzini
2157139c1837SPaolo Bonzini    case INDEX_op_sar_i32:
2158139c1837SPaolo Bonzini        if (c2) {
2159d2f3066eSZihao Yu            tcg_out_opc_imm(s, OPC_SRAIW, a0, a1, a2 & 0x1f);
2160139c1837SPaolo Bonzini        } else {
2161139c1837SPaolo Bonzini            tcg_out_opc_reg(s, OPC_SRAW, a0, a1, a2);
2162139c1837SPaolo Bonzini        }
2163139c1837SPaolo Bonzini        break;
2164139c1837SPaolo Bonzini    case INDEX_op_sar_i64:
2165139c1837SPaolo Bonzini        if (c2) {
2166d2f3066eSZihao Yu            tcg_out_opc_imm(s, OPC_SRAI, a0, a1, a2 & 0x3f);
2167139c1837SPaolo Bonzini        } else {
2168139c1837SPaolo Bonzini            tcg_out_opc_reg(s, OPC_SRA, a0, a1, a2);
2169139c1837SPaolo Bonzini        }
2170139c1837SPaolo Bonzini        break;
2171139c1837SPaolo Bonzini
217219d016adSRichard Henderson    case INDEX_op_rotl_i32:
217319d016adSRichard Henderson        if (c2) {
217419d016adSRichard Henderson            tcg_out_opc_imm(s, OPC_RORIW, a0, a1, -a2 & 0x1f);
217519d016adSRichard Henderson        } else {
217619d016adSRichard Henderson            tcg_out_opc_reg(s, OPC_ROLW, a0, a1, a2);
217719d016adSRichard Henderson        }
217819d016adSRichard Henderson        break;
217919d016adSRichard Henderson    case INDEX_op_rotl_i64:
218019d016adSRichard Henderson        if (c2) {
218119d016adSRichard Henderson            tcg_out_opc_imm(s, OPC_RORI, a0, a1, -a2 & 0x3f);
218219d016adSRichard Henderson        } else {
218319d016adSRichard Henderson            tcg_out_opc_reg(s, OPC_ROL, a0, a1, a2);
218419d016adSRichard Henderson        }
218519d016adSRichard Henderson        break;
218619d016adSRichard Henderson
218719d016adSRichard Henderson    case INDEX_op_rotr_i32:
218819d016adSRichard Henderson        if (c2) {
218919d016adSRichard Henderson            tcg_out_opc_imm(s, OPC_RORIW, a0, a1, a2 & 0x1f);
219019d016adSRichard Henderson        } else {
219119d016adSRichard Henderson            tcg_out_opc_reg(s, OPC_RORW, a0, a1, a2);
219219d016adSRichard Henderson        }
219319d016adSRichard Henderson        break;
219419d016adSRichard Henderson    case INDEX_op_rotr_i64:
219519d016adSRichard Henderson        if (c2) {
219619d016adSRichard Henderson            tcg_out_opc_imm(s, OPC_RORI, a0, a1, a2 & 0x3f);
219719d016adSRichard Henderson        } else {
219819d016adSRichard Henderson            tcg_out_opc_reg(s, OPC_ROR, a0, a1, a2);
219919d016adSRichard Henderson        }
220019d016adSRichard Henderson        break;
220119d016adSRichard Henderson
22027b4d5274SRichard Henderson    case INDEX_op_bswap64_i64:
22037b4d5274SRichard Henderson        tcg_out_opc_imm(s, OPC_REV8, a0, a1, 0);
22047b4d5274SRichard Henderson        break;
22057b4d5274SRichard Henderson    case INDEX_op_bswap32_i32:
22067b4d5274SRichard Henderson        a2 = 0;
22077b4d5274SRichard Henderson        /* fall through */
22087b4d5274SRichard Henderson    case INDEX_op_bswap32_i64:
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, 32);
22127b4d5274SRichard Henderson        } else {
22137b4d5274SRichard Henderson            tcg_out_opc_imm(s, OPC_SRAI, a0, a0, 32);
22147b4d5274SRichard Henderson        }
22157b4d5274SRichard Henderson        break;
22167b4d5274SRichard Henderson    case INDEX_op_bswap16_i64:
22177b4d5274SRichard Henderson    case INDEX_op_bswap16_i32:
22187b4d5274SRichard Henderson        tcg_out_opc_imm(s, OPC_REV8, a0, a1, 0);
22197b4d5274SRichard Henderson        if (a2 & TCG_BSWAP_OZ) {
22207b4d5274SRichard Henderson            tcg_out_opc_imm(s, OPC_SRLI, a0, a0, 48);
22217b4d5274SRichard Henderson        } else {
22227b4d5274SRichard Henderson            tcg_out_opc_imm(s, OPC_SRAI, a0, a0, 48);
22237b4d5274SRichard Henderson        }
22247b4d5274SRichard Henderson        break;
22257b4d5274SRichard Henderson
22260956ecdaSRichard Henderson    case INDEX_op_ctpop_i32:
22270956ecdaSRichard Henderson        tcg_out_opc_imm(s, OPC_CPOPW, a0, a1, 0);
22280956ecdaSRichard Henderson        break;
22290956ecdaSRichard Henderson    case INDEX_op_ctpop_i64:
22300956ecdaSRichard Henderson        tcg_out_opc_imm(s, OPC_CPOP, a0, a1, 0);
22310956ecdaSRichard Henderson        break;
22320956ecdaSRichard Henderson
2233a30498fcSRichard Henderson    case INDEX_op_clz_i32:
2234a30498fcSRichard Henderson        tcg_out_cltz(s, TCG_TYPE_I32, OPC_CLZW, a0, a1, a2, c2);
2235a30498fcSRichard Henderson        break;
2236a30498fcSRichard Henderson    case INDEX_op_clz_i64:
2237a30498fcSRichard Henderson        tcg_out_cltz(s, TCG_TYPE_I64, OPC_CLZ, a0, a1, a2, c2);
2238a30498fcSRichard Henderson        break;
2239a30498fcSRichard Henderson    case INDEX_op_ctz_i32:
2240a30498fcSRichard Henderson        tcg_out_cltz(s, TCG_TYPE_I32, OPC_CTZW, a0, a1, a2, c2);
2241a30498fcSRichard Henderson        break;
2242a30498fcSRichard Henderson    case INDEX_op_ctz_i64:
2243a30498fcSRichard Henderson        tcg_out_cltz(s, TCG_TYPE_I64, OPC_CTZ, a0, a1, a2, c2);
2244a30498fcSRichard Henderson        break;
2245a30498fcSRichard Henderson
2246139c1837SPaolo Bonzini    case INDEX_op_add2_i32:
2247139c1837SPaolo Bonzini        tcg_out_addsub2(s, a0, a1, a2, args[3], args[4], args[5],
2248139c1837SPaolo Bonzini                        const_args[4], const_args[5], false, true);
2249139c1837SPaolo Bonzini        break;
2250139c1837SPaolo Bonzini    case INDEX_op_add2_i64:
2251139c1837SPaolo Bonzini        tcg_out_addsub2(s, a0, a1, a2, args[3], args[4], args[5],
2252139c1837SPaolo Bonzini                        const_args[4], const_args[5], false, false);
2253139c1837SPaolo Bonzini        break;
2254139c1837SPaolo Bonzini    case INDEX_op_sub2_i32:
2255139c1837SPaolo Bonzini        tcg_out_addsub2(s, a0, a1, a2, args[3], args[4], args[5],
2256139c1837SPaolo Bonzini                        const_args[4], const_args[5], true, true);
2257139c1837SPaolo Bonzini        break;
2258139c1837SPaolo Bonzini    case INDEX_op_sub2_i64:
2259139c1837SPaolo Bonzini        tcg_out_addsub2(s, a0, a1, a2, args[3], args[4], args[5],
2260139c1837SPaolo Bonzini                        const_args[4], const_args[5], true, false);
2261139c1837SPaolo Bonzini        break;
2262139c1837SPaolo Bonzini
2263139c1837SPaolo Bonzini    case INDEX_op_brcond_i32:
2264139c1837SPaolo Bonzini    case INDEX_op_brcond_i64:
2265139c1837SPaolo Bonzini        tcg_out_brcond(s, a2, a0, a1, arg_label(args[3]));
2266139c1837SPaolo Bonzini        break;
2267139c1837SPaolo Bonzini
2268139c1837SPaolo Bonzini    case INDEX_op_setcond_i32:
2269139c1837SPaolo Bonzini    case INDEX_op_setcond_i64:
2270f6453695SRichard Henderson        tcg_out_setcond(s, args[3], a0, a1, a2, c2);
2271139c1837SPaolo Bonzini        break;
2272139c1837SPaolo Bonzini
227341e4c0a9SRichard Henderson    case INDEX_op_negsetcond_i32:
227441e4c0a9SRichard Henderson    case INDEX_op_negsetcond_i64:
227541e4c0a9SRichard Henderson        tcg_out_negsetcond(s, args[3], a0, a1, a2, c2);
227641e4c0a9SRichard Henderson        break;
227741e4c0a9SRichard Henderson
2278a18d783eSRichard Henderson    case INDEX_op_movcond_i32:
2279a18d783eSRichard Henderson    case INDEX_op_movcond_i64:
2280a18d783eSRichard Henderson        tcg_out_movcond(s, args[5], a0, a1, a2, c2,
2281a18d783eSRichard Henderson                        args[3], const_args[3], args[4], const_args[4]);
2282a18d783eSRichard Henderson        break;
2283a18d783eSRichard Henderson
2284fecccfccSRichard Henderson    case INDEX_op_qemu_ld_a32_i32:
2285fecccfccSRichard Henderson    case INDEX_op_qemu_ld_a64_i32:
2286f7041977SRichard Henderson        tcg_out_qemu_ld(s, a0, a1, a2, TCG_TYPE_I32);
2287139c1837SPaolo Bonzini        break;
2288fecccfccSRichard Henderson    case INDEX_op_qemu_ld_a32_i64:
2289fecccfccSRichard Henderson    case INDEX_op_qemu_ld_a64_i64:
2290f7041977SRichard Henderson        tcg_out_qemu_ld(s, a0, a1, a2, TCG_TYPE_I64);
2291139c1837SPaolo Bonzini        break;
2292fecccfccSRichard Henderson    case INDEX_op_qemu_st_a32_i32:
2293fecccfccSRichard Henderson    case INDEX_op_qemu_st_a64_i32:
2294f7041977SRichard Henderson        tcg_out_qemu_st(s, a0, a1, a2, TCG_TYPE_I32);
2295139c1837SPaolo Bonzini        break;
2296fecccfccSRichard Henderson    case INDEX_op_qemu_st_a32_i64:
2297fecccfccSRichard Henderson    case INDEX_op_qemu_st_a64_i64:
2298f7041977SRichard Henderson        tcg_out_qemu_st(s, a0, a1, a2, TCG_TYPE_I64);
2299139c1837SPaolo Bonzini        break;
2300139c1837SPaolo Bonzini
2301139c1837SPaolo Bonzini    case INDEX_op_extrh_i64_i32:
2302139c1837SPaolo Bonzini        tcg_out_opc_imm(s, OPC_SRAI, a0, a1, 32);
2303139c1837SPaolo Bonzini        break;
2304139c1837SPaolo Bonzini
2305139c1837SPaolo Bonzini    case INDEX_op_mulsh_i32:
2306139c1837SPaolo Bonzini    case INDEX_op_mulsh_i64:
2307139c1837SPaolo Bonzini        tcg_out_opc_reg(s, OPC_MULH, a0, a1, a2);
2308139c1837SPaolo Bonzini        break;
2309139c1837SPaolo Bonzini
2310139c1837SPaolo Bonzini    case INDEX_op_muluh_i32:
2311139c1837SPaolo Bonzini    case INDEX_op_muluh_i64:
2312139c1837SPaolo Bonzini        tcg_out_opc_reg(s, OPC_MULHU, a0, a1, a2);
2313139c1837SPaolo Bonzini        break;
2314139c1837SPaolo Bonzini
2315139c1837SPaolo Bonzini    case INDEX_op_mb:
2316139c1837SPaolo Bonzini        tcg_out_mb(s, a0);
2317139c1837SPaolo Bonzini        break;
2318139c1837SPaolo Bonzini
2319139c1837SPaolo Bonzini    case INDEX_op_mov_i32:  /* Always emitted via tcg_out_mov.  */
2320139c1837SPaolo Bonzini    case INDEX_op_mov_i64:
2321139c1837SPaolo Bonzini    case INDEX_op_call:     /* Always emitted via tcg_out_call.  */
2322b55a8d9dSRichard Henderson    case INDEX_op_exit_tb:  /* Always emitted via tcg_out_exit_tb.  */
2323cf7d6b8eSRichard Henderson    case INDEX_op_goto_tb:  /* Always emitted via tcg_out_goto_tb.  */
2324678155b2SRichard Henderson    case INDEX_op_ext8s_i32:  /* Always emitted via tcg_reg_alloc_op.  */
2325678155b2SRichard Henderson    case INDEX_op_ext8s_i64:
2326d0e66c89SRichard Henderson    case INDEX_op_ext8u_i32:
2327d0e66c89SRichard Henderson    case INDEX_op_ext8u_i64:
2328753e42eaSRichard Henderson    case INDEX_op_ext16s_i32:
2329753e42eaSRichard Henderson    case INDEX_op_ext16s_i64:
2330379afdffSRichard Henderson    case INDEX_op_ext16u_i32:
2331379afdffSRichard Henderson    case INDEX_op_ext16u_i64:
233252bf3398SRichard Henderson    case INDEX_op_ext32s_i64:
23339ecf5f61SRichard Henderson    case INDEX_op_ext32u_i64:
23349c6aa274SRichard Henderson    case INDEX_op_ext_i32_i64:
2335b9bfe000SRichard Henderson    case INDEX_op_extu_i32_i64:
2336b8b94ac6SRichard Henderson    case INDEX_op_extrl_i64_i32:
2337139c1837SPaolo Bonzini    default:
2338139c1837SPaolo Bonzini        g_assert_not_reached();
2339139c1837SPaolo Bonzini    }
2340139c1837SPaolo Bonzini}
2341139c1837SPaolo Bonzini
2342f63e7089SHuang Shiyuanstatic void tcg_out_vec_op(TCGContext *s, TCGOpcode opc,
2343f63e7089SHuang Shiyuan                           unsigned vecl, unsigned vece,
2344f63e7089SHuang Shiyuan                           const TCGArg args[TCG_MAX_OP_ARGS],
2345f63e7089SHuang Shiyuan                           const int const_args[TCG_MAX_OP_ARGS])
2346f63e7089SHuang Shiyuan{
2347f63e7089SHuang Shiyuan    TCGType type = vecl + TCG_TYPE_V64;
2348f63e7089SHuang Shiyuan    TCGArg a0, a1, a2;
23495a63f599STANG Tiancheng    int c2;
2350f63e7089SHuang Shiyuan
2351f63e7089SHuang Shiyuan    a0 = args[0];
2352f63e7089SHuang Shiyuan    a1 = args[1];
2353f63e7089SHuang Shiyuan    a2 = args[2];
23545a63f599STANG Tiancheng    c2 = const_args[2];
2355f63e7089SHuang Shiyuan
2356f63e7089SHuang Shiyuan    switch (opc) {
2357d4be6ee1STANG Tiancheng    case INDEX_op_dupm_vec:
2358d4be6ee1STANG Tiancheng        tcg_out_dupm_vec(s, type, vece, a0, a1, a2);
2359d4be6ee1STANG Tiancheng        break;
2360f63e7089SHuang Shiyuan    case INDEX_op_ld_vec:
2361f63e7089SHuang Shiyuan        tcg_out_ld(s, type, a0, a1, a2);
2362f63e7089SHuang Shiyuan        break;
2363f63e7089SHuang Shiyuan    case INDEX_op_st_vec:
2364f63e7089SHuang Shiyuan        tcg_out_st(s, type, a0, a1, a2);
2365f63e7089SHuang Shiyuan        break;
23665a63f599STANG Tiancheng    case INDEX_op_add_vec:
23675a63f599STANG Tiancheng        set_vtype_len_sew(s, type, vece);
23685a63f599STANG Tiancheng        tcg_out_opc_vv_vi(s, OPC_VADD_VV, OPC_VADD_VI, a0, a1, a2, c2);
23695a63f599STANG Tiancheng        break;
23705a63f599STANG Tiancheng    case INDEX_op_sub_vec:
23715a63f599STANG Tiancheng        set_vtype_len_sew(s, type, vece);
2372dc9cd4ecSRichard Henderson        if (const_args[1]) {
2373dc9cd4ecSRichard Henderson            tcg_out_opc_vi(s, OPC_VRSUB_VI, a0, a2, a1);
2374dc9cd4ecSRichard Henderson        } else {
23755a63f599STANG Tiancheng            tcg_out_opc_vv(s, OPC_VSUB_VV, a0, a1, a2);
2376dc9cd4ecSRichard Henderson        }
23775a63f599STANG Tiancheng        break;
23785a63f599STANG Tiancheng    case INDEX_op_and_vec:
23795a63f599STANG Tiancheng        set_vtype_len(s, type);
23805a63f599STANG Tiancheng        tcg_out_opc_vv_vi(s, OPC_VAND_VV, OPC_VAND_VI, a0, a1, a2, c2);
23815a63f599STANG Tiancheng        break;
23825a63f599STANG Tiancheng    case INDEX_op_or_vec:
23835a63f599STANG Tiancheng        set_vtype_len(s, type);
23845a63f599STANG Tiancheng        tcg_out_opc_vv_vi(s, OPC_VOR_VV, OPC_VOR_VI, a0, a1, a2, c2);
23855a63f599STANG Tiancheng        break;
23865a63f599STANG Tiancheng    case INDEX_op_xor_vec:
23875a63f599STANG Tiancheng        set_vtype_len(s, type);
23885a63f599STANG Tiancheng        tcg_out_opc_vv_vi(s, OPC_VXOR_VV, OPC_VXOR_VI, a0, a1, a2, c2);
23895a63f599STANG Tiancheng        break;
23905a63f599STANG Tiancheng    case INDEX_op_not_vec:
23915a63f599STANG Tiancheng        set_vtype_len(s, type);
23925a63f599STANG Tiancheng        tcg_out_opc_vi(s, OPC_VXOR_VI, a0, a1, -1);
23935a63f599STANG Tiancheng        break;
2394c283c074STANG Tiancheng    case INDEX_op_neg_vec:
2395c283c074STANG Tiancheng        set_vtype_len_sew(s, type, vece);
2396c283c074STANG Tiancheng        tcg_out_opc_vi(s, OPC_VRSUB_VI, a0, a1, 0);
2397c283c074STANG Tiancheng        break;
2398101c1ef5STANG Tiancheng    case INDEX_op_mul_vec:
2399101c1ef5STANG Tiancheng        set_vtype_len_sew(s, type, vece);
2400101c1ef5STANG Tiancheng        tcg_out_opc_vv(s, OPC_VMUL_VV, a0, a1, a2);
2401101c1ef5STANG Tiancheng        break;
2402101c1ef5STANG Tiancheng    case INDEX_op_ssadd_vec:
2403101c1ef5STANG Tiancheng        set_vtype_len_sew(s, type, vece);
2404101c1ef5STANG Tiancheng        tcg_out_opc_vv_vi(s, OPC_VSADD_VV, OPC_VSADD_VI, a0, a1, a2, c2);
2405101c1ef5STANG Tiancheng        break;
2406101c1ef5STANG Tiancheng    case INDEX_op_sssub_vec:
2407101c1ef5STANG Tiancheng        set_vtype_len_sew(s, type, vece);
2408101c1ef5STANG Tiancheng        tcg_out_opc_vv_vi(s, OPC_VSSUB_VV, OPC_VSSUB_VI, a0, a1, a2, c2);
2409101c1ef5STANG Tiancheng        break;
2410101c1ef5STANG Tiancheng    case INDEX_op_usadd_vec:
2411101c1ef5STANG Tiancheng        set_vtype_len_sew(s, type, vece);
2412101c1ef5STANG Tiancheng        tcg_out_opc_vv_vi(s, OPC_VSADDU_VV, OPC_VSADDU_VI, a0, a1, a2, c2);
2413101c1ef5STANG Tiancheng        break;
2414101c1ef5STANG Tiancheng    case INDEX_op_ussub_vec:
2415101c1ef5STANG Tiancheng        set_vtype_len_sew(s, type, vece);
2416101c1ef5STANG Tiancheng        tcg_out_opc_vv_vi(s, OPC_VSSUBU_VV, OPC_VSSUBU_VI, a0, a1, a2, c2);
2417101c1ef5STANG Tiancheng        break;
2418*1631f19bSTANG Tiancheng    case INDEX_op_smax_vec:
2419*1631f19bSTANG Tiancheng        set_vtype_len_sew(s, type, vece);
2420*1631f19bSTANG Tiancheng        tcg_out_opc_vv_vi(s, OPC_VMAX_VV, OPC_VMAX_VI, a0, a1, a2, c2);
2421*1631f19bSTANG Tiancheng        break;
2422*1631f19bSTANG Tiancheng    case INDEX_op_smin_vec:
2423*1631f19bSTANG Tiancheng        set_vtype_len_sew(s, type, vece);
2424*1631f19bSTANG Tiancheng        tcg_out_opc_vv_vi(s, OPC_VMIN_VV, OPC_VMIN_VI, a0, a1, a2, c2);
2425*1631f19bSTANG Tiancheng        break;
2426*1631f19bSTANG Tiancheng    case INDEX_op_umax_vec:
2427*1631f19bSTANG Tiancheng        set_vtype_len_sew(s, type, vece);
2428*1631f19bSTANG Tiancheng        tcg_out_opc_vv_vi(s, OPC_VMAXU_VV, OPC_VMAXU_VI, a0, a1, a2, c2);
2429*1631f19bSTANG Tiancheng        break;
2430*1631f19bSTANG Tiancheng    case INDEX_op_umin_vec:
2431*1631f19bSTANG Tiancheng        set_vtype_len_sew(s, type, vece);
2432*1631f19bSTANG Tiancheng        tcg_out_opc_vv_vi(s, OPC_VMINU_VV, OPC_VMINU_VI, a0, a1, a2, c2);
2433*1631f19bSTANG Tiancheng        break;
2434a31768c0STANG Tiancheng    case INDEX_op_cmp_vec:
2435a31768c0STANG Tiancheng        tcg_out_cmpsel(s, type, vece, args[3], a0, a1, a2, c2,
2436a31768c0STANG Tiancheng                       -1, true, 0, true);
2437a31768c0STANG Tiancheng        break;
2438a31768c0STANG Tiancheng    case INDEX_op_cmpsel_vec:
2439a31768c0STANG Tiancheng        tcg_out_cmpsel(s, type, vece, args[5], a0, a1, a2, c2,
2440a31768c0STANG Tiancheng                       args[3], const_args[3], args[4], const_args[4]);
2441a31768c0STANG Tiancheng        break;
2442f63e7089SHuang Shiyuan    case INDEX_op_mov_vec: /* Always emitted via tcg_out_mov.  */
2443f63e7089SHuang Shiyuan    case INDEX_op_dup_vec: /* Always emitted via tcg_out_dup_vec.  */
2444f63e7089SHuang Shiyuan    default:
2445f63e7089SHuang Shiyuan        g_assert_not_reached();
2446f63e7089SHuang Shiyuan    }
2447f63e7089SHuang Shiyuan}
2448f63e7089SHuang Shiyuan
2449f63e7089SHuang Shiyuanvoid tcg_expand_vec_op(TCGOpcode opc, TCGType type, unsigned vece,
2450f63e7089SHuang Shiyuan                       TCGArg a0, ...)
2451f63e7089SHuang Shiyuan{
2452f63e7089SHuang Shiyuan    g_assert_not_reached();
2453f63e7089SHuang Shiyuan}
2454f63e7089SHuang Shiyuan
2455f63e7089SHuang Shiyuanint tcg_can_emit_vec_op(TCGOpcode opc, TCGType type, unsigned vece)
2456f63e7089SHuang Shiyuan{
2457f63e7089SHuang Shiyuan    switch (opc) {
24585a63f599STANG Tiancheng    case INDEX_op_add_vec:
24595a63f599STANG Tiancheng    case INDEX_op_sub_vec:
24605a63f599STANG Tiancheng    case INDEX_op_and_vec:
24615a63f599STANG Tiancheng    case INDEX_op_or_vec:
24625a63f599STANG Tiancheng    case INDEX_op_xor_vec:
24635a63f599STANG Tiancheng    case INDEX_op_not_vec:
2464c283c074STANG Tiancheng    case INDEX_op_neg_vec:
2465101c1ef5STANG Tiancheng    case INDEX_op_mul_vec:
2466101c1ef5STANG Tiancheng    case INDEX_op_ssadd_vec:
2467101c1ef5STANG Tiancheng    case INDEX_op_sssub_vec:
2468101c1ef5STANG Tiancheng    case INDEX_op_usadd_vec:
2469101c1ef5STANG Tiancheng    case INDEX_op_ussub_vec:
2470*1631f19bSTANG Tiancheng    case INDEX_op_smax_vec:
2471*1631f19bSTANG Tiancheng    case INDEX_op_smin_vec:
2472*1631f19bSTANG Tiancheng    case INDEX_op_umax_vec:
2473*1631f19bSTANG Tiancheng    case INDEX_op_umin_vec:
2474a31768c0STANG Tiancheng    case INDEX_op_cmp_vec:
2475a31768c0STANG Tiancheng    case INDEX_op_cmpsel_vec:
24765a63f599STANG Tiancheng        return 1;
2477f63e7089SHuang Shiyuan    default:
2478f63e7089SHuang Shiyuan        return 0;
2479f63e7089SHuang Shiyuan    }
2480f63e7089SHuang Shiyuan}
2481f63e7089SHuang Shiyuan
2482665be288SRichard Hendersonstatic TCGConstraintSetIndex tcg_target_op_def(TCGOpcode op)
2483139c1837SPaolo Bonzini{
2484139c1837SPaolo Bonzini    switch (op) {
2485139c1837SPaolo Bonzini    case INDEX_op_goto_ptr:
2486665be288SRichard Henderson        return C_O0_I1(r);
2487139c1837SPaolo Bonzini
2488139c1837SPaolo Bonzini    case INDEX_op_ld8u_i32:
2489139c1837SPaolo Bonzini    case INDEX_op_ld8s_i32:
2490139c1837SPaolo Bonzini    case INDEX_op_ld16u_i32:
2491139c1837SPaolo Bonzini    case INDEX_op_ld16s_i32:
2492139c1837SPaolo Bonzini    case INDEX_op_ld_i32:
2493139c1837SPaolo Bonzini    case INDEX_op_not_i32:
2494139c1837SPaolo Bonzini    case INDEX_op_neg_i32:
2495139c1837SPaolo Bonzini    case INDEX_op_ld8u_i64:
2496139c1837SPaolo Bonzini    case INDEX_op_ld8s_i64:
2497139c1837SPaolo Bonzini    case INDEX_op_ld16u_i64:
2498139c1837SPaolo Bonzini    case INDEX_op_ld16s_i64:
2499139c1837SPaolo Bonzini    case INDEX_op_ld32s_i64:
2500139c1837SPaolo Bonzini    case INDEX_op_ld32u_i64:
2501139c1837SPaolo Bonzini    case INDEX_op_ld_i64:
2502139c1837SPaolo Bonzini    case INDEX_op_not_i64:
2503139c1837SPaolo Bonzini    case INDEX_op_neg_i64:
2504139c1837SPaolo Bonzini    case INDEX_op_ext8u_i32:
2505139c1837SPaolo Bonzini    case INDEX_op_ext8u_i64:
2506139c1837SPaolo Bonzini    case INDEX_op_ext16u_i32:
2507139c1837SPaolo Bonzini    case INDEX_op_ext16u_i64:
2508139c1837SPaolo Bonzini    case INDEX_op_ext32u_i64:
2509139c1837SPaolo Bonzini    case INDEX_op_extu_i32_i64:
2510139c1837SPaolo Bonzini    case INDEX_op_ext8s_i32:
2511139c1837SPaolo Bonzini    case INDEX_op_ext8s_i64:
2512139c1837SPaolo Bonzini    case INDEX_op_ext16s_i32:
2513139c1837SPaolo Bonzini    case INDEX_op_ext16s_i64:
2514139c1837SPaolo Bonzini    case INDEX_op_ext32s_i64:
2515139c1837SPaolo Bonzini    case INDEX_op_extrl_i64_i32:
2516139c1837SPaolo Bonzini    case INDEX_op_extrh_i64_i32:
2517139c1837SPaolo Bonzini    case INDEX_op_ext_i32_i64:
25187b4d5274SRichard Henderson    case INDEX_op_bswap16_i32:
25197b4d5274SRichard Henderson    case INDEX_op_bswap32_i32:
25207b4d5274SRichard Henderson    case INDEX_op_bswap16_i64:
25217b4d5274SRichard Henderson    case INDEX_op_bswap32_i64:
25227b4d5274SRichard Henderson    case INDEX_op_bswap64_i64:
25230956ecdaSRichard Henderson    case INDEX_op_ctpop_i32:
25240956ecdaSRichard Henderson    case INDEX_op_ctpop_i64:
2525665be288SRichard Henderson        return C_O1_I1(r, r);
2526139c1837SPaolo Bonzini
2527139c1837SPaolo Bonzini    case INDEX_op_st8_i32:
2528139c1837SPaolo Bonzini    case INDEX_op_st16_i32:
2529139c1837SPaolo Bonzini    case INDEX_op_st_i32:
2530139c1837SPaolo Bonzini    case INDEX_op_st8_i64:
2531139c1837SPaolo Bonzini    case INDEX_op_st16_i64:
2532139c1837SPaolo Bonzini    case INDEX_op_st32_i64:
2533139c1837SPaolo Bonzini    case INDEX_op_st_i64:
2534665be288SRichard Henderson        return C_O0_I2(rZ, r);
2535139c1837SPaolo Bonzini
2536139c1837SPaolo Bonzini    case INDEX_op_add_i32:
2537139c1837SPaolo Bonzini    case INDEX_op_and_i32:
2538139c1837SPaolo Bonzini    case INDEX_op_or_i32:
2539139c1837SPaolo Bonzini    case INDEX_op_xor_i32:
2540139c1837SPaolo Bonzini    case INDEX_op_add_i64:
2541139c1837SPaolo Bonzini    case INDEX_op_and_i64:
2542139c1837SPaolo Bonzini    case INDEX_op_or_i64:
2543139c1837SPaolo Bonzini    case INDEX_op_xor_i64:
2544f6453695SRichard Henderson    case INDEX_op_setcond_i32:
2545f6453695SRichard Henderson    case INDEX_op_setcond_i64:
254641e4c0a9SRichard Henderson    case INDEX_op_negsetcond_i32:
254741e4c0a9SRichard Henderson    case INDEX_op_negsetcond_i64:
2548665be288SRichard Henderson        return C_O1_I2(r, r, rI);
2549139c1837SPaolo Bonzini
255099f4ec6eSRichard Henderson    case INDEX_op_andc_i32:
255199f4ec6eSRichard Henderson    case INDEX_op_andc_i64:
255299f4ec6eSRichard Henderson    case INDEX_op_orc_i32:
255399f4ec6eSRichard Henderson    case INDEX_op_orc_i64:
255499f4ec6eSRichard Henderson    case INDEX_op_eqv_i32:
255599f4ec6eSRichard Henderson    case INDEX_op_eqv_i64:
255699f4ec6eSRichard Henderson        return C_O1_I2(r, r, rJ);
255799f4ec6eSRichard Henderson
2558139c1837SPaolo Bonzini    case INDEX_op_sub_i32:
2559139c1837SPaolo Bonzini    case INDEX_op_sub_i64:
2560665be288SRichard Henderson        return C_O1_I2(r, rZ, rN);
2561139c1837SPaolo Bonzini
2562139c1837SPaolo Bonzini    case INDEX_op_mul_i32:
2563139c1837SPaolo Bonzini    case INDEX_op_mulsh_i32:
2564139c1837SPaolo Bonzini    case INDEX_op_muluh_i32:
2565139c1837SPaolo Bonzini    case INDEX_op_div_i32:
2566139c1837SPaolo Bonzini    case INDEX_op_divu_i32:
2567139c1837SPaolo Bonzini    case INDEX_op_rem_i32:
2568139c1837SPaolo Bonzini    case INDEX_op_remu_i32:
2569139c1837SPaolo Bonzini    case INDEX_op_mul_i64:
2570139c1837SPaolo Bonzini    case INDEX_op_mulsh_i64:
2571139c1837SPaolo Bonzini    case INDEX_op_muluh_i64:
2572139c1837SPaolo Bonzini    case INDEX_op_div_i64:
2573139c1837SPaolo Bonzini    case INDEX_op_divu_i64:
2574139c1837SPaolo Bonzini    case INDEX_op_rem_i64:
2575139c1837SPaolo Bonzini    case INDEX_op_remu_i64:
2576665be288SRichard Henderson        return C_O1_I2(r, rZ, rZ);
2577139c1837SPaolo Bonzini
2578139c1837SPaolo Bonzini    case INDEX_op_shl_i32:
2579139c1837SPaolo Bonzini    case INDEX_op_shr_i32:
2580139c1837SPaolo Bonzini    case INDEX_op_sar_i32:
258119d016adSRichard Henderson    case INDEX_op_rotl_i32:
258219d016adSRichard Henderson    case INDEX_op_rotr_i32:
2583139c1837SPaolo Bonzini    case INDEX_op_shl_i64:
2584139c1837SPaolo Bonzini    case INDEX_op_shr_i64:
2585139c1837SPaolo Bonzini    case INDEX_op_sar_i64:
258619d016adSRichard Henderson    case INDEX_op_rotl_i64:
258719d016adSRichard Henderson    case INDEX_op_rotr_i64:
2588665be288SRichard Henderson        return C_O1_I2(r, r, ri);
2589139c1837SPaolo Bonzini
2590a30498fcSRichard Henderson    case INDEX_op_clz_i32:
2591a30498fcSRichard Henderson    case INDEX_op_clz_i64:
2592a30498fcSRichard Henderson    case INDEX_op_ctz_i32:
2593a30498fcSRichard Henderson    case INDEX_op_ctz_i64:
2594a30498fcSRichard Henderson        return C_N1_I2(r, r, rM);
2595a30498fcSRichard Henderson
2596139c1837SPaolo Bonzini    case INDEX_op_brcond_i32:
2597139c1837SPaolo Bonzini    case INDEX_op_brcond_i64:
2598665be288SRichard Henderson        return C_O0_I2(rZ, rZ);
2599139c1837SPaolo Bonzini
2600a18d783eSRichard Henderson    case INDEX_op_movcond_i32:
2601a18d783eSRichard Henderson    case INDEX_op_movcond_i64:
2602a18d783eSRichard Henderson        return C_O1_I4(r, r, rI, rM, rM);
2603a18d783eSRichard Henderson
2604139c1837SPaolo Bonzini    case INDEX_op_add2_i32:
2605139c1837SPaolo Bonzini    case INDEX_op_add2_i64:
2606139c1837SPaolo Bonzini    case INDEX_op_sub2_i32:
2607139c1837SPaolo Bonzini    case INDEX_op_sub2_i64:
2608665be288SRichard Henderson        return C_O2_I4(r, r, rZ, rZ, rM, rM);
2609139c1837SPaolo Bonzini
2610fecccfccSRichard Henderson    case INDEX_op_qemu_ld_a32_i32:
2611fecccfccSRichard Henderson    case INDEX_op_qemu_ld_a64_i32:
2612fecccfccSRichard Henderson    case INDEX_op_qemu_ld_a32_i64:
2613fecccfccSRichard Henderson    case INDEX_op_qemu_ld_a64_i64:
2614f0f43534SRichard Henderson        return C_O1_I1(r, r);
2615fecccfccSRichard Henderson    case INDEX_op_qemu_st_a32_i32:
2616fecccfccSRichard Henderson    case INDEX_op_qemu_st_a64_i32:
2617fecccfccSRichard Henderson    case INDEX_op_qemu_st_a32_i64:
2618fecccfccSRichard Henderson    case INDEX_op_qemu_st_a64_i64:
2619f0f43534SRichard Henderson        return C_O0_I2(rZ, r);
2620139c1837SPaolo Bonzini
2621f63e7089SHuang Shiyuan    case INDEX_op_st_vec:
2622f63e7089SHuang Shiyuan        return C_O0_I2(v, r);
2623d4be6ee1STANG Tiancheng    case INDEX_op_dup_vec:
2624d4be6ee1STANG Tiancheng    case INDEX_op_dupm_vec:
2625f63e7089SHuang Shiyuan    case INDEX_op_ld_vec:
2626f63e7089SHuang Shiyuan        return C_O1_I1(v, r);
2627c283c074STANG Tiancheng    case INDEX_op_neg_vec:
26285a63f599STANG Tiancheng    case INDEX_op_not_vec:
26295a63f599STANG Tiancheng        return C_O1_I1(v, v);
26305a63f599STANG Tiancheng    case INDEX_op_add_vec:
26315a63f599STANG Tiancheng    case INDEX_op_and_vec:
26325a63f599STANG Tiancheng    case INDEX_op_or_vec:
26335a63f599STANG Tiancheng    case INDEX_op_xor_vec:
2634101c1ef5STANG Tiancheng    case INDEX_op_ssadd_vec:
2635101c1ef5STANG Tiancheng    case INDEX_op_sssub_vec:
2636101c1ef5STANG Tiancheng    case INDEX_op_usadd_vec:
2637101c1ef5STANG Tiancheng    case INDEX_op_ussub_vec:
2638*1631f19bSTANG Tiancheng    case INDEX_op_smax_vec:
2639*1631f19bSTANG Tiancheng    case INDEX_op_smin_vec:
2640*1631f19bSTANG Tiancheng    case INDEX_op_umax_vec:
2641*1631f19bSTANG Tiancheng    case INDEX_op_umin_vec:
26425a63f599STANG Tiancheng        return C_O1_I2(v, v, vK);
26435a63f599STANG Tiancheng    case INDEX_op_sub_vec:
2644dc9cd4ecSRichard Henderson        return C_O1_I2(v, vK, v);
2645101c1ef5STANG Tiancheng    case INDEX_op_mul_vec:
2646101c1ef5STANG Tiancheng        return C_O1_I2(v, v, v);
2647a31768c0STANG Tiancheng    case INDEX_op_cmp_vec:
2648a31768c0STANG Tiancheng        return C_O1_I2(v, v, vL);
2649a31768c0STANG Tiancheng    case INDEX_op_cmpsel_vec:
2650a31768c0STANG Tiancheng        return C_O1_I4(v, v, vL, vK, vK);
2651139c1837SPaolo Bonzini    default:
2652665be288SRichard Henderson        g_assert_not_reached();
2653139c1837SPaolo Bonzini    }
2654139c1837SPaolo Bonzini}
2655139c1837SPaolo Bonzini
2656139c1837SPaolo Bonzinistatic const int tcg_target_callee_save_regs[] = {
2657139c1837SPaolo Bonzini    TCG_REG_S0,       /* used for the global env (TCG_AREG0) */
2658139c1837SPaolo Bonzini    TCG_REG_S1,
2659139c1837SPaolo Bonzini    TCG_REG_S2,
2660139c1837SPaolo Bonzini    TCG_REG_S3,
2661139c1837SPaolo Bonzini    TCG_REG_S4,
2662139c1837SPaolo Bonzini    TCG_REG_S5,
2663139c1837SPaolo Bonzini    TCG_REG_S6,
2664139c1837SPaolo Bonzini    TCG_REG_S7,
2665139c1837SPaolo Bonzini    TCG_REG_S8,
2666139c1837SPaolo Bonzini    TCG_REG_S9,
2667139c1837SPaolo Bonzini    TCG_REG_S10,
2668139c1837SPaolo Bonzini    TCG_REG_S11,
2669139c1837SPaolo Bonzini    TCG_REG_RA,       /* should be last for ABI compliance */
2670139c1837SPaolo Bonzini};
2671139c1837SPaolo Bonzini
2672139c1837SPaolo Bonzini/* Stack frame parameters.  */
2673139c1837SPaolo Bonzini#define REG_SIZE   (TCG_TARGET_REG_BITS / 8)
2674139c1837SPaolo Bonzini#define SAVE_SIZE  ((int)ARRAY_SIZE(tcg_target_callee_save_regs) * REG_SIZE)
2675139c1837SPaolo Bonzini#define TEMP_SIZE  (CPU_TEMP_BUF_NLONGS * (int)sizeof(long))
2676139c1837SPaolo Bonzini#define FRAME_SIZE ((TCG_STATIC_CALL_ARGS_SIZE + TEMP_SIZE + SAVE_SIZE \
2677139c1837SPaolo Bonzini                     + TCG_TARGET_STACK_ALIGN - 1) \
2678139c1837SPaolo Bonzini                    & -TCG_TARGET_STACK_ALIGN)
2679139c1837SPaolo Bonzini#define SAVE_OFS   (TCG_STATIC_CALL_ARGS_SIZE + TEMP_SIZE)
2680139c1837SPaolo Bonzini
2681139c1837SPaolo Bonzini/* We're expecting to be able to use an immediate for frame allocation.  */
2682139c1837SPaolo BonziniQEMU_BUILD_BUG_ON(FRAME_SIZE > 0x7ff);
2683139c1837SPaolo Bonzini
2684139c1837SPaolo Bonzini/* Generate global QEMU prologue and epilogue code */
2685139c1837SPaolo Bonzinistatic void tcg_target_qemu_prologue(TCGContext *s)
2686139c1837SPaolo Bonzini{
2687139c1837SPaolo Bonzini    int i;
2688139c1837SPaolo Bonzini
2689139c1837SPaolo Bonzini    tcg_set_frame(s, TCG_REG_SP, TCG_STATIC_CALL_ARGS_SIZE, TEMP_SIZE);
2690139c1837SPaolo Bonzini
2691139c1837SPaolo Bonzini    /* TB prologue */
2692139c1837SPaolo Bonzini    tcg_out_opc_imm(s, OPC_ADDI, TCG_REG_SP, TCG_REG_SP, -FRAME_SIZE);
2693139c1837SPaolo Bonzini    for (i = 0; i < ARRAY_SIZE(tcg_target_callee_save_regs); i++) {
2694139c1837SPaolo Bonzini        tcg_out_st(s, TCG_TYPE_REG, tcg_target_callee_save_regs[i],
2695139c1837SPaolo Bonzini                   TCG_REG_SP, SAVE_OFS + i * REG_SIZE);
2696139c1837SPaolo Bonzini    }
2697139c1837SPaolo Bonzini
26984944d359SRichard Henderson    if (!tcg_use_softmmu && guest_base) {
2699139c1837SPaolo Bonzini        tcg_out_movi(s, TCG_TYPE_PTR, TCG_GUEST_BASE_REG, guest_base);
2700139c1837SPaolo Bonzini        tcg_regset_set_reg(s->reserved_regs, TCG_GUEST_BASE_REG);
2701cf0ed30eSRichard Henderson    }
2702139c1837SPaolo Bonzini
2703139c1837SPaolo Bonzini    /* Call generated code */
2704139c1837SPaolo Bonzini    tcg_out_mov(s, TCG_TYPE_PTR, TCG_AREG0, tcg_target_call_iarg_regs[0]);
2705139c1837SPaolo Bonzini    tcg_out_opc_imm(s, OPC_JALR, TCG_REG_ZERO, tcg_target_call_iarg_regs[1], 0);
2706139c1837SPaolo Bonzini
2707139c1837SPaolo Bonzini    /* Return path for goto_ptr. Set return value to 0 */
2708c8bc1168SRichard Henderson    tcg_code_gen_epilogue = tcg_splitwx_to_rx(s->code_ptr);
2709139c1837SPaolo Bonzini    tcg_out_mov(s, TCG_TYPE_REG, TCG_REG_A0, TCG_REG_ZERO);
2710139c1837SPaolo Bonzini
2711139c1837SPaolo Bonzini    /* TB epilogue */
2712793f7381SRichard Henderson    tb_ret_addr = tcg_splitwx_to_rx(s->code_ptr);
2713139c1837SPaolo Bonzini    for (i = 0; i < ARRAY_SIZE(tcg_target_callee_save_regs); i++) {
2714139c1837SPaolo Bonzini        tcg_out_ld(s, TCG_TYPE_REG, tcg_target_callee_save_regs[i],
2715139c1837SPaolo Bonzini                   TCG_REG_SP, SAVE_OFS + i * REG_SIZE);
2716139c1837SPaolo Bonzini    }
2717139c1837SPaolo Bonzini
2718139c1837SPaolo Bonzini    tcg_out_opc_imm(s, OPC_ADDI, TCG_REG_SP, TCG_REG_SP, FRAME_SIZE);
2719139c1837SPaolo Bonzini    tcg_out_opc_imm(s, OPC_JALR, TCG_REG_ZERO, TCG_REG_RA, 0);
2720139c1837SPaolo Bonzini}
2721139c1837SPaolo Bonzini
27229358fbbfSRichard Hendersonstatic void tcg_out_tb_start(TCGContext *s)
27239358fbbfSRichard Henderson{
2724f63e7089SHuang Shiyuan    init_setting_vtype(s);
2725f63e7089SHuang Shiyuan}
2726f63e7089SHuang Shiyuan
2727f63e7089SHuang Shiyuanstatic bool vtype_check(unsigned vtype)
2728f63e7089SHuang Shiyuan{
2729f63e7089SHuang Shiyuan    unsigned long tmp;
2730f63e7089SHuang Shiyuan
2731f63e7089SHuang Shiyuan    /* vsetvl tmp, zero, vtype */
2732f63e7089SHuang Shiyuan    asm(".insn r 0x57, 7, 0x40, %0, zero, %1" : "=r"(tmp) : "r"(vtype));
2733f63e7089SHuang Shiyuan    return tmp != 0;
2734f63e7089SHuang Shiyuan}
2735f63e7089SHuang Shiyuan
2736f63e7089SHuang Shiyuanstatic void probe_frac_lmul_1(TCGType type, MemOp vsew)
2737f63e7089SHuang Shiyuan{
2738f63e7089SHuang Shiyuan    VsetCache *p = &riscv_vset_cache[type - TCG_TYPE_V64][vsew];
2739f63e7089SHuang Shiyuan    unsigned avl = tcg_type_size(type) >> vsew;
2740f63e7089SHuang Shiyuan    int lmul = type - riscv_lg2_vlenb;
2741f63e7089SHuang Shiyuan    unsigned vtype = encode_vtype(true, true, vsew, lmul & 7);
2742f63e7089SHuang Shiyuan    bool lmul_eq_avl = true;
2743f63e7089SHuang Shiyuan
2744f63e7089SHuang Shiyuan    /* Guaranteed by Zve64x. */
2745f63e7089SHuang Shiyuan    assert(lmul < 3);
2746f63e7089SHuang Shiyuan
2747f63e7089SHuang Shiyuan    /*
2748f63e7089SHuang Shiyuan     * For LMUL < -3, the host vector size is so large that TYPE
2749f63e7089SHuang Shiyuan     * is smaller than the minimum 1/8 fraction.
2750f63e7089SHuang Shiyuan     *
2751f63e7089SHuang Shiyuan     * For other fractional LMUL settings, implementations must
2752f63e7089SHuang Shiyuan     * support SEW settings between SEW_MIN and LMUL * ELEN, inclusive.
2753f63e7089SHuang Shiyuan     * So if ELEN = 64, LMUL = 1/2, then SEW will support e8, e16, e32,
2754f63e7089SHuang Shiyuan     * but e64 may not be supported. In other words, the hardware only
2755f63e7089SHuang Shiyuan     * guarantees SEW_MIN <= SEW <= LMUL * ELEN.  Check.
2756f63e7089SHuang Shiyuan     */
2757f63e7089SHuang Shiyuan    if (lmul < 0 && (lmul < -3 || !vtype_check(vtype))) {
2758f63e7089SHuang Shiyuan        vtype = encode_vtype(true, true, vsew, VLMUL_M1);
2759f63e7089SHuang Shiyuan        lmul_eq_avl = false;
2760f63e7089SHuang Shiyuan    }
2761f63e7089SHuang Shiyuan
2762f63e7089SHuang Shiyuan    if (avl < 32) {
2763f63e7089SHuang Shiyuan        p->vset_insn = encode_vseti(OPC_VSETIVLI, TCG_REG_ZERO, avl, vtype);
2764f63e7089SHuang Shiyuan    } else if (lmul_eq_avl) {
2765f63e7089SHuang Shiyuan        /* rd != 0 and rs1 == 0 uses vlmax */
2766f63e7089SHuang Shiyuan        p->vset_insn = encode_vset(OPC_VSETVLI, TCG_REG_TMP0, TCG_REG_ZERO, vtype);
2767f63e7089SHuang Shiyuan    } else {
2768f63e7089SHuang Shiyuan        p->movi_insn = encode_i(OPC_ADDI, TCG_REG_TMP0, TCG_REG_ZERO, avl);
2769f63e7089SHuang Shiyuan        p->vset_insn = encode_vset(OPC_VSETVLI, TCG_REG_ZERO, TCG_REG_TMP0, vtype);
2770f63e7089SHuang Shiyuan    }
2771f63e7089SHuang Shiyuan}
2772f63e7089SHuang Shiyuan
2773f63e7089SHuang Shiyuanstatic void probe_frac_lmul(void)
2774f63e7089SHuang Shiyuan{
2775f63e7089SHuang Shiyuan    /* Match riscv_lg2_vlenb to TCG_TYPE_V64. */
2776f63e7089SHuang Shiyuan    QEMU_BUILD_BUG_ON(TCG_TYPE_V64 != 3);
2777f63e7089SHuang Shiyuan
2778f63e7089SHuang Shiyuan    for (TCGType t = TCG_TYPE_V64; t <= TCG_TYPE_V256; t++) {
2779f63e7089SHuang Shiyuan        for (MemOp e = MO_8; e <= MO_64; e++) {
2780f63e7089SHuang Shiyuan            probe_frac_lmul_1(t, e);
2781f63e7089SHuang Shiyuan        }
2782f63e7089SHuang Shiyuan    }
27839358fbbfSRichard Henderson}
27849358fbbfSRichard Henderson
2785139c1837SPaolo Bonzinistatic void tcg_target_init(TCGContext *s)
2786139c1837SPaolo Bonzini{
2787139c1837SPaolo Bonzini    tcg_target_available_regs[TCG_TYPE_I32] = 0xffffffff;
2788139c1837SPaolo Bonzini    tcg_target_available_regs[TCG_TYPE_I64] = 0xffffffff;
2789139c1837SPaolo Bonzini
2790f63e7089SHuang Shiyuan    tcg_target_call_clobber_regs = -1;
2791139c1837SPaolo Bonzini    tcg_regset_reset_reg(tcg_target_call_clobber_regs, TCG_REG_S0);
2792139c1837SPaolo Bonzini    tcg_regset_reset_reg(tcg_target_call_clobber_regs, TCG_REG_S1);
2793139c1837SPaolo Bonzini    tcg_regset_reset_reg(tcg_target_call_clobber_regs, TCG_REG_S2);
2794139c1837SPaolo Bonzini    tcg_regset_reset_reg(tcg_target_call_clobber_regs, TCG_REG_S3);
2795139c1837SPaolo Bonzini    tcg_regset_reset_reg(tcg_target_call_clobber_regs, TCG_REG_S4);
2796139c1837SPaolo Bonzini    tcg_regset_reset_reg(tcg_target_call_clobber_regs, TCG_REG_S5);
2797139c1837SPaolo Bonzini    tcg_regset_reset_reg(tcg_target_call_clobber_regs, TCG_REG_S6);
2798139c1837SPaolo Bonzini    tcg_regset_reset_reg(tcg_target_call_clobber_regs, TCG_REG_S7);
2799139c1837SPaolo Bonzini    tcg_regset_reset_reg(tcg_target_call_clobber_regs, TCG_REG_S8);
2800139c1837SPaolo Bonzini    tcg_regset_reset_reg(tcg_target_call_clobber_regs, TCG_REG_S9);
2801139c1837SPaolo Bonzini    tcg_regset_reset_reg(tcg_target_call_clobber_regs, TCG_REG_S10);
2802139c1837SPaolo Bonzini    tcg_regset_reset_reg(tcg_target_call_clobber_regs, TCG_REG_S11);
2803139c1837SPaolo Bonzini
2804139c1837SPaolo Bonzini    s->reserved_regs = 0;
2805139c1837SPaolo Bonzini    tcg_regset_set_reg(s->reserved_regs, TCG_REG_ZERO);
2806139c1837SPaolo Bonzini    tcg_regset_set_reg(s->reserved_regs, TCG_REG_TMP0);
2807139c1837SPaolo Bonzini    tcg_regset_set_reg(s->reserved_regs, TCG_REG_TMP1);
2808139c1837SPaolo Bonzini    tcg_regset_set_reg(s->reserved_regs, TCG_REG_TMP2);
2809139c1837SPaolo Bonzini    tcg_regset_set_reg(s->reserved_regs, TCG_REG_SP);
2810139c1837SPaolo Bonzini    tcg_regset_set_reg(s->reserved_regs, TCG_REG_GP);
2811139c1837SPaolo Bonzini    tcg_regset_set_reg(s->reserved_regs, TCG_REG_TP);
2812f63e7089SHuang Shiyuan
2813f63e7089SHuang Shiyuan    if (cpuinfo & CPUINFO_ZVE64X) {
2814f63e7089SHuang Shiyuan        switch (riscv_lg2_vlenb) {
2815f63e7089SHuang Shiyuan        case TCG_TYPE_V64:
2816f63e7089SHuang Shiyuan            tcg_target_available_regs[TCG_TYPE_V64] = ALL_VECTOR_REGS;
2817f63e7089SHuang Shiyuan            tcg_target_available_regs[TCG_TYPE_V128] = ALL_DVECTOR_REG_GROUPS;
2818f63e7089SHuang Shiyuan            tcg_target_available_regs[TCG_TYPE_V256] = ALL_QVECTOR_REG_GROUPS;
2819f63e7089SHuang Shiyuan            s->reserved_regs |= (~ALL_QVECTOR_REG_GROUPS & ALL_VECTOR_REGS);
2820f63e7089SHuang Shiyuan            break;
2821f63e7089SHuang Shiyuan        case TCG_TYPE_V128:
2822f63e7089SHuang Shiyuan            tcg_target_available_regs[TCG_TYPE_V64] = ALL_VECTOR_REGS;
2823f63e7089SHuang Shiyuan            tcg_target_available_regs[TCG_TYPE_V128] = ALL_VECTOR_REGS;
2824f63e7089SHuang Shiyuan            tcg_target_available_regs[TCG_TYPE_V256] = ALL_DVECTOR_REG_GROUPS;
2825f63e7089SHuang Shiyuan            s->reserved_regs |= (~ALL_DVECTOR_REG_GROUPS & ALL_VECTOR_REGS);
2826f63e7089SHuang Shiyuan            break;
2827f63e7089SHuang Shiyuan        default:
2828f63e7089SHuang Shiyuan            /* Guaranteed by Zve64x. */
2829f63e7089SHuang Shiyuan            tcg_debug_assert(riscv_lg2_vlenb >= TCG_TYPE_V256);
2830f63e7089SHuang Shiyuan            tcg_target_available_regs[TCG_TYPE_V64] = ALL_VECTOR_REGS;
2831f63e7089SHuang Shiyuan            tcg_target_available_regs[TCG_TYPE_V128] = ALL_VECTOR_REGS;
2832f63e7089SHuang Shiyuan            tcg_target_available_regs[TCG_TYPE_V256] = ALL_VECTOR_REGS;
2833f63e7089SHuang Shiyuan            break;
2834f63e7089SHuang Shiyuan        }
2835f63e7089SHuang Shiyuan        tcg_regset_set_reg(s->reserved_regs, TCG_REG_V0);
2836f63e7089SHuang Shiyuan        probe_frac_lmul();
2837f63e7089SHuang Shiyuan    }
2838139c1837SPaolo Bonzini}
2839139c1837SPaolo Bonzini
2840139c1837SPaolo Bonzinitypedef struct {
2841139c1837SPaolo Bonzini    DebugFrameHeader h;
2842139c1837SPaolo Bonzini    uint8_t fde_def_cfa[4];
2843139c1837SPaolo Bonzini    uint8_t fde_reg_ofs[ARRAY_SIZE(tcg_target_callee_save_regs) * 2];
2844139c1837SPaolo Bonzini} DebugFrame;
2845139c1837SPaolo Bonzini
2846139c1837SPaolo Bonzini#define ELF_HOST_MACHINE EM_RISCV
2847139c1837SPaolo Bonzini
2848139c1837SPaolo Bonzinistatic const DebugFrame debug_frame = {
2849139c1837SPaolo Bonzini    .h.cie.len = sizeof(DebugFrameCIE) - 4, /* length after .len member */
2850139c1837SPaolo Bonzini    .h.cie.id = -1,
2851139c1837SPaolo Bonzini    .h.cie.version = 1,
2852139c1837SPaolo Bonzini    .h.cie.code_align = 1,
2853139c1837SPaolo Bonzini    .h.cie.data_align = -(TCG_TARGET_REG_BITS / 8) & 0x7f, /* sleb128 */
2854139c1837SPaolo Bonzini    .h.cie.return_column = TCG_REG_RA,
2855139c1837SPaolo Bonzini
2856139c1837SPaolo Bonzini    /* Total FDE size does not include the "len" member.  */
2857139c1837SPaolo Bonzini    .h.fde.len = sizeof(DebugFrame) - offsetof(DebugFrame, h.fde.cie_offset),
2858139c1837SPaolo Bonzini
2859139c1837SPaolo Bonzini    .fde_def_cfa = {
2860139c1837SPaolo Bonzini        12, TCG_REG_SP,                 /* DW_CFA_def_cfa sp, ... */
2861139c1837SPaolo Bonzini        (FRAME_SIZE & 0x7f) | 0x80,     /* ... uleb128 FRAME_SIZE */
2862139c1837SPaolo Bonzini        (FRAME_SIZE >> 7)
2863139c1837SPaolo Bonzini    },
2864139c1837SPaolo Bonzini    .fde_reg_ofs = {
2865139c1837SPaolo Bonzini        0x80 + 9,  12,                  /* DW_CFA_offset, s1,  -96 */
2866139c1837SPaolo Bonzini        0x80 + 18, 11,                  /* DW_CFA_offset, s2,  -88 */
2867139c1837SPaolo Bonzini        0x80 + 19, 10,                  /* DW_CFA_offset, s3,  -80 */
2868139c1837SPaolo Bonzini        0x80 + 20, 9,                   /* DW_CFA_offset, s4,  -72 */
2869139c1837SPaolo Bonzini        0x80 + 21, 8,                   /* DW_CFA_offset, s5,  -64 */
2870139c1837SPaolo Bonzini        0x80 + 22, 7,                   /* DW_CFA_offset, s6,  -56 */
2871139c1837SPaolo Bonzini        0x80 + 23, 6,                   /* DW_CFA_offset, s7,  -48 */
2872139c1837SPaolo Bonzini        0x80 + 24, 5,                   /* DW_CFA_offset, s8,  -40 */
2873139c1837SPaolo Bonzini        0x80 + 25, 4,                   /* DW_CFA_offset, s9,  -32 */
2874139c1837SPaolo Bonzini        0x80 + 26, 3,                   /* DW_CFA_offset, s10, -24 */
2875139c1837SPaolo Bonzini        0x80 + 27, 2,                   /* DW_CFA_offset, s11, -16 */
2876139c1837SPaolo Bonzini        0x80 + 1 , 1,                   /* DW_CFA_offset, ra,  -8 */
2877139c1837SPaolo Bonzini    }
2878139c1837SPaolo Bonzini};
2879139c1837SPaolo Bonzini
2880755bf9e5SRichard Hendersonvoid tcg_register_jit(const void *buf, size_t buf_size)
2881139c1837SPaolo Bonzini{
2882139c1837SPaolo Bonzini    tcg_register_jit_int(buf, buf_size, &debug_frame, sizeof(debug_frame));
2883139c1837SPaolo Bonzini}
2884