xref: /openbmc/qemu/tcg/riscv/tcg-target.c.inc (revision 6b3756503b00d42f1f506815b44ce83aa23ee322)
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
2971631f19bSTANG Tiancheng    OPC_VMAX_VV = 0x1c000057 | V_OPIVV,
2981631f19bSTANG Tiancheng    OPC_VMAX_VI = 0x1c000057 | V_OPIVI,
2991631f19bSTANG Tiancheng    OPC_VMAXU_VV = 0x18000057 | V_OPIVV,
3001631f19bSTANG Tiancheng    OPC_VMAXU_VI = 0x18000057 | V_OPIVI,
3011631f19bSTANG Tiancheng    OPC_VMIN_VV = 0x14000057 | V_OPIVV,
3021631f19bSTANG Tiancheng    OPC_VMIN_VI = 0x14000057 | V_OPIVI,
3031631f19bSTANG Tiancheng    OPC_VMINU_VV = 0x10000057 | V_OPIVV,
3041631f19bSTANG Tiancheng    OPC_VMINU_VI = 0x10000057 | V_OPIVI,
3051631f19bSTANG 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
329cbde22f1STANG Tiancheng    OPC_VSLL_VV = 0x94000057 | V_OPIVV,
330cbde22f1STANG Tiancheng    OPC_VSLL_VI = 0x94000057 | V_OPIVI,
331cbde22f1STANG Tiancheng    OPC_VSLL_VX = 0x94000057 | V_OPIVX,
332cbde22f1STANG Tiancheng    OPC_VSRL_VV = 0xa0000057 | V_OPIVV,
333cbde22f1STANG Tiancheng    OPC_VSRL_VI = 0xa0000057 | V_OPIVI,
334cbde22f1STANG Tiancheng    OPC_VSRL_VX = 0xa0000057 | V_OPIVX,
335cbde22f1STANG Tiancheng    OPC_VSRA_VV = 0xa4000057 | V_OPIVV,
336cbde22f1STANG Tiancheng    OPC_VSRA_VI = 0xa4000057 | V_OPIVI,
337cbde22f1STANG Tiancheng    OPC_VSRA_VX = 0xa4000057 | V_OPIVX,
338cbde22f1STANG Tiancheng
339d4be6ee1STANG Tiancheng    OPC_VMV_V_V = 0x5e000057 | V_OPIVV,
340d4be6ee1STANG Tiancheng    OPC_VMV_V_I = 0x5e000057 | V_OPIVI,
341d4be6ee1STANG Tiancheng    OPC_VMV_V_X = 0x5e000057 | V_OPIVX,
342d4be6ee1STANG Tiancheng
343d4be6ee1STANG Tiancheng    OPC_VMVNR_V = 0x9e000057 | V_OPIVI,
344139c1837SPaolo Bonzini} RISCVInsn;
345139c1837SPaolo Bonzini
346a31768c0STANG Tianchengstatic const struct {
347a31768c0STANG Tiancheng    RISCVInsn op;
348a31768c0STANG Tiancheng    bool swap;
349a31768c0STANG Tiancheng} tcg_cmpcond_to_rvv_vv[] = {
350a31768c0STANG Tiancheng    [TCG_COND_EQ] =  { OPC_VMSEQ_VV,  false },
351a31768c0STANG Tiancheng    [TCG_COND_NE] =  { OPC_VMSNE_VV,  false },
352a31768c0STANG Tiancheng    [TCG_COND_LT] =  { OPC_VMSLT_VV,  false },
353a31768c0STANG Tiancheng    [TCG_COND_GE] =  { OPC_VMSLE_VV,  true  },
354a31768c0STANG Tiancheng    [TCG_COND_GT] =  { OPC_VMSLT_VV,  true  },
355a31768c0STANG Tiancheng    [TCG_COND_LE] =  { OPC_VMSLE_VV,  false },
356a31768c0STANG Tiancheng    [TCG_COND_LTU] = { OPC_VMSLTU_VV, false },
357a31768c0STANG Tiancheng    [TCG_COND_GEU] = { OPC_VMSLEU_VV, true  },
358a31768c0STANG Tiancheng    [TCG_COND_GTU] = { OPC_VMSLTU_VV, true  },
359a31768c0STANG Tiancheng    [TCG_COND_LEU] = { OPC_VMSLEU_VV, false }
360a31768c0STANG Tiancheng};
361a31768c0STANG Tiancheng
362a31768c0STANG Tianchengstatic const struct {
363a31768c0STANG Tiancheng    RISCVInsn op;
364a31768c0STANG Tiancheng    int min;
365a31768c0STANG Tiancheng    int max;
366a31768c0STANG Tiancheng    bool adjust;
367a31768c0STANG Tiancheng}  tcg_cmpcond_to_rvv_vi[] = {
368a31768c0STANG Tiancheng    [TCG_COND_EQ]  = { OPC_VMSEQ_VI,  -16, 15, false },
369a31768c0STANG Tiancheng    [TCG_COND_NE]  = { OPC_VMSNE_VI,  -16, 15, false },
370a31768c0STANG Tiancheng    [TCG_COND_GT]  = { OPC_VMSGT_VI,  -16, 15, false },
371a31768c0STANG Tiancheng    [TCG_COND_LE]  = { OPC_VMSLE_VI,  -16, 15, false },
372a31768c0STANG Tiancheng    [TCG_COND_LT]  = { OPC_VMSLE_VI,  -15, 16, true  },
373a31768c0STANG Tiancheng    [TCG_COND_GE]  = { OPC_VMSGT_VI,  -15, 16, true  },
374a31768c0STANG Tiancheng    [TCG_COND_LEU] = { OPC_VMSLEU_VI,   0, 15, false },
375a31768c0STANG Tiancheng    [TCG_COND_GTU] = { OPC_VMSGTU_VI,   0, 15, false },
376a31768c0STANG Tiancheng    [TCG_COND_LTU] = { OPC_VMSLEU_VI,   1, 16, true  },
377a31768c0STANG Tiancheng    [TCG_COND_GEU] = { OPC_VMSGTU_VI,   1, 16, true  },
378a31768c0STANG Tiancheng};
379a31768c0STANG Tiancheng
380a31768c0STANG Tiancheng/* test if a constant matches the constraint */
381a31768c0STANG Tianchengstatic bool tcg_target_const_match(int64_t val, int ct,
382a31768c0STANG Tiancheng                                   TCGType type, TCGCond cond, int vece)
383a31768c0STANG Tiancheng{
384a31768c0STANG Tiancheng    if (ct & TCG_CT_CONST) {
385a31768c0STANG Tiancheng        return 1;
386a31768c0STANG Tiancheng    }
387a31768c0STANG Tiancheng    if ((ct & TCG_CT_CONST_ZERO) && val == 0) {
388a31768c0STANG Tiancheng        return 1;
389a31768c0STANG Tiancheng    }
390a31768c0STANG Tiancheng    if (type >= TCG_TYPE_V64) {
391a31768c0STANG Tiancheng        /* Val is replicated by VECE; extract the highest element. */
392a31768c0STANG Tiancheng        val >>= (-8 << vece) & 63;
393a31768c0STANG Tiancheng    }
394a31768c0STANG Tiancheng    /*
395a31768c0STANG Tiancheng     * Sign extended from 12 bits: [-0x800, 0x7ff].
396a31768c0STANG Tiancheng     * Used for most arithmetic, as this is the isa field.
397a31768c0STANG Tiancheng     */
398a31768c0STANG Tiancheng    if ((ct & TCG_CT_CONST_S12) && val >= -0x800 && val <= 0x7ff) {
399a31768c0STANG Tiancheng        return 1;
400a31768c0STANG Tiancheng    }
401a31768c0STANG Tiancheng    /*
402a31768c0STANG Tiancheng     * Sign extended from 12 bits, negated: [-0x7ff, 0x800].
403a31768c0STANG Tiancheng     * Used for subtraction, where a constant must be handled by ADDI.
404a31768c0STANG Tiancheng     */
405a31768c0STANG Tiancheng    if ((ct & TCG_CT_CONST_N12) && val >= -0x7ff && val <= 0x800) {
406a31768c0STANG Tiancheng        return 1;
407a31768c0STANG Tiancheng    }
408a31768c0STANG Tiancheng    /*
409a31768c0STANG Tiancheng     * Sign extended from 12 bits, +/- matching: [-0x7ff, 0x7ff].
410a31768c0STANG Tiancheng     * Used by addsub2 and movcond, which may need the negative value,
411a31768c0STANG Tiancheng     * and requires the modified constant to be representable.
412a31768c0STANG Tiancheng     */
413a31768c0STANG Tiancheng    if ((ct & TCG_CT_CONST_M12) && val >= -0x7ff && val <= 0x7ff) {
414a31768c0STANG Tiancheng        return 1;
415a31768c0STANG Tiancheng    }
416a31768c0STANG Tiancheng    /*
417a31768c0STANG Tiancheng     * Inverse of sign extended from 12 bits: ~[-0x800, 0x7ff].
418a31768c0STANG Tiancheng     * Used to map ANDN back to ANDI, etc.
419a31768c0STANG Tiancheng     */
420a31768c0STANG Tiancheng    if ((ct & TCG_CT_CONST_J12) && ~val >= -0x800 && ~val <= 0x7ff) {
421a31768c0STANG Tiancheng        return 1;
422a31768c0STANG Tiancheng    }
423a31768c0STANG Tiancheng    /*
424a31768c0STANG Tiancheng     * Sign extended from 5 bits: [-0x10, 0x0f].
425a31768c0STANG Tiancheng     * Used for vector-immediate.
426a31768c0STANG Tiancheng     */
427a31768c0STANG Tiancheng    if ((ct & TCG_CT_CONST_S5) && val >= -0x10 && val <= 0x0f) {
428a31768c0STANG Tiancheng        return 1;
429a31768c0STANG Tiancheng    }
430a31768c0STANG Tiancheng    /*
431a31768c0STANG Tiancheng     * Used for vector compare OPIVI instructions.
432a31768c0STANG Tiancheng     */
433a31768c0STANG Tiancheng    if ((ct & TCG_CT_CONST_CMP_VI) &&
434a31768c0STANG Tiancheng        val >= tcg_cmpcond_to_rvv_vi[cond].min &&
435a31768c0STANG Tiancheng        val <= tcg_cmpcond_to_rvv_vi[cond].max) {
436a31768c0STANG Tiancheng        return true;
437a31768c0STANG Tiancheng     }
438a31768c0STANG Tiancheng    return 0;
439a31768c0STANG Tiancheng}
440a31768c0STANG Tiancheng
441139c1837SPaolo Bonzini/*
442139c1837SPaolo Bonzini * RISC-V immediate and instruction encoders (excludes 16-bit RVC)
443139c1837SPaolo Bonzini */
444139c1837SPaolo Bonzini
445139c1837SPaolo Bonzini/* Type-R */
446139c1837SPaolo Bonzini
447139c1837SPaolo Bonzinistatic int32_t encode_r(RISCVInsn opc, TCGReg rd, TCGReg rs1, TCGReg rs2)
448139c1837SPaolo Bonzini{
449139c1837SPaolo Bonzini    return opc | (rd & 0x1f) << 7 | (rs1 & 0x1f) << 15 | (rs2 & 0x1f) << 20;
450139c1837SPaolo Bonzini}
451139c1837SPaolo Bonzini
452139c1837SPaolo Bonzini/* Type-I */
453139c1837SPaolo Bonzini
454139c1837SPaolo Bonzinistatic int32_t encode_imm12(uint32_t imm)
455139c1837SPaolo Bonzini{
456139c1837SPaolo Bonzini    return (imm & 0xfff) << 20;
457139c1837SPaolo Bonzini}
458139c1837SPaolo Bonzini
459139c1837SPaolo Bonzinistatic int32_t encode_i(RISCVInsn opc, TCGReg rd, TCGReg rs1, uint32_t imm)
460139c1837SPaolo Bonzini{
461139c1837SPaolo Bonzini    return opc | (rd & 0x1f) << 7 | (rs1 & 0x1f) << 15 | encode_imm12(imm);
462139c1837SPaolo Bonzini}
463139c1837SPaolo Bonzini
464139c1837SPaolo Bonzini/* Type-S */
465139c1837SPaolo Bonzini
466139c1837SPaolo Bonzinistatic int32_t encode_simm12(uint32_t imm)
467139c1837SPaolo Bonzini{
468139c1837SPaolo Bonzini    int32_t ret = 0;
469139c1837SPaolo Bonzini
470139c1837SPaolo Bonzini    ret |= (imm & 0xFE0) << 20;
471139c1837SPaolo Bonzini    ret |= (imm & 0x1F) << 7;
472139c1837SPaolo Bonzini
473139c1837SPaolo Bonzini    return ret;
474139c1837SPaolo Bonzini}
475139c1837SPaolo Bonzini
476139c1837SPaolo Bonzinistatic int32_t encode_s(RISCVInsn opc, TCGReg rs1, TCGReg rs2, uint32_t imm)
477139c1837SPaolo Bonzini{
478139c1837SPaolo Bonzini    return opc | (rs1 & 0x1f) << 15 | (rs2 & 0x1f) << 20 | encode_simm12(imm);
479139c1837SPaolo Bonzini}
480139c1837SPaolo Bonzini
481139c1837SPaolo Bonzini/* Type-SB */
482139c1837SPaolo Bonzini
483139c1837SPaolo Bonzinistatic int32_t encode_sbimm12(uint32_t imm)
484139c1837SPaolo Bonzini{
485139c1837SPaolo Bonzini    int32_t ret = 0;
486139c1837SPaolo Bonzini
487139c1837SPaolo Bonzini    ret |= (imm & 0x1000) << 19;
488139c1837SPaolo Bonzini    ret |= (imm & 0x7e0) << 20;
489139c1837SPaolo Bonzini    ret |= (imm & 0x1e) << 7;
490139c1837SPaolo Bonzini    ret |= (imm & 0x800) >> 4;
491139c1837SPaolo Bonzini
492139c1837SPaolo Bonzini    return ret;
493139c1837SPaolo Bonzini}
494139c1837SPaolo Bonzini
495139c1837SPaolo Bonzinistatic int32_t encode_sb(RISCVInsn opc, TCGReg rs1, TCGReg rs2, uint32_t imm)
496139c1837SPaolo Bonzini{
497139c1837SPaolo Bonzini    return opc | (rs1 & 0x1f) << 15 | (rs2 & 0x1f) << 20 | encode_sbimm12(imm);
498139c1837SPaolo Bonzini}
499139c1837SPaolo Bonzini
500139c1837SPaolo Bonzini/* Type-U */
501139c1837SPaolo Bonzini
502139c1837SPaolo Bonzinistatic int32_t encode_uimm20(uint32_t imm)
503139c1837SPaolo Bonzini{
504139c1837SPaolo Bonzini    return imm & 0xfffff000;
505139c1837SPaolo Bonzini}
506139c1837SPaolo Bonzini
507139c1837SPaolo Bonzinistatic int32_t encode_u(RISCVInsn opc, TCGReg rd, uint32_t imm)
508139c1837SPaolo Bonzini{
509139c1837SPaolo Bonzini    return opc | (rd & 0x1f) << 7 | encode_uimm20(imm);
510139c1837SPaolo Bonzini}
511139c1837SPaolo Bonzini
512139c1837SPaolo Bonzini/* Type-UJ */
513139c1837SPaolo Bonzini
514139c1837SPaolo Bonzinistatic int32_t encode_ujimm20(uint32_t imm)
515139c1837SPaolo Bonzini{
516139c1837SPaolo Bonzini    int32_t ret = 0;
517139c1837SPaolo Bonzini
518139c1837SPaolo Bonzini    ret |= (imm & 0x0007fe) << (21 - 1);
519139c1837SPaolo Bonzini    ret |= (imm & 0x000800) << (20 - 11);
520139c1837SPaolo Bonzini    ret |= (imm & 0x0ff000) << (12 - 12);
521139c1837SPaolo Bonzini    ret |= (imm & 0x100000) << (31 - 20);
522139c1837SPaolo Bonzini
523139c1837SPaolo Bonzini    return ret;
524139c1837SPaolo Bonzini}
525139c1837SPaolo Bonzini
526139c1837SPaolo Bonzinistatic int32_t encode_uj(RISCVInsn opc, TCGReg rd, uint32_t imm)
527139c1837SPaolo Bonzini{
528139c1837SPaolo Bonzini    return opc | (rd & 0x1f) << 7 | encode_ujimm20(imm);
529139c1837SPaolo Bonzini}
530139c1837SPaolo Bonzini
531d4be6ee1STANG Tiancheng
532d4be6ee1STANG Tiancheng/* Type-OPIVI */
533d4be6ee1STANG Tiancheng
534d4be6ee1STANG Tianchengstatic int32_t encode_vi(RISCVInsn opc, TCGReg rd, int32_t imm,
535d4be6ee1STANG Tiancheng                         TCGReg vs2, bool vm)
536d4be6ee1STANG Tiancheng{
537d4be6ee1STANG Tiancheng    return opc | (rd & 0x1f) << 7 | (imm & 0x1f) << 15 |
538d4be6ee1STANG Tiancheng           (vs2 & 0x1f) << 20 | (vm << 25);
539d4be6ee1STANG Tiancheng}
540d4be6ee1STANG Tiancheng
541f63e7089SHuang Shiyuan/* Type-OPIVV/OPMVV/OPIVX/OPMVX, Vector load and store */
542f63e7089SHuang Shiyuan
543f63e7089SHuang Shiyuanstatic int32_t encode_v(RISCVInsn opc, TCGReg d, TCGReg s1,
544f63e7089SHuang Shiyuan                        TCGReg s2, bool vm)
545f63e7089SHuang Shiyuan{
546f63e7089SHuang Shiyuan    return opc | (d & 0x1f) << 7 | (s1 & 0x1f) << 15 |
547f63e7089SHuang Shiyuan           (s2 & 0x1f) << 20 | (vm << 25);
548f63e7089SHuang Shiyuan}
549f63e7089SHuang Shiyuan
550f63e7089SHuang Shiyuan/* Vector vtype */
551f63e7089SHuang Shiyuan
552f63e7089SHuang Shiyuanstatic uint32_t encode_vtype(bool vta, bool vma,
553f63e7089SHuang Shiyuan                            MemOp vsew, RISCVVlmul vlmul)
554f63e7089SHuang Shiyuan{
555f63e7089SHuang Shiyuan    return vma << 7 | vta << 6 | vsew << 3 | vlmul;
556f63e7089SHuang Shiyuan}
557f63e7089SHuang Shiyuan
558f63e7089SHuang Shiyuanstatic int32_t encode_vset(RISCVInsn opc, TCGReg rd,
559f63e7089SHuang Shiyuan                           TCGArg rs1, uint32_t vtype)
560f63e7089SHuang Shiyuan{
561f63e7089SHuang Shiyuan    return opc | (rd & 0x1f) << 7 | (rs1 & 0x1f) << 15 | (vtype & 0x7ff) << 20;
562f63e7089SHuang Shiyuan}
563f63e7089SHuang Shiyuan
564f63e7089SHuang Shiyuanstatic int32_t encode_vseti(RISCVInsn opc, TCGReg rd,
565f63e7089SHuang Shiyuan                            uint32_t uimm, uint32_t vtype)
566f63e7089SHuang Shiyuan{
567f63e7089SHuang Shiyuan    return opc | (rd & 0x1f) << 7 | (uimm & 0x1f) << 15 | (vtype & 0x3ff) << 20;
568f63e7089SHuang Shiyuan}
569f63e7089SHuang Shiyuan
570139c1837SPaolo Bonzini/*
571139c1837SPaolo Bonzini * RISC-V instruction emitters
572139c1837SPaolo Bonzini */
573139c1837SPaolo Bonzini
574139c1837SPaolo Bonzinistatic void tcg_out_opc_reg(TCGContext *s, RISCVInsn opc,
575139c1837SPaolo Bonzini                            TCGReg rd, TCGReg rs1, TCGReg rs2)
576139c1837SPaolo Bonzini{
577139c1837SPaolo Bonzini    tcg_out32(s, encode_r(opc, rd, rs1, rs2));
578139c1837SPaolo Bonzini}
579139c1837SPaolo Bonzini
580139c1837SPaolo Bonzinistatic void tcg_out_opc_imm(TCGContext *s, RISCVInsn opc,
581139c1837SPaolo Bonzini                            TCGReg rd, TCGReg rs1, TCGArg imm)
582139c1837SPaolo Bonzini{
583139c1837SPaolo Bonzini    tcg_out32(s, encode_i(opc, rd, rs1, imm));
584139c1837SPaolo Bonzini}
585139c1837SPaolo Bonzini
586139c1837SPaolo Bonzinistatic void tcg_out_opc_store(TCGContext *s, RISCVInsn opc,
587139c1837SPaolo Bonzini                              TCGReg rs1, TCGReg rs2, uint32_t imm)
588139c1837SPaolo Bonzini{
589139c1837SPaolo Bonzini    tcg_out32(s, encode_s(opc, rs1, rs2, imm));
590139c1837SPaolo Bonzini}
591139c1837SPaolo Bonzini
592139c1837SPaolo Bonzinistatic void tcg_out_opc_branch(TCGContext *s, RISCVInsn opc,
593139c1837SPaolo Bonzini                               TCGReg rs1, TCGReg rs2, uint32_t imm)
594139c1837SPaolo Bonzini{
595139c1837SPaolo Bonzini    tcg_out32(s, encode_sb(opc, rs1, rs2, imm));
596139c1837SPaolo Bonzini}
597139c1837SPaolo Bonzini
598139c1837SPaolo Bonzinistatic void tcg_out_opc_upper(TCGContext *s, RISCVInsn opc,
599139c1837SPaolo Bonzini                              TCGReg rd, uint32_t imm)
600139c1837SPaolo Bonzini{
601139c1837SPaolo Bonzini    tcg_out32(s, encode_u(opc, rd, imm));
602139c1837SPaolo Bonzini}
603139c1837SPaolo Bonzini
604139c1837SPaolo Bonzinistatic void tcg_out_opc_jump(TCGContext *s, RISCVInsn opc,
605139c1837SPaolo Bonzini                             TCGReg rd, uint32_t imm)
606139c1837SPaolo Bonzini{
607139c1837SPaolo Bonzini    tcg_out32(s, encode_uj(opc, rd, imm));
608139c1837SPaolo Bonzini}
609139c1837SPaolo Bonzini
610139c1837SPaolo Bonzinistatic void tcg_out_nop_fill(tcg_insn_unit *p, int count)
611139c1837SPaolo Bonzini{
612139c1837SPaolo Bonzini    int i;
613139c1837SPaolo Bonzini    for (i = 0; i < count; ++i) {
6149ae958e4SRichard Henderson        p[i] = OPC_NOP;
615139c1837SPaolo Bonzini    }
616139c1837SPaolo Bonzini}
617139c1837SPaolo Bonzini
618139c1837SPaolo Bonzini/*
619139c1837SPaolo Bonzini * Relocations
620139c1837SPaolo Bonzini */
621139c1837SPaolo Bonzini
622793f7381SRichard Hendersonstatic bool reloc_sbimm12(tcg_insn_unit *src_rw, const tcg_insn_unit *target)
623139c1837SPaolo Bonzini{
624793f7381SRichard Henderson    const tcg_insn_unit *src_rx = tcg_splitwx_to_rx(src_rw);
625793f7381SRichard Henderson    intptr_t offset = (intptr_t)target - (intptr_t)src_rx;
626139c1837SPaolo Bonzini
627844d0442SRichard Henderson    tcg_debug_assert((offset & 1) == 0);
628844d0442SRichard Henderson    if (offset == sextreg(offset, 0, 12)) {
629793f7381SRichard Henderson        *src_rw |= encode_sbimm12(offset);
630139c1837SPaolo Bonzini        return true;
631139c1837SPaolo Bonzini    }
632139c1837SPaolo Bonzini
633139c1837SPaolo Bonzini    return false;
634139c1837SPaolo Bonzini}
635139c1837SPaolo Bonzini
636793f7381SRichard Hendersonstatic bool reloc_jimm20(tcg_insn_unit *src_rw, const tcg_insn_unit *target)
637139c1837SPaolo Bonzini{
638793f7381SRichard Henderson    const tcg_insn_unit *src_rx = tcg_splitwx_to_rx(src_rw);
639793f7381SRichard Henderson    intptr_t offset = (intptr_t)target - (intptr_t)src_rx;
640139c1837SPaolo Bonzini
641844d0442SRichard Henderson    tcg_debug_assert((offset & 1) == 0);
642844d0442SRichard Henderson    if (offset == sextreg(offset, 0, 20)) {
643793f7381SRichard Henderson        *src_rw |= encode_ujimm20(offset);
644139c1837SPaolo Bonzini        return true;
645139c1837SPaolo Bonzini    }
646139c1837SPaolo Bonzini
647139c1837SPaolo Bonzini    return false;
648139c1837SPaolo Bonzini}
649139c1837SPaolo Bonzini
650793f7381SRichard Hendersonstatic bool reloc_call(tcg_insn_unit *src_rw, const tcg_insn_unit *target)
651139c1837SPaolo Bonzini{
652793f7381SRichard Henderson    const tcg_insn_unit *src_rx = tcg_splitwx_to_rx(src_rw);
653793f7381SRichard Henderson    intptr_t offset = (intptr_t)target - (intptr_t)src_rx;
654139c1837SPaolo Bonzini    int32_t lo = sextreg(offset, 0, 12);
655139c1837SPaolo Bonzini    int32_t hi = offset - lo;
656139c1837SPaolo Bonzini
657139c1837SPaolo Bonzini    if (offset == hi + lo) {
658793f7381SRichard Henderson        src_rw[0] |= encode_uimm20(hi);
659793f7381SRichard Henderson        src_rw[1] |= encode_imm12(lo);
660139c1837SPaolo Bonzini        return true;
661139c1837SPaolo Bonzini    }
662139c1837SPaolo Bonzini
663139c1837SPaolo Bonzini    return false;
664139c1837SPaolo Bonzini}
665139c1837SPaolo Bonzini
666139c1837SPaolo Bonzinistatic bool patch_reloc(tcg_insn_unit *code_ptr, int type,
667139c1837SPaolo Bonzini                        intptr_t value, intptr_t addend)
668139c1837SPaolo Bonzini{
669139c1837SPaolo Bonzini    tcg_debug_assert(addend == 0);
670139c1837SPaolo Bonzini    switch (type) {
671139c1837SPaolo Bonzini    case R_RISCV_BRANCH:
672139c1837SPaolo Bonzini        return reloc_sbimm12(code_ptr, (tcg_insn_unit *)value);
673139c1837SPaolo Bonzini    case R_RISCV_JAL:
674139c1837SPaolo Bonzini        return reloc_jimm20(code_ptr, (tcg_insn_unit *)value);
675139c1837SPaolo Bonzini    case R_RISCV_CALL:
676139c1837SPaolo Bonzini        return reloc_call(code_ptr, (tcg_insn_unit *)value);
677139c1837SPaolo Bonzini    default:
6784b6a52d0SRichard Henderson        g_assert_not_reached();
679139c1837SPaolo Bonzini    }
680139c1837SPaolo Bonzini}
681139c1837SPaolo Bonzini
682139c1837SPaolo Bonzini/*
683f63e7089SHuang Shiyuan * RISC-V vector instruction emitters
684f63e7089SHuang Shiyuan */
685f63e7089SHuang Shiyuan
686d4be6ee1STANG Tiancheng/*
687d4be6ee1STANG Tiancheng * Vector registers uses the same 5 lower bits as GPR registers,
688d4be6ee1STANG Tiancheng * and vm=0 (vm = false) means vector masking ENABLED.
689d4be6ee1STANG Tiancheng * With RVV 1.0, vs2 is the first operand, while rs1/imm is the
690d4be6ee1STANG Tiancheng * second operand.
691d4be6ee1STANG Tiancheng */
6925a63f599STANG Tianchengstatic void tcg_out_opc_vv(TCGContext *s, RISCVInsn opc,
6935a63f599STANG Tiancheng                           TCGReg vd, TCGReg vs2, TCGReg vs1)
6945a63f599STANG Tiancheng{
6955a63f599STANG Tiancheng    tcg_out32(s, encode_v(opc, vd, vs1, vs2, true));
6965a63f599STANG Tiancheng}
6975a63f599STANG Tiancheng
698d4be6ee1STANG Tianchengstatic void tcg_out_opc_vx(TCGContext *s, RISCVInsn opc,
699d4be6ee1STANG Tiancheng                           TCGReg vd, TCGReg vs2, TCGReg rs1)
700d4be6ee1STANG Tiancheng{
701d4be6ee1STANG Tiancheng    tcg_out32(s, encode_v(opc, vd, rs1, vs2, true));
702d4be6ee1STANG Tiancheng}
703d4be6ee1STANG Tiancheng
704d4be6ee1STANG Tianchengstatic void tcg_out_opc_vi(TCGContext *s, RISCVInsn opc,
705d4be6ee1STANG Tiancheng                           TCGReg vd, TCGReg vs2, int32_t imm)
706d4be6ee1STANG Tiancheng{
707d4be6ee1STANG Tiancheng    tcg_out32(s, encode_vi(opc, vd, imm, vs2, true));
708d4be6ee1STANG Tiancheng}
709d4be6ee1STANG Tiancheng
7105a63f599STANG Tianchengstatic void tcg_out_opc_vv_vi(TCGContext *s, RISCVInsn o_vv, RISCVInsn o_vi,
7115a63f599STANG Tiancheng                              TCGReg vd, TCGReg vs2, TCGArg vi1, int c_vi1)
7125a63f599STANG Tiancheng{
7135a63f599STANG Tiancheng    if (c_vi1) {
7145a63f599STANG Tiancheng        tcg_out_opc_vi(s, o_vi, vd, vs2, vi1);
7155a63f599STANG Tiancheng    } else {
7165a63f599STANG Tiancheng        tcg_out_opc_vv(s, o_vv, vd, vs2, vi1);
7175a63f599STANG Tiancheng    }
7185a63f599STANG Tiancheng}
7195a63f599STANG Tiancheng
720a31768c0STANG Tianchengstatic void tcg_out_opc_vim_mask(TCGContext *s, RISCVInsn opc, TCGReg vd,
721a31768c0STANG Tiancheng                                 TCGReg vs2, int32_t imm)
722a31768c0STANG Tiancheng{
723a31768c0STANG Tiancheng    tcg_out32(s, encode_vi(opc, vd, imm, vs2, false));
724a31768c0STANG Tiancheng}
725a31768c0STANG Tiancheng
726a31768c0STANG Tianchengstatic void tcg_out_opc_vvm_mask(TCGContext *s, RISCVInsn opc, TCGReg vd,
727a31768c0STANG Tiancheng                                 TCGReg vs2, TCGReg vs1)
728a31768c0STANG Tiancheng{
729a31768c0STANG Tiancheng    tcg_out32(s, encode_v(opc, vd, vs1, vs2, false));
730a31768c0STANG Tiancheng}
731a31768c0STANG Tiancheng
732f63e7089SHuang Shiyuantypedef struct VsetCache {
733f63e7089SHuang Shiyuan    uint32_t movi_insn;
734f63e7089SHuang Shiyuan    uint32_t vset_insn;
735f63e7089SHuang Shiyuan} VsetCache;
736f63e7089SHuang Shiyuan
737f63e7089SHuang Shiyuanstatic VsetCache riscv_vset_cache[3][4];
738f63e7089SHuang Shiyuan
739f63e7089SHuang Shiyuanstatic void set_vtype(TCGContext *s, TCGType type, MemOp vsew)
740f63e7089SHuang Shiyuan{
741f63e7089SHuang Shiyuan    const VsetCache *p = &riscv_vset_cache[type - TCG_TYPE_V64][vsew];
742f63e7089SHuang Shiyuan
743f63e7089SHuang Shiyuan    s->riscv_cur_type = type;
744f63e7089SHuang Shiyuan    s->riscv_cur_vsew = vsew;
745f63e7089SHuang Shiyuan
746f63e7089SHuang Shiyuan    if (p->movi_insn) {
747f63e7089SHuang Shiyuan        tcg_out32(s, p->movi_insn);
748f63e7089SHuang Shiyuan    }
749f63e7089SHuang Shiyuan    tcg_out32(s, p->vset_insn);
750f63e7089SHuang Shiyuan}
751f63e7089SHuang Shiyuan
752f63e7089SHuang Shiyuanstatic MemOp set_vtype_len(TCGContext *s, TCGType type)
753f63e7089SHuang Shiyuan{
754f63e7089SHuang Shiyuan    if (type != s->riscv_cur_type) {
755f63e7089SHuang Shiyuan        set_vtype(s, type, MO_64);
756f63e7089SHuang Shiyuan    }
757f63e7089SHuang Shiyuan    return s->riscv_cur_vsew;
758f63e7089SHuang Shiyuan}
759f63e7089SHuang Shiyuan
760d4be6ee1STANG Tianchengstatic void set_vtype_len_sew(TCGContext *s, TCGType type, MemOp vsew)
761d4be6ee1STANG Tiancheng{
762d4be6ee1STANG Tiancheng    if (type != s->riscv_cur_type || vsew != s->riscv_cur_vsew) {
763d4be6ee1STANG Tiancheng        set_vtype(s, type, vsew);
764d4be6ee1STANG Tiancheng    }
765d4be6ee1STANG Tiancheng}
766d4be6ee1STANG Tiancheng
767f63e7089SHuang Shiyuan/*
768139c1837SPaolo Bonzini * TCG intrinsics
769139c1837SPaolo Bonzini */
770139c1837SPaolo Bonzini
771139c1837SPaolo Bonzinistatic bool tcg_out_mov(TCGContext *s, TCGType type, TCGReg ret, TCGReg arg)
772139c1837SPaolo Bonzini{
773139c1837SPaolo Bonzini    if (ret == arg) {
774139c1837SPaolo Bonzini        return true;
775139c1837SPaolo Bonzini    }
776139c1837SPaolo Bonzini    switch (type) {
777139c1837SPaolo Bonzini    case TCG_TYPE_I32:
778139c1837SPaolo Bonzini    case TCG_TYPE_I64:
779139c1837SPaolo Bonzini        tcg_out_opc_imm(s, OPC_ADDI, ret, arg, 0);
780139c1837SPaolo Bonzini        break;
781d4be6ee1STANG Tiancheng    case TCG_TYPE_V64:
782d4be6ee1STANG Tiancheng    case TCG_TYPE_V128:
783d4be6ee1STANG Tiancheng    case TCG_TYPE_V256:
784d4be6ee1STANG Tiancheng        {
785d4be6ee1STANG Tiancheng            int lmul = type - riscv_lg2_vlenb;
786d4be6ee1STANG Tiancheng            int nf = 1 << MAX(lmul, 0);
787d4be6ee1STANG Tiancheng            tcg_out_opc_vi(s, OPC_VMVNR_V, ret, arg, nf - 1);
788d4be6ee1STANG Tiancheng        }
789d4be6ee1STANG Tiancheng        break;
790139c1837SPaolo Bonzini    default:
791139c1837SPaolo Bonzini        g_assert_not_reached();
792139c1837SPaolo Bonzini    }
793139c1837SPaolo Bonzini    return true;
794139c1837SPaolo Bonzini}
795139c1837SPaolo Bonzini
796139c1837SPaolo Bonzinistatic void tcg_out_movi(TCGContext *s, TCGType type, TCGReg rd,
797139c1837SPaolo Bonzini                         tcg_target_long val)
798139c1837SPaolo Bonzini{
799139c1837SPaolo Bonzini    tcg_target_long lo, hi, tmp;
800139c1837SPaolo Bonzini    int shift, ret;
801139c1837SPaolo Bonzini
802aeb6326eSRichard Henderson    if (type == TCG_TYPE_I32) {
803139c1837SPaolo Bonzini        val = (int32_t)val;
804139c1837SPaolo Bonzini    }
805139c1837SPaolo Bonzini
806139c1837SPaolo Bonzini    lo = sextreg(val, 0, 12);
807139c1837SPaolo Bonzini    if (val == lo) {
808139c1837SPaolo Bonzini        tcg_out_opc_imm(s, OPC_ADDI, rd, TCG_REG_ZERO, lo);
809139c1837SPaolo Bonzini        return;
810139c1837SPaolo Bonzini    }
811139c1837SPaolo Bonzini
812139c1837SPaolo Bonzini    hi = val - lo;
813aeb6326eSRichard Henderson    if (val == (int32_t)val) {
814139c1837SPaolo Bonzini        tcg_out_opc_upper(s, OPC_LUI, rd, hi);
815139c1837SPaolo Bonzini        if (lo != 0) {
816139c1837SPaolo Bonzini            tcg_out_opc_imm(s, OPC_ADDIW, rd, rd, lo);
817139c1837SPaolo Bonzini        }
818139c1837SPaolo Bonzini        return;
819139c1837SPaolo Bonzini    }
820139c1837SPaolo Bonzini
821139c1837SPaolo Bonzini    tmp = tcg_pcrel_diff(s, (void *)val);
822139c1837SPaolo Bonzini    if (tmp == (int32_t)tmp) {
823139c1837SPaolo Bonzini        tcg_out_opc_upper(s, OPC_AUIPC, rd, 0);
824139c1837SPaolo Bonzini        tcg_out_opc_imm(s, OPC_ADDI, rd, rd, 0);
825793f7381SRichard Henderson        ret = reloc_call(s->code_ptr - 2, (const tcg_insn_unit *)val);
826139c1837SPaolo Bonzini        tcg_debug_assert(ret == true);
827139c1837SPaolo Bonzini        return;
828139c1837SPaolo Bonzini    }
829139c1837SPaolo Bonzini
830139c1837SPaolo Bonzini    /* Look for a single 20-bit section.  */
831139c1837SPaolo Bonzini    shift = ctz64(val);
832139c1837SPaolo Bonzini    tmp = val >> shift;
833139c1837SPaolo Bonzini    if (tmp == sextreg(tmp, 0, 20)) {
834139c1837SPaolo Bonzini        tcg_out_opc_upper(s, OPC_LUI, rd, tmp << 12);
835139c1837SPaolo Bonzini        if (shift > 12) {
836139c1837SPaolo Bonzini            tcg_out_opc_imm(s, OPC_SLLI, rd, rd, shift - 12);
837139c1837SPaolo Bonzini        } else {
838139c1837SPaolo Bonzini            tcg_out_opc_imm(s, OPC_SRAI, rd, rd, 12 - shift);
839139c1837SPaolo Bonzini        }
840139c1837SPaolo Bonzini        return;
841139c1837SPaolo Bonzini    }
842139c1837SPaolo Bonzini
843139c1837SPaolo Bonzini    /* Look for a few high zero bits, with lots of bits set in the middle.  */
844139c1837SPaolo Bonzini    shift = clz64(val);
845139c1837SPaolo Bonzini    tmp = val << shift;
846139c1837SPaolo Bonzini    if (tmp == sextreg(tmp, 12, 20) << 12) {
847139c1837SPaolo Bonzini        tcg_out_opc_upper(s, OPC_LUI, rd, tmp);
848139c1837SPaolo Bonzini        tcg_out_opc_imm(s, OPC_SRLI, rd, rd, shift);
849139c1837SPaolo Bonzini        return;
850139c1837SPaolo Bonzini    } else if (tmp == sextreg(tmp, 0, 12)) {
851139c1837SPaolo Bonzini        tcg_out_opc_imm(s, OPC_ADDI, rd, TCG_REG_ZERO, tmp);
852139c1837SPaolo Bonzini        tcg_out_opc_imm(s, OPC_SRLI, rd, rd, shift);
853139c1837SPaolo Bonzini        return;
854139c1837SPaolo Bonzini    }
855139c1837SPaolo Bonzini
856139c1837SPaolo Bonzini    /* Drop into the constant pool.  */
857139c1837SPaolo Bonzini    new_pool_label(s, val, R_RISCV_CALL, s->code_ptr, 0);
858139c1837SPaolo Bonzini    tcg_out_opc_upper(s, OPC_AUIPC, rd, 0);
859139c1837SPaolo Bonzini    tcg_out_opc_imm(s, OPC_LD, rd, rd, 0);
860139c1837SPaolo Bonzini}
861139c1837SPaolo Bonzini
862767c2503SRichard Hendersonstatic bool tcg_out_xchg(TCGContext *s, TCGType type, TCGReg r1, TCGReg r2)
863767c2503SRichard Henderson{
864767c2503SRichard Henderson    return false;
865767c2503SRichard Henderson}
866767c2503SRichard Henderson
8676a6d772eSRichard Hendersonstatic void tcg_out_addi_ptr(TCGContext *s, TCGReg rd, TCGReg rs,
8686a6d772eSRichard Henderson                             tcg_target_long imm)
8696a6d772eSRichard Henderson{
8706a6d772eSRichard Henderson    /* This function is only used for passing structs by reference. */
8716a6d772eSRichard Henderson    g_assert_not_reached();
8726a6d772eSRichard Henderson}
8736a6d772eSRichard Henderson
874139c1837SPaolo Bonzinistatic void tcg_out_ext8u(TCGContext *s, TCGReg ret, TCGReg arg)
875139c1837SPaolo Bonzini{
876139c1837SPaolo Bonzini    tcg_out_opc_imm(s, OPC_ANDI, ret, arg, 0xff);
877139c1837SPaolo Bonzini}
878139c1837SPaolo Bonzini
879139c1837SPaolo Bonzinistatic void tcg_out_ext16u(TCGContext *s, TCGReg ret, TCGReg arg)
880139c1837SPaolo Bonzini{
881b86c6ba6SRichard Henderson    if (cpuinfo & CPUINFO_ZBB) {
882d1c3f4e9SRichard Henderson        tcg_out_opc_reg(s, OPC_ZEXT_H, ret, arg, TCG_REG_ZERO);
883d1c3f4e9SRichard Henderson    } else {
884139c1837SPaolo Bonzini        tcg_out_opc_imm(s, OPC_SLLIW, ret, arg, 16);
885139c1837SPaolo Bonzini        tcg_out_opc_imm(s, OPC_SRLIW, ret, ret, 16);
886139c1837SPaolo Bonzini    }
887d1c3f4e9SRichard Henderson}
888139c1837SPaolo Bonzini
889139c1837SPaolo Bonzinistatic void tcg_out_ext32u(TCGContext *s, TCGReg ret, TCGReg arg)
890139c1837SPaolo Bonzini{
891b86c6ba6SRichard Henderson    if (cpuinfo & CPUINFO_ZBA) {
892d1c3f4e9SRichard Henderson        tcg_out_opc_reg(s, OPC_ADD_UW, ret, arg, TCG_REG_ZERO);
893d1c3f4e9SRichard Henderson    } else {
894139c1837SPaolo Bonzini        tcg_out_opc_imm(s, OPC_SLLI, ret, arg, 32);
895139c1837SPaolo Bonzini        tcg_out_opc_imm(s, OPC_SRLI, ret, ret, 32);
896139c1837SPaolo Bonzini    }
897d1c3f4e9SRichard Henderson}
898139c1837SPaolo Bonzini
899678155b2SRichard Hendersonstatic void tcg_out_ext8s(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_B, ret, arg, 0);
903d1c3f4e9SRichard Henderson    } else {
904139c1837SPaolo Bonzini        tcg_out_opc_imm(s, OPC_SLLIW, ret, arg, 24);
905139c1837SPaolo Bonzini        tcg_out_opc_imm(s, OPC_SRAIW, ret, ret, 24);
906139c1837SPaolo Bonzini    }
907d1c3f4e9SRichard Henderson}
908139c1837SPaolo Bonzini
909753e42eaSRichard Hendersonstatic void tcg_out_ext16s(TCGContext *s, TCGType type, TCGReg ret, TCGReg arg)
910139c1837SPaolo Bonzini{
911b86c6ba6SRichard Henderson    if (cpuinfo & CPUINFO_ZBB) {
912d1c3f4e9SRichard Henderson        tcg_out_opc_imm(s, OPC_SEXT_H, ret, arg, 0);
913d1c3f4e9SRichard Henderson    } else {
914139c1837SPaolo Bonzini        tcg_out_opc_imm(s, OPC_SLLIW, ret, arg, 16);
915139c1837SPaolo Bonzini        tcg_out_opc_imm(s, OPC_SRAIW, ret, ret, 16);
916139c1837SPaolo Bonzini    }
917d1c3f4e9SRichard Henderson}
918139c1837SPaolo Bonzini
919139c1837SPaolo Bonzinistatic void tcg_out_ext32s(TCGContext *s, TCGReg ret, TCGReg arg)
920139c1837SPaolo Bonzini{
921139c1837SPaolo Bonzini    tcg_out_opc_imm(s, OPC_ADDIW, ret, arg, 0);
922139c1837SPaolo Bonzini}
923139c1837SPaolo Bonzini
9249c6aa274SRichard Hendersonstatic void tcg_out_exts_i32_i64(TCGContext *s, TCGReg ret, TCGReg arg)
9259c6aa274SRichard Henderson{
9263ea9be33SRichard Henderson    if (ret != arg) {
9279c6aa274SRichard Henderson        tcg_out_ext32s(s, ret, arg);
9289c6aa274SRichard Henderson    }
9293ea9be33SRichard Henderson}
9309c6aa274SRichard Henderson
931b9bfe000SRichard Hendersonstatic void tcg_out_extu_i32_i64(TCGContext *s, TCGReg ret, TCGReg arg)
932b9bfe000SRichard Henderson{
933b9bfe000SRichard Henderson    tcg_out_ext32u(s, ret, arg);
934b9bfe000SRichard Henderson}
935b9bfe000SRichard Henderson
936b8b94ac6SRichard Hendersonstatic void tcg_out_extrl_i64_i32(TCGContext *s, TCGReg ret, TCGReg arg)
937b8b94ac6SRichard Henderson{
938b8b94ac6SRichard Henderson    tcg_out_ext32s(s, ret, arg);
939b8b94ac6SRichard Henderson}
940b8b94ac6SRichard Henderson
941139c1837SPaolo Bonzinistatic void tcg_out_ldst(TCGContext *s, RISCVInsn opc, TCGReg data,
942139c1837SPaolo Bonzini                         TCGReg addr, intptr_t offset)
943139c1837SPaolo Bonzini{
944139c1837SPaolo Bonzini    intptr_t imm12 = sextreg(offset, 0, 12);
945139c1837SPaolo Bonzini
946139c1837SPaolo Bonzini    if (offset != imm12) {
9479d9db413SRichard Henderson        intptr_t diff = tcg_pcrel_diff(s, (void *)offset);
948139c1837SPaolo Bonzini
949139c1837SPaolo Bonzini        if (addr == TCG_REG_ZERO && diff == (int32_t)diff) {
950139c1837SPaolo Bonzini            imm12 = sextreg(diff, 0, 12);
951139c1837SPaolo Bonzini            tcg_out_opc_upper(s, OPC_AUIPC, TCG_REG_TMP2, diff - imm12);
952139c1837SPaolo Bonzini        } else {
953139c1837SPaolo Bonzini            tcg_out_movi(s, TCG_TYPE_PTR, TCG_REG_TMP2, offset - imm12);
954139c1837SPaolo Bonzini            if (addr != TCG_REG_ZERO) {
955139c1837SPaolo Bonzini                tcg_out_opc_reg(s, OPC_ADD, TCG_REG_TMP2, TCG_REG_TMP2, addr);
956139c1837SPaolo Bonzini            }
957139c1837SPaolo Bonzini        }
958139c1837SPaolo Bonzini        addr = TCG_REG_TMP2;
959139c1837SPaolo Bonzini    }
960139c1837SPaolo Bonzini
961139c1837SPaolo Bonzini    switch (opc) {
962139c1837SPaolo Bonzini    case OPC_SB:
963139c1837SPaolo Bonzini    case OPC_SH:
964139c1837SPaolo Bonzini    case OPC_SW:
965139c1837SPaolo Bonzini    case OPC_SD:
966139c1837SPaolo Bonzini        tcg_out_opc_store(s, opc, addr, data, imm12);
967139c1837SPaolo Bonzini        break;
968139c1837SPaolo Bonzini    case OPC_LB:
969139c1837SPaolo Bonzini    case OPC_LBU:
970139c1837SPaolo Bonzini    case OPC_LH:
971139c1837SPaolo Bonzini    case OPC_LHU:
972139c1837SPaolo Bonzini    case OPC_LW:
973139c1837SPaolo Bonzini    case OPC_LWU:
974139c1837SPaolo Bonzini    case OPC_LD:
975139c1837SPaolo Bonzini        tcg_out_opc_imm(s, opc, data, addr, imm12);
976139c1837SPaolo Bonzini        break;
977139c1837SPaolo Bonzini    default:
978139c1837SPaolo Bonzini        g_assert_not_reached();
979139c1837SPaolo Bonzini    }
980139c1837SPaolo Bonzini}
981139c1837SPaolo Bonzini
982f63e7089SHuang Shiyuanstatic void tcg_out_vec_ldst(TCGContext *s, RISCVInsn opc, TCGReg data,
983f63e7089SHuang Shiyuan                             TCGReg addr, intptr_t offset)
984f63e7089SHuang Shiyuan{
985f63e7089SHuang Shiyuan    tcg_debug_assert(data >= TCG_REG_V0);
986f63e7089SHuang Shiyuan    tcg_debug_assert(addr < TCG_REG_V0);
987f63e7089SHuang Shiyuan
988f63e7089SHuang Shiyuan    if (offset) {
989f63e7089SHuang Shiyuan        tcg_debug_assert(addr != TCG_REG_ZERO);
990f63e7089SHuang Shiyuan        if (offset == sextreg(offset, 0, 12)) {
991f63e7089SHuang Shiyuan            tcg_out_opc_imm(s, OPC_ADDI, TCG_REG_TMP0, addr, offset);
992f63e7089SHuang Shiyuan        } else {
993f63e7089SHuang Shiyuan            tcg_out_movi(s, TCG_TYPE_PTR, TCG_REG_TMP0, offset);
994f63e7089SHuang Shiyuan            tcg_out_opc_reg(s, OPC_ADD, TCG_REG_TMP0, TCG_REG_TMP0, addr);
995f63e7089SHuang Shiyuan        }
996f63e7089SHuang Shiyuan        addr = TCG_REG_TMP0;
997f63e7089SHuang Shiyuan    }
998f63e7089SHuang Shiyuan    tcg_out32(s, encode_v(opc, data, addr, 0, true));
999f63e7089SHuang Shiyuan}
1000f63e7089SHuang Shiyuan
1001139c1837SPaolo Bonzinistatic void tcg_out_ld(TCGContext *s, TCGType type, TCGReg arg,
1002139c1837SPaolo Bonzini                       TCGReg arg1, intptr_t arg2)
1003139c1837SPaolo Bonzini{
1004f63e7089SHuang Shiyuan    RISCVInsn insn;
1005f63e7089SHuang Shiyuan
1006f63e7089SHuang Shiyuan    switch (type) {
1007f63e7089SHuang Shiyuan    case TCG_TYPE_I32:
1008f63e7089SHuang Shiyuan        tcg_out_ldst(s, OPC_LW, arg, arg1, arg2);
1009f63e7089SHuang Shiyuan        break;
1010f63e7089SHuang Shiyuan    case TCG_TYPE_I64:
1011f63e7089SHuang Shiyuan        tcg_out_ldst(s, OPC_LD, arg, arg1, arg2);
1012f63e7089SHuang Shiyuan        break;
1013f63e7089SHuang Shiyuan    case TCG_TYPE_V64:
1014f63e7089SHuang Shiyuan    case TCG_TYPE_V128:
1015f63e7089SHuang Shiyuan    case TCG_TYPE_V256:
1016f63e7089SHuang Shiyuan        if (type >= riscv_lg2_vlenb) {
1017f63e7089SHuang Shiyuan            static const RISCVInsn whole_reg_ld[] = {
1018f63e7089SHuang Shiyuan                OPC_VL1RE64_V, OPC_VL2RE64_V, OPC_VL4RE64_V, OPC_VL8RE64_V
1019f63e7089SHuang Shiyuan            };
1020f63e7089SHuang Shiyuan            unsigned idx = type - riscv_lg2_vlenb;
1021f63e7089SHuang Shiyuan
1022f63e7089SHuang Shiyuan            tcg_debug_assert(idx < ARRAY_SIZE(whole_reg_ld));
1023f63e7089SHuang Shiyuan            insn = whole_reg_ld[idx];
1024f63e7089SHuang Shiyuan        } else {
1025f63e7089SHuang Shiyuan            static const RISCVInsn unit_stride_ld[] = {
1026f63e7089SHuang Shiyuan                OPC_VLE8_V, OPC_VLE16_V, OPC_VLE32_V, OPC_VLE64_V
1027f63e7089SHuang Shiyuan            };
1028f63e7089SHuang Shiyuan            MemOp prev_vsew = set_vtype_len(s, type);
1029f63e7089SHuang Shiyuan
1030f63e7089SHuang Shiyuan            tcg_debug_assert(prev_vsew < ARRAY_SIZE(unit_stride_ld));
1031f63e7089SHuang Shiyuan            insn = unit_stride_ld[prev_vsew];
1032f63e7089SHuang Shiyuan        }
1033f63e7089SHuang Shiyuan        tcg_out_vec_ldst(s, insn, arg, arg1, arg2);
1034f63e7089SHuang Shiyuan        break;
1035f63e7089SHuang Shiyuan    default:
1036f63e7089SHuang Shiyuan        g_assert_not_reached();
1037f63e7089SHuang Shiyuan    }
1038139c1837SPaolo Bonzini}
1039139c1837SPaolo Bonzini
1040139c1837SPaolo Bonzinistatic void tcg_out_st(TCGContext *s, TCGType type, TCGReg arg,
1041139c1837SPaolo Bonzini                       TCGReg arg1, intptr_t arg2)
1042139c1837SPaolo Bonzini{
1043f63e7089SHuang Shiyuan    RISCVInsn insn;
1044f63e7089SHuang Shiyuan
1045f63e7089SHuang Shiyuan    switch (type) {
1046f63e7089SHuang Shiyuan    case TCG_TYPE_I32:
1047f63e7089SHuang Shiyuan        tcg_out_ldst(s, OPC_SW, arg, arg1, arg2);
1048f63e7089SHuang Shiyuan        break;
1049f63e7089SHuang Shiyuan    case TCG_TYPE_I64:
1050f63e7089SHuang Shiyuan        tcg_out_ldst(s, OPC_SD, arg, arg1, arg2);
1051f63e7089SHuang Shiyuan        break;
1052f63e7089SHuang Shiyuan    case TCG_TYPE_V64:
1053f63e7089SHuang Shiyuan    case TCG_TYPE_V128:
1054f63e7089SHuang Shiyuan    case TCG_TYPE_V256:
1055f63e7089SHuang Shiyuan        if (type >= riscv_lg2_vlenb) {
1056f63e7089SHuang Shiyuan            static const RISCVInsn whole_reg_st[] = {
1057f63e7089SHuang Shiyuan                OPC_VS1R_V, OPC_VS2R_V, OPC_VS4R_V, OPC_VS8R_V
1058f63e7089SHuang Shiyuan            };
1059f63e7089SHuang Shiyuan            unsigned idx = type - riscv_lg2_vlenb;
1060f63e7089SHuang Shiyuan
1061f63e7089SHuang Shiyuan            tcg_debug_assert(idx < ARRAY_SIZE(whole_reg_st));
1062f63e7089SHuang Shiyuan            insn = whole_reg_st[idx];
1063f63e7089SHuang Shiyuan        } else {
1064f63e7089SHuang Shiyuan            static const RISCVInsn unit_stride_st[] = {
1065f63e7089SHuang Shiyuan                OPC_VSE8_V, OPC_VSE16_V, OPC_VSE32_V, OPC_VSE64_V
1066f63e7089SHuang Shiyuan            };
1067f63e7089SHuang Shiyuan            MemOp prev_vsew = set_vtype_len(s, type);
1068f63e7089SHuang Shiyuan
1069f63e7089SHuang Shiyuan            tcg_debug_assert(prev_vsew < ARRAY_SIZE(unit_stride_st));
1070f63e7089SHuang Shiyuan            insn = unit_stride_st[prev_vsew];
1071f63e7089SHuang Shiyuan        }
1072f63e7089SHuang Shiyuan        tcg_out_vec_ldst(s, insn, arg, arg1, arg2);
1073f63e7089SHuang Shiyuan        break;
1074f63e7089SHuang Shiyuan    default:
1075f63e7089SHuang Shiyuan        g_assert_not_reached();
1076f63e7089SHuang Shiyuan    }
1077139c1837SPaolo Bonzini}
1078139c1837SPaolo Bonzini
1079139c1837SPaolo Bonzinistatic bool tcg_out_sti(TCGContext *s, TCGType type, TCGArg val,
1080139c1837SPaolo Bonzini                        TCGReg base, intptr_t ofs)
1081139c1837SPaolo Bonzini{
1082139c1837SPaolo Bonzini    if (val == 0) {
1083139c1837SPaolo Bonzini        tcg_out_st(s, type, TCG_REG_ZERO, base, ofs);
1084139c1837SPaolo Bonzini        return true;
1085139c1837SPaolo Bonzini    }
1086139c1837SPaolo Bonzini    return false;
1087139c1837SPaolo Bonzini}
1088139c1837SPaolo Bonzini
1089139c1837SPaolo Bonzinistatic void tcg_out_addsub2(TCGContext *s,
1090139c1837SPaolo Bonzini                            TCGReg rl, TCGReg rh,
1091139c1837SPaolo Bonzini                            TCGReg al, TCGReg ah,
1092139c1837SPaolo Bonzini                            TCGArg bl, TCGArg bh,
1093139c1837SPaolo Bonzini                            bool cbl, bool cbh, bool is_sub, bool is32bit)
1094139c1837SPaolo Bonzini{
1095139c1837SPaolo Bonzini    const RISCVInsn opc_add = is32bit ? OPC_ADDW : OPC_ADD;
1096139c1837SPaolo Bonzini    const RISCVInsn opc_addi = is32bit ? OPC_ADDIW : OPC_ADDI;
1097139c1837SPaolo Bonzini    const RISCVInsn opc_sub = is32bit ? OPC_SUBW : OPC_SUB;
1098139c1837SPaolo Bonzini    TCGReg th = TCG_REG_TMP1;
1099139c1837SPaolo Bonzini
1100139c1837SPaolo Bonzini    /* If we have a negative constant such that negating it would
1101139c1837SPaolo Bonzini       make the high part zero, we can (usually) eliminate one insn.  */
1102139c1837SPaolo Bonzini    if (cbl && cbh && bh == -1 && bl != 0) {
1103139c1837SPaolo Bonzini        bl = -bl;
1104139c1837SPaolo Bonzini        bh = 0;
1105139c1837SPaolo Bonzini        is_sub = !is_sub;
1106139c1837SPaolo Bonzini    }
1107139c1837SPaolo Bonzini
1108139c1837SPaolo Bonzini    /* By operating on the high part first, we get to use the final
1109139c1837SPaolo Bonzini       carry operation to move back from the temporary.  */
1110139c1837SPaolo Bonzini    if (!cbh) {
1111139c1837SPaolo Bonzini        tcg_out_opc_reg(s, (is_sub ? opc_sub : opc_add), th, ah, bh);
1112139c1837SPaolo Bonzini    } else if (bh != 0 || ah == rl) {
1113139c1837SPaolo Bonzini        tcg_out_opc_imm(s, opc_addi, th, ah, (is_sub ? -bh : bh));
1114139c1837SPaolo Bonzini    } else {
1115139c1837SPaolo Bonzini        th = ah;
1116139c1837SPaolo Bonzini    }
1117139c1837SPaolo Bonzini
1118139c1837SPaolo Bonzini    /* Note that tcg optimization should eliminate the bl == 0 case.  */
1119139c1837SPaolo Bonzini    if (is_sub) {
1120139c1837SPaolo Bonzini        if (cbl) {
1121139c1837SPaolo Bonzini            tcg_out_opc_imm(s, OPC_SLTIU, TCG_REG_TMP0, al, bl);
1122139c1837SPaolo Bonzini            tcg_out_opc_imm(s, opc_addi, rl, al, -bl);
1123139c1837SPaolo Bonzini        } else {
1124139c1837SPaolo Bonzini            tcg_out_opc_reg(s, OPC_SLTU, TCG_REG_TMP0, al, bl);
1125139c1837SPaolo Bonzini            tcg_out_opc_reg(s, opc_sub, rl, al, bl);
1126139c1837SPaolo Bonzini        }
1127139c1837SPaolo Bonzini        tcg_out_opc_reg(s, opc_sub, rh, th, TCG_REG_TMP0);
1128139c1837SPaolo Bonzini    } else {
1129139c1837SPaolo Bonzini        if (cbl) {
1130139c1837SPaolo Bonzini            tcg_out_opc_imm(s, opc_addi, rl, al, bl);
1131139c1837SPaolo Bonzini            tcg_out_opc_imm(s, OPC_SLTIU, TCG_REG_TMP0, rl, bl);
11329b246685SRichard Henderson        } else if (al == bl) {
11339b246685SRichard Henderson            /*
11349b246685SRichard Henderson             * If the input regs overlap, this is a simple doubling
11359b246685SRichard Henderson             * and carry-out is the input msb.  This special case is
11369b246685SRichard Henderson             * required when the output reg overlaps the input,
11379b246685SRichard Henderson             * but we might as well use it always.
11389b246685SRichard Henderson             */
1139139c1837SPaolo Bonzini            tcg_out_opc_imm(s, OPC_SLTI, TCG_REG_TMP0, al, 0);
11409b246685SRichard Henderson            tcg_out_opc_reg(s, opc_add, rl, al, al);
1141139c1837SPaolo Bonzini        } else {
1142139c1837SPaolo Bonzini            tcg_out_opc_reg(s, opc_add, rl, al, bl);
1143139c1837SPaolo Bonzini            tcg_out_opc_reg(s, OPC_SLTU, TCG_REG_TMP0,
1144139c1837SPaolo Bonzini                            rl, (rl == bl ? al : bl));
1145139c1837SPaolo Bonzini        }
1146139c1837SPaolo Bonzini        tcg_out_opc_reg(s, opc_add, rh, th, TCG_REG_TMP0);
1147139c1837SPaolo Bonzini    }
1148139c1837SPaolo Bonzini}
1149139c1837SPaolo Bonzini
1150f63e7089SHuang Shiyuanstatic bool tcg_out_dup_vec(TCGContext *s, TCGType type, unsigned vece,
1151f63e7089SHuang Shiyuan                                   TCGReg dst, TCGReg src)
1152f63e7089SHuang Shiyuan{
1153d4be6ee1STANG Tiancheng    set_vtype_len_sew(s, type, vece);
1154d4be6ee1STANG Tiancheng    tcg_out_opc_vx(s, OPC_VMV_V_X, dst, 0, src);
1155d4be6ee1STANG Tiancheng    return true;
1156f63e7089SHuang Shiyuan}
1157f63e7089SHuang Shiyuan
1158f63e7089SHuang Shiyuanstatic bool tcg_out_dupm_vec(TCGContext *s, TCGType type, unsigned vece,
1159f63e7089SHuang Shiyuan                                    TCGReg dst, TCGReg base, intptr_t offset)
1160f63e7089SHuang Shiyuan{
1161d4be6ee1STANG Tiancheng    tcg_out_ld(s, TCG_TYPE_REG, TCG_REG_TMP0, base, offset);
1162d4be6ee1STANG Tiancheng    return tcg_out_dup_vec(s, type, vece, dst, TCG_REG_TMP0);
1163f63e7089SHuang Shiyuan}
1164f63e7089SHuang Shiyuan
1165f63e7089SHuang Shiyuanstatic void tcg_out_dupi_vec(TCGContext *s, TCGType type, unsigned vece,
1166f63e7089SHuang Shiyuan                                    TCGReg dst, int64_t arg)
1167f63e7089SHuang Shiyuan{
1168d4be6ee1STANG Tiancheng    /* Arg is replicated by VECE; extract the highest element. */
1169d4be6ee1STANG Tiancheng    arg >>= (-8 << vece) & 63;
1170d4be6ee1STANG Tiancheng
1171d4be6ee1STANG Tiancheng    if (arg >= -16 && arg < 16) {
1172d4be6ee1STANG Tiancheng        if (arg == 0 || arg == -1) {
1173d4be6ee1STANG Tiancheng            set_vtype_len(s, type);
1174d4be6ee1STANG Tiancheng        } else {
1175d4be6ee1STANG Tiancheng            set_vtype_len_sew(s, type, vece);
1176d4be6ee1STANG Tiancheng        }
1177d4be6ee1STANG Tiancheng        tcg_out_opc_vi(s, OPC_VMV_V_I, dst, 0, arg);
1178d4be6ee1STANG Tiancheng        return;
1179d4be6ee1STANG Tiancheng    }
1180d4be6ee1STANG Tiancheng    tcg_out_movi(s, TCG_TYPE_I64, TCG_REG_TMP0, arg);
1181d4be6ee1STANG Tiancheng    tcg_out_dup_vec(s, type, vece, dst, TCG_REG_TMP0);
1182f63e7089SHuang Shiyuan}
1183f63e7089SHuang Shiyuan
1184139c1837SPaolo Bonzinistatic const struct {
1185139c1837SPaolo Bonzini    RISCVInsn op;
1186139c1837SPaolo Bonzini    bool swap;
1187139c1837SPaolo Bonzini} tcg_brcond_to_riscv[] = {
1188139c1837SPaolo Bonzini    [TCG_COND_EQ] =  { OPC_BEQ,  false },
1189139c1837SPaolo Bonzini    [TCG_COND_NE] =  { OPC_BNE,  false },
1190139c1837SPaolo Bonzini    [TCG_COND_LT] =  { OPC_BLT,  false },
1191139c1837SPaolo Bonzini    [TCG_COND_GE] =  { OPC_BGE,  false },
1192139c1837SPaolo Bonzini    [TCG_COND_LE] =  { OPC_BGE,  true  },
1193139c1837SPaolo Bonzini    [TCG_COND_GT] =  { OPC_BLT,  true  },
1194139c1837SPaolo Bonzini    [TCG_COND_LTU] = { OPC_BLTU, false },
1195139c1837SPaolo Bonzini    [TCG_COND_GEU] = { OPC_BGEU, false },
1196139c1837SPaolo Bonzini    [TCG_COND_LEU] = { OPC_BGEU, true  },
1197139c1837SPaolo Bonzini    [TCG_COND_GTU] = { OPC_BLTU, true  }
1198139c1837SPaolo Bonzini};
1199139c1837SPaolo Bonzini
1200139c1837SPaolo Bonzinistatic void tcg_out_brcond(TCGContext *s, TCGCond cond, TCGReg arg1,
1201139c1837SPaolo Bonzini                           TCGReg arg2, TCGLabel *l)
1202139c1837SPaolo Bonzini{
1203139c1837SPaolo Bonzini    RISCVInsn op = tcg_brcond_to_riscv[cond].op;
1204139c1837SPaolo Bonzini
1205139c1837SPaolo Bonzini    tcg_debug_assert(op != 0);
1206139c1837SPaolo Bonzini
1207139c1837SPaolo Bonzini    if (tcg_brcond_to_riscv[cond].swap) {
1208139c1837SPaolo Bonzini        TCGReg t = arg1;
1209139c1837SPaolo Bonzini        arg1 = arg2;
1210139c1837SPaolo Bonzini        arg2 = t;
1211139c1837SPaolo Bonzini    }
1212139c1837SPaolo Bonzini
1213139c1837SPaolo Bonzini    tcg_out_reloc(s, s->code_ptr, R_RISCV_BRANCH, l, 0);
1214139c1837SPaolo Bonzini    tcg_out_opc_branch(s, op, arg1, arg2, 0);
1215139c1837SPaolo Bonzini}
1216139c1837SPaolo Bonzini
1217f6453695SRichard Henderson#define SETCOND_INV    TCG_TARGET_NB_REGS
1218f6453695SRichard Henderson#define SETCOND_NEZ    (SETCOND_INV << 1)
1219f6453695SRichard Henderson#define SETCOND_FLAGS  (SETCOND_INV | SETCOND_NEZ)
1220f6453695SRichard Henderson
1221f6453695SRichard Hendersonstatic int tcg_out_setcond_int(TCGContext *s, TCGCond cond, TCGReg ret,
1222f6453695SRichard Henderson                               TCGReg arg1, tcg_target_long arg2, bool c2)
1223139c1837SPaolo Bonzini{
1224f6453695SRichard Henderson    int flags = 0;
1225f6453695SRichard Henderson
1226139c1837SPaolo Bonzini    switch (cond) {
1227f6453695SRichard Henderson    case TCG_COND_EQ:    /* -> NE  */
1228f6453695SRichard Henderson    case TCG_COND_GE:    /* -> LT  */
1229f6453695SRichard Henderson    case TCG_COND_GEU:   /* -> LTU */
1230f6453695SRichard Henderson    case TCG_COND_GT:    /* -> LE  */
1231f6453695SRichard Henderson    case TCG_COND_GTU:   /* -> LEU */
1232f6453695SRichard Henderson        cond = tcg_invert_cond(cond);
1233f6453695SRichard Henderson        flags ^= SETCOND_INV;
1234139c1837SPaolo Bonzini        break;
1235f6453695SRichard Henderson    default:
1236139c1837SPaolo Bonzini        break;
1237f6453695SRichard Henderson    }
1238f6453695SRichard Henderson
1239f6453695SRichard Henderson    switch (cond) {
1240139c1837SPaolo Bonzini    case TCG_COND_LE:
1241139c1837SPaolo Bonzini    case TCG_COND_LEU:
1242f6453695SRichard Henderson        /*
1243f6453695SRichard Henderson         * If we have a constant input, the most efficient way to implement
1244f6453695SRichard Henderson         * LE is by adding 1 and using LT.  Watch out for wrap around for LEU.
1245f6453695SRichard Henderson         * We don't need to care for this for LE because the constant input
1246f6453695SRichard Henderson         * is constrained to signed 12-bit, and 0x800 is representable in the
1247f6453695SRichard Henderson         * temporary register.
1248f6453695SRichard Henderson         */
1249f6453695SRichard Henderson        if (c2) {
1250f6453695SRichard Henderson            if (cond == TCG_COND_LEU) {
1251f6453695SRichard Henderson                /* unsigned <= -1 is true */
1252f6453695SRichard Henderson                if (arg2 == -1) {
1253f6453695SRichard Henderson                    tcg_out_movi(s, TCG_TYPE_REG, ret, !(flags & SETCOND_INV));
1254f6453695SRichard Henderson                    return ret;
1255f6453695SRichard Henderson                }
1256f6453695SRichard Henderson                cond = TCG_COND_LTU;
1257f6453695SRichard Henderson            } else {
1258f6453695SRichard Henderson                cond = TCG_COND_LT;
1259f6453695SRichard Henderson            }
1260f6453695SRichard Henderson            tcg_debug_assert(arg2 <= 0x7ff);
1261f6453695SRichard Henderson            if (++arg2 == 0x800) {
1262f6453695SRichard Henderson                tcg_out_movi(s, TCG_TYPE_REG, TCG_REG_TMP0, arg2);
1263f6453695SRichard Henderson                arg2 = TCG_REG_TMP0;
1264f6453695SRichard Henderson                c2 = false;
1265f6453695SRichard Henderson            }
1266f6453695SRichard Henderson        } else {
1267f6453695SRichard Henderson            TCGReg tmp = arg2;
1268f6453695SRichard Henderson            arg2 = arg1;
1269f6453695SRichard Henderson            arg1 = tmp;
1270f6453695SRichard Henderson            cond = tcg_swap_cond(cond);    /* LE -> GE */
1271f6453695SRichard Henderson            cond = tcg_invert_cond(cond);  /* GE -> LT */
1272f6453695SRichard Henderson            flags ^= SETCOND_INV;
1273f6453695SRichard Henderson        }
1274139c1837SPaolo Bonzini        break;
1275f6453695SRichard Henderson    default:
1276f6453695SRichard Henderson        break;
1277f6453695SRichard Henderson    }
1278f6453695SRichard Henderson
1279f6453695SRichard Henderson    switch (cond) {
1280f6453695SRichard Henderson    case TCG_COND_NE:
1281f6453695SRichard Henderson        flags |= SETCOND_NEZ;
1282f6453695SRichard Henderson        if (!c2) {
1283f6453695SRichard Henderson            tcg_out_opc_reg(s, OPC_XOR, ret, arg1, arg2);
1284f6453695SRichard Henderson        } else if (arg2 == 0) {
1285f6453695SRichard Henderson            ret = arg1;
1286f6453695SRichard Henderson        } else {
1287f6453695SRichard Henderson            tcg_out_opc_imm(s, OPC_XORI, ret, arg1, arg2);
1288f6453695SRichard Henderson        }
1289f6453695SRichard Henderson        break;
1290f6453695SRichard Henderson
1291f6453695SRichard Henderson    case TCG_COND_LT:
1292f6453695SRichard Henderson        if (c2) {
1293f6453695SRichard Henderson            tcg_out_opc_imm(s, OPC_SLTI, ret, arg1, arg2);
1294f6453695SRichard Henderson        } else {
1295f6453695SRichard Henderson            tcg_out_opc_reg(s, OPC_SLT, ret, arg1, arg2);
1296f6453695SRichard Henderson        }
1297f6453695SRichard Henderson        break;
1298f6453695SRichard Henderson
1299f6453695SRichard Henderson    case TCG_COND_LTU:
1300f6453695SRichard Henderson        if (c2) {
1301f6453695SRichard Henderson            tcg_out_opc_imm(s, OPC_SLTIU, ret, arg1, arg2);
1302f6453695SRichard Henderson        } else {
1303f6453695SRichard Henderson            tcg_out_opc_reg(s, OPC_SLTU, ret, arg1, arg2);
1304f6453695SRichard Henderson        }
1305f6453695SRichard Henderson        break;
1306f6453695SRichard Henderson
1307f6453695SRichard Henderson    default:
1308f6453695SRichard Henderson        g_assert_not_reached();
1309f6453695SRichard Henderson    }
1310f6453695SRichard Henderson
1311f6453695SRichard Henderson    return ret | flags;
1312f6453695SRichard Henderson}
1313f6453695SRichard Henderson
1314f6453695SRichard Hendersonstatic void tcg_out_setcond(TCGContext *s, TCGCond cond, TCGReg ret,
1315f6453695SRichard Henderson                            TCGReg arg1, tcg_target_long arg2, bool c2)
1316f6453695SRichard Henderson{
1317f6453695SRichard Henderson    int tmpflags = tcg_out_setcond_int(s, cond, ret, arg1, arg2, c2);
1318f6453695SRichard Henderson
1319f6453695SRichard Henderson    if (tmpflags != ret) {
1320f6453695SRichard Henderson        TCGReg tmp = tmpflags & ~SETCOND_FLAGS;
1321f6453695SRichard Henderson
1322f6453695SRichard Henderson        switch (tmpflags & SETCOND_FLAGS) {
1323f6453695SRichard Henderson        case SETCOND_INV:
1324f6453695SRichard Henderson            /* Intermediate result is boolean: simply invert. */
1325f6453695SRichard Henderson            tcg_out_opc_imm(s, OPC_XORI, ret, tmp, 1);
1326f6453695SRichard Henderson            break;
1327f6453695SRichard Henderson        case SETCOND_NEZ:
1328f6453695SRichard Henderson            /* Intermediate result is zero/non-zero: test != 0. */
1329f6453695SRichard Henderson            tcg_out_opc_reg(s, OPC_SLTU, ret, TCG_REG_ZERO, tmp);
1330f6453695SRichard Henderson            break;
1331f6453695SRichard Henderson        case SETCOND_NEZ | SETCOND_INV:
1332f6453695SRichard Henderson            /* Intermediate result is zero/non-zero: test == 0. */
1333f6453695SRichard Henderson            tcg_out_opc_imm(s, OPC_SLTIU, ret, tmp, 1);
1334139c1837SPaolo Bonzini            break;
1335139c1837SPaolo Bonzini        default:
1336139c1837SPaolo Bonzini            g_assert_not_reached();
1337f6453695SRichard Henderson        }
1338139c1837SPaolo Bonzini    }
1339139c1837SPaolo Bonzini}
1340139c1837SPaolo Bonzini
134141e4c0a9SRichard Hendersonstatic void tcg_out_negsetcond(TCGContext *s, TCGCond cond, TCGReg ret,
134241e4c0a9SRichard Henderson                               TCGReg arg1, tcg_target_long arg2, bool c2)
134341e4c0a9SRichard Henderson{
134441e4c0a9SRichard Henderson    int tmpflags;
134541e4c0a9SRichard Henderson    TCGReg tmp;
134641e4c0a9SRichard Henderson
134741e4c0a9SRichard Henderson    /* For LT/GE comparison against 0, replicate the sign bit. */
134841e4c0a9SRichard Henderson    if (c2 && arg2 == 0) {
134941e4c0a9SRichard Henderson        switch (cond) {
135041e4c0a9SRichard Henderson        case TCG_COND_GE:
135141e4c0a9SRichard Henderson            tcg_out_opc_imm(s, OPC_XORI, ret, arg1, -1);
135241e4c0a9SRichard Henderson            arg1 = ret;
135341e4c0a9SRichard Henderson            /* fall through */
135441e4c0a9SRichard Henderson        case TCG_COND_LT:
135541e4c0a9SRichard Henderson            tcg_out_opc_imm(s, OPC_SRAI, ret, arg1, TCG_TARGET_REG_BITS - 1);
135641e4c0a9SRichard Henderson            return;
135741e4c0a9SRichard Henderson        default:
135841e4c0a9SRichard Henderson            break;
135941e4c0a9SRichard Henderson        }
136041e4c0a9SRichard Henderson    }
136141e4c0a9SRichard Henderson
136241e4c0a9SRichard Henderson    tmpflags = tcg_out_setcond_int(s, cond, ret, arg1, arg2, c2);
136341e4c0a9SRichard Henderson    tmp = tmpflags & ~SETCOND_FLAGS;
136441e4c0a9SRichard Henderson
136541e4c0a9SRichard Henderson    /* If intermediate result is zero/non-zero: test != 0. */
136641e4c0a9SRichard Henderson    if (tmpflags & SETCOND_NEZ) {
136741e4c0a9SRichard Henderson        tcg_out_opc_reg(s, OPC_SLTU, ret, TCG_REG_ZERO, tmp);
136841e4c0a9SRichard Henderson        tmp = ret;
136941e4c0a9SRichard Henderson    }
137041e4c0a9SRichard Henderson
137141e4c0a9SRichard Henderson    /* Produce the 0/-1 result. */
137241e4c0a9SRichard Henderson    if (tmpflags & SETCOND_INV) {
137341e4c0a9SRichard Henderson        tcg_out_opc_imm(s, OPC_ADDI, ret, tmp, -1);
137441e4c0a9SRichard Henderson    } else {
137541e4c0a9SRichard Henderson        tcg_out_opc_reg(s, OPC_SUB, ret, TCG_REG_ZERO, tmp);
137641e4c0a9SRichard Henderson    }
137741e4c0a9SRichard Henderson}
137841e4c0a9SRichard Henderson
1379a18d783eSRichard Hendersonstatic void tcg_out_movcond_zicond(TCGContext *s, TCGReg ret, TCGReg test_ne,
1380a18d783eSRichard Henderson                                   int val1, bool c_val1,
1381a18d783eSRichard Henderson                                   int val2, bool c_val2)
1382a18d783eSRichard Henderson{
1383a18d783eSRichard Henderson    if (val1 == 0) {
1384a18d783eSRichard Henderson        if (c_val2) {
1385a18d783eSRichard Henderson            tcg_out_movi(s, TCG_TYPE_REG, TCG_REG_TMP1, val2);
1386a18d783eSRichard Henderson            val2 = TCG_REG_TMP1;
1387a18d783eSRichard Henderson        }
1388a18d783eSRichard Henderson        tcg_out_opc_reg(s, OPC_CZERO_NEZ, ret, val2, test_ne);
1389a18d783eSRichard Henderson        return;
1390a18d783eSRichard Henderson    }
1391a18d783eSRichard Henderson
1392a18d783eSRichard Henderson    if (val2 == 0) {
1393a18d783eSRichard Henderson        if (c_val1) {
1394a18d783eSRichard Henderson            tcg_out_movi(s, TCG_TYPE_REG, TCG_REG_TMP1, val1);
1395a18d783eSRichard Henderson            val1 = TCG_REG_TMP1;
1396a18d783eSRichard Henderson        }
1397a18d783eSRichard Henderson        tcg_out_opc_reg(s, OPC_CZERO_EQZ, ret, val1, test_ne);
1398a18d783eSRichard Henderson        return;
1399a18d783eSRichard Henderson    }
1400a18d783eSRichard Henderson
1401a18d783eSRichard Henderson    if (c_val2) {
1402a18d783eSRichard Henderson        if (c_val1) {
1403a18d783eSRichard Henderson            tcg_out_movi(s, TCG_TYPE_REG, TCG_REG_TMP1, val1 - val2);
1404a18d783eSRichard Henderson        } else {
1405a18d783eSRichard Henderson            tcg_out_opc_imm(s, OPC_ADDI, TCG_REG_TMP1, val1, -val2);
1406a18d783eSRichard Henderson        }
1407a18d783eSRichard Henderson        tcg_out_opc_reg(s, OPC_CZERO_EQZ, ret, TCG_REG_TMP1, test_ne);
1408a18d783eSRichard Henderson        tcg_out_opc_imm(s, OPC_ADDI, ret, ret, val2);
1409a18d783eSRichard Henderson        return;
1410a18d783eSRichard Henderson    }
1411a18d783eSRichard Henderson
1412a18d783eSRichard Henderson    if (c_val1) {
1413a18d783eSRichard Henderson        tcg_out_opc_imm(s, OPC_ADDI, TCG_REG_TMP1, val2, -val1);
1414a18d783eSRichard Henderson        tcg_out_opc_reg(s, OPC_CZERO_NEZ, ret, TCG_REG_TMP1, test_ne);
1415a18d783eSRichard Henderson        tcg_out_opc_imm(s, OPC_ADDI, ret, ret, val1);
1416a18d783eSRichard Henderson        return;
1417a18d783eSRichard Henderson    }
1418a18d783eSRichard Henderson
1419a18d783eSRichard Henderson    tcg_out_opc_reg(s, OPC_CZERO_NEZ, TCG_REG_TMP1, val2, test_ne);
1420a18d783eSRichard Henderson    tcg_out_opc_reg(s, OPC_CZERO_EQZ, TCG_REG_TMP0, val1, test_ne);
1421a18d783eSRichard Henderson    tcg_out_opc_reg(s, OPC_OR, ret, TCG_REG_TMP0, TCG_REG_TMP1);
1422a18d783eSRichard Henderson}
1423a18d783eSRichard Henderson
1424a18d783eSRichard Hendersonstatic void tcg_out_movcond_br1(TCGContext *s, TCGCond cond, TCGReg ret,
1425a18d783eSRichard Henderson                                TCGReg cmp1, TCGReg cmp2,
1426a18d783eSRichard Henderson                                int val, bool c_val)
1427a18d783eSRichard Henderson{
1428a18d783eSRichard Henderson    RISCVInsn op;
1429a18d783eSRichard Henderson    int disp = 8;
1430a18d783eSRichard Henderson
1431a18d783eSRichard Henderson    tcg_debug_assert((unsigned)cond < ARRAY_SIZE(tcg_brcond_to_riscv));
1432a18d783eSRichard Henderson    op = tcg_brcond_to_riscv[cond].op;
1433a18d783eSRichard Henderson    tcg_debug_assert(op != 0);
1434a18d783eSRichard Henderson
1435a18d783eSRichard Henderson    if (tcg_brcond_to_riscv[cond].swap) {
1436a18d783eSRichard Henderson        tcg_out_opc_branch(s, op, cmp2, cmp1, disp);
1437a18d783eSRichard Henderson    } else {
1438a18d783eSRichard Henderson        tcg_out_opc_branch(s, op, cmp1, cmp2, disp);
1439a18d783eSRichard Henderson    }
1440a18d783eSRichard Henderson    if (c_val) {
1441a18d783eSRichard Henderson        tcg_out_opc_imm(s, OPC_ADDI, ret, TCG_REG_ZERO, val);
1442a18d783eSRichard Henderson    } else {
1443a18d783eSRichard Henderson        tcg_out_opc_imm(s, OPC_ADDI, ret, val, 0);
1444a18d783eSRichard Henderson    }
1445a18d783eSRichard Henderson}
1446a18d783eSRichard Henderson
1447a18d783eSRichard Hendersonstatic void tcg_out_movcond_br2(TCGContext *s, TCGCond cond, TCGReg ret,
1448a18d783eSRichard Henderson                                TCGReg cmp1, TCGReg cmp2,
1449a18d783eSRichard Henderson                                int val1, bool c_val1,
1450a18d783eSRichard Henderson                                int val2, bool c_val2)
1451a18d783eSRichard Henderson{
1452a18d783eSRichard Henderson    TCGReg tmp;
1453a18d783eSRichard Henderson
1454a18d783eSRichard Henderson    /* TCG optimizer reorders to prefer ret matching val2. */
1455a18d783eSRichard Henderson    if (!c_val2 && ret == val2) {
1456a18d783eSRichard Henderson        cond = tcg_invert_cond(cond);
1457a18d783eSRichard Henderson        tcg_out_movcond_br1(s, cond, ret, cmp1, cmp2, val1, c_val1);
1458a18d783eSRichard Henderson        return;
1459a18d783eSRichard Henderson    }
1460a18d783eSRichard Henderson
1461a18d783eSRichard Henderson    if (!c_val1 && ret == val1) {
1462a18d783eSRichard Henderson        tcg_out_movcond_br1(s, cond, ret, cmp1, cmp2, val2, c_val2);
1463a18d783eSRichard Henderson        return;
1464a18d783eSRichard Henderson    }
1465a18d783eSRichard Henderson
1466a18d783eSRichard Henderson    tmp = (ret == cmp1 || ret == cmp2 ? TCG_REG_TMP1 : ret);
1467a18d783eSRichard Henderson    if (c_val1) {
1468a18d783eSRichard Henderson        tcg_out_movi(s, TCG_TYPE_REG, tmp, val1);
1469a18d783eSRichard Henderson    } else {
1470a18d783eSRichard Henderson        tcg_out_mov(s, TCG_TYPE_REG, tmp, val1);
1471a18d783eSRichard Henderson    }
1472a18d783eSRichard Henderson    tcg_out_movcond_br1(s, cond, tmp, cmp1, cmp2, val2, c_val2);
1473a18d783eSRichard Henderson    tcg_out_mov(s, TCG_TYPE_REG, ret, tmp);
1474a18d783eSRichard Henderson}
1475a18d783eSRichard Henderson
1476a18d783eSRichard Hendersonstatic void tcg_out_movcond(TCGContext *s, TCGCond cond, TCGReg ret,
1477a18d783eSRichard Henderson                            TCGReg cmp1, int cmp2, bool c_cmp2,
1478a18d783eSRichard Henderson                            TCGReg val1, bool c_val1,
1479a18d783eSRichard Henderson                            TCGReg val2, bool c_val2)
1480a18d783eSRichard Henderson{
1481a18d783eSRichard Henderson    int tmpflags;
1482a18d783eSRichard Henderson    TCGReg t;
1483a18d783eSRichard Henderson
1484b86c6ba6SRichard Henderson    if (!(cpuinfo & CPUINFO_ZICOND) && (!c_cmp2 || cmp2 == 0)) {
1485a18d783eSRichard Henderson        tcg_out_movcond_br2(s, cond, ret, cmp1, cmp2,
1486a18d783eSRichard Henderson                            val1, c_val1, val2, c_val2);
1487a18d783eSRichard Henderson        return;
1488a18d783eSRichard Henderson    }
1489a18d783eSRichard Henderson
1490a18d783eSRichard Henderson    tmpflags = tcg_out_setcond_int(s, cond, TCG_REG_TMP0, cmp1, cmp2, c_cmp2);
1491a18d783eSRichard Henderson    t = tmpflags & ~SETCOND_FLAGS;
1492a18d783eSRichard Henderson
1493b86c6ba6SRichard Henderson    if (cpuinfo & CPUINFO_ZICOND) {
1494a18d783eSRichard Henderson        if (tmpflags & SETCOND_INV) {
1495a18d783eSRichard Henderson            tcg_out_movcond_zicond(s, ret, t, val2, c_val2, val1, c_val1);
1496a18d783eSRichard Henderson        } else {
1497a18d783eSRichard Henderson            tcg_out_movcond_zicond(s, ret, t, val1, c_val1, val2, c_val2);
1498a18d783eSRichard Henderson        }
1499a18d783eSRichard Henderson    } else {
1500a18d783eSRichard Henderson        cond = tmpflags & SETCOND_INV ? TCG_COND_EQ : TCG_COND_NE;
1501a18d783eSRichard Henderson        tcg_out_movcond_br2(s, cond, ret, t, TCG_REG_ZERO,
1502a18d783eSRichard Henderson                            val1, c_val1, val2, c_val2);
1503a18d783eSRichard Henderson    }
1504a18d783eSRichard Henderson}
1505a18d783eSRichard Henderson
1506a30498fcSRichard Hendersonstatic void tcg_out_cltz(TCGContext *s, TCGType type, RISCVInsn insn,
1507a30498fcSRichard Henderson                         TCGReg ret, TCGReg src1, int src2, bool c_src2)
1508a30498fcSRichard Henderson{
1509a30498fcSRichard Henderson    tcg_out_opc_imm(s, insn, ret, src1, 0);
1510a30498fcSRichard Henderson
1511a30498fcSRichard Henderson    if (!c_src2 || src2 != (type == TCG_TYPE_I32 ? 32 : 64)) {
1512a30498fcSRichard Henderson        /*
1513a30498fcSRichard Henderson         * The requested zero result does not match the insn, so adjust.
1514a30498fcSRichard Henderson         * Note that constraints put 'ret' in a new register, so the
1515a30498fcSRichard Henderson         * computation above did not clobber either 'src1' or 'src2'.
1516a30498fcSRichard Henderson         */
1517a30498fcSRichard Henderson        tcg_out_movcond(s, TCG_COND_EQ, ret, src1, 0, true,
1518a30498fcSRichard Henderson                        src2, c_src2, ret, false);
1519a30498fcSRichard Henderson    }
1520a30498fcSRichard Henderson}
1521a30498fcSRichard Henderson
1522a31768c0STANG Tianchengstatic void tcg_out_cmpsel(TCGContext *s, TCGType type, unsigned vece,
1523a31768c0STANG Tiancheng                           TCGCond cond, TCGReg ret,
1524a31768c0STANG Tiancheng                           TCGReg cmp1, TCGReg cmp2, bool c_cmp2,
1525a31768c0STANG Tiancheng                           TCGReg val1, bool c_val1,
1526a31768c0STANG Tiancheng                           TCGReg val2, bool c_val2)
1527a31768c0STANG Tiancheng{
1528a31768c0STANG Tiancheng    set_vtype_len_sew(s, type, vece);
1529a31768c0STANG Tiancheng
1530a31768c0STANG Tiancheng    /* Use only vmerge_vim if possible, by inverting the test. */
1531a31768c0STANG Tiancheng    if (c_val2 && !c_val1) {
1532a31768c0STANG Tiancheng        TCGArg temp = val1;
1533a31768c0STANG Tiancheng        cond = tcg_invert_cond(cond);
1534a31768c0STANG Tiancheng        val1 = val2;
1535a31768c0STANG Tiancheng        val2 = temp;
1536a31768c0STANG Tiancheng        c_val1 = true;
1537a31768c0STANG Tiancheng        c_val2 = false;
1538a31768c0STANG Tiancheng    }
1539a31768c0STANG Tiancheng
1540a31768c0STANG Tiancheng    /* Perform the comparison into V0 mask. */
1541a31768c0STANG Tiancheng    if (c_cmp2) {
1542a31768c0STANG Tiancheng        tcg_out_opc_vi(s, tcg_cmpcond_to_rvv_vi[cond].op, TCG_REG_V0, cmp1,
1543a31768c0STANG Tiancheng                       cmp2 - tcg_cmpcond_to_rvv_vi[cond].adjust);
1544a31768c0STANG Tiancheng    } else if (tcg_cmpcond_to_rvv_vv[cond].swap) {
1545a31768c0STANG Tiancheng        tcg_out_opc_vv(s, tcg_cmpcond_to_rvv_vv[cond].op,
1546a31768c0STANG Tiancheng                       TCG_REG_V0, cmp2, cmp1);
1547a31768c0STANG Tiancheng    } else {
1548a31768c0STANG Tiancheng        tcg_out_opc_vv(s, tcg_cmpcond_to_rvv_vv[cond].op,
1549a31768c0STANG Tiancheng                       TCG_REG_V0, cmp1, cmp2);
1550a31768c0STANG Tiancheng    }
1551a31768c0STANG Tiancheng    if (c_val1) {
1552a31768c0STANG Tiancheng        if (c_val2) {
1553a31768c0STANG Tiancheng            tcg_out_opc_vi(s, OPC_VMV_V_I, ret, 0, val2);
1554a31768c0STANG Tiancheng            val2 = ret;
1555a31768c0STANG Tiancheng        }
1556a31768c0STANG Tiancheng        /* vd[i] == v0.mask[i] ? imm : vs2[i] */
1557a31768c0STANG Tiancheng        tcg_out_opc_vim_mask(s, OPC_VMERGE_VIM, ret, val2, val1);
1558a31768c0STANG Tiancheng    } else {
1559a31768c0STANG Tiancheng        /* vd[i] == v0.mask[i] ? vs1[i] : vs2[i] */
1560a31768c0STANG Tiancheng        tcg_out_opc_vvm_mask(s, OPC_VMERGE_VVM, ret, val2, val1);
1561a31768c0STANG Tiancheng    }
1562a31768c0STANG Tiancheng}
1563a31768c0STANG Tiancheng
1564cbde22f1STANG Tianchengstatic void tcg_out_vshifti(TCGContext *s, RISCVInsn opc_vi, RISCVInsn opc_vx,
1565cbde22f1STANG Tiancheng                             TCGReg dst, TCGReg src, unsigned imm)
1566cbde22f1STANG Tiancheng{
1567cbde22f1STANG Tiancheng    if (imm < 32) {
1568cbde22f1STANG Tiancheng        tcg_out_opc_vi(s, opc_vi, dst, src, imm);
1569cbde22f1STANG Tiancheng    } else {
1570cbde22f1STANG Tiancheng        tcg_out_movi(s, TCG_TYPE_I32, TCG_REG_TMP0, imm);
1571cbde22f1STANG Tiancheng        tcg_out_opc_vx(s, opc_vx, dst, src, TCG_REG_TMP0);
1572cbde22f1STANG Tiancheng    }
1573cbde22f1STANG Tiancheng}
1574cbde22f1STANG Tiancheng
1575f63e7089SHuang Shiyuanstatic void init_setting_vtype(TCGContext *s)
1576f63e7089SHuang Shiyuan{
1577f63e7089SHuang Shiyuan    s->riscv_cur_type = TCG_TYPE_COUNT;
1578f63e7089SHuang Shiyuan}
1579f63e7089SHuang Shiyuan
15802be7d76bSRichard Hendersonstatic void tcg_out_call_int(TCGContext *s, const tcg_insn_unit *arg, bool tail)
1581139c1837SPaolo Bonzini{
1582139c1837SPaolo Bonzini    TCGReg link = tail ? TCG_REG_ZERO : TCG_REG_RA;
1583139c1837SPaolo Bonzini    ptrdiff_t offset = tcg_pcrel_diff(s, arg);
1584139c1837SPaolo Bonzini    int ret;
1585139c1837SPaolo Bonzini
1586f63e7089SHuang Shiyuan    init_setting_vtype(s);
1587f63e7089SHuang Shiyuan
1588844d0442SRichard Henderson    tcg_debug_assert((offset & 1) == 0);
1589844d0442SRichard Henderson    if (offset == sextreg(offset, 0, 20)) {
1590139c1837SPaolo Bonzini        /* short jump: -2097150 to 2097152 */
1591139c1837SPaolo Bonzini        tcg_out_opc_jump(s, OPC_JAL, link, offset);
1592aeb6326eSRichard Henderson    } else if (offset == (int32_t)offset) {
1593139c1837SPaolo Bonzini        /* long jump: -2147483646 to 2147483648 */
1594139c1837SPaolo Bonzini        tcg_out_opc_upper(s, OPC_AUIPC, TCG_REG_TMP0, 0);
1595139c1837SPaolo Bonzini        tcg_out_opc_imm(s, OPC_JALR, link, TCG_REG_TMP0, 0);
1596844d0442SRichard Henderson        ret = reloc_call(s->code_ptr - 2, arg);
1597139c1837SPaolo Bonzini        tcg_debug_assert(ret == true);
1598aeb6326eSRichard Henderson    } else {
1599139c1837SPaolo Bonzini        /* far jump: 64-bit */
1600139c1837SPaolo Bonzini        tcg_target_long imm = sextreg((tcg_target_long)arg, 0, 12);
1601139c1837SPaolo Bonzini        tcg_target_long base = (tcg_target_long)arg - imm;
1602139c1837SPaolo Bonzini        tcg_out_movi(s, TCG_TYPE_PTR, TCG_REG_TMP0, base);
1603139c1837SPaolo Bonzini        tcg_out_opc_imm(s, OPC_JALR, link, TCG_REG_TMP0, imm);
1604139c1837SPaolo Bonzini    }
1605139c1837SPaolo Bonzini}
1606139c1837SPaolo Bonzini
1607cee44b03SRichard Hendersonstatic void tcg_out_call(TCGContext *s, const tcg_insn_unit *arg,
1608cee44b03SRichard Henderson                         const TCGHelperInfo *info)
1609139c1837SPaolo Bonzini{
1610139c1837SPaolo Bonzini    tcg_out_call_int(s, arg, false);
1611139c1837SPaolo Bonzini}
1612139c1837SPaolo Bonzini
1613139c1837SPaolo Bonzinistatic void tcg_out_mb(TCGContext *s, TCGArg a0)
1614139c1837SPaolo Bonzini{
1615139c1837SPaolo Bonzini    tcg_insn_unit insn = OPC_FENCE;
1616139c1837SPaolo Bonzini
1617139c1837SPaolo Bonzini    if (a0 & TCG_MO_LD_LD) {
1618139c1837SPaolo Bonzini        insn |= 0x02200000;
1619139c1837SPaolo Bonzini    }
1620139c1837SPaolo Bonzini    if (a0 & TCG_MO_ST_LD) {
1621139c1837SPaolo Bonzini        insn |= 0x01200000;
1622139c1837SPaolo Bonzini    }
1623139c1837SPaolo Bonzini    if (a0 & TCG_MO_LD_ST) {
1624139c1837SPaolo Bonzini        insn |= 0x02100000;
1625139c1837SPaolo Bonzini    }
1626139c1837SPaolo Bonzini    if (a0 & TCG_MO_ST_ST) {
1627139c1837SPaolo Bonzini        insn |= 0x02200000;
1628139c1837SPaolo Bonzini    }
1629139c1837SPaolo Bonzini    tcg_out32(s, insn);
1630139c1837SPaolo Bonzini}
1631139c1837SPaolo Bonzini
1632139c1837SPaolo Bonzini/*
1633139c1837SPaolo Bonzini * Load/store and TLB
1634139c1837SPaolo Bonzini */
1635139c1837SPaolo Bonzini
1636793f7381SRichard Hendersonstatic void tcg_out_goto(TCGContext *s, const tcg_insn_unit *target)
1637844d0442SRichard Henderson{
1638844d0442SRichard Henderson    tcg_out_opc_jump(s, OPC_JAL, TCG_REG_ZERO, 0);
1639844d0442SRichard Henderson    bool ok = reloc_jimm20(s->code_ptr - 1, target);
1640844d0442SRichard Henderson    tcg_debug_assert(ok);
1641844d0442SRichard Henderson}
1642844d0442SRichard Henderson
16437b880107SRichard Hendersonbool tcg_target_has_memory_bswap(MemOp memop)
16447b880107SRichard Henderson{
16457b880107SRichard Henderson    return false;
16467b880107SRichard Henderson}
16477b880107SRichard Henderson
164861b6daafSRichard Henderson/* We have three temps, we might as well expose them. */
164961b6daafSRichard Hendersonstatic const TCGLdstHelperParam ldst_helper_param = {
165061b6daafSRichard Henderson    .ntmp = 3, .tmp = { TCG_REG_TMP0, TCG_REG_TMP1, TCG_REG_TMP2 }
165161b6daafSRichard Henderson};
165261b6daafSRichard Henderson
1653139c1837SPaolo Bonzinistatic bool tcg_out_qemu_ld_slow_path(TCGContext *s, TCGLabelQemuLdst *l)
1654139c1837SPaolo Bonzini{
165561b6daafSRichard Henderson    MemOp opc = get_memop(l->oi);
1656139c1837SPaolo Bonzini
1657139c1837SPaolo Bonzini    /* resolve label address */
1658793f7381SRichard Henderson    if (!reloc_sbimm12(l->label_ptr[0], tcg_splitwx_to_rx(s->code_ptr))) {
1659139c1837SPaolo Bonzini        return false;
1660139c1837SPaolo Bonzini    }
1661139c1837SPaolo Bonzini
1662139c1837SPaolo Bonzini    /* call load helper */
166361b6daafSRichard Henderson    tcg_out_ld_helper_args(s, l, &ldst_helper_param);
1664cee44b03SRichard Henderson    tcg_out_call_int(s, qemu_ld_helpers[opc & MO_SSIZE], false);
166561b6daafSRichard Henderson    tcg_out_ld_helper_ret(s, l, true, &ldst_helper_param);
1666139c1837SPaolo Bonzini
1667139c1837SPaolo Bonzini    tcg_out_goto(s, l->raddr);
1668139c1837SPaolo Bonzini    return true;
1669139c1837SPaolo Bonzini}
1670139c1837SPaolo Bonzini
1671139c1837SPaolo Bonzinistatic bool tcg_out_qemu_st_slow_path(TCGContext *s, TCGLabelQemuLdst *l)
1672139c1837SPaolo Bonzini{
167361b6daafSRichard Henderson    MemOp opc = get_memop(l->oi);
1674139c1837SPaolo Bonzini
1675139c1837SPaolo Bonzini    /* resolve label address */
1676793f7381SRichard Henderson    if (!reloc_sbimm12(l->label_ptr[0], tcg_splitwx_to_rx(s->code_ptr))) {
1677139c1837SPaolo Bonzini        return false;
1678139c1837SPaolo Bonzini    }
1679139c1837SPaolo Bonzini
1680139c1837SPaolo Bonzini    /* call store helper */
168161b6daafSRichard Henderson    tcg_out_st_helper_args(s, l, &ldst_helper_param);
1682cee44b03SRichard Henderson    tcg_out_call_int(s, qemu_st_helpers[opc & MO_SIZE], false);
1683139c1837SPaolo Bonzini
1684139c1837SPaolo Bonzini    tcg_out_goto(s, l->raddr);
1685139c1837SPaolo Bonzini    return true;
1686139c1837SPaolo Bonzini}
1687139c1837SPaolo Bonzini
1688d0a9bb5eSRichard Henderson/* We expect to use a 12-bit negative offset from ENV.  */
1689d0a9bb5eSRichard Henderson#define MIN_TLB_MASK_TABLE_OFS  -(1 << 11)
1690d0a9bb5eSRichard Henderson
1691001dddfeSRichard Henderson/*
16927893e42dSPhilippe Mathieu-Daudé * For system-mode, perform the TLB load and compare.
16937893e42dSPhilippe Mathieu-Daudé * For user-mode, perform any required alignment tests.
1694001dddfeSRichard Henderson * In both cases, return a TCGLabelQemuLdst structure if the slow path
1695001dddfeSRichard Henderson * is required and fill in @h with the host address for the fast path.
1696001dddfeSRichard Henderson */
1697001dddfeSRichard Hendersonstatic TCGLabelQemuLdst *prepare_host_addr(TCGContext *s, TCGReg *pbase,
1698001dddfeSRichard Henderson                                           TCGReg addr_reg, MemOpIdx oi,
1699001dddfeSRichard Henderson                                           bool is_ld)
1700001dddfeSRichard Henderson{
17018aefe1fbSRichard Henderson    TCGType addr_type = s->addr_type;
1702001dddfeSRichard Henderson    TCGLabelQemuLdst *ldst = NULL;
1703001dddfeSRichard Henderson    MemOp opc = get_memop(oi);
170437e523f0SRichard Henderson    TCGAtomAlign aa;
170537e523f0SRichard Henderson    unsigned a_mask;
170637e523f0SRichard Henderson
170737e523f0SRichard Henderson    aa = atom_and_align_for_opc(s, opc, MO_ATOM_IFALIGN, false);
170837e523f0SRichard Henderson    a_mask = (1u << aa.align) - 1;
1709001dddfeSRichard Henderson
17104944d359SRichard Henderson    if (tcg_use_softmmu) {
1711001dddfeSRichard Henderson        unsigned s_bits = opc & MO_SIZE;
1712933b331bSRichard Henderson        unsigned s_mask = (1u << s_bits) - 1;
1713001dddfeSRichard Henderson        int mem_index = get_mmuidx(oi);
1714d0a9bb5eSRichard Henderson        int fast_ofs = tlb_mask_table_ofs(s, mem_index);
1715001dddfeSRichard Henderson        int mask_ofs = fast_ofs + offsetof(CPUTLBDescFast, mask);
1716001dddfeSRichard Henderson        int table_ofs = fast_ofs + offsetof(CPUTLBDescFast, table);
1717933b331bSRichard Henderson        int compare_mask;
1718933b331bSRichard Henderson        TCGReg addr_adj;
1719001dddfeSRichard Henderson
1720001dddfeSRichard Henderson        ldst = new_ldst_label(s);
1721001dddfeSRichard Henderson        ldst->is_ld = is_ld;
1722001dddfeSRichard Henderson        ldst->oi = oi;
1723001dddfeSRichard Henderson        ldst->addrlo_reg = addr_reg;
1724001dddfeSRichard Henderson
1725f63e7089SHuang Shiyuan        init_setting_vtype(s);
1726f63e7089SHuang Shiyuan
1727933b331bSRichard Henderson        tcg_out_ld(s, TCG_TYPE_PTR, TCG_REG_TMP0, TCG_AREG0, mask_ofs);
1728933b331bSRichard Henderson        tcg_out_ld(s, TCG_TYPE_PTR, TCG_REG_TMP1, TCG_AREG0, table_ofs);
1729001dddfeSRichard Henderson
1730001dddfeSRichard Henderson        tcg_out_opc_imm(s, OPC_SRLI, TCG_REG_TMP2, addr_reg,
1731aece72b7SRichard Henderson                        s->page_bits - CPU_TLB_ENTRY_BITS);
1732001dddfeSRichard Henderson        tcg_out_opc_reg(s, OPC_AND, TCG_REG_TMP2, TCG_REG_TMP2, TCG_REG_TMP0);
1733001dddfeSRichard Henderson        tcg_out_opc_reg(s, OPC_ADD, TCG_REG_TMP2, TCG_REG_TMP2, TCG_REG_TMP1);
1734001dddfeSRichard Henderson
1735933b331bSRichard Henderson        /*
17364944d359SRichard Henderson         * For aligned accesses, we check the first byte and include the
17374944d359SRichard Henderson         * alignment bits within the address.  For unaligned access, we
17384944d359SRichard Henderson         * check that we don't cross pages using the address of the last
17394944d359SRichard Henderson         * byte of the access.
1740933b331bSRichard Henderson         */
1741933b331bSRichard Henderson        addr_adj = addr_reg;
174237e523f0SRichard Henderson        if (a_mask < s_mask) {
1743933b331bSRichard Henderson            addr_adj = TCG_REG_TMP0;
17448aefe1fbSRichard Henderson            tcg_out_opc_imm(s, addr_type == TCG_TYPE_I32 ? OPC_ADDIW : OPC_ADDI,
1745933b331bSRichard Henderson                            addr_adj, addr_reg, s_mask - a_mask);
1746933b331bSRichard Henderson        }
1747aece72b7SRichard Henderson        compare_mask = s->page_mask | a_mask;
1748933b331bSRichard Henderson        if (compare_mask == sextreg(compare_mask, 0, 12)) {
1749933b331bSRichard Henderson            tcg_out_opc_imm(s, OPC_ANDI, TCG_REG_TMP1, addr_adj, compare_mask);
1750933b331bSRichard Henderson        } else {
17518aefe1fbSRichard Henderson            tcg_out_movi(s, addr_type, TCG_REG_TMP1, compare_mask);
1752933b331bSRichard Henderson            tcg_out_opc_reg(s, OPC_AND, TCG_REG_TMP1, TCG_REG_TMP1, addr_adj);
1753933b331bSRichard Henderson        }
1754933b331bSRichard Henderson
1755001dddfeSRichard Henderson        /* Load the tlb comparator and the addend.  */
1756238f4380SRichard Henderson        QEMU_BUILD_BUG_ON(HOST_BIG_ENDIAN);
17578aefe1fbSRichard Henderson        tcg_out_ld(s, addr_type, TCG_REG_TMP0, TCG_REG_TMP2,
1758001dddfeSRichard Henderson                   is_ld ? offsetof(CPUTLBEntry, addr_read)
1759001dddfeSRichard Henderson                         : offsetof(CPUTLBEntry, addr_write));
1760001dddfeSRichard Henderson        tcg_out_ld(s, TCG_TYPE_PTR, TCG_REG_TMP2, TCG_REG_TMP2,
1761001dddfeSRichard Henderson                   offsetof(CPUTLBEntry, addend));
1762001dddfeSRichard Henderson
1763001dddfeSRichard Henderson        /* Compare masked address with the TLB entry. */
1764001dddfeSRichard Henderson        ldst->label_ptr[0] = s->code_ptr;
1765001dddfeSRichard Henderson        tcg_out_opc_branch(s, OPC_BNE, TCG_REG_TMP0, TCG_REG_TMP1, 0);
1766001dddfeSRichard Henderson
1767001dddfeSRichard Henderson        /* TLB Hit - translate address using addend.  */
17688aefe1fbSRichard Henderson        if (addr_type != TCG_TYPE_I32) {
1769eda15159SRichard Henderson            tcg_out_opc_reg(s, OPC_ADD, TCG_REG_TMP0, addr_reg, TCG_REG_TMP2);
1770b86c6ba6SRichard Henderson        } else if (cpuinfo & CPUINFO_ZBA) {
17714944d359SRichard Henderson            tcg_out_opc_reg(s, OPC_ADD_UW, TCG_REG_TMP0,
17724944d359SRichard Henderson                            addr_reg, TCG_REG_TMP2);
1773eda15159SRichard Henderson        } else {
1774eda15159SRichard Henderson            tcg_out_ext32u(s, TCG_REG_TMP0, addr_reg);
17754944d359SRichard Henderson            tcg_out_opc_reg(s, OPC_ADD, TCG_REG_TMP0,
17764944d359SRichard Henderson                            TCG_REG_TMP0, TCG_REG_TMP2);
1777001dddfeSRichard Henderson        }
1778001dddfeSRichard Henderson        *pbase = TCG_REG_TMP0;
17794944d359SRichard Henderson    } else {
1780eda15159SRichard Henderson        TCGReg base;
1781eda15159SRichard Henderson
1782001dddfeSRichard Henderson        if (a_mask) {
1783001dddfeSRichard Henderson            ldst = new_ldst_label(s);
1784001dddfeSRichard Henderson            ldst->is_ld = is_ld;
1785001dddfeSRichard Henderson            ldst->oi = oi;
1786001dddfeSRichard Henderson            ldst->addrlo_reg = addr_reg;
1787001dddfeSRichard Henderson
1788f63e7089SHuang Shiyuan            init_setting_vtype(s);
1789f63e7089SHuang Shiyuan
179037e523f0SRichard Henderson            /* We are expecting alignment max 7, so we can always use andi. */
179137e523f0SRichard Henderson            tcg_debug_assert(a_mask == sextreg(a_mask, 0, 12));
1792001dddfeSRichard Henderson            tcg_out_opc_imm(s, OPC_ANDI, TCG_REG_TMP1, addr_reg, a_mask);
1793001dddfeSRichard Henderson
1794001dddfeSRichard Henderson            ldst->label_ptr[0] = s->code_ptr;
1795001dddfeSRichard Henderson            tcg_out_opc_branch(s, OPC_BNE, TCG_REG_TMP1, TCG_REG_ZERO, 0);
1796001dddfeSRichard Henderson        }
1797001dddfeSRichard Henderson
1798001dddfeSRichard Henderson        if (guest_base != 0) {
1799001dddfeSRichard Henderson            base = TCG_REG_TMP0;
18008aefe1fbSRichard Henderson            if (addr_type != TCG_TYPE_I32) {
18014944d359SRichard Henderson                tcg_out_opc_reg(s, OPC_ADD, base, addr_reg,
18024944d359SRichard Henderson                                TCG_GUEST_BASE_REG);
1803b86c6ba6SRichard Henderson            } else if (cpuinfo & CPUINFO_ZBA) {
18044944d359SRichard Henderson                tcg_out_opc_reg(s, OPC_ADD_UW, base, addr_reg,
18054944d359SRichard Henderson                                TCG_GUEST_BASE_REG);
1806eda15159SRichard Henderson            } else {
1807eda15159SRichard Henderson                tcg_out_ext32u(s, base, addr_reg);
1808eda15159SRichard Henderson                tcg_out_opc_reg(s, OPC_ADD, base, base, TCG_GUEST_BASE_REG);
1809eda15159SRichard Henderson            }
18108aefe1fbSRichard Henderson        } else if (addr_type != TCG_TYPE_I32) {
1811eda15159SRichard Henderson            base = addr_reg;
1812eda15159SRichard Henderson        } else {
1813eda15159SRichard Henderson            base = TCG_REG_TMP0;
1814eda15159SRichard Henderson            tcg_out_ext32u(s, base, addr_reg);
1815001dddfeSRichard Henderson        }
1816001dddfeSRichard Henderson        *pbase = base;
18174944d359SRichard Henderson    }
1818001dddfeSRichard Henderson
1819001dddfeSRichard Henderson    return ldst;
1820001dddfeSRichard Henderson}
1821001dddfeSRichard Henderson
1822aeb6326eSRichard Hendersonstatic void tcg_out_qemu_ld_direct(TCGContext *s, TCGReg val,
1823f7041977SRichard Henderson                                   TCGReg base, MemOp opc, TCGType type)
1824139c1837SPaolo Bonzini{
1825c86bd2dcSRichard Henderson    /* Byte swapping is left to middle-end expansion. */
1826c86bd2dcSRichard Henderson    tcg_debug_assert((opc & MO_BSWAP) == 0);
1827139c1837SPaolo Bonzini
1828139c1837SPaolo Bonzini    switch (opc & (MO_SSIZE)) {
1829139c1837SPaolo Bonzini    case MO_UB:
1830aeb6326eSRichard Henderson        tcg_out_opc_imm(s, OPC_LBU, val, base, 0);
1831139c1837SPaolo Bonzini        break;
1832139c1837SPaolo Bonzini    case MO_SB:
1833aeb6326eSRichard Henderson        tcg_out_opc_imm(s, OPC_LB, val, base, 0);
1834139c1837SPaolo Bonzini        break;
1835139c1837SPaolo Bonzini    case MO_UW:
1836aeb6326eSRichard Henderson        tcg_out_opc_imm(s, OPC_LHU, val, base, 0);
1837139c1837SPaolo Bonzini        break;
1838139c1837SPaolo Bonzini    case MO_SW:
1839aeb6326eSRichard Henderson        tcg_out_opc_imm(s, OPC_LH, val, base, 0);
1840139c1837SPaolo Bonzini        break;
1841139c1837SPaolo Bonzini    case MO_UL:
1842f7041977SRichard Henderson        if (type == TCG_TYPE_I64) {
1843aeb6326eSRichard Henderson            tcg_out_opc_imm(s, OPC_LWU, val, base, 0);
1844139c1837SPaolo Bonzini            break;
1845139c1837SPaolo Bonzini        }
1846139c1837SPaolo Bonzini        /* FALLTHRU */
1847139c1837SPaolo Bonzini    case MO_SL:
1848aeb6326eSRichard Henderson        tcg_out_opc_imm(s, OPC_LW, val, base, 0);
1849139c1837SPaolo Bonzini        break;
1850fc313c64SFrédéric Pétrot    case MO_UQ:
1851aeb6326eSRichard Henderson        tcg_out_opc_imm(s, OPC_LD, val, base, 0);
1852139c1837SPaolo Bonzini        break;
1853139c1837SPaolo Bonzini    default:
1854139c1837SPaolo Bonzini        g_assert_not_reached();
1855139c1837SPaolo Bonzini    }
1856139c1837SPaolo Bonzini}
1857139c1837SPaolo Bonzini
1858f7041977SRichard Hendersonstatic void tcg_out_qemu_ld(TCGContext *s, TCGReg data_reg, TCGReg addr_reg,
1859f7041977SRichard Henderson                            MemOpIdx oi, TCGType data_type)
1860139c1837SPaolo Bonzini{
1861001dddfeSRichard Henderson    TCGLabelQemuLdst *ldst;
18622e3a933aSRichard Henderson    TCGReg base;
1863139c1837SPaolo Bonzini
1864001dddfeSRichard Henderson    ldst = prepare_host_addr(s, &base, addr_reg, oi, true);
1865001dddfeSRichard Henderson    tcg_out_qemu_ld_direct(s, data_reg, base, get_memop(oi), data_type);
1866f7041977SRichard Henderson
1867001dddfeSRichard Henderson    if (ldst) {
1868001dddfeSRichard Henderson        ldst->type = data_type;
1869001dddfeSRichard Henderson        ldst->datalo_reg = data_reg;
1870001dddfeSRichard Henderson        ldst->raddr = tcg_splitwx_to_rx(s->code_ptr);
1871a3fb7c99SRichard Henderson    }
1872139c1837SPaolo Bonzini}
1873139c1837SPaolo Bonzini
1874aeb6326eSRichard Hendersonstatic void tcg_out_qemu_st_direct(TCGContext *s, TCGReg val,
1875139c1837SPaolo Bonzini                                   TCGReg base, MemOp opc)
1876139c1837SPaolo Bonzini{
1877c86bd2dcSRichard Henderson    /* Byte swapping is left to middle-end expansion. */
1878c86bd2dcSRichard Henderson    tcg_debug_assert((opc & MO_BSWAP) == 0);
1879139c1837SPaolo Bonzini
1880139c1837SPaolo Bonzini    switch (opc & (MO_SSIZE)) {
1881139c1837SPaolo Bonzini    case MO_8:
1882aeb6326eSRichard Henderson        tcg_out_opc_store(s, OPC_SB, base, val, 0);
1883139c1837SPaolo Bonzini        break;
1884139c1837SPaolo Bonzini    case MO_16:
1885aeb6326eSRichard Henderson        tcg_out_opc_store(s, OPC_SH, base, val, 0);
1886139c1837SPaolo Bonzini        break;
1887139c1837SPaolo Bonzini    case MO_32:
1888aeb6326eSRichard Henderson        tcg_out_opc_store(s, OPC_SW, base, val, 0);
1889139c1837SPaolo Bonzini        break;
1890139c1837SPaolo Bonzini    case MO_64:
1891aeb6326eSRichard Henderson        tcg_out_opc_store(s, OPC_SD, base, val, 0);
1892139c1837SPaolo Bonzini        break;
1893139c1837SPaolo Bonzini    default:
1894139c1837SPaolo Bonzini        g_assert_not_reached();
1895139c1837SPaolo Bonzini    }
1896139c1837SPaolo Bonzini}
1897139c1837SPaolo Bonzini
1898f7041977SRichard Hendersonstatic void tcg_out_qemu_st(TCGContext *s, TCGReg data_reg, TCGReg addr_reg,
1899f7041977SRichard Henderson                            MemOpIdx oi, TCGType data_type)
1900139c1837SPaolo Bonzini{
1901001dddfeSRichard Henderson    TCGLabelQemuLdst *ldst;
19022e3a933aSRichard Henderson    TCGReg base;
1903139c1837SPaolo Bonzini
1904001dddfeSRichard Henderson    ldst = prepare_host_addr(s, &base, addr_reg, oi, false);
1905001dddfeSRichard Henderson    tcg_out_qemu_st_direct(s, data_reg, base, get_memop(oi));
1906f7041977SRichard Henderson
1907001dddfeSRichard Henderson    if (ldst) {
1908001dddfeSRichard Henderson        ldst->type = data_type;
1909001dddfeSRichard Henderson        ldst->datalo_reg = data_reg;
1910001dddfeSRichard Henderson        ldst->raddr = tcg_splitwx_to_rx(s->code_ptr);
1911a3fb7c99SRichard Henderson    }
1912139c1837SPaolo Bonzini}
1913139c1837SPaolo Bonzini
1914793f7381SRichard Hendersonstatic const tcg_insn_unit *tb_ret_addr;
1915139c1837SPaolo Bonzini
1916b55a8d9dSRichard Hendersonstatic void tcg_out_exit_tb(TCGContext *s, uintptr_t a0)
1917b55a8d9dSRichard Henderson{
1918b55a8d9dSRichard Henderson    /* Reuse the zeroing that exists for goto_ptr.  */
1919b55a8d9dSRichard Henderson    if (a0 == 0) {
1920b55a8d9dSRichard Henderson        tcg_out_call_int(s, tcg_code_gen_epilogue, true);
1921b55a8d9dSRichard Henderson    } else {
1922b55a8d9dSRichard Henderson        tcg_out_movi(s, TCG_TYPE_PTR, TCG_REG_A0, a0);
1923b55a8d9dSRichard Henderson        tcg_out_call_int(s, tb_ret_addr, true);
1924b55a8d9dSRichard Henderson    }
1925b55a8d9dSRichard Henderson}
1926b55a8d9dSRichard Henderson
1927cf7d6b8eSRichard Hendersonstatic void tcg_out_goto_tb(TCGContext *s, int which)
1928cf7d6b8eSRichard Henderson{
1929493c9b19SRichard Henderson    /* Direct branch will be patched by tb_target_set_jmp_target. */
1930493c9b19SRichard Henderson    set_jmp_insn_offset(s, which);
1931493c9b19SRichard Henderson    tcg_out32(s, OPC_JAL);
1932493c9b19SRichard Henderson
1933493c9b19SRichard Henderson    /* When branch is out of range, fall through to indirect. */
1934cf7d6b8eSRichard Henderson    tcg_out_ld(s, TCG_TYPE_PTR, TCG_REG_TMP0, TCG_REG_ZERO,
1935cf7d6b8eSRichard Henderson               get_jmp_target_addr(s, which));
1936cf7d6b8eSRichard Henderson    tcg_out_opc_imm(s, OPC_JALR, TCG_REG_ZERO, TCG_REG_TMP0, 0);
1937cf7d6b8eSRichard Henderson    set_jmp_reset_offset(s, which);
1938cf7d6b8eSRichard Henderson}
1939cf7d6b8eSRichard Henderson
194090c0fee3SRichard Hendersonvoid tb_target_set_jmp_target(const TranslationBlock *tb, int n,
194190c0fee3SRichard Henderson                              uintptr_t jmp_rx, uintptr_t jmp_rw)
194290c0fee3SRichard Henderson{
1943493c9b19SRichard Henderson    uintptr_t addr = tb->jmp_target_addr[n];
1944493c9b19SRichard Henderson    ptrdiff_t offset = addr - jmp_rx;
1945493c9b19SRichard Henderson    tcg_insn_unit insn;
1946493c9b19SRichard Henderson
1947493c9b19SRichard Henderson    /* Either directly branch, or fall through to indirect branch. */
1948493c9b19SRichard Henderson    if (offset == sextreg(offset, 0, 20)) {
1949493c9b19SRichard Henderson        insn = encode_uj(OPC_JAL, TCG_REG_ZERO, offset);
1950493c9b19SRichard Henderson    } else {
1951493c9b19SRichard Henderson        insn = OPC_NOP;
1952493c9b19SRichard Henderson    }
1953493c9b19SRichard Henderson    qatomic_set((uint32_t *)jmp_rw, insn);
1954493c9b19SRichard Henderson    flush_idcache_range(jmp_rx, jmp_rw, 4);
195590c0fee3SRichard Henderson}
195690c0fee3SRichard Henderson
1957139c1837SPaolo Bonzinistatic void tcg_out_op(TCGContext *s, TCGOpcode opc,
19585e8892dbSMiroslav Rezanina                       const TCGArg args[TCG_MAX_OP_ARGS],
19595e8892dbSMiroslav Rezanina                       const int const_args[TCG_MAX_OP_ARGS])
1960139c1837SPaolo Bonzini{
1961139c1837SPaolo Bonzini    TCGArg a0 = args[0];
1962139c1837SPaolo Bonzini    TCGArg a1 = args[1];
1963139c1837SPaolo Bonzini    TCGArg a2 = args[2];
1964139c1837SPaolo Bonzini    int c2 = const_args[2];
1965139c1837SPaolo Bonzini
1966139c1837SPaolo Bonzini    switch (opc) {
1967139c1837SPaolo Bonzini    case INDEX_op_goto_ptr:
1968139c1837SPaolo Bonzini        tcg_out_opc_imm(s, OPC_JALR, TCG_REG_ZERO, a0, 0);
1969139c1837SPaolo Bonzini        break;
1970139c1837SPaolo Bonzini
1971139c1837SPaolo Bonzini    case INDEX_op_br:
1972139c1837SPaolo Bonzini        tcg_out_reloc(s, s->code_ptr, R_RISCV_JAL, arg_label(a0), 0);
1973139c1837SPaolo Bonzini        tcg_out_opc_jump(s, OPC_JAL, TCG_REG_ZERO, 0);
1974139c1837SPaolo Bonzini        break;
1975139c1837SPaolo Bonzini
1976139c1837SPaolo Bonzini    case INDEX_op_ld8u_i32:
1977139c1837SPaolo Bonzini    case INDEX_op_ld8u_i64:
1978139c1837SPaolo Bonzini        tcg_out_ldst(s, OPC_LBU, a0, a1, a2);
1979139c1837SPaolo Bonzini        break;
1980139c1837SPaolo Bonzini    case INDEX_op_ld8s_i32:
1981139c1837SPaolo Bonzini    case INDEX_op_ld8s_i64:
1982139c1837SPaolo Bonzini        tcg_out_ldst(s, OPC_LB, a0, a1, a2);
1983139c1837SPaolo Bonzini        break;
1984139c1837SPaolo Bonzini    case INDEX_op_ld16u_i32:
1985139c1837SPaolo Bonzini    case INDEX_op_ld16u_i64:
1986139c1837SPaolo Bonzini        tcg_out_ldst(s, OPC_LHU, a0, a1, a2);
1987139c1837SPaolo Bonzini        break;
1988139c1837SPaolo Bonzini    case INDEX_op_ld16s_i32:
1989139c1837SPaolo Bonzini    case INDEX_op_ld16s_i64:
1990139c1837SPaolo Bonzini        tcg_out_ldst(s, OPC_LH, a0, a1, a2);
1991139c1837SPaolo Bonzini        break;
1992139c1837SPaolo Bonzini    case INDEX_op_ld32u_i64:
1993139c1837SPaolo Bonzini        tcg_out_ldst(s, OPC_LWU, a0, a1, a2);
1994139c1837SPaolo Bonzini        break;
1995139c1837SPaolo Bonzini    case INDEX_op_ld_i32:
1996139c1837SPaolo Bonzini    case INDEX_op_ld32s_i64:
1997139c1837SPaolo Bonzini        tcg_out_ldst(s, OPC_LW, a0, a1, a2);
1998139c1837SPaolo Bonzini        break;
1999139c1837SPaolo Bonzini    case INDEX_op_ld_i64:
2000139c1837SPaolo Bonzini        tcg_out_ldst(s, OPC_LD, a0, a1, a2);
2001139c1837SPaolo Bonzini        break;
2002139c1837SPaolo Bonzini
2003139c1837SPaolo Bonzini    case INDEX_op_st8_i32:
2004139c1837SPaolo Bonzini    case INDEX_op_st8_i64:
2005139c1837SPaolo Bonzini        tcg_out_ldst(s, OPC_SB, a0, a1, a2);
2006139c1837SPaolo Bonzini        break;
2007139c1837SPaolo Bonzini    case INDEX_op_st16_i32:
2008139c1837SPaolo Bonzini    case INDEX_op_st16_i64:
2009139c1837SPaolo Bonzini        tcg_out_ldst(s, OPC_SH, a0, a1, a2);
2010139c1837SPaolo Bonzini        break;
2011139c1837SPaolo Bonzini    case INDEX_op_st_i32:
2012139c1837SPaolo Bonzini    case INDEX_op_st32_i64:
2013139c1837SPaolo Bonzini        tcg_out_ldst(s, OPC_SW, a0, a1, a2);
2014139c1837SPaolo Bonzini        break;
2015139c1837SPaolo Bonzini    case INDEX_op_st_i64:
2016139c1837SPaolo Bonzini        tcg_out_ldst(s, OPC_SD, a0, a1, a2);
2017139c1837SPaolo Bonzini        break;
2018139c1837SPaolo Bonzini
2019139c1837SPaolo Bonzini    case INDEX_op_add_i32:
2020139c1837SPaolo Bonzini        if (c2) {
2021139c1837SPaolo Bonzini            tcg_out_opc_imm(s, OPC_ADDIW, a0, a1, a2);
2022139c1837SPaolo Bonzini        } else {
2023139c1837SPaolo Bonzini            tcg_out_opc_reg(s, OPC_ADDW, a0, a1, a2);
2024139c1837SPaolo Bonzini        }
2025139c1837SPaolo Bonzini        break;
2026139c1837SPaolo Bonzini    case INDEX_op_add_i64:
2027139c1837SPaolo Bonzini        if (c2) {
2028139c1837SPaolo Bonzini            tcg_out_opc_imm(s, OPC_ADDI, a0, a1, a2);
2029139c1837SPaolo Bonzini        } else {
2030139c1837SPaolo Bonzini            tcg_out_opc_reg(s, OPC_ADD, a0, a1, a2);
2031139c1837SPaolo Bonzini        }
2032139c1837SPaolo Bonzini        break;
2033139c1837SPaolo Bonzini
2034139c1837SPaolo Bonzini    case INDEX_op_sub_i32:
2035139c1837SPaolo Bonzini        if (c2) {
2036139c1837SPaolo Bonzini            tcg_out_opc_imm(s, OPC_ADDIW, a0, a1, -a2);
2037139c1837SPaolo Bonzini        } else {
2038139c1837SPaolo Bonzini            tcg_out_opc_reg(s, OPC_SUBW, a0, a1, a2);
2039139c1837SPaolo Bonzini        }
2040139c1837SPaolo Bonzini        break;
2041139c1837SPaolo Bonzini    case INDEX_op_sub_i64:
2042139c1837SPaolo Bonzini        if (c2) {
2043139c1837SPaolo Bonzini            tcg_out_opc_imm(s, OPC_ADDI, a0, a1, -a2);
2044139c1837SPaolo Bonzini        } else {
2045139c1837SPaolo Bonzini            tcg_out_opc_reg(s, OPC_SUB, a0, a1, a2);
2046139c1837SPaolo Bonzini        }
2047139c1837SPaolo Bonzini        break;
2048139c1837SPaolo Bonzini
2049139c1837SPaolo Bonzini    case INDEX_op_and_i32:
2050139c1837SPaolo Bonzini    case INDEX_op_and_i64:
2051139c1837SPaolo Bonzini        if (c2) {
2052139c1837SPaolo Bonzini            tcg_out_opc_imm(s, OPC_ANDI, a0, a1, a2);
2053139c1837SPaolo Bonzini        } else {
2054139c1837SPaolo Bonzini            tcg_out_opc_reg(s, OPC_AND, a0, a1, a2);
2055139c1837SPaolo Bonzini        }
2056139c1837SPaolo Bonzini        break;
2057139c1837SPaolo Bonzini
2058139c1837SPaolo Bonzini    case INDEX_op_or_i32:
2059139c1837SPaolo Bonzini    case INDEX_op_or_i64:
2060139c1837SPaolo Bonzini        if (c2) {
2061139c1837SPaolo Bonzini            tcg_out_opc_imm(s, OPC_ORI, a0, a1, a2);
2062139c1837SPaolo Bonzini        } else {
2063139c1837SPaolo Bonzini            tcg_out_opc_reg(s, OPC_OR, a0, a1, a2);
2064139c1837SPaolo Bonzini        }
2065139c1837SPaolo Bonzini        break;
2066139c1837SPaolo Bonzini
2067139c1837SPaolo Bonzini    case INDEX_op_xor_i32:
2068139c1837SPaolo Bonzini    case INDEX_op_xor_i64:
2069139c1837SPaolo Bonzini        if (c2) {
2070139c1837SPaolo Bonzini            tcg_out_opc_imm(s, OPC_XORI, a0, a1, a2);
2071139c1837SPaolo Bonzini        } else {
2072139c1837SPaolo Bonzini            tcg_out_opc_reg(s, OPC_XOR, a0, a1, a2);
2073139c1837SPaolo Bonzini        }
2074139c1837SPaolo Bonzini        break;
2075139c1837SPaolo Bonzini
207699f4ec6eSRichard Henderson    case INDEX_op_andc_i32:
207799f4ec6eSRichard Henderson    case INDEX_op_andc_i64:
207899f4ec6eSRichard Henderson        if (c2) {
207999f4ec6eSRichard Henderson            tcg_out_opc_imm(s, OPC_ANDI, a0, a1, ~a2);
208099f4ec6eSRichard Henderson        } else {
208199f4ec6eSRichard Henderson            tcg_out_opc_reg(s, OPC_ANDN, a0, a1, a2);
208299f4ec6eSRichard Henderson        }
208399f4ec6eSRichard Henderson        break;
208499f4ec6eSRichard Henderson    case INDEX_op_orc_i32:
208599f4ec6eSRichard Henderson    case INDEX_op_orc_i64:
208699f4ec6eSRichard Henderson        if (c2) {
208799f4ec6eSRichard Henderson            tcg_out_opc_imm(s, OPC_ORI, a0, a1, ~a2);
208899f4ec6eSRichard Henderson        } else {
208999f4ec6eSRichard Henderson            tcg_out_opc_reg(s, OPC_ORN, a0, a1, a2);
209099f4ec6eSRichard Henderson        }
209199f4ec6eSRichard Henderson        break;
209299f4ec6eSRichard Henderson    case INDEX_op_eqv_i32:
209399f4ec6eSRichard Henderson    case INDEX_op_eqv_i64:
209499f4ec6eSRichard Henderson        if (c2) {
209599f4ec6eSRichard Henderson            tcg_out_opc_imm(s, OPC_XORI, a0, a1, ~a2);
209699f4ec6eSRichard Henderson        } else {
209799f4ec6eSRichard Henderson            tcg_out_opc_reg(s, OPC_XNOR, a0, a1, a2);
209899f4ec6eSRichard Henderson        }
209999f4ec6eSRichard Henderson        break;
210099f4ec6eSRichard Henderson
2101139c1837SPaolo Bonzini    case INDEX_op_not_i32:
2102139c1837SPaolo Bonzini    case INDEX_op_not_i64:
2103139c1837SPaolo Bonzini        tcg_out_opc_imm(s, OPC_XORI, a0, a1, -1);
2104139c1837SPaolo Bonzini        break;
2105139c1837SPaolo Bonzini
2106139c1837SPaolo Bonzini    case INDEX_op_neg_i32:
2107139c1837SPaolo Bonzini        tcg_out_opc_reg(s, OPC_SUBW, a0, TCG_REG_ZERO, a1);
2108139c1837SPaolo Bonzini        break;
2109139c1837SPaolo Bonzini    case INDEX_op_neg_i64:
2110139c1837SPaolo Bonzini        tcg_out_opc_reg(s, OPC_SUB, a0, TCG_REG_ZERO, a1);
2111139c1837SPaolo Bonzini        break;
2112139c1837SPaolo Bonzini
2113139c1837SPaolo Bonzini    case INDEX_op_mul_i32:
2114139c1837SPaolo Bonzini        tcg_out_opc_reg(s, OPC_MULW, a0, a1, a2);
2115139c1837SPaolo Bonzini        break;
2116139c1837SPaolo Bonzini    case INDEX_op_mul_i64:
2117139c1837SPaolo Bonzini        tcg_out_opc_reg(s, OPC_MUL, a0, a1, a2);
2118139c1837SPaolo Bonzini        break;
2119139c1837SPaolo Bonzini
2120139c1837SPaolo Bonzini    case INDEX_op_div_i32:
2121139c1837SPaolo Bonzini        tcg_out_opc_reg(s, OPC_DIVW, a0, a1, a2);
2122139c1837SPaolo Bonzini        break;
2123139c1837SPaolo Bonzini    case INDEX_op_div_i64:
2124139c1837SPaolo Bonzini        tcg_out_opc_reg(s, OPC_DIV, a0, a1, a2);
2125139c1837SPaolo Bonzini        break;
2126139c1837SPaolo Bonzini
2127139c1837SPaolo Bonzini    case INDEX_op_divu_i32:
2128139c1837SPaolo Bonzini        tcg_out_opc_reg(s, OPC_DIVUW, a0, a1, a2);
2129139c1837SPaolo Bonzini        break;
2130139c1837SPaolo Bonzini    case INDEX_op_divu_i64:
2131139c1837SPaolo Bonzini        tcg_out_opc_reg(s, OPC_DIVU, a0, a1, a2);
2132139c1837SPaolo Bonzini        break;
2133139c1837SPaolo Bonzini
2134139c1837SPaolo Bonzini    case INDEX_op_rem_i32:
2135139c1837SPaolo Bonzini        tcg_out_opc_reg(s, OPC_REMW, a0, a1, a2);
2136139c1837SPaolo Bonzini        break;
2137139c1837SPaolo Bonzini    case INDEX_op_rem_i64:
2138139c1837SPaolo Bonzini        tcg_out_opc_reg(s, OPC_REM, a0, a1, a2);
2139139c1837SPaolo Bonzini        break;
2140139c1837SPaolo Bonzini
2141139c1837SPaolo Bonzini    case INDEX_op_remu_i32:
2142139c1837SPaolo Bonzini        tcg_out_opc_reg(s, OPC_REMUW, a0, a1, a2);
2143139c1837SPaolo Bonzini        break;
2144139c1837SPaolo Bonzini    case INDEX_op_remu_i64:
2145139c1837SPaolo Bonzini        tcg_out_opc_reg(s, OPC_REMU, a0, a1, a2);
2146139c1837SPaolo Bonzini        break;
2147139c1837SPaolo Bonzini
2148139c1837SPaolo Bonzini    case INDEX_op_shl_i32:
2149139c1837SPaolo Bonzini        if (c2) {
2150d2f3066eSZihao Yu            tcg_out_opc_imm(s, OPC_SLLIW, a0, a1, a2 & 0x1f);
2151139c1837SPaolo Bonzini        } else {
2152139c1837SPaolo Bonzini            tcg_out_opc_reg(s, OPC_SLLW, a0, a1, a2);
2153139c1837SPaolo Bonzini        }
2154139c1837SPaolo Bonzini        break;
2155139c1837SPaolo Bonzini    case INDEX_op_shl_i64:
2156139c1837SPaolo Bonzini        if (c2) {
2157d2f3066eSZihao Yu            tcg_out_opc_imm(s, OPC_SLLI, a0, a1, a2 & 0x3f);
2158139c1837SPaolo Bonzini        } else {
2159139c1837SPaolo Bonzini            tcg_out_opc_reg(s, OPC_SLL, a0, a1, a2);
2160139c1837SPaolo Bonzini        }
2161139c1837SPaolo Bonzini        break;
2162139c1837SPaolo Bonzini
2163139c1837SPaolo Bonzini    case INDEX_op_shr_i32:
2164139c1837SPaolo Bonzini        if (c2) {
2165d2f3066eSZihao Yu            tcg_out_opc_imm(s, OPC_SRLIW, a0, a1, a2 & 0x1f);
2166139c1837SPaolo Bonzini        } else {
2167139c1837SPaolo Bonzini            tcg_out_opc_reg(s, OPC_SRLW, a0, a1, a2);
2168139c1837SPaolo Bonzini        }
2169139c1837SPaolo Bonzini        break;
2170139c1837SPaolo Bonzini    case INDEX_op_shr_i64:
2171139c1837SPaolo Bonzini        if (c2) {
2172d2f3066eSZihao Yu            tcg_out_opc_imm(s, OPC_SRLI, a0, a1, a2 & 0x3f);
2173139c1837SPaolo Bonzini        } else {
2174139c1837SPaolo Bonzini            tcg_out_opc_reg(s, OPC_SRL, a0, a1, a2);
2175139c1837SPaolo Bonzini        }
2176139c1837SPaolo Bonzini        break;
2177139c1837SPaolo Bonzini
2178139c1837SPaolo Bonzini    case INDEX_op_sar_i32:
2179139c1837SPaolo Bonzini        if (c2) {
2180d2f3066eSZihao Yu            tcg_out_opc_imm(s, OPC_SRAIW, a0, a1, a2 & 0x1f);
2181139c1837SPaolo Bonzini        } else {
2182139c1837SPaolo Bonzini            tcg_out_opc_reg(s, OPC_SRAW, a0, a1, a2);
2183139c1837SPaolo Bonzini        }
2184139c1837SPaolo Bonzini        break;
2185139c1837SPaolo Bonzini    case INDEX_op_sar_i64:
2186139c1837SPaolo Bonzini        if (c2) {
2187d2f3066eSZihao Yu            tcg_out_opc_imm(s, OPC_SRAI, a0, a1, a2 & 0x3f);
2188139c1837SPaolo Bonzini        } else {
2189139c1837SPaolo Bonzini            tcg_out_opc_reg(s, OPC_SRA, a0, a1, a2);
2190139c1837SPaolo Bonzini        }
2191139c1837SPaolo Bonzini        break;
2192139c1837SPaolo Bonzini
219319d016adSRichard Henderson    case INDEX_op_rotl_i32:
219419d016adSRichard Henderson        if (c2) {
219519d016adSRichard Henderson            tcg_out_opc_imm(s, OPC_RORIW, a0, a1, -a2 & 0x1f);
219619d016adSRichard Henderson        } else {
219719d016adSRichard Henderson            tcg_out_opc_reg(s, OPC_ROLW, a0, a1, a2);
219819d016adSRichard Henderson        }
219919d016adSRichard Henderson        break;
220019d016adSRichard Henderson    case INDEX_op_rotl_i64:
220119d016adSRichard Henderson        if (c2) {
220219d016adSRichard Henderson            tcg_out_opc_imm(s, OPC_RORI, a0, a1, -a2 & 0x3f);
220319d016adSRichard Henderson        } else {
220419d016adSRichard Henderson            tcg_out_opc_reg(s, OPC_ROL, a0, a1, a2);
220519d016adSRichard Henderson        }
220619d016adSRichard Henderson        break;
220719d016adSRichard Henderson
220819d016adSRichard Henderson    case INDEX_op_rotr_i32:
220919d016adSRichard Henderson        if (c2) {
221019d016adSRichard Henderson            tcg_out_opc_imm(s, OPC_RORIW, a0, a1, a2 & 0x1f);
221119d016adSRichard Henderson        } else {
221219d016adSRichard Henderson            tcg_out_opc_reg(s, OPC_RORW, a0, a1, a2);
221319d016adSRichard Henderson        }
221419d016adSRichard Henderson        break;
221519d016adSRichard Henderson    case INDEX_op_rotr_i64:
221619d016adSRichard Henderson        if (c2) {
221719d016adSRichard Henderson            tcg_out_opc_imm(s, OPC_RORI, a0, a1, a2 & 0x3f);
221819d016adSRichard Henderson        } else {
221919d016adSRichard Henderson            tcg_out_opc_reg(s, OPC_ROR, a0, a1, a2);
222019d016adSRichard Henderson        }
222119d016adSRichard Henderson        break;
222219d016adSRichard Henderson
22237b4d5274SRichard Henderson    case INDEX_op_bswap64_i64:
22247b4d5274SRichard Henderson        tcg_out_opc_imm(s, OPC_REV8, a0, a1, 0);
22257b4d5274SRichard Henderson        break;
22267b4d5274SRichard Henderson    case INDEX_op_bswap32_i32:
22277b4d5274SRichard Henderson        a2 = 0;
22287b4d5274SRichard Henderson        /* fall through */
22297b4d5274SRichard Henderson    case INDEX_op_bswap32_i64:
22307b4d5274SRichard Henderson        tcg_out_opc_imm(s, OPC_REV8, a0, a1, 0);
22317b4d5274SRichard Henderson        if (a2 & TCG_BSWAP_OZ) {
22327b4d5274SRichard Henderson            tcg_out_opc_imm(s, OPC_SRLI, a0, a0, 32);
22337b4d5274SRichard Henderson        } else {
22347b4d5274SRichard Henderson            tcg_out_opc_imm(s, OPC_SRAI, a0, a0, 32);
22357b4d5274SRichard Henderson        }
22367b4d5274SRichard Henderson        break;
22377b4d5274SRichard Henderson    case INDEX_op_bswap16_i64:
22387b4d5274SRichard Henderson    case INDEX_op_bswap16_i32:
22397b4d5274SRichard Henderson        tcg_out_opc_imm(s, OPC_REV8, a0, a1, 0);
22407b4d5274SRichard Henderson        if (a2 & TCG_BSWAP_OZ) {
22417b4d5274SRichard Henderson            tcg_out_opc_imm(s, OPC_SRLI, a0, a0, 48);
22427b4d5274SRichard Henderson        } else {
22437b4d5274SRichard Henderson            tcg_out_opc_imm(s, OPC_SRAI, a0, a0, 48);
22447b4d5274SRichard Henderson        }
22457b4d5274SRichard Henderson        break;
22467b4d5274SRichard Henderson
22470956ecdaSRichard Henderson    case INDEX_op_ctpop_i32:
22480956ecdaSRichard Henderson        tcg_out_opc_imm(s, OPC_CPOPW, a0, a1, 0);
22490956ecdaSRichard Henderson        break;
22500956ecdaSRichard Henderson    case INDEX_op_ctpop_i64:
22510956ecdaSRichard Henderson        tcg_out_opc_imm(s, OPC_CPOP, a0, a1, 0);
22520956ecdaSRichard Henderson        break;
22530956ecdaSRichard Henderson
2254a30498fcSRichard Henderson    case INDEX_op_clz_i32:
2255a30498fcSRichard Henderson        tcg_out_cltz(s, TCG_TYPE_I32, OPC_CLZW, a0, a1, a2, c2);
2256a30498fcSRichard Henderson        break;
2257a30498fcSRichard Henderson    case INDEX_op_clz_i64:
2258a30498fcSRichard Henderson        tcg_out_cltz(s, TCG_TYPE_I64, OPC_CLZ, a0, a1, a2, c2);
2259a30498fcSRichard Henderson        break;
2260a30498fcSRichard Henderson    case INDEX_op_ctz_i32:
2261a30498fcSRichard Henderson        tcg_out_cltz(s, TCG_TYPE_I32, OPC_CTZW, a0, a1, a2, c2);
2262a30498fcSRichard Henderson        break;
2263a30498fcSRichard Henderson    case INDEX_op_ctz_i64:
2264a30498fcSRichard Henderson        tcg_out_cltz(s, TCG_TYPE_I64, OPC_CTZ, a0, a1, a2, c2);
2265a30498fcSRichard Henderson        break;
2266a30498fcSRichard Henderson
2267139c1837SPaolo Bonzini    case INDEX_op_add2_i32:
2268139c1837SPaolo Bonzini        tcg_out_addsub2(s, a0, a1, a2, args[3], args[4], args[5],
2269139c1837SPaolo Bonzini                        const_args[4], const_args[5], false, true);
2270139c1837SPaolo Bonzini        break;
2271139c1837SPaolo Bonzini    case INDEX_op_add2_i64:
2272139c1837SPaolo Bonzini        tcg_out_addsub2(s, a0, a1, a2, args[3], args[4], args[5],
2273139c1837SPaolo Bonzini                        const_args[4], const_args[5], false, false);
2274139c1837SPaolo Bonzini        break;
2275139c1837SPaolo Bonzini    case INDEX_op_sub2_i32:
2276139c1837SPaolo Bonzini        tcg_out_addsub2(s, a0, a1, a2, args[3], args[4], args[5],
2277139c1837SPaolo Bonzini                        const_args[4], const_args[5], true, true);
2278139c1837SPaolo Bonzini        break;
2279139c1837SPaolo Bonzini    case INDEX_op_sub2_i64:
2280139c1837SPaolo Bonzini        tcg_out_addsub2(s, a0, a1, a2, args[3], args[4], args[5],
2281139c1837SPaolo Bonzini                        const_args[4], const_args[5], true, false);
2282139c1837SPaolo Bonzini        break;
2283139c1837SPaolo Bonzini
2284139c1837SPaolo Bonzini    case INDEX_op_brcond_i32:
2285139c1837SPaolo Bonzini    case INDEX_op_brcond_i64:
2286139c1837SPaolo Bonzini        tcg_out_brcond(s, a2, a0, a1, arg_label(args[3]));
2287139c1837SPaolo Bonzini        break;
2288139c1837SPaolo Bonzini
2289139c1837SPaolo Bonzini    case INDEX_op_setcond_i32:
2290139c1837SPaolo Bonzini    case INDEX_op_setcond_i64:
2291f6453695SRichard Henderson        tcg_out_setcond(s, args[3], a0, a1, a2, c2);
2292139c1837SPaolo Bonzini        break;
2293139c1837SPaolo Bonzini
229441e4c0a9SRichard Henderson    case INDEX_op_negsetcond_i32:
229541e4c0a9SRichard Henderson    case INDEX_op_negsetcond_i64:
229641e4c0a9SRichard Henderson        tcg_out_negsetcond(s, args[3], a0, a1, a2, c2);
229741e4c0a9SRichard Henderson        break;
229841e4c0a9SRichard Henderson
2299a18d783eSRichard Henderson    case INDEX_op_movcond_i32:
2300a18d783eSRichard Henderson    case INDEX_op_movcond_i64:
2301a18d783eSRichard Henderson        tcg_out_movcond(s, args[5], a0, a1, a2, c2,
2302a18d783eSRichard Henderson                        args[3], const_args[3], args[4], const_args[4]);
2303a18d783eSRichard Henderson        break;
2304a18d783eSRichard Henderson
2305fecccfccSRichard Henderson    case INDEX_op_qemu_ld_a32_i32:
2306fecccfccSRichard Henderson    case INDEX_op_qemu_ld_a64_i32:
2307f7041977SRichard Henderson        tcg_out_qemu_ld(s, a0, a1, a2, TCG_TYPE_I32);
2308139c1837SPaolo Bonzini        break;
2309fecccfccSRichard Henderson    case INDEX_op_qemu_ld_a32_i64:
2310fecccfccSRichard Henderson    case INDEX_op_qemu_ld_a64_i64:
2311f7041977SRichard Henderson        tcg_out_qemu_ld(s, a0, a1, a2, TCG_TYPE_I64);
2312139c1837SPaolo Bonzini        break;
2313fecccfccSRichard Henderson    case INDEX_op_qemu_st_a32_i32:
2314fecccfccSRichard Henderson    case INDEX_op_qemu_st_a64_i32:
2315f7041977SRichard Henderson        tcg_out_qemu_st(s, a0, a1, a2, TCG_TYPE_I32);
2316139c1837SPaolo Bonzini        break;
2317fecccfccSRichard Henderson    case INDEX_op_qemu_st_a32_i64:
2318fecccfccSRichard Henderson    case INDEX_op_qemu_st_a64_i64:
2319f7041977SRichard Henderson        tcg_out_qemu_st(s, a0, a1, a2, TCG_TYPE_I64);
2320139c1837SPaolo Bonzini        break;
2321139c1837SPaolo Bonzini
2322139c1837SPaolo Bonzini    case INDEX_op_extrh_i64_i32:
2323139c1837SPaolo Bonzini        tcg_out_opc_imm(s, OPC_SRAI, a0, a1, 32);
2324139c1837SPaolo Bonzini        break;
2325139c1837SPaolo Bonzini
2326139c1837SPaolo Bonzini    case INDEX_op_mulsh_i32:
2327139c1837SPaolo Bonzini    case INDEX_op_mulsh_i64:
2328139c1837SPaolo Bonzini        tcg_out_opc_reg(s, OPC_MULH, a0, a1, a2);
2329139c1837SPaolo Bonzini        break;
2330139c1837SPaolo Bonzini
2331139c1837SPaolo Bonzini    case INDEX_op_muluh_i32:
2332139c1837SPaolo Bonzini    case INDEX_op_muluh_i64:
2333139c1837SPaolo Bonzini        tcg_out_opc_reg(s, OPC_MULHU, a0, a1, a2);
2334139c1837SPaolo Bonzini        break;
2335139c1837SPaolo Bonzini
2336139c1837SPaolo Bonzini    case INDEX_op_mb:
2337139c1837SPaolo Bonzini        tcg_out_mb(s, a0);
2338139c1837SPaolo Bonzini        break;
2339139c1837SPaolo Bonzini
2340139c1837SPaolo Bonzini    case INDEX_op_mov_i32:  /* Always emitted via tcg_out_mov.  */
2341139c1837SPaolo Bonzini    case INDEX_op_mov_i64:
2342139c1837SPaolo Bonzini    case INDEX_op_call:     /* Always emitted via tcg_out_call.  */
2343b55a8d9dSRichard Henderson    case INDEX_op_exit_tb:  /* Always emitted via tcg_out_exit_tb.  */
2344cf7d6b8eSRichard Henderson    case INDEX_op_goto_tb:  /* Always emitted via tcg_out_goto_tb.  */
2345678155b2SRichard Henderson    case INDEX_op_ext8s_i32:  /* Always emitted via tcg_reg_alloc_op.  */
2346678155b2SRichard Henderson    case INDEX_op_ext8s_i64:
2347d0e66c89SRichard Henderson    case INDEX_op_ext8u_i32:
2348d0e66c89SRichard Henderson    case INDEX_op_ext8u_i64:
2349753e42eaSRichard Henderson    case INDEX_op_ext16s_i32:
2350753e42eaSRichard Henderson    case INDEX_op_ext16s_i64:
2351379afdffSRichard Henderson    case INDEX_op_ext16u_i32:
2352379afdffSRichard Henderson    case INDEX_op_ext16u_i64:
235352bf3398SRichard Henderson    case INDEX_op_ext32s_i64:
23549ecf5f61SRichard Henderson    case INDEX_op_ext32u_i64:
23559c6aa274SRichard Henderson    case INDEX_op_ext_i32_i64:
2356b9bfe000SRichard Henderson    case INDEX_op_extu_i32_i64:
2357b8b94ac6SRichard Henderson    case INDEX_op_extrl_i64_i32:
2358139c1837SPaolo Bonzini    default:
2359139c1837SPaolo Bonzini        g_assert_not_reached();
2360139c1837SPaolo Bonzini    }
2361139c1837SPaolo Bonzini}
2362139c1837SPaolo Bonzini
2363f63e7089SHuang Shiyuanstatic void tcg_out_vec_op(TCGContext *s, TCGOpcode opc,
2364f63e7089SHuang Shiyuan                           unsigned vecl, unsigned vece,
2365f63e7089SHuang Shiyuan                           const TCGArg args[TCG_MAX_OP_ARGS],
2366f63e7089SHuang Shiyuan                           const int const_args[TCG_MAX_OP_ARGS])
2367f63e7089SHuang Shiyuan{
2368f63e7089SHuang Shiyuan    TCGType type = vecl + TCG_TYPE_V64;
2369f63e7089SHuang Shiyuan    TCGArg a0, a1, a2;
23705a63f599STANG Tiancheng    int c2;
2371f63e7089SHuang Shiyuan
2372f63e7089SHuang Shiyuan    a0 = args[0];
2373f63e7089SHuang Shiyuan    a1 = args[1];
2374f63e7089SHuang Shiyuan    a2 = args[2];
23755a63f599STANG Tiancheng    c2 = const_args[2];
2376f63e7089SHuang Shiyuan
2377f63e7089SHuang Shiyuan    switch (opc) {
2378d4be6ee1STANG Tiancheng    case INDEX_op_dupm_vec:
2379d4be6ee1STANG Tiancheng        tcg_out_dupm_vec(s, type, vece, a0, a1, a2);
2380d4be6ee1STANG Tiancheng        break;
2381f63e7089SHuang Shiyuan    case INDEX_op_ld_vec:
2382f63e7089SHuang Shiyuan        tcg_out_ld(s, type, a0, a1, a2);
2383f63e7089SHuang Shiyuan        break;
2384f63e7089SHuang Shiyuan    case INDEX_op_st_vec:
2385f63e7089SHuang Shiyuan        tcg_out_st(s, type, a0, a1, a2);
2386f63e7089SHuang Shiyuan        break;
23875a63f599STANG Tiancheng    case INDEX_op_add_vec:
23885a63f599STANG Tiancheng        set_vtype_len_sew(s, type, vece);
23895a63f599STANG Tiancheng        tcg_out_opc_vv_vi(s, OPC_VADD_VV, OPC_VADD_VI, a0, a1, a2, c2);
23905a63f599STANG Tiancheng        break;
23915a63f599STANG Tiancheng    case INDEX_op_sub_vec:
23925a63f599STANG Tiancheng        set_vtype_len_sew(s, type, vece);
2393dc9cd4ecSRichard Henderson        if (const_args[1]) {
2394dc9cd4ecSRichard Henderson            tcg_out_opc_vi(s, OPC_VRSUB_VI, a0, a2, a1);
2395dc9cd4ecSRichard Henderson        } else {
23965a63f599STANG Tiancheng            tcg_out_opc_vv(s, OPC_VSUB_VV, a0, a1, a2);
2397dc9cd4ecSRichard Henderson        }
23985a63f599STANG Tiancheng        break;
23995a63f599STANG Tiancheng    case INDEX_op_and_vec:
24005a63f599STANG Tiancheng        set_vtype_len(s, type);
24015a63f599STANG Tiancheng        tcg_out_opc_vv_vi(s, OPC_VAND_VV, OPC_VAND_VI, a0, a1, a2, c2);
24025a63f599STANG Tiancheng        break;
24035a63f599STANG Tiancheng    case INDEX_op_or_vec:
24045a63f599STANG Tiancheng        set_vtype_len(s, type);
24055a63f599STANG Tiancheng        tcg_out_opc_vv_vi(s, OPC_VOR_VV, OPC_VOR_VI, a0, a1, a2, c2);
24065a63f599STANG Tiancheng        break;
24075a63f599STANG Tiancheng    case INDEX_op_xor_vec:
24085a63f599STANG Tiancheng        set_vtype_len(s, type);
24095a63f599STANG Tiancheng        tcg_out_opc_vv_vi(s, OPC_VXOR_VV, OPC_VXOR_VI, a0, a1, a2, c2);
24105a63f599STANG Tiancheng        break;
24115a63f599STANG Tiancheng    case INDEX_op_not_vec:
24125a63f599STANG Tiancheng        set_vtype_len(s, type);
24135a63f599STANG Tiancheng        tcg_out_opc_vi(s, OPC_VXOR_VI, a0, a1, -1);
24145a63f599STANG Tiancheng        break;
2415c283c074STANG Tiancheng    case INDEX_op_neg_vec:
2416c283c074STANG Tiancheng        set_vtype_len_sew(s, type, vece);
2417c283c074STANG Tiancheng        tcg_out_opc_vi(s, OPC_VRSUB_VI, a0, a1, 0);
2418c283c074STANG Tiancheng        break;
2419101c1ef5STANG Tiancheng    case INDEX_op_mul_vec:
2420101c1ef5STANG Tiancheng        set_vtype_len_sew(s, type, vece);
2421101c1ef5STANG Tiancheng        tcg_out_opc_vv(s, OPC_VMUL_VV, a0, a1, a2);
2422101c1ef5STANG Tiancheng        break;
2423101c1ef5STANG Tiancheng    case INDEX_op_ssadd_vec:
2424101c1ef5STANG Tiancheng        set_vtype_len_sew(s, type, vece);
2425101c1ef5STANG Tiancheng        tcg_out_opc_vv_vi(s, OPC_VSADD_VV, OPC_VSADD_VI, a0, a1, a2, c2);
2426101c1ef5STANG Tiancheng        break;
2427101c1ef5STANG Tiancheng    case INDEX_op_sssub_vec:
2428101c1ef5STANG Tiancheng        set_vtype_len_sew(s, type, vece);
2429101c1ef5STANG Tiancheng        tcg_out_opc_vv_vi(s, OPC_VSSUB_VV, OPC_VSSUB_VI, a0, a1, a2, c2);
2430101c1ef5STANG Tiancheng        break;
2431101c1ef5STANG Tiancheng    case INDEX_op_usadd_vec:
2432101c1ef5STANG Tiancheng        set_vtype_len_sew(s, type, vece);
2433101c1ef5STANG Tiancheng        tcg_out_opc_vv_vi(s, OPC_VSADDU_VV, OPC_VSADDU_VI, a0, a1, a2, c2);
2434101c1ef5STANG Tiancheng        break;
2435101c1ef5STANG Tiancheng    case INDEX_op_ussub_vec:
2436101c1ef5STANG Tiancheng        set_vtype_len_sew(s, type, vece);
2437101c1ef5STANG Tiancheng        tcg_out_opc_vv_vi(s, OPC_VSSUBU_VV, OPC_VSSUBU_VI, a0, a1, a2, c2);
2438101c1ef5STANG Tiancheng        break;
24391631f19bSTANG Tiancheng    case INDEX_op_smax_vec:
24401631f19bSTANG Tiancheng        set_vtype_len_sew(s, type, vece);
24411631f19bSTANG Tiancheng        tcg_out_opc_vv_vi(s, OPC_VMAX_VV, OPC_VMAX_VI, a0, a1, a2, c2);
24421631f19bSTANG Tiancheng        break;
24431631f19bSTANG Tiancheng    case INDEX_op_smin_vec:
24441631f19bSTANG Tiancheng        set_vtype_len_sew(s, type, vece);
24451631f19bSTANG Tiancheng        tcg_out_opc_vv_vi(s, OPC_VMIN_VV, OPC_VMIN_VI, a0, a1, a2, c2);
24461631f19bSTANG Tiancheng        break;
24471631f19bSTANG Tiancheng    case INDEX_op_umax_vec:
24481631f19bSTANG Tiancheng        set_vtype_len_sew(s, type, vece);
24491631f19bSTANG Tiancheng        tcg_out_opc_vv_vi(s, OPC_VMAXU_VV, OPC_VMAXU_VI, a0, a1, a2, c2);
24501631f19bSTANG Tiancheng        break;
24511631f19bSTANG Tiancheng    case INDEX_op_umin_vec:
24521631f19bSTANG Tiancheng        set_vtype_len_sew(s, type, vece);
24531631f19bSTANG Tiancheng        tcg_out_opc_vv_vi(s, OPC_VMINU_VV, OPC_VMINU_VI, a0, a1, a2, c2);
24541631f19bSTANG Tiancheng        break;
2455cbde22f1STANG Tiancheng    case INDEX_op_shls_vec:
2456cbde22f1STANG Tiancheng        set_vtype_len_sew(s, type, vece);
2457cbde22f1STANG Tiancheng        tcg_out_opc_vx(s, OPC_VSLL_VX, a0, a1, a2);
2458cbde22f1STANG Tiancheng        break;
2459cbde22f1STANG Tiancheng    case INDEX_op_shrs_vec:
2460cbde22f1STANG Tiancheng        set_vtype_len_sew(s, type, vece);
2461cbde22f1STANG Tiancheng        tcg_out_opc_vx(s, OPC_VSRL_VX, a0, a1, a2);
2462cbde22f1STANG Tiancheng        break;
2463cbde22f1STANG Tiancheng    case INDEX_op_sars_vec:
2464cbde22f1STANG Tiancheng        set_vtype_len_sew(s, type, vece);
2465cbde22f1STANG Tiancheng        tcg_out_opc_vx(s, OPC_VSRA_VX, a0, a1, a2);
2466cbde22f1STANG Tiancheng        break;
2467cbde22f1STANG Tiancheng    case INDEX_op_shlv_vec:
2468cbde22f1STANG Tiancheng        set_vtype_len_sew(s, type, vece);
2469cbde22f1STANG Tiancheng        tcg_out_opc_vv(s, OPC_VSLL_VV, a0, a1, a2);
2470cbde22f1STANG Tiancheng        break;
2471cbde22f1STANG Tiancheng    case INDEX_op_shrv_vec:
2472cbde22f1STANG Tiancheng        set_vtype_len_sew(s, type, vece);
2473cbde22f1STANG Tiancheng        tcg_out_opc_vv(s, OPC_VSRL_VV, a0, a1, a2);
2474cbde22f1STANG Tiancheng        break;
2475cbde22f1STANG Tiancheng    case INDEX_op_sarv_vec:
2476cbde22f1STANG Tiancheng        set_vtype_len_sew(s, type, vece);
2477cbde22f1STANG Tiancheng        tcg_out_opc_vv(s, OPC_VSRA_VV, a0, a1, a2);
2478cbde22f1STANG Tiancheng        break;
2479cbde22f1STANG Tiancheng    case INDEX_op_shli_vec:
2480cbde22f1STANG Tiancheng        set_vtype_len_sew(s, type, vece);
2481cbde22f1STANG Tiancheng        tcg_out_vshifti(s, OPC_VSLL_VI, OPC_VSLL_VX, a0, a1, a2);
2482cbde22f1STANG Tiancheng        break;
2483cbde22f1STANG Tiancheng    case INDEX_op_shri_vec:
2484cbde22f1STANG Tiancheng        set_vtype_len_sew(s, type, vece);
2485cbde22f1STANG Tiancheng        tcg_out_vshifti(s, OPC_VSRL_VI, OPC_VSRL_VX, a0, a1, a2);
2486cbde22f1STANG Tiancheng        break;
2487cbde22f1STANG Tiancheng    case INDEX_op_sari_vec:
2488cbde22f1STANG Tiancheng        set_vtype_len_sew(s, type, vece);
2489cbde22f1STANG Tiancheng        tcg_out_vshifti(s, OPC_VSRA_VI, OPC_VSRA_VX, a0, a1, a2);
2490cbde22f1STANG Tiancheng        break;
2491*d1843219STANG Tiancheng    case INDEX_op_rotli_vec:
2492*d1843219STANG Tiancheng        set_vtype_len_sew(s, type, vece);
2493*d1843219STANG Tiancheng        tcg_out_vshifti(s, OPC_VSLL_VI, OPC_VSLL_VX, TCG_REG_V0, a1, a2);
2494*d1843219STANG Tiancheng        tcg_out_vshifti(s, OPC_VSRL_VI, OPC_VSRL_VX, a0, a1,
2495*d1843219STANG Tiancheng                        -a2 & ((8 << vece) - 1));
2496*d1843219STANG Tiancheng        tcg_out_opc_vv(s, OPC_VOR_VV, a0, a0, TCG_REG_V0);
2497*d1843219STANG Tiancheng        break;
2498*d1843219STANG Tiancheng    case INDEX_op_rotls_vec:
2499*d1843219STANG Tiancheng        set_vtype_len_sew(s, type, vece);
2500*d1843219STANG Tiancheng        tcg_out_opc_vx(s, OPC_VSLL_VX, TCG_REG_V0, a1, a2);
2501*d1843219STANG Tiancheng        tcg_out_opc_reg(s, OPC_SUBW, TCG_REG_TMP0, TCG_REG_ZERO, a2);
2502*d1843219STANG Tiancheng        tcg_out_opc_vx(s, OPC_VSRL_VX, a0, a1, TCG_REG_TMP0);
2503*d1843219STANG Tiancheng        tcg_out_opc_vv(s, OPC_VOR_VV, a0, a0, TCG_REG_V0);
2504*d1843219STANG Tiancheng        break;
2505*d1843219STANG Tiancheng    case INDEX_op_rotlv_vec:
2506*d1843219STANG Tiancheng        set_vtype_len_sew(s, type, vece);
2507*d1843219STANG Tiancheng        tcg_out_opc_vi(s, OPC_VRSUB_VI, TCG_REG_V0, a2, 0);
2508*d1843219STANG Tiancheng        tcg_out_opc_vv(s, OPC_VSRL_VV, TCG_REG_V0, a1, TCG_REG_V0);
2509*d1843219STANG Tiancheng        tcg_out_opc_vv(s, OPC_VSLL_VV, a0, a1, a2);
2510*d1843219STANG Tiancheng        tcg_out_opc_vv(s, OPC_VOR_VV, a0, a0, TCG_REG_V0);
2511*d1843219STANG Tiancheng        break;
2512*d1843219STANG Tiancheng    case INDEX_op_rotrv_vec:
2513*d1843219STANG Tiancheng        set_vtype_len_sew(s, type, vece);
2514*d1843219STANG Tiancheng        tcg_out_opc_vi(s, OPC_VRSUB_VI, TCG_REG_V0, a2, 0);
2515*d1843219STANG Tiancheng        tcg_out_opc_vv(s, OPC_VSLL_VV, TCG_REG_V0, a1, TCG_REG_V0);
2516*d1843219STANG Tiancheng        tcg_out_opc_vv(s, OPC_VSRL_VV, a0, a1, a2);
2517*d1843219STANG Tiancheng        tcg_out_opc_vv(s, OPC_VOR_VV, a0, a0, TCG_REG_V0);
2518*d1843219STANG Tiancheng        break;
2519a31768c0STANG Tiancheng    case INDEX_op_cmp_vec:
2520a31768c0STANG Tiancheng        tcg_out_cmpsel(s, type, vece, args[3], a0, a1, a2, c2,
2521a31768c0STANG Tiancheng                       -1, true, 0, true);
2522a31768c0STANG Tiancheng        break;
2523a31768c0STANG Tiancheng    case INDEX_op_cmpsel_vec:
2524a31768c0STANG Tiancheng        tcg_out_cmpsel(s, type, vece, args[5], a0, a1, a2, c2,
2525a31768c0STANG Tiancheng                       args[3], const_args[3], args[4], const_args[4]);
2526a31768c0STANG Tiancheng        break;
2527f63e7089SHuang Shiyuan    case INDEX_op_mov_vec: /* Always emitted via tcg_out_mov.  */
2528f63e7089SHuang Shiyuan    case INDEX_op_dup_vec: /* Always emitted via tcg_out_dup_vec.  */
2529f63e7089SHuang Shiyuan    default:
2530f63e7089SHuang Shiyuan        g_assert_not_reached();
2531f63e7089SHuang Shiyuan    }
2532f63e7089SHuang Shiyuan}
2533f63e7089SHuang Shiyuan
2534f63e7089SHuang Shiyuanvoid tcg_expand_vec_op(TCGOpcode opc, TCGType type, unsigned vece,
2535f63e7089SHuang Shiyuan                       TCGArg a0, ...)
2536f63e7089SHuang Shiyuan{
2537f63e7089SHuang Shiyuan    g_assert_not_reached();
2538f63e7089SHuang Shiyuan}
2539f63e7089SHuang Shiyuan
2540f63e7089SHuang Shiyuanint tcg_can_emit_vec_op(TCGOpcode opc, TCGType type, unsigned vece)
2541f63e7089SHuang Shiyuan{
2542f63e7089SHuang Shiyuan    switch (opc) {
25435a63f599STANG Tiancheng    case INDEX_op_add_vec:
25445a63f599STANG Tiancheng    case INDEX_op_sub_vec:
25455a63f599STANG Tiancheng    case INDEX_op_and_vec:
25465a63f599STANG Tiancheng    case INDEX_op_or_vec:
25475a63f599STANG Tiancheng    case INDEX_op_xor_vec:
25485a63f599STANG Tiancheng    case INDEX_op_not_vec:
2549c283c074STANG Tiancheng    case INDEX_op_neg_vec:
2550101c1ef5STANG Tiancheng    case INDEX_op_mul_vec:
2551101c1ef5STANG Tiancheng    case INDEX_op_ssadd_vec:
2552101c1ef5STANG Tiancheng    case INDEX_op_sssub_vec:
2553101c1ef5STANG Tiancheng    case INDEX_op_usadd_vec:
2554101c1ef5STANG Tiancheng    case INDEX_op_ussub_vec:
25551631f19bSTANG Tiancheng    case INDEX_op_smax_vec:
25561631f19bSTANG Tiancheng    case INDEX_op_smin_vec:
25571631f19bSTANG Tiancheng    case INDEX_op_umax_vec:
25581631f19bSTANG Tiancheng    case INDEX_op_umin_vec:
2559cbde22f1STANG Tiancheng    case INDEX_op_shls_vec:
2560cbde22f1STANG Tiancheng    case INDEX_op_shrs_vec:
2561cbde22f1STANG Tiancheng    case INDEX_op_sars_vec:
2562cbde22f1STANG Tiancheng    case INDEX_op_shlv_vec:
2563cbde22f1STANG Tiancheng    case INDEX_op_shrv_vec:
2564cbde22f1STANG Tiancheng    case INDEX_op_sarv_vec:
2565cbde22f1STANG Tiancheng    case INDEX_op_shri_vec:
2566cbde22f1STANG Tiancheng    case INDEX_op_shli_vec:
2567cbde22f1STANG Tiancheng    case INDEX_op_sari_vec:
2568*d1843219STANG Tiancheng    case INDEX_op_rotls_vec:
2569*d1843219STANG Tiancheng    case INDEX_op_rotlv_vec:
2570*d1843219STANG Tiancheng    case INDEX_op_rotrv_vec:
2571*d1843219STANG Tiancheng    case INDEX_op_rotli_vec:
2572a31768c0STANG Tiancheng    case INDEX_op_cmp_vec:
2573a31768c0STANG Tiancheng    case INDEX_op_cmpsel_vec:
25745a63f599STANG Tiancheng        return 1;
2575f63e7089SHuang Shiyuan    default:
2576f63e7089SHuang Shiyuan        return 0;
2577f63e7089SHuang Shiyuan    }
2578f63e7089SHuang Shiyuan}
2579f63e7089SHuang Shiyuan
2580665be288SRichard Hendersonstatic TCGConstraintSetIndex tcg_target_op_def(TCGOpcode op)
2581139c1837SPaolo Bonzini{
2582139c1837SPaolo Bonzini    switch (op) {
2583139c1837SPaolo Bonzini    case INDEX_op_goto_ptr:
2584665be288SRichard Henderson        return C_O0_I1(r);
2585139c1837SPaolo Bonzini
2586139c1837SPaolo Bonzini    case INDEX_op_ld8u_i32:
2587139c1837SPaolo Bonzini    case INDEX_op_ld8s_i32:
2588139c1837SPaolo Bonzini    case INDEX_op_ld16u_i32:
2589139c1837SPaolo Bonzini    case INDEX_op_ld16s_i32:
2590139c1837SPaolo Bonzini    case INDEX_op_ld_i32:
2591139c1837SPaolo Bonzini    case INDEX_op_not_i32:
2592139c1837SPaolo Bonzini    case INDEX_op_neg_i32:
2593139c1837SPaolo Bonzini    case INDEX_op_ld8u_i64:
2594139c1837SPaolo Bonzini    case INDEX_op_ld8s_i64:
2595139c1837SPaolo Bonzini    case INDEX_op_ld16u_i64:
2596139c1837SPaolo Bonzini    case INDEX_op_ld16s_i64:
2597139c1837SPaolo Bonzini    case INDEX_op_ld32s_i64:
2598139c1837SPaolo Bonzini    case INDEX_op_ld32u_i64:
2599139c1837SPaolo Bonzini    case INDEX_op_ld_i64:
2600139c1837SPaolo Bonzini    case INDEX_op_not_i64:
2601139c1837SPaolo Bonzini    case INDEX_op_neg_i64:
2602139c1837SPaolo Bonzini    case INDEX_op_ext8u_i32:
2603139c1837SPaolo Bonzini    case INDEX_op_ext8u_i64:
2604139c1837SPaolo Bonzini    case INDEX_op_ext16u_i32:
2605139c1837SPaolo Bonzini    case INDEX_op_ext16u_i64:
2606139c1837SPaolo Bonzini    case INDEX_op_ext32u_i64:
2607139c1837SPaolo Bonzini    case INDEX_op_extu_i32_i64:
2608139c1837SPaolo Bonzini    case INDEX_op_ext8s_i32:
2609139c1837SPaolo Bonzini    case INDEX_op_ext8s_i64:
2610139c1837SPaolo Bonzini    case INDEX_op_ext16s_i32:
2611139c1837SPaolo Bonzini    case INDEX_op_ext16s_i64:
2612139c1837SPaolo Bonzini    case INDEX_op_ext32s_i64:
2613139c1837SPaolo Bonzini    case INDEX_op_extrl_i64_i32:
2614139c1837SPaolo Bonzini    case INDEX_op_extrh_i64_i32:
2615139c1837SPaolo Bonzini    case INDEX_op_ext_i32_i64:
26167b4d5274SRichard Henderson    case INDEX_op_bswap16_i32:
26177b4d5274SRichard Henderson    case INDEX_op_bswap32_i32:
26187b4d5274SRichard Henderson    case INDEX_op_bswap16_i64:
26197b4d5274SRichard Henderson    case INDEX_op_bswap32_i64:
26207b4d5274SRichard Henderson    case INDEX_op_bswap64_i64:
26210956ecdaSRichard Henderson    case INDEX_op_ctpop_i32:
26220956ecdaSRichard Henderson    case INDEX_op_ctpop_i64:
2623665be288SRichard Henderson        return C_O1_I1(r, r);
2624139c1837SPaolo Bonzini
2625139c1837SPaolo Bonzini    case INDEX_op_st8_i32:
2626139c1837SPaolo Bonzini    case INDEX_op_st16_i32:
2627139c1837SPaolo Bonzini    case INDEX_op_st_i32:
2628139c1837SPaolo Bonzini    case INDEX_op_st8_i64:
2629139c1837SPaolo Bonzini    case INDEX_op_st16_i64:
2630139c1837SPaolo Bonzini    case INDEX_op_st32_i64:
2631139c1837SPaolo Bonzini    case INDEX_op_st_i64:
2632665be288SRichard Henderson        return C_O0_I2(rZ, r);
2633139c1837SPaolo Bonzini
2634139c1837SPaolo Bonzini    case INDEX_op_add_i32:
2635139c1837SPaolo Bonzini    case INDEX_op_and_i32:
2636139c1837SPaolo Bonzini    case INDEX_op_or_i32:
2637139c1837SPaolo Bonzini    case INDEX_op_xor_i32:
2638139c1837SPaolo Bonzini    case INDEX_op_add_i64:
2639139c1837SPaolo Bonzini    case INDEX_op_and_i64:
2640139c1837SPaolo Bonzini    case INDEX_op_or_i64:
2641139c1837SPaolo Bonzini    case INDEX_op_xor_i64:
2642f6453695SRichard Henderson    case INDEX_op_setcond_i32:
2643f6453695SRichard Henderson    case INDEX_op_setcond_i64:
264441e4c0a9SRichard Henderson    case INDEX_op_negsetcond_i32:
264541e4c0a9SRichard Henderson    case INDEX_op_negsetcond_i64:
2646665be288SRichard Henderson        return C_O1_I2(r, r, rI);
2647139c1837SPaolo Bonzini
264899f4ec6eSRichard Henderson    case INDEX_op_andc_i32:
264999f4ec6eSRichard Henderson    case INDEX_op_andc_i64:
265099f4ec6eSRichard Henderson    case INDEX_op_orc_i32:
265199f4ec6eSRichard Henderson    case INDEX_op_orc_i64:
265299f4ec6eSRichard Henderson    case INDEX_op_eqv_i32:
265399f4ec6eSRichard Henderson    case INDEX_op_eqv_i64:
265499f4ec6eSRichard Henderson        return C_O1_I2(r, r, rJ);
265599f4ec6eSRichard Henderson
2656139c1837SPaolo Bonzini    case INDEX_op_sub_i32:
2657139c1837SPaolo Bonzini    case INDEX_op_sub_i64:
2658665be288SRichard Henderson        return C_O1_I2(r, rZ, rN);
2659139c1837SPaolo Bonzini
2660139c1837SPaolo Bonzini    case INDEX_op_mul_i32:
2661139c1837SPaolo Bonzini    case INDEX_op_mulsh_i32:
2662139c1837SPaolo Bonzini    case INDEX_op_muluh_i32:
2663139c1837SPaolo Bonzini    case INDEX_op_div_i32:
2664139c1837SPaolo Bonzini    case INDEX_op_divu_i32:
2665139c1837SPaolo Bonzini    case INDEX_op_rem_i32:
2666139c1837SPaolo Bonzini    case INDEX_op_remu_i32:
2667139c1837SPaolo Bonzini    case INDEX_op_mul_i64:
2668139c1837SPaolo Bonzini    case INDEX_op_mulsh_i64:
2669139c1837SPaolo Bonzini    case INDEX_op_muluh_i64:
2670139c1837SPaolo Bonzini    case INDEX_op_div_i64:
2671139c1837SPaolo Bonzini    case INDEX_op_divu_i64:
2672139c1837SPaolo Bonzini    case INDEX_op_rem_i64:
2673139c1837SPaolo Bonzini    case INDEX_op_remu_i64:
2674665be288SRichard Henderson        return C_O1_I2(r, rZ, rZ);
2675139c1837SPaolo Bonzini
2676139c1837SPaolo Bonzini    case INDEX_op_shl_i32:
2677139c1837SPaolo Bonzini    case INDEX_op_shr_i32:
2678139c1837SPaolo Bonzini    case INDEX_op_sar_i32:
267919d016adSRichard Henderson    case INDEX_op_rotl_i32:
268019d016adSRichard Henderson    case INDEX_op_rotr_i32:
2681139c1837SPaolo Bonzini    case INDEX_op_shl_i64:
2682139c1837SPaolo Bonzini    case INDEX_op_shr_i64:
2683139c1837SPaolo Bonzini    case INDEX_op_sar_i64:
268419d016adSRichard Henderson    case INDEX_op_rotl_i64:
268519d016adSRichard Henderson    case INDEX_op_rotr_i64:
2686665be288SRichard Henderson        return C_O1_I2(r, r, ri);
2687139c1837SPaolo Bonzini
2688a30498fcSRichard Henderson    case INDEX_op_clz_i32:
2689a30498fcSRichard Henderson    case INDEX_op_clz_i64:
2690a30498fcSRichard Henderson    case INDEX_op_ctz_i32:
2691a30498fcSRichard Henderson    case INDEX_op_ctz_i64:
2692a30498fcSRichard Henderson        return C_N1_I2(r, r, rM);
2693a30498fcSRichard Henderson
2694139c1837SPaolo Bonzini    case INDEX_op_brcond_i32:
2695139c1837SPaolo Bonzini    case INDEX_op_brcond_i64:
2696665be288SRichard Henderson        return C_O0_I2(rZ, rZ);
2697139c1837SPaolo Bonzini
2698a18d783eSRichard Henderson    case INDEX_op_movcond_i32:
2699a18d783eSRichard Henderson    case INDEX_op_movcond_i64:
2700a18d783eSRichard Henderson        return C_O1_I4(r, r, rI, rM, rM);
2701a18d783eSRichard Henderson
2702139c1837SPaolo Bonzini    case INDEX_op_add2_i32:
2703139c1837SPaolo Bonzini    case INDEX_op_add2_i64:
2704139c1837SPaolo Bonzini    case INDEX_op_sub2_i32:
2705139c1837SPaolo Bonzini    case INDEX_op_sub2_i64:
2706665be288SRichard Henderson        return C_O2_I4(r, r, rZ, rZ, rM, rM);
2707139c1837SPaolo Bonzini
2708fecccfccSRichard Henderson    case INDEX_op_qemu_ld_a32_i32:
2709fecccfccSRichard Henderson    case INDEX_op_qemu_ld_a64_i32:
2710fecccfccSRichard Henderson    case INDEX_op_qemu_ld_a32_i64:
2711fecccfccSRichard Henderson    case INDEX_op_qemu_ld_a64_i64:
2712f0f43534SRichard Henderson        return C_O1_I1(r, r);
2713fecccfccSRichard Henderson    case INDEX_op_qemu_st_a32_i32:
2714fecccfccSRichard Henderson    case INDEX_op_qemu_st_a64_i32:
2715fecccfccSRichard Henderson    case INDEX_op_qemu_st_a32_i64:
2716fecccfccSRichard Henderson    case INDEX_op_qemu_st_a64_i64:
2717f0f43534SRichard Henderson        return C_O0_I2(rZ, r);
2718139c1837SPaolo Bonzini
2719f63e7089SHuang Shiyuan    case INDEX_op_st_vec:
2720f63e7089SHuang Shiyuan        return C_O0_I2(v, r);
2721d4be6ee1STANG Tiancheng    case INDEX_op_dup_vec:
2722d4be6ee1STANG Tiancheng    case INDEX_op_dupm_vec:
2723f63e7089SHuang Shiyuan    case INDEX_op_ld_vec:
2724f63e7089SHuang Shiyuan        return C_O1_I1(v, r);
2725c283c074STANG Tiancheng    case INDEX_op_neg_vec:
27265a63f599STANG Tiancheng    case INDEX_op_not_vec:
2727cbde22f1STANG Tiancheng    case INDEX_op_shli_vec:
2728cbde22f1STANG Tiancheng    case INDEX_op_shri_vec:
2729cbde22f1STANG Tiancheng    case INDEX_op_sari_vec:
2730*d1843219STANG Tiancheng    case INDEX_op_rotli_vec:
27315a63f599STANG Tiancheng        return C_O1_I1(v, v);
27325a63f599STANG Tiancheng    case INDEX_op_add_vec:
27335a63f599STANG Tiancheng    case INDEX_op_and_vec:
27345a63f599STANG Tiancheng    case INDEX_op_or_vec:
27355a63f599STANG Tiancheng    case INDEX_op_xor_vec:
2736101c1ef5STANG Tiancheng    case INDEX_op_ssadd_vec:
2737101c1ef5STANG Tiancheng    case INDEX_op_sssub_vec:
2738101c1ef5STANG Tiancheng    case INDEX_op_usadd_vec:
2739101c1ef5STANG Tiancheng    case INDEX_op_ussub_vec:
27401631f19bSTANG Tiancheng    case INDEX_op_smax_vec:
27411631f19bSTANG Tiancheng    case INDEX_op_smin_vec:
27421631f19bSTANG Tiancheng    case INDEX_op_umax_vec:
27431631f19bSTANG Tiancheng    case INDEX_op_umin_vec:
27445a63f599STANG Tiancheng        return C_O1_I2(v, v, vK);
27455a63f599STANG Tiancheng    case INDEX_op_sub_vec:
2746dc9cd4ecSRichard Henderson        return C_O1_I2(v, vK, v);
2747101c1ef5STANG Tiancheng    case INDEX_op_mul_vec:
2748cbde22f1STANG Tiancheng    case INDEX_op_shlv_vec:
2749cbde22f1STANG Tiancheng    case INDEX_op_shrv_vec:
2750cbde22f1STANG Tiancheng    case INDEX_op_sarv_vec:
2751*d1843219STANG Tiancheng    case INDEX_op_rotlv_vec:
2752*d1843219STANG Tiancheng    case INDEX_op_rotrv_vec:
2753101c1ef5STANG Tiancheng        return C_O1_I2(v, v, v);
2754cbde22f1STANG Tiancheng    case INDEX_op_shls_vec:
2755cbde22f1STANG Tiancheng    case INDEX_op_shrs_vec:
2756cbde22f1STANG Tiancheng    case INDEX_op_sars_vec:
2757*d1843219STANG Tiancheng    case INDEX_op_rotls_vec:
2758cbde22f1STANG Tiancheng        return C_O1_I2(v, v, r);
2759a31768c0STANG Tiancheng    case INDEX_op_cmp_vec:
2760a31768c0STANG Tiancheng        return C_O1_I2(v, v, vL);
2761a31768c0STANG Tiancheng    case INDEX_op_cmpsel_vec:
2762a31768c0STANG Tiancheng        return C_O1_I4(v, v, vL, vK, vK);
2763139c1837SPaolo Bonzini    default:
2764665be288SRichard Henderson        g_assert_not_reached();
2765139c1837SPaolo Bonzini    }
2766139c1837SPaolo Bonzini}
2767139c1837SPaolo Bonzini
2768139c1837SPaolo Bonzinistatic const int tcg_target_callee_save_regs[] = {
2769139c1837SPaolo Bonzini    TCG_REG_S0,       /* used for the global env (TCG_AREG0) */
2770139c1837SPaolo Bonzini    TCG_REG_S1,
2771139c1837SPaolo Bonzini    TCG_REG_S2,
2772139c1837SPaolo Bonzini    TCG_REG_S3,
2773139c1837SPaolo Bonzini    TCG_REG_S4,
2774139c1837SPaolo Bonzini    TCG_REG_S5,
2775139c1837SPaolo Bonzini    TCG_REG_S6,
2776139c1837SPaolo Bonzini    TCG_REG_S7,
2777139c1837SPaolo Bonzini    TCG_REG_S8,
2778139c1837SPaolo Bonzini    TCG_REG_S9,
2779139c1837SPaolo Bonzini    TCG_REG_S10,
2780139c1837SPaolo Bonzini    TCG_REG_S11,
2781139c1837SPaolo Bonzini    TCG_REG_RA,       /* should be last for ABI compliance */
2782139c1837SPaolo Bonzini};
2783139c1837SPaolo Bonzini
2784139c1837SPaolo Bonzini/* Stack frame parameters.  */
2785139c1837SPaolo Bonzini#define REG_SIZE   (TCG_TARGET_REG_BITS / 8)
2786139c1837SPaolo Bonzini#define SAVE_SIZE  ((int)ARRAY_SIZE(tcg_target_callee_save_regs) * REG_SIZE)
2787139c1837SPaolo Bonzini#define TEMP_SIZE  (CPU_TEMP_BUF_NLONGS * (int)sizeof(long))
2788139c1837SPaolo Bonzini#define FRAME_SIZE ((TCG_STATIC_CALL_ARGS_SIZE + TEMP_SIZE + SAVE_SIZE \
2789139c1837SPaolo Bonzini                     + TCG_TARGET_STACK_ALIGN - 1) \
2790139c1837SPaolo Bonzini                    & -TCG_TARGET_STACK_ALIGN)
2791139c1837SPaolo Bonzini#define SAVE_OFS   (TCG_STATIC_CALL_ARGS_SIZE + TEMP_SIZE)
2792139c1837SPaolo Bonzini
2793139c1837SPaolo Bonzini/* We're expecting to be able to use an immediate for frame allocation.  */
2794139c1837SPaolo BonziniQEMU_BUILD_BUG_ON(FRAME_SIZE > 0x7ff);
2795139c1837SPaolo Bonzini
2796139c1837SPaolo Bonzini/* Generate global QEMU prologue and epilogue code */
2797139c1837SPaolo Bonzinistatic void tcg_target_qemu_prologue(TCGContext *s)
2798139c1837SPaolo Bonzini{
2799139c1837SPaolo Bonzini    int i;
2800139c1837SPaolo Bonzini
2801139c1837SPaolo Bonzini    tcg_set_frame(s, TCG_REG_SP, TCG_STATIC_CALL_ARGS_SIZE, TEMP_SIZE);
2802139c1837SPaolo Bonzini
2803139c1837SPaolo Bonzini    /* TB prologue */
2804139c1837SPaolo Bonzini    tcg_out_opc_imm(s, OPC_ADDI, TCG_REG_SP, TCG_REG_SP, -FRAME_SIZE);
2805139c1837SPaolo Bonzini    for (i = 0; i < ARRAY_SIZE(tcg_target_callee_save_regs); i++) {
2806139c1837SPaolo Bonzini        tcg_out_st(s, TCG_TYPE_REG, tcg_target_callee_save_regs[i],
2807139c1837SPaolo Bonzini                   TCG_REG_SP, SAVE_OFS + i * REG_SIZE);
2808139c1837SPaolo Bonzini    }
2809139c1837SPaolo Bonzini
28104944d359SRichard Henderson    if (!tcg_use_softmmu && guest_base) {
2811139c1837SPaolo Bonzini        tcg_out_movi(s, TCG_TYPE_PTR, TCG_GUEST_BASE_REG, guest_base);
2812139c1837SPaolo Bonzini        tcg_regset_set_reg(s->reserved_regs, TCG_GUEST_BASE_REG);
2813cf0ed30eSRichard Henderson    }
2814139c1837SPaolo Bonzini
2815139c1837SPaolo Bonzini    /* Call generated code */
2816139c1837SPaolo Bonzini    tcg_out_mov(s, TCG_TYPE_PTR, TCG_AREG0, tcg_target_call_iarg_regs[0]);
2817139c1837SPaolo Bonzini    tcg_out_opc_imm(s, OPC_JALR, TCG_REG_ZERO, tcg_target_call_iarg_regs[1], 0);
2818139c1837SPaolo Bonzini
2819139c1837SPaolo Bonzini    /* Return path for goto_ptr. Set return value to 0 */
2820c8bc1168SRichard Henderson    tcg_code_gen_epilogue = tcg_splitwx_to_rx(s->code_ptr);
2821139c1837SPaolo Bonzini    tcg_out_mov(s, TCG_TYPE_REG, TCG_REG_A0, TCG_REG_ZERO);
2822139c1837SPaolo Bonzini
2823139c1837SPaolo Bonzini    /* TB epilogue */
2824793f7381SRichard Henderson    tb_ret_addr = tcg_splitwx_to_rx(s->code_ptr);
2825139c1837SPaolo Bonzini    for (i = 0; i < ARRAY_SIZE(tcg_target_callee_save_regs); i++) {
2826139c1837SPaolo Bonzini        tcg_out_ld(s, TCG_TYPE_REG, tcg_target_callee_save_regs[i],
2827139c1837SPaolo Bonzini                   TCG_REG_SP, SAVE_OFS + i * REG_SIZE);
2828139c1837SPaolo Bonzini    }
2829139c1837SPaolo Bonzini
2830139c1837SPaolo Bonzini    tcg_out_opc_imm(s, OPC_ADDI, TCG_REG_SP, TCG_REG_SP, FRAME_SIZE);
2831139c1837SPaolo Bonzini    tcg_out_opc_imm(s, OPC_JALR, TCG_REG_ZERO, TCG_REG_RA, 0);
2832139c1837SPaolo Bonzini}
2833139c1837SPaolo Bonzini
28349358fbbfSRichard Hendersonstatic void tcg_out_tb_start(TCGContext *s)
28359358fbbfSRichard Henderson{
2836f63e7089SHuang Shiyuan    init_setting_vtype(s);
2837f63e7089SHuang Shiyuan}
2838f63e7089SHuang Shiyuan
2839f63e7089SHuang Shiyuanstatic bool vtype_check(unsigned vtype)
2840f63e7089SHuang Shiyuan{
2841f63e7089SHuang Shiyuan    unsigned long tmp;
2842f63e7089SHuang Shiyuan
2843f63e7089SHuang Shiyuan    /* vsetvl tmp, zero, vtype */
2844f63e7089SHuang Shiyuan    asm(".insn r 0x57, 7, 0x40, %0, zero, %1" : "=r"(tmp) : "r"(vtype));
2845f63e7089SHuang Shiyuan    return tmp != 0;
2846f63e7089SHuang Shiyuan}
2847f63e7089SHuang Shiyuan
2848f63e7089SHuang Shiyuanstatic void probe_frac_lmul_1(TCGType type, MemOp vsew)
2849f63e7089SHuang Shiyuan{
2850f63e7089SHuang Shiyuan    VsetCache *p = &riscv_vset_cache[type - TCG_TYPE_V64][vsew];
2851f63e7089SHuang Shiyuan    unsigned avl = tcg_type_size(type) >> vsew;
2852f63e7089SHuang Shiyuan    int lmul = type - riscv_lg2_vlenb;
2853f63e7089SHuang Shiyuan    unsigned vtype = encode_vtype(true, true, vsew, lmul & 7);
2854f63e7089SHuang Shiyuan    bool lmul_eq_avl = true;
2855f63e7089SHuang Shiyuan
2856f63e7089SHuang Shiyuan    /* Guaranteed by Zve64x. */
2857f63e7089SHuang Shiyuan    assert(lmul < 3);
2858f63e7089SHuang Shiyuan
2859f63e7089SHuang Shiyuan    /*
2860f63e7089SHuang Shiyuan     * For LMUL < -3, the host vector size is so large that TYPE
2861f63e7089SHuang Shiyuan     * is smaller than the minimum 1/8 fraction.
2862f63e7089SHuang Shiyuan     *
2863f63e7089SHuang Shiyuan     * For other fractional LMUL settings, implementations must
2864f63e7089SHuang Shiyuan     * support SEW settings between SEW_MIN and LMUL * ELEN, inclusive.
2865f63e7089SHuang Shiyuan     * So if ELEN = 64, LMUL = 1/2, then SEW will support e8, e16, e32,
2866f63e7089SHuang Shiyuan     * but e64 may not be supported. In other words, the hardware only
2867f63e7089SHuang Shiyuan     * guarantees SEW_MIN <= SEW <= LMUL * ELEN.  Check.
2868f63e7089SHuang Shiyuan     */
2869f63e7089SHuang Shiyuan    if (lmul < 0 && (lmul < -3 || !vtype_check(vtype))) {
2870f63e7089SHuang Shiyuan        vtype = encode_vtype(true, true, vsew, VLMUL_M1);
2871f63e7089SHuang Shiyuan        lmul_eq_avl = false;
2872f63e7089SHuang Shiyuan    }
2873f63e7089SHuang Shiyuan
2874f63e7089SHuang Shiyuan    if (avl < 32) {
2875f63e7089SHuang Shiyuan        p->vset_insn = encode_vseti(OPC_VSETIVLI, TCG_REG_ZERO, avl, vtype);
2876f63e7089SHuang Shiyuan    } else if (lmul_eq_avl) {
2877f63e7089SHuang Shiyuan        /* rd != 0 and rs1 == 0 uses vlmax */
2878f63e7089SHuang Shiyuan        p->vset_insn = encode_vset(OPC_VSETVLI, TCG_REG_TMP0, TCG_REG_ZERO, vtype);
2879f63e7089SHuang Shiyuan    } else {
2880f63e7089SHuang Shiyuan        p->movi_insn = encode_i(OPC_ADDI, TCG_REG_TMP0, TCG_REG_ZERO, avl);
2881f63e7089SHuang Shiyuan        p->vset_insn = encode_vset(OPC_VSETVLI, TCG_REG_ZERO, TCG_REG_TMP0, vtype);
2882f63e7089SHuang Shiyuan    }
2883f63e7089SHuang Shiyuan}
2884f63e7089SHuang Shiyuan
2885f63e7089SHuang Shiyuanstatic void probe_frac_lmul(void)
2886f63e7089SHuang Shiyuan{
2887f63e7089SHuang Shiyuan    /* Match riscv_lg2_vlenb to TCG_TYPE_V64. */
2888f63e7089SHuang Shiyuan    QEMU_BUILD_BUG_ON(TCG_TYPE_V64 != 3);
2889f63e7089SHuang Shiyuan
2890f63e7089SHuang Shiyuan    for (TCGType t = TCG_TYPE_V64; t <= TCG_TYPE_V256; t++) {
2891f63e7089SHuang Shiyuan        for (MemOp e = MO_8; e <= MO_64; e++) {
2892f63e7089SHuang Shiyuan            probe_frac_lmul_1(t, e);
2893f63e7089SHuang Shiyuan        }
2894f63e7089SHuang Shiyuan    }
28959358fbbfSRichard Henderson}
28969358fbbfSRichard Henderson
2897139c1837SPaolo Bonzinistatic void tcg_target_init(TCGContext *s)
2898139c1837SPaolo Bonzini{
2899139c1837SPaolo Bonzini    tcg_target_available_regs[TCG_TYPE_I32] = 0xffffffff;
2900139c1837SPaolo Bonzini    tcg_target_available_regs[TCG_TYPE_I64] = 0xffffffff;
2901139c1837SPaolo Bonzini
2902f63e7089SHuang Shiyuan    tcg_target_call_clobber_regs = -1;
2903139c1837SPaolo Bonzini    tcg_regset_reset_reg(tcg_target_call_clobber_regs, TCG_REG_S0);
2904139c1837SPaolo Bonzini    tcg_regset_reset_reg(tcg_target_call_clobber_regs, TCG_REG_S1);
2905139c1837SPaolo Bonzini    tcg_regset_reset_reg(tcg_target_call_clobber_regs, TCG_REG_S2);
2906139c1837SPaolo Bonzini    tcg_regset_reset_reg(tcg_target_call_clobber_regs, TCG_REG_S3);
2907139c1837SPaolo Bonzini    tcg_regset_reset_reg(tcg_target_call_clobber_regs, TCG_REG_S4);
2908139c1837SPaolo Bonzini    tcg_regset_reset_reg(tcg_target_call_clobber_regs, TCG_REG_S5);
2909139c1837SPaolo Bonzini    tcg_regset_reset_reg(tcg_target_call_clobber_regs, TCG_REG_S6);
2910139c1837SPaolo Bonzini    tcg_regset_reset_reg(tcg_target_call_clobber_regs, TCG_REG_S7);
2911139c1837SPaolo Bonzini    tcg_regset_reset_reg(tcg_target_call_clobber_regs, TCG_REG_S8);
2912139c1837SPaolo Bonzini    tcg_regset_reset_reg(tcg_target_call_clobber_regs, TCG_REG_S9);
2913139c1837SPaolo Bonzini    tcg_regset_reset_reg(tcg_target_call_clobber_regs, TCG_REG_S10);
2914139c1837SPaolo Bonzini    tcg_regset_reset_reg(tcg_target_call_clobber_regs, TCG_REG_S11);
2915139c1837SPaolo Bonzini
2916139c1837SPaolo Bonzini    s->reserved_regs = 0;
2917139c1837SPaolo Bonzini    tcg_regset_set_reg(s->reserved_regs, TCG_REG_ZERO);
2918139c1837SPaolo Bonzini    tcg_regset_set_reg(s->reserved_regs, TCG_REG_TMP0);
2919139c1837SPaolo Bonzini    tcg_regset_set_reg(s->reserved_regs, TCG_REG_TMP1);
2920139c1837SPaolo Bonzini    tcg_regset_set_reg(s->reserved_regs, TCG_REG_TMP2);
2921139c1837SPaolo Bonzini    tcg_regset_set_reg(s->reserved_regs, TCG_REG_SP);
2922139c1837SPaolo Bonzini    tcg_regset_set_reg(s->reserved_regs, TCG_REG_GP);
2923139c1837SPaolo Bonzini    tcg_regset_set_reg(s->reserved_regs, TCG_REG_TP);
2924f63e7089SHuang Shiyuan
2925f63e7089SHuang Shiyuan    if (cpuinfo & CPUINFO_ZVE64X) {
2926f63e7089SHuang Shiyuan        switch (riscv_lg2_vlenb) {
2927f63e7089SHuang Shiyuan        case TCG_TYPE_V64:
2928f63e7089SHuang Shiyuan            tcg_target_available_regs[TCG_TYPE_V64] = ALL_VECTOR_REGS;
2929f63e7089SHuang Shiyuan            tcg_target_available_regs[TCG_TYPE_V128] = ALL_DVECTOR_REG_GROUPS;
2930f63e7089SHuang Shiyuan            tcg_target_available_regs[TCG_TYPE_V256] = ALL_QVECTOR_REG_GROUPS;
2931f63e7089SHuang Shiyuan            s->reserved_regs |= (~ALL_QVECTOR_REG_GROUPS & ALL_VECTOR_REGS);
2932f63e7089SHuang Shiyuan            break;
2933f63e7089SHuang Shiyuan        case TCG_TYPE_V128:
2934f63e7089SHuang Shiyuan            tcg_target_available_regs[TCG_TYPE_V64] = ALL_VECTOR_REGS;
2935f63e7089SHuang Shiyuan            tcg_target_available_regs[TCG_TYPE_V128] = ALL_VECTOR_REGS;
2936f63e7089SHuang Shiyuan            tcg_target_available_regs[TCG_TYPE_V256] = ALL_DVECTOR_REG_GROUPS;
2937f63e7089SHuang Shiyuan            s->reserved_regs |= (~ALL_DVECTOR_REG_GROUPS & ALL_VECTOR_REGS);
2938f63e7089SHuang Shiyuan            break;
2939f63e7089SHuang Shiyuan        default:
2940f63e7089SHuang Shiyuan            /* Guaranteed by Zve64x. */
2941f63e7089SHuang Shiyuan            tcg_debug_assert(riscv_lg2_vlenb >= TCG_TYPE_V256);
2942f63e7089SHuang Shiyuan            tcg_target_available_regs[TCG_TYPE_V64] = ALL_VECTOR_REGS;
2943f63e7089SHuang Shiyuan            tcg_target_available_regs[TCG_TYPE_V128] = ALL_VECTOR_REGS;
2944f63e7089SHuang Shiyuan            tcg_target_available_regs[TCG_TYPE_V256] = ALL_VECTOR_REGS;
2945f63e7089SHuang Shiyuan            break;
2946f63e7089SHuang Shiyuan        }
2947f63e7089SHuang Shiyuan        tcg_regset_set_reg(s->reserved_regs, TCG_REG_V0);
2948f63e7089SHuang Shiyuan        probe_frac_lmul();
2949f63e7089SHuang Shiyuan    }
2950139c1837SPaolo Bonzini}
2951139c1837SPaolo Bonzini
2952139c1837SPaolo Bonzinitypedef struct {
2953139c1837SPaolo Bonzini    DebugFrameHeader h;
2954139c1837SPaolo Bonzini    uint8_t fde_def_cfa[4];
2955139c1837SPaolo Bonzini    uint8_t fde_reg_ofs[ARRAY_SIZE(tcg_target_callee_save_regs) * 2];
2956139c1837SPaolo Bonzini} DebugFrame;
2957139c1837SPaolo Bonzini
2958139c1837SPaolo Bonzini#define ELF_HOST_MACHINE EM_RISCV
2959139c1837SPaolo Bonzini
2960139c1837SPaolo Bonzinistatic const DebugFrame debug_frame = {
2961139c1837SPaolo Bonzini    .h.cie.len = sizeof(DebugFrameCIE) - 4, /* length after .len member */
2962139c1837SPaolo Bonzini    .h.cie.id = -1,
2963139c1837SPaolo Bonzini    .h.cie.version = 1,
2964139c1837SPaolo Bonzini    .h.cie.code_align = 1,
2965139c1837SPaolo Bonzini    .h.cie.data_align = -(TCG_TARGET_REG_BITS / 8) & 0x7f, /* sleb128 */
2966139c1837SPaolo Bonzini    .h.cie.return_column = TCG_REG_RA,
2967139c1837SPaolo Bonzini
2968139c1837SPaolo Bonzini    /* Total FDE size does not include the "len" member.  */
2969139c1837SPaolo Bonzini    .h.fde.len = sizeof(DebugFrame) - offsetof(DebugFrame, h.fde.cie_offset),
2970139c1837SPaolo Bonzini
2971139c1837SPaolo Bonzini    .fde_def_cfa = {
2972139c1837SPaolo Bonzini        12, TCG_REG_SP,                 /* DW_CFA_def_cfa sp, ... */
2973139c1837SPaolo Bonzini        (FRAME_SIZE & 0x7f) | 0x80,     /* ... uleb128 FRAME_SIZE */
2974139c1837SPaolo Bonzini        (FRAME_SIZE >> 7)
2975139c1837SPaolo Bonzini    },
2976139c1837SPaolo Bonzini    .fde_reg_ofs = {
2977139c1837SPaolo Bonzini        0x80 + 9,  12,                  /* DW_CFA_offset, s1,  -96 */
2978139c1837SPaolo Bonzini        0x80 + 18, 11,                  /* DW_CFA_offset, s2,  -88 */
2979139c1837SPaolo Bonzini        0x80 + 19, 10,                  /* DW_CFA_offset, s3,  -80 */
2980139c1837SPaolo Bonzini        0x80 + 20, 9,                   /* DW_CFA_offset, s4,  -72 */
2981139c1837SPaolo Bonzini        0x80 + 21, 8,                   /* DW_CFA_offset, s5,  -64 */
2982139c1837SPaolo Bonzini        0x80 + 22, 7,                   /* DW_CFA_offset, s6,  -56 */
2983139c1837SPaolo Bonzini        0x80 + 23, 6,                   /* DW_CFA_offset, s7,  -48 */
2984139c1837SPaolo Bonzini        0x80 + 24, 5,                   /* DW_CFA_offset, s8,  -40 */
2985139c1837SPaolo Bonzini        0x80 + 25, 4,                   /* DW_CFA_offset, s9,  -32 */
2986139c1837SPaolo Bonzini        0x80 + 26, 3,                   /* DW_CFA_offset, s10, -24 */
2987139c1837SPaolo Bonzini        0x80 + 27, 2,                   /* DW_CFA_offset, s11, -16 */
2988139c1837SPaolo Bonzini        0x80 + 1 , 1,                   /* DW_CFA_offset, ra,  -8 */
2989139c1837SPaolo Bonzini    }
2990139c1837SPaolo Bonzini};
2991139c1837SPaolo Bonzini
2992755bf9e5SRichard Hendersonvoid tcg_register_jit(const void *buf, size_t buf_size)
2993139c1837SPaolo Bonzini{
2994139c1837SPaolo Bonzini    tcg_register_jit_int(buf, buf_size, &debug_frame, sizeof(debug_frame));
2995139c1837SPaolo Bonzini}
2996