xref: /openbmc/qemu/tcg/riscv/tcg-target.c.inc (revision a31768c0192a6f1f62d07c4985a77814be34a915)
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
115*a31768c0STANG 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
273*a31768c0STANG Tiancheng    OPC_VMERGE_VIM = 0x5c000057 | V_OPIVI,
274*a31768c0STANG Tiancheng    OPC_VMERGE_VVM = 0x5c000057 | V_OPIVV,
275*a31768c0STANG 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,
2795a63f599STANG Tiancheng    OPC_VAND_VV = 0x24000057 | V_OPIVV,
2805a63f599STANG Tiancheng    OPC_VAND_VI = 0x24000057 | V_OPIVI,
2815a63f599STANG Tiancheng    OPC_VOR_VV = 0x28000057 | V_OPIVV,
2825a63f599STANG Tiancheng    OPC_VOR_VI = 0x28000057 | V_OPIVI,
2835a63f599STANG Tiancheng    OPC_VXOR_VV = 0x2c000057 | V_OPIVV,
2845a63f599STANG Tiancheng    OPC_VXOR_VI = 0x2c000057 | V_OPIVI,
2855a63f599STANG Tiancheng
286*a31768c0STANG Tiancheng    OPC_VMSEQ_VV = 0x60000057 | V_OPIVV,
287*a31768c0STANG Tiancheng    OPC_VMSEQ_VI = 0x60000057 | V_OPIVI,
288*a31768c0STANG Tiancheng    OPC_VMSEQ_VX = 0x60000057 | V_OPIVX,
289*a31768c0STANG Tiancheng    OPC_VMSNE_VV = 0x64000057 | V_OPIVV,
290*a31768c0STANG Tiancheng    OPC_VMSNE_VI = 0x64000057 | V_OPIVI,
291*a31768c0STANG Tiancheng    OPC_VMSNE_VX = 0x64000057 | V_OPIVX,
292*a31768c0STANG Tiancheng
293*a31768c0STANG Tiancheng    OPC_VMSLTU_VV = 0x68000057 | V_OPIVV,
294*a31768c0STANG Tiancheng    OPC_VMSLTU_VX = 0x68000057 | V_OPIVX,
295*a31768c0STANG Tiancheng    OPC_VMSLT_VV = 0x6c000057 | V_OPIVV,
296*a31768c0STANG Tiancheng    OPC_VMSLT_VX = 0x6c000057 | V_OPIVX,
297*a31768c0STANG Tiancheng    OPC_VMSLEU_VV = 0x70000057 | V_OPIVV,
298*a31768c0STANG Tiancheng    OPC_VMSLEU_VX = 0x70000057 | V_OPIVX,
299*a31768c0STANG Tiancheng    OPC_VMSLE_VV = 0x74000057 | V_OPIVV,
300*a31768c0STANG Tiancheng    OPC_VMSLE_VX = 0x74000057 | V_OPIVX,
301*a31768c0STANG Tiancheng
302*a31768c0STANG Tiancheng    OPC_VMSLEU_VI = 0x70000057 | V_OPIVI,
303*a31768c0STANG Tiancheng    OPC_VMSLE_VI = 0x74000057 | V_OPIVI,
304*a31768c0STANG Tiancheng    OPC_VMSGTU_VI = 0x78000057 | V_OPIVI,
305*a31768c0STANG Tiancheng    OPC_VMSGTU_VX = 0x78000057 | V_OPIVX,
306*a31768c0STANG Tiancheng    OPC_VMSGT_VI = 0x7c000057 | V_OPIVI,
307*a31768c0STANG Tiancheng    OPC_VMSGT_VX = 0x7c000057 | V_OPIVX,
308*a31768c0STANG Tiancheng
309d4be6ee1STANG Tiancheng    OPC_VMV_V_V = 0x5e000057 | V_OPIVV,
310d4be6ee1STANG Tiancheng    OPC_VMV_V_I = 0x5e000057 | V_OPIVI,
311d4be6ee1STANG Tiancheng    OPC_VMV_V_X = 0x5e000057 | V_OPIVX,
312d4be6ee1STANG Tiancheng
313d4be6ee1STANG Tiancheng    OPC_VMVNR_V = 0x9e000057 | V_OPIVI,
314139c1837SPaolo Bonzini} RISCVInsn;
315139c1837SPaolo Bonzini
316*a31768c0STANG Tianchengstatic const struct {
317*a31768c0STANG Tiancheng    RISCVInsn op;
318*a31768c0STANG Tiancheng    bool swap;
319*a31768c0STANG Tiancheng} tcg_cmpcond_to_rvv_vv[] = {
320*a31768c0STANG Tiancheng    [TCG_COND_EQ] =  { OPC_VMSEQ_VV,  false },
321*a31768c0STANG Tiancheng    [TCG_COND_NE] =  { OPC_VMSNE_VV,  false },
322*a31768c0STANG Tiancheng    [TCG_COND_LT] =  { OPC_VMSLT_VV,  false },
323*a31768c0STANG Tiancheng    [TCG_COND_GE] =  { OPC_VMSLE_VV,  true  },
324*a31768c0STANG Tiancheng    [TCG_COND_GT] =  { OPC_VMSLT_VV,  true  },
325*a31768c0STANG Tiancheng    [TCG_COND_LE] =  { OPC_VMSLE_VV,  false },
326*a31768c0STANG Tiancheng    [TCG_COND_LTU] = { OPC_VMSLTU_VV, false },
327*a31768c0STANG Tiancheng    [TCG_COND_GEU] = { OPC_VMSLEU_VV, true  },
328*a31768c0STANG Tiancheng    [TCG_COND_GTU] = { OPC_VMSLTU_VV, true  },
329*a31768c0STANG Tiancheng    [TCG_COND_LEU] = { OPC_VMSLEU_VV, false }
330*a31768c0STANG Tiancheng};
331*a31768c0STANG Tiancheng
332*a31768c0STANG Tianchengstatic const struct {
333*a31768c0STANG Tiancheng    RISCVInsn op;
334*a31768c0STANG Tiancheng    int min;
335*a31768c0STANG Tiancheng    int max;
336*a31768c0STANG Tiancheng    bool adjust;
337*a31768c0STANG Tiancheng}  tcg_cmpcond_to_rvv_vi[] = {
338*a31768c0STANG Tiancheng    [TCG_COND_EQ]  = { OPC_VMSEQ_VI,  -16, 15, false },
339*a31768c0STANG Tiancheng    [TCG_COND_NE]  = { OPC_VMSNE_VI,  -16, 15, false },
340*a31768c0STANG Tiancheng    [TCG_COND_GT]  = { OPC_VMSGT_VI,  -16, 15, false },
341*a31768c0STANG Tiancheng    [TCG_COND_LE]  = { OPC_VMSLE_VI,  -16, 15, false },
342*a31768c0STANG Tiancheng    [TCG_COND_LT]  = { OPC_VMSLE_VI,  -15, 16, true  },
343*a31768c0STANG Tiancheng    [TCG_COND_GE]  = { OPC_VMSGT_VI,  -15, 16, true  },
344*a31768c0STANG Tiancheng    [TCG_COND_LEU] = { OPC_VMSLEU_VI,   0, 15, false },
345*a31768c0STANG Tiancheng    [TCG_COND_GTU] = { OPC_VMSGTU_VI,   0, 15, false },
346*a31768c0STANG Tiancheng    [TCG_COND_LTU] = { OPC_VMSLEU_VI,   1, 16, true  },
347*a31768c0STANG Tiancheng    [TCG_COND_GEU] = { OPC_VMSGTU_VI,   1, 16, true  },
348*a31768c0STANG Tiancheng};
349*a31768c0STANG Tiancheng
350*a31768c0STANG Tiancheng/* test if a constant matches the constraint */
351*a31768c0STANG Tianchengstatic bool tcg_target_const_match(int64_t val, int ct,
352*a31768c0STANG Tiancheng                                   TCGType type, TCGCond cond, int vece)
353*a31768c0STANG Tiancheng{
354*a31768c0STANG Tiancheng    if (ct & TCG_CT_CONST) {
355*a31768c0STANG Tiancheng        return 1;
356*a31768c0STANG Tiancheng    }
357*a31768c0STANG Tiancheng    if ((ct & TCG_CT_CONST_ZERO) && val == 0) {
358*a31768c0STANG Tiancheng        return 1;
359*a31768c0STANG Tiancheng    }
360*a31768c0STANG Tiancheng    if (type >= TCG_TYPE_V64) {
361*a31768c0STANG Tiancheng        /* Val is replicated by VECE; extract the highest element. */
362*a31768c0STANG Tiancheng        val >>= (-8 << vece) & 63;
363*a31768c0STANG Tiancheng    }
364*a31768c0STANG Tiancheng    /*
365*a31768c0STANG Tiancheng     * Sign extended from 12 bits: [-0x800, 0x7ff].
366*a31768c0STANG Tiancheng     * Used for most arithmetic, as this is the isa field.
367*a31768c0STANG Tiancheng     */
368*a31768c0STANG Tiancheng    if ((ct & TCG_CT_CONST_S12) && val >= -0x800 && val <= 0x7ff) {
369*a31768c0STANG Tiancheng        return 1;
370*a31768c0STANG Tiancheng    }
371*a31768c0STANG Tiancheng    /*
372*a31768c0STANG Tiancheng     * Sign extended from 12 bits, negated: [-0x7ff, 0x800].
373*a31768c0STANG Tiancheng     * Used for subtraction, where a constant must be handled by ADDI.
374*a31768c0STANG Tiancheng     */
375*a31768c0STANG Tiancheng    if ((ct & TCG_CT_CONST_N12) && val >= -0x7ff && val <= 0x800) {
376*a31768c0STANG Tiancheng        return 1;
377*a31768c0STANG Tiancheng    }
378*a31768c0STANG Tiancheng    /*
379*a31768c0STANG Tiancheng     * Sign extended from 12 bits, +/- matching: [-0x7ff, 0x7ff].
380*a31768c0STANG Tiancheng     * Used by addsub2 and movcond, which may need the negative value,
381*a31768c0STANG Tiancheng     * and requires the modified constant to be representable.
382*a31768c0STANG Tiancheng     */
383*a31768c0STANG Tiancheng    if ((ct & TCG_CT_CONST_M12) && val >= -0x7ff && val <= 0x7ff) {
384*a31768c0STANG Tiancheng        return 1;
385*a31768c0STANG Tiancheng    }
386*a31768c0STANG Tiancheng    /*
387*a31768c0STANG Tiancheng     * Inverse of sign extended from 12 bits: ~[-0x800, 0x7ff].
388*a31768c0STANG Tiancheng     * Used to map ANDN back to ANDI, etc.
389*a31768c0STANG Tiancheng     */
390*a31768c0STANG Tiancheng    if ((ct & TCG_CT_CONST_J12) && ~val >= -0x800 && ~val <= 0x7ff) {
391*a31768c0STANG Tiancheng        return 1;
392*a31768c0STANG Tiancheng    }
393*a31768c0STANG Tiancheng    /*
394*a31768c0STANG Tiancheng     * Sign extended from 5 bits: [-0x10, 0x0f].
395*a31768c0STANG Tiancheng     * Used for vector-immediate.
396*a31768c0STANG Tiancheng     */
397*a31768c0STANG Tiancheng    if ((ct & TCG_CT_CONST_S5) && val >= -0x10 && val <= 0x0f) {
398*a31768c0STANG Tiancheng        return 1;
399*a31768c0STANG Tiancheng    }
400*a31768c0STANG Tiancheng    /*
401*a31768c0STANG Tiancheng     * Used for vector compare OPIVI instructions.
402*a31768c0STANG Tiancheng     */
403*a31768c0STANG Tiancheng    if ((ct & TCG_CT_CONST_CMP_VI) &&
404*a31768c0STANG Tiancheng        val >= tcg_cmpcond_to_rvv_vi[cond].min &&
405*a31768c0STANG Tiancheng        val <= tcg_cmpcond_to_rvv_vi[cond].max) {
406*a31768c0STANG Tiancheng        return true;
407*a31768c0STANG Tiancheng     }
408*a31768c0STANG Tiancheng    return 0;
409*a31768c0STANG Tiancheng}
410*a31768c0STANG Tiancheng
411139c1837SPaolo Bonzini/*
412139c1837SPaolo Bonzini * RISC-V immediate and instruction encoders (excludes 16-bit RVC)
413139c1837SPaolo Bonzini */
414139c1837SPaolo Bonzini
415139c1837SPaolo Bonzini/* Type-R */
416139c1837SPaolo Bonzini
417139c1837SPaolo Bonzinistatic int32_t encode_r(RISCVInsn opc, TCGReg rd, TCGReg rs1, TCGReg rs2)
418139c1837SPaolo Bonzini{
419139c1837SPaolo Bonzini    return opc | (rd & 0x1f) << 7 | (rs1 & 0x1f) << 15 | (rs2 & 0x1f) << 20;
420139c1837SPaolo Bonzini}
421139c1837SPaolo Bonzini
422139c1837SPaolo Bonzini/* Type-I */
423139c1837SPaolo Bonzini
424139c1837SPaolo Bonzinistatic int32_t encode_imm12(uint32_t imm)
425139c1837SPaolo Bonzini{
426139c1837SPaolo Bonzini    return (imm & 0xfff) << 20;
427139c1837SPaolo Bonzini}
428139c1837SPaolo Bonzini
429139c1837SPaolo Bonzinistatic int32_t encode_i(RISCVInsn opc, TCGReg rd, TCGReg rs1, uint32_t imm)
430139c1837SPaolo Bonzini{
431139c1837SPaolo Bonzini    return opc | (rd & 0x1f) << 7 | (rs1 & 0x1f) << 15 | encode_imm12(imm);
432139c1837SPaolo Bonzini}
433139c1837SPaolo Bonzini
434139c1837SPaolo Bonzini/* Type-S */
435139c1837SPaolo Bonzini
436139c1837SPaolo Bonzinistatic int32_t encode_simm12(uint32_t imm)
437139c1837SPaolo Bonzini{
438139c1837SPaolo Bonzini    int32_t ret = 0;
439139c1837SPaolo Bonzini
440139c1837SPaolo Bonzini    ret |= (imm & 0xFE0) << 20;
441139c1837SPaolo Bonzini    ret |= (imm & 0x1F) << 7;
442139c1837SPaolo Bonzini
443139c1837SPaolo Bonzini    return ret;
444139c1837SPaolo Bonzini}
445139c1837SPaolo Bonzini
446139c1837SPaolo Bonzinistatic int32_t encode_s(RISCVInsn opc, TCGReg rs1, TCGReg rs2, uint32_t imm)
447139c1837SPaolo Bonzini{
448139c1837SPaolo Bonzini    return opc | (rs1 & 0x1f) << 15 | (rs2 & 0x1f) << 20 | encode_simm12(imm);
449139c1837SPaolo Bonzini}
450139c1837SPaolo Bonzini
451139c1837SPaolo Bonzini/* Type-SB */
452139c1837SPaolo Bonzini
453139c1837SPaolo Bonzinistatic int32_t encode_sbimm12(uint32_t imm)
454139c1837SPaolo Bonzini{
455139c1837SPaolo Bonzini    int32_t ret = 0;
456139c1837SPaolo Bonzini
457139c1837SPaolo Bonzini    ret |= (imm & 0x1000) << 19;
458139c1837SPaolo Bonzini    ret |= (imm & 0x7e0) << 20;
459139c1837SPaolo Bonzini    ret |= (imm & 0x1e) << 7;
460139c1837SPaolo Bonzini    ret |= (imm & 0x800) >> 4;
461139c1837SPaolo Bonzini
462139c1837SPaolo Bonzini    return ret;
463139c1837SPaolo Bonzini}
464139c1837SPaolo Bonzini
465139c1837SPaolo Bonzinistatic int32_t encode_sb(RISCVInsn opc, TCGReg rs1, TCGReg rs2, uint32_t imm)
466139c1837SPaolo Bonzini{
467139c1837SPaolo Bonzini    return opc | (rs1 & 0x1f) << 15 | (rs2 & 0x1f) << 20 | encode_sbimm12(imm);
468139c1837SPaolo Bonzini}
469139c1837SPaolo Bonzini
470139c1837SPaolo Bonzini/* Type-U */
471139c1837SPaolo Bonzini
472139c1837SPaolo Bonzinistatic int32_t encode_uimm20(uint32_t imm)
473139c1837SPaolo Bonzini{
474139c1837SPaolo Bonzini    return imm & 0xfffff000;
475139c1837SPaolo Bonzini}
476139c1837SPaolo Bonzini
477139c1837SPaolo Bonzinistatic int32_t encode_u(RISCVInsn opc, TCGReg rd, uint32_t imm)
478139c1837SPaolo Bonzini{
479139c1837SPaolo Bonzini    return opc | (rd & 0x1f) << 7 | encode_uimm20(imm);
480139c1837SPaolo Bonzini}
481139c1837SPaolo Bonzini
482139c1837SPaolo Bonzini/* Type-UJ */
483139c1837SPaolo Bonzini
484139c1837SPaolo Bonzinistatic int32_t encode_ujimm20(uint32_t imm)
485139c1837SPaolo Bonzini{
486139c1837SPaolo Bonzini    int32_t ret = 0;
487139c1837SPaolo Bonzini
488139c1837SPaolo Bonzini    ret |= (imm & 0x0007fe) << (21 - 1);
489139c1837SPaolo Bonzini    ret |= (imm & 0x000800) << (20 - 11);
490139c1837SPaolo Bonzini    ret |= (imm & 0x0ff000) << (12 - 12);
491139c1837SPaolo Bonzini    ret |= (imm & 0x100000) << (31 - 20);
492139c1837SPaolo Bonzini
493139c1837SPaolo Bonzini    return ret;
494139c1837SPaolo Bonzini}
495139c1837SPaolo Bonzini
496139c1837SPaolo Bonzinistatic int32_t encode_uj(RISCVInsn opc, TCGReg rd, uint32_t imm)
497139c1837SPaolo Bonzini{
498139c1837SPaolo Bonzini    return opc | (rd & 0x1f) << 7 | encode_ujimm20(imm);
499139c1837SPaolo Bonzini}
500139c1837SPaolo Bonzini
501d4be6ee1STANG Tiancheng
502d4be6ee1STANG Tiancheng/* Type-OPIVI */
503d4be6ee1STANG Tiancheng
504d4be6ee1STANG Tianchengstatic int32_t encode_vi(RISCVInsn opc, TCGReg rd, int32_t imm,
505d4be6ee1STANG Tiancheng                         TCGReg vs2, bool vm)
506d4be6ee1STANG Tiancheng{
507d4be6ee1STANG Tiancheng    return opc | (rd & 0x1f) << 7 | (imm & 0x1f) << 15 |
508d4be6ee1STANG Tiancheng           (vs2 & 0x1f) << 20 | (vm << 25);
509d4be6ee1STANG Tiancheng}
510d4be6ee1STANG Tiancheng
511f63e7089SHuang Shiyuan/* Type-OPIVV/OPMVV/OPIVX/OPMVX, Vector load and store */
512f63e7089SHuang Shiyuan
513f63e7089SHuang Shiyuanstatic int32_t encode_v(RISCVInsn opc, TCGReg d, TCGReg s1,
514f63e7089SHuang Shiyuan                        TCGReg s2, bool vm)
515f63e7089SHuang Shiyuan{
516f63e7089SHuang Shiyuan    return opc | (d & 0x1f) << 7 | (s1 & 0x1f) << 15 |
517f63e7089SHuang Shiyuan           (s2 & 0x1f) << 20 | (vm << 25);
518f63e7089SHuang Shiyuan}
519f63e7089SHuang Shiyuan
520f63e7089SHuang Shiyuan/* Vector vtype */
521f63e7089SHuang Shiyuan
522f63e7089SHuang Shiyuanstatic uint32_t encode_vtype(bool vta, bool vma,
523f63e7089SHuang Shiyuan                            MemOp vsew, RISCVVlmul vlmul)
524f63e7089SHuang Shiyuan{
525f63e7089SHuang Shiyuan    return vma << 7 | vta << 6 | vsew << 3 | vlmul;
526f63e7089SHuang Shiyuan}
527f63e7089SHuang Shiyuan
528f63e7089SHuang Shiyuanstatic int32_t encode_vset(RISCVInsn opc, TCGReg rd,
529f63e7089SHuang Shiyuan                           TCGArg rs1, uint32_t vtype)
530f63e7089SHuang Shiyuan{
531f63e7089SHuang Shiyuan    return opc | (rd & 0x1f) << 7 | (rs1 & 0x1f) << 15 | (vtype & 0x7ff) << 20;
532f63e7089SHuang Shiyuan}
533f63e7089SHuang Shiyuan
534f63e7089SHuang Shiyuanstatic int32_t encode_vseti(RISCVInsn opc, TCGReg rd,
535f63e7089SHuang Shiyuan                            uint32_t uimm, uint32_t vtype)
536f63e7089SHuang Shiyuan{
537f63e7089SHuang Shiyuan    return opc | (rd & 0x1f) << 7 | (uimm & 0x1f) << 15 | (vtype & 0x3ff) << 20;
538f63e7089SHuang Shiyuan}
539f63e7089SHuang Shiyuan
540139c1837SPaolo Bonzini/*
541139c1837SPaolo Bonzini * RISC-V instruction emitters
542139c1837SPaolo Bonzini */
543139c1837SPaolo Bonzini
544139c1837SPaolo Bonzinistatic void tcg_out_opc_reg(TCGContext *s, RISCVInsn opc,
545139c1837SPaolo Bonzini                            TCGReg rd, TCGReg rs1, TCGReg rs2)
546139c1837SPaolo Bonzini{
547139c1837SPaolo Bonzini    tcg_out32(s, encode_r(opc, rd, rs1, rs2));
548139c1837SPaolo Bonzini}
549139c1837SPaolo Bonzini
550139c1837SPaolo Bonzinistatic void tcg_out_opc_imm(TCGContext *s, RISCVInsn opc,
551139c1837SPaolo Bonzini                            TCGReg rd, TCGReg rs1, TCGArg imm)
552139c1837SPaolo Bonzini{
553139c1837SPaolo Bonzini    tcg_out32(s, encode_i(opc, rd, rs1, imm));
554139c1837SPaolo Bonzini}
555139c1837SPaolo Bonzini
556139c1837SPaolo Bonzinistatic void tcg_out_opc_store(TCGContext *s, RISCVInsn opc,
557139c1837SPaolo Bonzini                              TCGReg rs1, TCGReg rs2, uint32_t imm)
558139c1837SPaolo Bonzini{
559139c1837SPaolo Bonzini    tcg_out32(s, encode_s(opc, rs1, rs2, imm));
560139c1837SPaolo Bonzini}
561139c1837SPaolo Bonzini
562139c1837SPaolo Bonzinistatic void tcg_out_opc_branch(TCGContext *s, RISCVInsn opc,
563139c1837SPaolo Bonzini                               TCGReg rs1, TCGReg rs2, uint32_t imm)
564139c1837SPaolo Bonzini{
565139c1837SPaolo Bonzini    tcg_out32(s, encode_sb(opc, rs1, rs2, imm));
566139c1837SPaolo Bonzini}
567139c1837SPaolo Bonzini
568139c1837SPaolo Bonzinistatic void tcg_out_opc_upper(TCGContext *s, RISCVInsn opc,
569139c1837SPaolo Bonzini                              TCGReg rd, uint32_t imm)
570139c1837SPaolo Bonzini{
571139c1837SPaolo Bonzini    tcg_out32(s, encode_u(opc, rd, imm));
572139c1837SPaolo Bonzini}
573139c1837SPaolo Bonzini
574139c1837SPaolo Bonzinistatic void tcg_out_opc_jump(TCGContext *s, RISCVInsn opc,
575139c1837SPaolo Bonzini                             TCGReg rd, uint32_t imm)
576139c1837SPaolo Bonzini{
577139c1837SPaolo Bonzini    tcg_out32(s, encode_uj(opc, rd, imm));
578139c1837SPaolo Bonzini}
579139c1837SPaolo Bonzini
580139c1837SPaolo Bonzinistatic void tcg_out_nop_fill(tcg_insn_unit *p, int count)
581139c1837SPaolo Bonzini{
582139c1837SPaolo Bonzini    int i;
583139c1837SPaolo Bonzini    for (i = 0; i < count; ++i) {
5849ae958e4SRichard Henderson        p[i] = OPC_NOP;
585139c1837SPaolo Bonzini    }
586139c1837SPaolo Bonzini}
587139c1837SPaolo Bonzini
588139c1837SPaolo Bonzini/*
589139c1837SPaolo Bonzini * Relocations
590139c1837SPaolo Bonzini */
591139c1837SPaolo Bonzini
592793f7381SRichard Hendersonstatic bool reloc_sbimm12(tcg_insn_unit *src_rw, const tcg_insn_unit *target)
593139c1837SPaolo Bonzini{
594793f7381SRichard Henderson    const tcg_insn_unit *src_rx = tcg_splitwx_to_rx(src_rw);
595793f7381SRichard Henderson    intptr_t offset = (intptr_t)target - (intptr_t)src_rx;
596139c1837SPaolo Bonzini
597844d0442SRichard Henderson    tcg_debug_assert((offset & 1) == 0);
598844d0442SRichard Henderson    if (offset == sextreg(offset, 0, 12)) {
599793f7381SRichard Henderson        *src_rw |= encode_sbimm12(offset);
600139c1837SPaolo Bonzini        return true;
601139c1837SPaolo Bonzini    }
602139c1837SPaolo Bonzini
603139c1837SPaolo Bonzini    return false;
604139c1837SPaolo Bonzini}
605139c1837SPaolo Bonzini
606793f7381SRichard Hendersonstatic bool reloc_jimm20(tcg_insn_unit *src_rw, const tcg_insn_unit *target)
607139c1837SPaolo Bonzini{
608793f7381SRichard Henderson    const tcg_insn_unit *src_rx = tcg_splitwx_to_rx(src_rw);
609793f7381SRichard Henderson    intptr_t offset = (intptr_t)target - (intptr_t)src_rx;
610139c1837SPaolo Bonzini
611844d0442SRichard Henderson    tcg_debug_assert((offset & 1) == 0);
612844d0442SRichard Henderson    if (offset == sextreg(offset, 0, 20)) {
613793f7381SRichard Henderson        *src_rw |= encode_ujimm20(offset);
614139c1837SPaolo Bonzini        return true;
615139c1837SPaolo Bonzini    }
616139c1837SPaolo Bonzini
617139c1837SPaolo Bonzini    return false;
618139c1837SPaolo Bonzini}
619139c1837SPaolo Bonzini
620793f7381SRichard Hendersonstatic bool reloc_call(tcg_insn_unit *src_rw, const tcg_insn_unit *target)
621139c1837SPaolo Bonzini{
622793f7381SRichard Henderson    const tcg_insn_unit *src_rx = tcg_splitwx_to_rx(src_rw);
623793f7381SRichard Henderson    intptr_t offset = (intptr_t)target - (intptr_t)src_rx;
624139c1837SPaolo Bonzini    int32_t lo = sextreg(offset, 0, 12);
625139c1837SPaolo Bonzini    int32_t hi = offset - lo;
626139c1837SPaolo Bonzini
627139c1837SPaolo Bonzini    if (offset == hi + lo) {
628793f7381SRichard Henderson        src_rw[0] |= encode_uimm20(hi);
629793f7381SRichard Henderson        src_rw[1] |= encode_imm12(lo);
630139c1837SPaolo Bonzini        return true;
631139c1837SPaolo Bonzini    }
632139c1837SPaolo Bonzini
633139c1837SPaolo Bonzini    return false;
634139c1837SPaolo Bonzini}
635139c1837SPaolo Bonzini
636139c1837SPaolo Bonzinistatic bool patch_reloc(tcg_insn_unit *code_ptr, int type,
637139c1837SPaolo Bonzini                        intptr_t value, intptr_t addend)
638139c1837SPaolo Bonzini{
639139c1837SPaolo Bonzini    tcg_debug_assert(addend == 0);
640139c1837SPaolo Bonzini    switch (type) {
641139c1837SPaolo Bonzini    case R_RISCV_BRANCH:
642139c1837SPaolo Bonzini        return reloc_sbimm12(code_ptr, (tcg_insn_unit *)value);
643139c1837SPaolo Bonzini    case R_RISCV_JAL:
644139c1837SPaolo Bonzini        return reloc_jimm20(code_ptr, (tcg_insn_unit *)value);
645139c1837SPaolo Bonzini    case R_RISCV_CALL:
646139c1837SPaolo Bonzini        return reloc_call(code_ptr, (tcg_insn_unit *)value);
647139c1837SPaolo Bonzini    default:
6484b6a52d0SRichard Henderson        g_assert_not_reached();
649139c1837SPaolo Bonzini    }
650139c1837SPaolo Bonzini}
651139c1837SPaolo Bonzini
652139c1837SPaolo Bonzini/*
653f63e7089SHuang Shiyuan * RISC-V vector instruction emitters
654f63e7089SHuang Shiyuan */
655f63e7089SHuang Shiyuan
656d4be6ee1STANG Tiancheng/*
657d4be6ee1STANG Tiancheng * Vector registers uses the same 5 lower bits as GPR registers,
658d4be6ee1STANG Tiancheng * and vm=0 (vm = false) means vector masking ENABLED.
659d4be6ee1STANG Tiancheng * With RVV 1.0, vs2 is the first operand, while rs1/imm is the
660d4be6ee1STANG Tiancheng * second operand.
661d4be6ee1STANG Tiancheng */
6625a63f599STANG Tianchengstatic void tcg_out_opc_vv(TCGContext *s, RISCVInsn opc,
6635a63f599STANG Tiancheng                           TCGReg vd, TCGReg vs2, TCGReg vs1)
6645a63f599STANG Tiancheng{
6655a63f599STANG Tiancheng    tcg_out32(s, encode_v(opc, vd, vs1, vs2, true));
6665a63f599STANG Tiancheng}
6675a63f599STANG Tiancheng
668d4be6ee1STANG Tianchengstatic void tcg_out_opc_vx(TCGContext *s, RISCVInsn opc,
669d4be6ee1STANG Tiancheng                           TCGReg vd, TCGReg vs2, TCGReg rs1)
670d4be6ee1STANG Tiancheng{
671d4be6ee1STANG Tiancheng    tcg_out32(s, encode_v(opc, vd, rs1, vs2, true));
672d4be6ee1STANG Tiancheng}
673d4be6ee1STANG Tiancheng
674d4be6ee1STANG Tianchengstatic void tcg_out_opc_vi(TCGContext *s, RISCVInsn opc,
675d4be6ee1STANG Tiancheng                           TCGReg vd, TCGReg vs2, int32_t imm)
676d4be6ee1STANG Tiancheng{
677d4be6ee1STANG Tiancheng    tcg_out32(s, encode_vi(opc, vd, imm, vs2, true));
678d4be6ee1STANG Tiancheng}
679d4be6ee1STANG Tiancheng
6805a63f599STANG Tianchengstatic void tcg_out_opc_vv_vi(TCGContext *s, RISCVInsn o_vv, RISCVInsn o_vi,
6815a63f599STANG Tiancheng                              TCGReg vd, TCGReg vs2, TCGArg vi1, int c_vi1)
6825a63f599STANG Tiancheng{
6835a63f599STANG Tiancheng    if (c_vi1) {
6845a63f599STANG Tiancheng        tcg_out_opc_vi(s, o_vi, vd, vs2, vi1);
6855a63f599STANG Tiancheng    } else {
6865a63f599STANG Tiancheng        tcg_out_opc_vv(s, o_vv, vd, vs2, vi1);
6875a63f599STANG Tiancheng    }
6885a63f599STANG Tiancheng}
6895a63f599STANG Tiancheng
690*a31768c0STANG Tianchengstatic void tcg_out_opc_vim_mask(TCGContext *s, RISCVInsn opc, TCGReg vd,
691*a31768c0STANG Tiancheng                                 TCGReg vs2, int32_t imm)
692*a31768c0STANG Tiancheng{
693*a31768c0STANG Tiancheng    tcg_out32(s, encode_vi(opc, vd, imm, vs2, false));
694*a31768c0STANG Tiancheng}
695*a31768c0STANG Tiancheng
696*a31768c0STANG Tianchengstatic void tcg_out_opc_vvm_mask(TCGContext *s, RISCVInsn opc, TCGReg vd,
697*a31768c0STANG Tiancheng                                 TCGReg vs2, TCGReg vs1)
698*a31768c0STANG Tiancheng{
699*a31768c0STANG Tiancheng    tcg_out32(s, encode_v(opc, vd, vs1, vs2, false));
700*a31768c0STANG Tiancheng}
701*a31768c0STANG Tiancheng
702f63e7089SHuang Shiyuantypedef struct VsetCache {
703f63e7089SHuang Shiyuan    uint32_t movi_insn;
704f63e7089SHuang Shiyuan    uint32_t vset_insn;
705f63e7089SHuang Shiyuan} VsetCache;
706f63e7089SHuang Shiyuan
707f63e7089SHuang Shiyuanstatic VsetCache riscv_vset_cache[3][4];
708f63e7089SHuang Shiyuan
709f63e7089SHuang Shiyuanstatic void set_vtype(TCGContext *s, TCGType type, MemOp vsew)
710f63e7089SHuang Shiyuan{
711f63e7089SHuang Shiyuan    const VsetCache *p = &riscv_vset_cache[type - TCG_TYPE_V64][vsew];
712f63e7089SHuang Shiyuan
713f63e7089SHuang Shiyuan    s->riscv_cur_type = type;
714f63e7089SHuang Shiyuan    s->riscv_cur_vsew = vsew;
715f63e7089SHuang Shiyuan
716f63e7089SHuang Shiyuan    if (p->movi_insn) {
717f63e7089SHuang Shiyuan        tcg_out32(s, p->movi_insn);
718f63e7089SHuang Shiyuan    }
719f63e7089SHuang Shiyuan    tcg_out32(s, p->vset_insn);
720f63e7089SHuang Shiyuan}
721f63e7089SHuang Shiyuan
722f63e7089SHuang Shiyuanstatic MemOp set_vtype_len(TCGContext *s, TCGType type)
723f63e7089SHuang Shiyuan{
724f63e7089SHuang Shiyuan    if (type != s->riscv_cur_type) {
725f63e7089SHuang Shiyuan        set_vtype(s, type, MO_64);
726f63e7089SHuang Shiyuan    }
727f63e7089SHuang Shiyuan    return s->riscv_cur_vsew;
728f63e7089SHuang Shiyuan}
729f63e7089SHuang Shiyuan
730d4be6ee1STANG Tianchengstatic void set_vtype_len_sew(TCGContext *s, TCGType type, MemOp vsew)
731d4be6ee1STANG Tiancheng{
732d4be6ee1STANG Tiancheng    if (type != s->riscv_cur_type || vsew != s->riscv_cur_vsew) {
733d4be6ee1STANG Tiancheng        set_vtype(s, type, vsew);
734d4be6ee1STANG Tiancheng    }
735d4be6ee1STANG Tiancheng}
736d4be6ee1STANG Tiancheng
737f63e7089SHuang Shiyuan/*
738139c1837SPaolo Bonzini * TCG intrinsics
739139c1837SPaolo Bonzini */
740139c1837SPaolo Bonzini
741139c1837SPaolo Bonzinistatic bool tcg_out_mov(TCGContext *s, TCGType type, TCGReg ret, TCGReg arg)
742139c1837SPaolo Bonzini{
743139c1837SPaolo Bonzini    if (ret == arg) {
744139c1837SPaolo Bonzini        return true;
745139c1837SPaolo Bonzini    }
746139c1837SPaolo Bonzini    switch (type) {
747139c1837SPaolo Bonzini    case TCG_TYPE_I32:
748139c1837SPaolo Bonzini    case TCG_TYPE_I64:
749139c1837SPaolo Bonzini        tcg_out_opc_imm(s, OPC_ADDI, ret, arg, 0);
750139c1837SPaolo Bonzini        break;
751d4be6ee1STANG Tiancheng    case TCG_TYPE_V64:
752d4be6ee1STANG Tiancheng    case TCG_TYPE_V128:
753d4be6ee1STANG Tiancheng    case TCG_TYPE_V256:
754d4be6ee1STANG Tiancheng        {
755d4be6ee1STANG Tiancheng            int lmul = type - riscv_lg2_vlenb;
756d4be6ee1STANG Tiancheng            int nf = 1 << MAX(lmul, 0);
757d4be6ee1STANG Tiancheng            tcg_out_opc_vi(s, OPC_VMVNR_V, ret, arg, nf - 1);
758d4be6ee1STANG Tiancheng        }
759d4be6ee1STANG Tiancheng        break;
760139c1837SPaolo Bonzini    default:
761139c1837SPaolo Bonzini        g_assert_not_reached();
762139c1837SPaolo Bonzini    }
763139c1837SPaolo Bonzini    return true;
764139c1837SPaolo Bonzini}
765139c1837SPaolo Bonzini
766139c1837SPaolo Bonzinistatic void tcg_out_movi(TCGContext *s, TCGType type, TCGReg rd,
767139c1837SPaolo Bonzini                         tcg_target_long val)
768139c1837SPaolo Bonzini{
769139c1837SPaolo Bonzini    tcg_target_long lo, hi, tmp;
770139c1837SPaolo Bonzini    int shift, ret;
771139c1837SPaolo Bonzini
772aeb6326eSRichard Henderson    if (type == TCG_TYPE_I32) {
773139c1837SPaolo Bonzini        val = (int32_t)val;
774139c1837SPaolo Bonzini    }
775139c1837SPaolo Bonzini
776139c1837SPaolo Bonzini    lo = sextreg(val, 0, 12);
777139c1837SPaolo Bonzini    if (val == lo) {
778139c1837SPaolo Bonzini        tcg_out_opc_imm(s, OPC_ADDI, rd, TCG_REG_ZERO, lo);
779139c1837SPaolo Bonzini        return;
780139c1837SPaolo Bonzini    }
781139c1837SPaolo Bonzini
782139c1837SPaolo Bonzini    hi = val - lo;
783aeb6326eSRichard Henderson    if (val == (int32_t)val) {
784139c1837SPaolo Bonzini        tcg_out_opc_upper(s, OPC_LUI, rd, hi);
785139c1837SPaolo Bonzini        if (lo != 0) {
786139c1837SPaolo Bonzini            tcg_out_opc_imm(s, OPC_ADDIW, rd, rd, lo);
787139c1837SPaolo Bonzini        }
788139c1837SPaolo Bonzini        return;
789139c1837SPaolo Bonzini    }
790139c1837SPaolo Bonzini
791139c1837SPaolo Bonzini    tmp = tcg_pcrel_diff(s, (void *)val);
792139c1837SPaolo Bonzini    if (tmp == (int32_t)tmp) {
793139c1837SPaolo Bonzini        tcg_out_opc_upper(s, OPC_AUIPC, rd, 0);
794139c1837SPaolo Bonzini        tcg_out_opc_imm(s, OPC_ADDI, rd, rd, 0);
795793f7381SRichard Henderson        ret = reloc_call(s->code_ptr - 2, (const tcg_insn_unit *)val);
796139c1837SPaolo Bonzini        tcg_debug_assert(ret == true);
797139c1837SPaolo Bonzini        return;
798139c1837SPaolo Bonzini    }
799139c1837SPaolo Bonzini
800139c1837SPaolo Bonzini    /* Look for a single 20-bit section.  */
801139c1837SPaolo Bonzini    shift = ctz64(val);
802139c1837SPaolo Bonzini    tmp = val >> shift;
803139c1837SPaolo Bonzini    if (tmp == sextreg(tmp, 0, 20)) {
804139c1837SPaolo Bonzini        tcg_out_opc_upper(s, OPC_LUI, rd, tmp << 12);
805139c1837SPaolo Bonzini        if (shift > 12) {
806139c1837SPaolo Bonzini            tcg_out_opc_imm(s, OPC_SLLI, rd, rd, shift - 12);
807139c1837SPaolo Bonzini        } else {
808139c1837SPaolo Bonzini            tcg_out_opc_imm(s, OPC_SRAI, rd, rd, 12 - shift);
809139c1837SPaolo Bonzini        }
810139c1837SPaolo Bonzini        return;
811139c1837SPaolo Bonzini    }
812139c1837SPaolo Bonzini
813139c1837SPaolo Bonzini    /* Look for a few high zero bits, with lots of bits set in the middle.  */
814139c1837SPaolo Bonzini    shift = clz64(val);
815139c1837SPaolo Bonzini    tmp = val << shift;
816139c1837SPaolo Bonzini    if (tmp == sextreg(tmp, 12, 20) << 12) {
817139c1837SPaolo Bonzini        tcg_out_opc_upper(s, OPC_LUI, rd, tmp);
818139c1837SPaolo Bonzini        tcg_out_opc_imm(s, OPC_SRLI, rd, rd, shift);
819139c1837SPaolo Bonzini        return;
820139c1837SPaolo Bonzini    } else if (tmp == sextreg(tmp, 0, 12)) {
821139c1837SPaolo Bonzini        tcg_out_opc_imm(s, OPC_ADDI, rd, TCG_REG_ZERO, tmp);
822139c1837SPaolo Bonzini        tcg_out_opc_imm(s, OPC_SRLI, rd, rd, shift);
823139c1837SPaolo Bonzini        return;
824139c1837SPaolo Bonzini    }
825139c1837SPaolo Bonzini
826139c1837SPaolo Bonzini    /* Drop into the constant pool.  */
827139c1837SPaolo Bonzini    new_pool_label(s, val, R_RISCV_CALL, s->code_ptr, 0);
828139c1837SPaolo Bonzini    tcg_out_opc_upper(s, OPC_AUIPC, rd, 0);
829139c1837SPaolo Bonzini    tcg_out_opc_imm(s, OPC_LD, rd, rd, 0);
830139c1837SPaolo Bonzini}
831139c1837SPaolo Bonzini
832767c2503SRichard Hendersonstatic bool tcg_out_xchg(TCGContext *s, TCGType type, TCGReg r1, TCGReg r2)
833767c2503SRichard Henderson{
834767c2503SRichard Henderson    return false;
835767c2503SRichard Henderson}
836767c2503SRichard Henderson
8376a6d772eSRichard Hendersonstatic void tcg_out_addi_ptr(TCGContext *s, TCGReg rd, TCGReg rs,
8386a6d772eSRichard Henderson                             tcg_target_long imm)
8396a6d772eSRichard Henderson{
8406a6d772eSRichard Henderson    /* This function is only used for passing structs by reference. */
8416a6d772eSRichard Henderson    g_assert_not_reached();
8426a6d772eSRichard Henderson}
8436a6d772eSRichard Henderson
844139c1837SPaolo Bonzinistatic void tcg_out_ext8u(TCGContext *s, TCGReg ret, TCGReg arg)
845139c1837SPaolo Bonzini{
846139c1837SPaolo Bonzini    tcg_out_opc_imm(s, OPC_ANDI, ret, arg, 0xff);
847139c1837SPaolo Bonzini}
848139c1837SPaolo Bonzini
849139c1837SPaolo Bonzinistatic void tcg_out_ext16u(TCGContext *s, TCGReg ret, TCGReg arg)
850139c1837SPaolo Bonzini{
851b86c6ba6SRichard Henderson    if (cpuinfo & CPUINFO_ZBB) {
852d1c3f4e9SRichard Henderson        tcg_out_opc_reg(s, OPC_ZEXT_H, ret, arg, TCG_REG_ZERO);
853d1c3f4e9SRichard Henderson    } else {
854139c1837SPaolo Bonzini        tcg_out_opc_imm(s, OPC_SLLIW, ret, arg, 16);
855139c1837SPaolo Bonzini        tcg_out_opc_imm(s, OPC_SRLIW, ret, ret, 16);
856139c1837SPaolo Bonzini    }
857d1c3f4e9SRichard Henderson}
858139c1837SPaolo Bonzini
859139c1837SPaolo Bonzinistatic void tcg_out_ext32u(TCGContext *s, TCGReg ret, TCGReg arg)
860139c1837SPaolo Bonzini{
861b86c6ba6SRichard Henderson    if (cpuinfo & CPUINFO_ZBA) {
862d1c3f4e9SRichard Henderson        tcg_out_opc_reg(s, OPC_ADD_UW, ret, arg, TCG_REG_ZERO);
863d1c3f4e9SRichard Henderson    } else {
864139c1837SPaolo Bonzini        tcg_out_opc_imm(s, OPC_SLLI, ret, arg, 32);
865139c1837SPaolo Bonzini        tcg_out_opc_imm(s, OPC_SRLI, ret, ret, 32);
866139c1837SPaolo Bonzini    }
867d1c3f4e9SRichard Henderson}
868139c1837SPaolo Bonzini
869678155b2SRichard Hendersonstatic void tcg_out_ext8s(TCGContext *s, TCGType type, TCGReg ret, TCGReg arg)
870139c1837SPaolo Bonzini{
871b86c6ba6SRichard Henderson    if (cpuinfo & CPUINFO_ZBB) {
872d1c3f4e9SRichard Henderson        tcg_out_opc_imm(s, OPC_SEXT_B, ret, arg, 0);
873d1c3f4e9SRichard Henderson    } else {
874139c1837SPaolo Bonzini        tcg_out_opc_imm(s, OPC_SLLIW, ret, arg, 24);
875139c1837SPaolo Bonzini        tcg_out_opc_imm(s, OPC_SRAIW, ret, ret, 24);
876139c1837SPaolo Bonzini    }
877d1c3f4e9SRichard Henderson}
878139c1837SPaolo Bonzini
879753e42eaSRichard Hendersonstatic void tcg_out_ext16s(TCGContext *s, TCGType type, TCGReg ret, TCGReg arg)
880139c1837SPaolo Bonzini{
881b86c6ba6SRichard Henderson    if (cpuinfo & CPUINFO_ZBB) {
882d1c3f4e9SRichard Henderson        tcg_out_opc_imm(s, OPC_SEXT_H, ret, arg, 0);
883d1c3f4e9SRichard Henderson    } else {
884139c1837SPaolo Bonzini        tcg_out_opc_imm(s, OPC_SLLIW, ret, arg, 16);
885139c1837SPaolo Bonzini        tcg_out_opc_imm(s, OPC_SRAIW, ret, ret, 16);
886139c1837SPaolo Bonzini    }
887d1c3f4e9SRichard Henderson}
888139c1837SPaolo Bonzini
889139c1837SPaolo Bonzinistatic void tcg_out_ext32s(TCGContext *s, TCGReg ret, TCGReg arg)
890139c1837SPaolo Bonzini{
891139c1837SPaolo Bonzini    tcg_out_opc_imm(s, OPC_ADDIW, ret, arg, 0);
892139c1837SPaolo Bonzini}
893139c1837SPaolo Bonzini
8949c6aa274SRichard Hendersonstatic void tcg_out_exts_i32_i64(TCGContext *s, TCGReg ret, TCGReg arg)
8959c6aa274SRichard Henderson{
8963ea9be33SRichard Henderson    if (ret != arg) {
8979c6aa274SRichard Henderson        tcg_out_ext32s(s, ret, arg);
8989c6aa274SRichard Henderson    }
8993ea9be33SRichard Henderson}
9009c6aa274SRichard Henderson
901b9bfe000SRichard Hendersonstatic void tcg_out_extu_i32_i64(TCGContext *s, TCGReg ret, TCGReg arg)
902b9bfe000SRichard Henderson{
903b9bfe000SRichard Henderson    tcg_out_ext32u(s, ret, arg);
904b9bfe000SRichard Henderson}
905b9bfe000SRichard Henderson
906b8b94ac6SRichard Hendersonstatic void tcg_out_extrl_i64_i32(TCGContext *s, TCGReg ret, TCGReg arg)
907b8b94ac6SRichard Henderson{
908b8b94ac6SRichard Henderson    tcg_out_ext32s(s, ret, arg);
909b8b94ac6SRichard Henderson}
910b8b94ac6SRichard Henderson
911139c1837SPaolo Bonzinistatic void tcg_out_ldst(TCGContext *s, RISCVInsn opc, TCGReg data,
912139c1837SPaolo Bonzini                         TCGReg addr, intptr_t offset)
913139c1837SPaolo Bonzini{
914139c1837SPaolo Bonzini    intptr_t imm12 = sextreg(offset, 0, 12);
915139c1837SPaolo Bonzini
916139c1837SPaolo Bonzini    if (offset != imm12) {
9179d9db413SRichard Henderson        intptr_t diff = tcg_pcrel_diff(s, (void *)offset);
918139c1837SPaolo Bonzini
919139c1837SPaolo Bonzini        if (addr == TCG_REG_ZERO && diff == (int32_t)diff) {
920139c1837SPaolo Bonzini            imm12 = sextreg(diff, 0, 12);
921139c1837SPaolo Bonzini            tcg_out_opc_upper(s, OPC_AUIPC, TCG_REG_TMP2, diff - imm12);
922139c1837SPaolo Bonzini        } else {
923139c1837SPaolo Bonzini            tcg_out_movi(s, TCG_TYPE_PTR, TCG_REG_TMP2, offset - imm12);
924139c1837SPaolo Bonzini            if (addr != TCG_REG_ZERO) {
925139c1837SPaolo Bonzini                tcg_out_opc_reg(s, OPC_ADD, TCG_REG_TMP2, TCG_REG_TMP2, addr);
926139c1837SPaolo Bonzini            }
927139c1837SPaolo Bonzini        }
928139c1837SPaolo Bonzini        addr = TCG_REG_TMP2;
929139c1837SPaolo Bonzini    }
930139c1837SPaolo Bonzini
931139c1837SPaolo Bonzini    switch (opc) {
932139c1837SPaolo Bonzini    case OPC_SB:
933139c1837SPaolo Bonzini    case OPC_SH:
934139c1837SPaolo Bonzini    case OPC_SW:
935139c1837SPaolo Bonzini    case OPC_SD:
936139c1837SPaolo Bonzini        tcg_out_opc_store(s, opc, addr, data, imm12);
937139c1837SPaolo Bonzini        break;
938139c1837SPaolo Bonzini    case OPC_LB:
939139c1837SPaolo Bonzini    case OPC_LBU:
940139c1837SPaolo Bonzini    case OPC_LH:
941139c1837SPaolo Bonzini    case OPC_LHU:
942139c1837SPaolo Bonzini    case OPC_LW:
943139c1837SPaolo Bonzini    case OPC_LWU:
944139c1837SPaolo Bonzini    case OPC_LD:
945139c1837SPaolo Bonzini        tcg_out_opc_imm(s, opc, data, addr, imm12);
946139c1837SPaolo Bonzini        break;
947139c1837SPaolo Bonzini    default:
948139c1837SPaolo Bonzini        g_assert_not_reached();
949139c1837SPaolo Bonzini    }
950139c1837SPaolo Bonzini}
951139c1837SPaolo Bonzini
952f63e7089SHuang Shiyuanstatic void tcg_out_vec_ldst(TCGContext *s, RISCVInsn opc, TCGReg data,
953f63e7089SHuang Shiyuan                             TCGReg addr, intptr_t offset)
954f63e7089SHuang Shiyuan{
955f63e7089SHuang Shiyuan    tcg_debug_assert(data >= TCG_REG_V0);
956f63e7089SHuang Shiyuan    tcg_debug_assert(addr < TCG_REG_V0);
957f63e7089SHuang Shiyuan
958f63e7089SHuang Shiyuan    if (offset) {
959f63e7089SHuang Shiyuan        tcg_debug_assert(addr != TCG_REG_ZERO);
960f63e7089SHuang Shiyuan        if (offset == sextreg(offset, 0, 12)) {
961f63e7089SHuang Shiyuan            tcg_out_opc_imm(s, OPC_ADDI, TCG_REG_TMP0, addr, offset);
962f63e7089SHuang Shiyuan        } else {
963f63e7089SHuang Shiyuan            tcg_out_movi(s, TCG_TYPE_PTR, TCG_REG_TMP0, offset);
964f63e7089SHuang Shiyuan            tcg_out_opc_reg(s, OPC_ADD, TCG_REG_TMP0, TCG_REG_TMP0, addr);
965f63e7089SHuang Shiyuan        }
966f63e7089SHuang Shiyuan        addr = TCG_REG_TMP0;
967f63e7089SHuang Shiyuan    }
968f63e7089SHuang Shiyuan    tcg_out32(s, encode_v(opc, data, addr, 0, true));
969f63e7089SHuang Shiyuan}
970f63e7089SHuang Shiyuan
971139c1837SPaolo Bonzinistatic void tcg_out_ld(TCGContext *s, TCGType type, TCGReg arg,
972139c1837SPaolo Bonzini                       TCGReg arg1, intptr_t arg2)
973139c1837SPaolo Bonzini{
974f63e7089SHuang Shiyuan    RISCVInsn insn;
975f63e7089SHuang Shiyuan
976f63e7089SHuang Shiyuan    switch (type) {
977f63e7089SHuang Shiyuan    case TCG_TYPE_I32:
978f63e7089SHuang Shiyuan        tcg_out_ldst(s, OPC_LW, arg, arg1, arg2);
979f63e7089SHuang Shiyuan        break;
980f63e7089SHuang Shiyuan    case TCG_TYPE_I64:
981f63e7089SHuang Shiyuan        tcg_out_ldst(s, OPC_LD, arg, arg1, arg2);
982f63e7089SHuang Shiyuan        break;
983f63e7089SHuang Shiyuan    case TCG_TYPE_V64:
984f63e7089SHuang Shiyuan    case TCG_TYPE_V128:
985f63e7089SHuang Shiyuan    case TCG_TYPE_V256:
986f63e7089SHuang Shiyuan        if (type >= riscv_lg2_vlenb) {
987f63e7089SHuang Shiyuan            static const RISCVInsn whole_reg_ld[] = {
988f63e7089SHuang Shiyuan                OPC_VL1RE64_V, OPC_VL2RE64_V, OPC_VL4RE64_V, OPC_VL8RE64_V
989f63e7089SHuang Shiyuan            };
990f63e7089SHuang Shiyuan            unsigned idx = type - riscv_lg2_vlenb;
991f63e7089SHuang Shiyuan
992f63e7089SHuang Shiyuan            tcg_debug_assert(idx < ARRAY_SIZE(whole_reg_ld));
993f63e7089SHuang Shiyuan            insn = whole_reg_ld[idx];
994f63e7089SHuang Shiyuan        } else {
995f63e7089SHuang Shiyuan            static const RISCVInsn unit_stride_ld[] = {
996f63e7089SHuang Shiyuan                OPC_VLE8_V, OPC_VLE16_V, OPC_VLE32_V, OPC_VLE64_V
997f63e7089SHuang Shiyuan            };
998f63e7089SHuang Shiyuan            MemOp prev_vsew = set_vtype_len(s, type);
999f63e7089SHuang Shiyuan
1000f63e7089SHuang Shiyuan            tcg_debug_assert(prev_vsew < ARRAY_SIZE(unit_stride_ld));
1001f63e7089SHuang Shiyuan            insn = unit_stride_ld[prev_vsew];
1002f63e7089SHuang Shiyuan        }
1003f63e7089SHuang Shiyuan        tcg_out_vec_ldst(s, insn, arg, arg1, arg2);
1004f63e7089SHuang Shiyuan        break;
1005f63e7089SHuang Shiyuan    default:
1006f63e7089SHuang Shiyuan        g_assert_not_reached();
1007f63e7089SHuang Shiyuan    }
1008139c1837SPaolo Bonzini}
1009139c1837SPaolo Bonzini
1010139c1837SPaolo Bonzinistatic void tcg_out_st(TCGContext *s, TCGType type, TCGReg arg,
1011139c1837SPaolo Bonzini                       TCGReg arg1, intptr_t arg2)
1012139c1837SPaolo Bonzini{
1013f63e7089SHuang Shiyuan    RISCVInsn insn;
1014f63e7089SHuang Shiyuan
1015f63e7089SHuang Shiyuan    switch (type) {
1016f63e7089SHuang Shiyuan    case TCG_TYPE_I32:
1017f63e7089SHuang Shiyuan        tcg_out_ldst(s, OPC_SW, arg, arg1, arg2);
1018f63e7089SHuang Shiyuan        break;
1019f63e7089SHuang Shiyuan    case TCG_TYPE_I64:
1020f63e7089SHuang Shiyuan        tcg_out_ldst(s, OPC_SD, arg, arg1, arg2);
1021f63e7089SHuang Shiyuan        break;
1022f63e7089SHuang Shiyuan    case TCG_TYPE_V64:
1023f63e7089SHuang Shiyuan    case TCG_TYPE_V128:
1024f63e7089SHuang Shiyuan    case TCG_TYPE_V256:
1025f63e7089SHuang Shiyuan        if (type >= riscv_lg2_vlenb) {
1026f63e7089SHuang Shiyuan            static const RISCVInsn whole_reg_st[] = {
1027f63e7089SHuang Shiyuan                OPC_VS1R_V, OPC_VS2R_V, OPC_VS4R_V, OPC_VS8R_V
1028f63e7089SHuang Shiyuan            };
1029f63e7089SHuang Shiyuan            unsigned idx = type - riscv_lg2_vlenb;
1030f63e7089SHuang Shiyuan
1031f63e7089SHuang Shiyuan            tcg_debug_assert(idx < ARRAY_SIZE(whole_reg_st));
1032f63e7089SHuang Shiyuan            insn = whole_reg_st[idx];
1033f63e7089SHuang Shiyuan        } else {
1034f63e7089SHuang Shiyuan            static const RISCVInsn unit_stride_st[] = {
1035f63e7089SHuang Shiyuan                OPC_VSE8_V, OPC_VSE16_V, OPC_VSE32_V, OPC_VSE64_V
1036f63e7089SHuang Shiyuan            };
1037f63e7089SHuang Shiyuan            MemOp prev_vsew = set_vtype_len(s, type);
1038f63e7089SHuang Shiyuan
1039f63e7089SHuang Shiyuan            tcg_debug_assert(prev_vsew < ARRAY_SIZE(unit_stride_st));
1040f63e7089SHuang Shiyuan            insn = unit_stride_st[prev_vsew];
1041f63e7089SHuang Shiyuan        }
1042f63e7089SHuang Shiyuan        tcg_out_vec_ldst(s, insn, arg, arg1, arg2);
1043f63e7089SHuang Shiyuan        break;
1044f63e7089SHuang Shiyuan    default:
1045f63e7089SHuang Shiyuan        g_assert_not_reached();
1046f63e7089SHuang Shiyuan    }
1047139c1837SPaolo Bonzini}
1048139c1837SPaolo Bonzini
1049139c1837SPaolo Bonzinistatic bool tcg_out_sti(TCGContext *s, TCGType type, TCGArg val,
1050139c1837SPaolo Bonzini                        TCGReg base, intptr_t ofs)
1051139c1837SPaolo Bonzini{
1052139c1837SPaolo Bonzini    if (val == 0) {
1053139c1837SPaolo Bonzini        tcg_out_st(s, type, TCG_REG_ZERO, base, ofs);
1054139c1837SPaolo Bonzini        return true;
1055139c1837SPaolo Bonzini    }
1056139c1837SPaolo Bonzini    return false;
1057139c1837SPaolo Bonzini}
1058139c1837SPaolo Bonzini
1059139c1837SPaolo Bonzinistatic void tcg_out_addsub2(TCGContext *s,
1060139c1837SPaolo Bonzini                            TCGReg rl, TCGReg rh,
1061139c1837SPaolo Bonzini                            TCGReg al, TCGReg ah,
1062139c1837SPaolo Bonzini                            TCGArg bl, TCGArg bh,
1063139c1837SPaolo Bonzini                            bool cbl, bool cbh, bool is_sub, bool is32bit)
1064139c1837SPaolo Bonzini{
1065139c1837SPaolo Bonzini    const RISCVInsn opc_add = is32bit ? OPC_ADDW : OPC_ADD;
1066139c1837SPaolo Bonzini    const RISCVInsn opc_addi = is32bit ? OPC_ADDIW : OPC_ADDI;
1067139c1837SPaolo Bonzini    const RISCVInsn opc_sub = is32bit ? OPC_SUBW : OPC_SUB;
1068139c1837SPaolo Bonzini    TCGReg th = TCG_REG_TMP1;
1069139c1837SPaolo Bonzini
1070139c1837SPaolo Bonzini    /* If we have a negative constant such that negating it would
1071139c1837SPaolo Bonzini       make the high part zero, we can (usually) eliminate one insn.  */
1072139c1837SPaolo Bonzini    if (cbl && cbh && bh == -1 && bl != 0) {
1073139c1837SPaolo Bonzini        bl = -bl;
1074139c1837SPaolo Bonzini        bh = 0;
1075139c1837SPaolo Bonzini        is_sub = !is_sub;
1076139c1837SPaolo Bonzini    }
1077139c1837SPaolo Bonzini
1078139c1837SPaolo Bonzini    /* By operating on the high part first, we get to use the final
1079139c1837SPaolo Bonzini       carry operation to move back from the temporary.  */
1080139c1837SPaolo Bonzini    if (!cbh) {
1081139c1837SPaolo Bonzini        tcg_out_opc_reg(s, (is_sub ? opc_sub : opc_add), th, ah, bh);
1082139c1837SPaolo Bonzini    } else if (bh != 0 || ah == rl) {
1083139c1837SPaolo Bonzini        tcg_out_opc_imm(s, opc_addi, th, ah, (is_sub ? -bh : bh));
1084139c1837SPaolo Bonzini    } else {
1085139c1837SPaolo Bonzini        th = ah;
1086139c1837SPaolo Bonzini    }
1087139c1837SPaolo Bonzini
1088139c1837SPaolo Bonzini    /* Note that tcg optimization should eliminate the bl == 0 case.  */
1089139c1837SPaolo Bonzini    if (is_sub) {
1090139c1837SPaolo Bonzini        if (cbl) {
1091139c1837SPaolo Bonzini            tcg_out_opc_imm(s, OPC_SLTIU, TCG_REG_TMP0, al, bl);
1092139c1837SPaolo Bonzini            tcg_out_opc_imm(s, opc_addi, rl, al, -bl);
1093139c1837SPaolo Bonzini        } else {
1094139c1837SPaolo Bonzini            tcg_out_opc_reg(s, OPC_SLTU, TCG_REG_TMP0, al, bl);
1095139c1837SPaolo Bonzini            tcg_out_opc_reg(s, opc_sub, rl, al, bl);
1096139c1837SPaolo Bonzini        }
1097139c1837SPaolo Bonzini        tcg_out_opc_reg(s, opc_sub, rh, th, TCG_REG_TMP0);
1098139c1837SPaolo Bonzini    } else {
1099139c1837SPaolo Bonzini        if (cbl) {
1100139c1837SPaolo Bonzini            tcg_out_opc_imm(s, opc_addi, rl, al, bl);
1101139c1837SPaolo Bonzini            tcg_out_opc_imm(s, OPC_SLTIU, TCG_REG_TMP0, rl, bl);
11029b246685SRichard Henderson        } else if (al == bl) {
11039b246685SRichard Henderson            /*
11049b246685SRichard Henderson             * If the input regs overlap, this is a simple doubling
11059b246685SRichard Henderson             * and carry-out is the input msb.  This special case is
11069b246685SRichard Henderson             * required when the output reg overlaps the input,
11079b246685SRichard Henderson             * but we might as well use it always.
11089b246685SRichard Henderson             */
1109139c1837SPaolo Bonzini            tcg_out_opc_imm(s, OPC_SLTI, TCG_REG_TMP0, al, 0);
11109b246685SRichard Henderson            tcg_out_opc_reg(s, opc_add, rl, al, al);
1111139c1837SPaolo Bonzini        } else {
1112139c1837SPaolo Bonzini            tcg_out_opc_reg(s, opc_add, rl, al, bl);
1113139c1837SPaolo Bonzini            tcg_out_opc_reg(s, OPC_SLTU, TCG_REG_TMP0,
1114139c1837SPaolo Bonzini                            rl, (rl == bl ? al : bl));
1115139c1837SPaolo Bonzini        }
1116139c1837SPaolo Bonzini        tcg_out_opc_reg(s, opc_add, rh, th, TCG_REG_TMP0);
1117139c1837SPaolo Bonzini    }
1118139c1837SPaolo Bonzini}
1119139c1837SPaolo Bonzini
1120f63e7089SHuang Shiyuanstatic bool tcg_out_dup_vec(TCGContext *s, TCGType type, unsigned vece,
1121f63e7089SHuang Shiyuan                                   TCGReg dst, TCGReg src)
1122f63e7089SHuang Shiyuan{
1123d4be6ee1STANG Tiancheng    set_vtype_len_sew(s, type, vece);
1124d4be6ee1STANG Tiancheng    tcg_out_opc_vx(s, OPC_VMV_V_X, dst, 0, src);
1125d4be6ee1STANG Tiancheng    return true;
1126f63e7089SHuang Shiyuan}
1127f63e7089SHuang Shiyuan
1128f63e7089SHuang Shiyuanstatic bool tcg_out_dupm_vec(TCGContext *s, TCGType type, unsigned vece,
1129f63e7089SHuang Shiyuan                                    TCGReg dst, TCGReg base, intptr_t offset)
1130f63e7089SHuang Shiyuan{
1131d4be6ee1STANG Tiancheng    tcg_out_ld(s, TCG_TYPE_REG, TCG_REG_TMP0, base, offset);
1132d4be6ee1STANG Tiancheng    return tcg_out_dup_vec(s, type, vece, dst, TCG_REG_TMP0);
1133f63e7089SHuang Shiyuan}
1134f63e7089SHuang Shiyuan
1135f63e7089SHuang Shiyuanstatic void tcg_out_dupi_vec(TCGContext *s, TCGType type, unsigned vece,
1136f63e7089SHuang Shiyuan                                    TCGReg dst, int64_t arg)
1137f63e7089SHuang Shiyuan{
1138d4be6ee1STANG Tiancheng    /* Arg is replicated by VECE; extract the highest element. */
1139d4be6ee1STANG Tiancheng    arg >>= (-8 << vece) & 63;
1140d4be6ee1STANG Tiancheng
1141d4be6ee1STANG Tiancheng    if (arg >= -16 && arg < 16) {
1142d4be6ee1STANG Tiancheng        if (arg == 0 || arg == -1) {
1143d4be6ee1STANG Tiancheng            set_vtype_len(s, type);
1144d4be6ee1STANG Tiancheng        } else {
1145d4be6ee1STANG Tiancheng            set_vtype_len_sew(s, type, vece);
1146d4be6ee1STANG Tiancheng        }
1147d4be6ee1STANG Tiancheng        tcg_out_opc_vi(s, OPC_VMV_V_I, dst, 0, arg);
1148d4be6ee1STANG Tiancheng        return;
1149d4be6ee1STANG Tiancheng    }
1150d4be6ee1STANG Tiancheng    tcg_out_movi(s, TCG_TYPE_I64, TCG_REG_TMP0, arg);
1151d4be6ee1STANG Tiancheng    tcg_out_dup_vec(s, type, vece, dst, TCG_REG_TMP0);
1152f63e7089SHuang Shiyuan}
1153f63e7089SHuang Shiyuan
1154139c1837SPaolo Bonzinistatic const struct {
1155139c1837SPaolo Bonzini    RISCVInsn op;
1156139c1837SPaolo Bonzini    bool swap;
1157139c1837SPaolo Bonzini} tcg_brcond_to_riscv[] = {
1158139c1837SPaolo Bonzini    [TCG_COND_EQ] =  { OPC_BEQ,  false },
1159139c1837SPaolo Bonzini    [TCG_COND_NE] =  { OPC_BNE,  false },
1160139c1837SPaolo Bonzini    [TCG_COND_LT] =  { OPC_BLT,  false },
1161139c1837SPaolo Bonzini    [TCG_COND_GE] =  { OPC_BGE,  false },
1162139c1837SPaolo Bonzini    [TCG_COND_LE] =  { OPC_BGE,  true  },
1163139c1837SPaolo Bonzini    [TCG_COND_GT] =  { OPC_BLT,  true  },
1164139c1837SPaolo Bonzini    [TCG_COND_LTU] = { OPC_BLTU, false },
1165139c1837SPaolo Bonzini    [TCG_COND_GEU] = { OPC_BGEU, false },
1166139c1837SPaolo Bonzini    [TCG_COND_LEU] = { OPC_BGEU, true  },
1167139c1837SPaolo Bonzini    [TCG_COND_GTU] = { OPC_BLTU, true  }
1168139c1837SPaolo Bonzini};
1169139c1837SPaolo Bonzini
1170139c1837SPaolo Bonzinistatic void tcg_out_brcond(TCGContext *s, TCGCond cond, TCGReg arg1,
1171139c1837SPaolo Bonzini                           TCGReg arg2, TCGLabel *l)
1172139c1837SPaolo Bonzini{
1173139c1837SPaolo Bonzini    RISCVInsn op = tcg_brcond_to_riscv[cond].op;
1174139c1837SPaolo Bonzini
1175139c1837SPaolo Bonzini    tcg_debug_assert(op != 0);
1176139c1837SPaolo Bonzini
1177139c1837SPaolo Bonzini    if (tcg_brcond_to_riscv[cond].swap) {
1178139c1837SPaolo Bonzini        TCGReg t = arg1;
1179139c1837SPaolo Bonzini        arg1 = arg2;
1180139c1837SPaolo Bonzini        arg2 = t;
1181139c1837SPaolo Bonzini    }
1182139c1837SPaolo Bonzini
1183139c1837SPaolo Bonzini    tcg_out_reloc(s, s->code_ptr, R_RISCV_BRANCH, l, 0);
1184139c1837SPaolo Bonzini    tcg_out_opc_branch(s, op, arg1, arg2, 0);
1185139c1837SPaolo Bonzini}
1186139c1837SPaolo Bonzini
1187f6453695SRichard Henderson#define SETCOND_INV    TCG_TARGET_NB_REGS
1188f6453695SRichard Henderson#define SETCOND_NEZ    (SETCOND_INV << 1)
1189f6453695SRichard Henderson#define SETCOND_FLAGS  (SETCOND_INV | SETCOND_NEZ)
1190f6453695SRichard Henderson
1191f6453695SRichard Hendersonstatic int tcg_out_setcond_int(TCGContext *s, TCGCond cond, TCGReg ret,
1192f6453695SRichard Henderson                               TCGReg arg1, tcg_target_long arg2, bool c2)
1193139c1837SPaolo Bonzini{
1194f6453695SRichard Henderson    int flags = 0;
1195f6453695SRichard Henderson
1196139c1837SPaolo Bonzini    switch (cond) {
1197f6453695SRichard Henderson    case TCG_COND_EQ:    /* -> NE  */
1198f6453695SRichard Henderson    case TCG_COND_GE:    /* -> LT  */
1199f6453695SRichard Henderson    case TCG_COND_GEU:   /* -> LTU */
1200f6453695SRichard Henderson    case TCG_COND_GT:    /* -> LE  */
1201f6453695SRichard Henderson    case TCG_COND_GTU:   /* -> LEU */
1202f6453695SRichard Henderson        cond = tcg_invert_cond(cond);
1203f6453695SRichard Henderson        flags ^= SETCOND_INV;
1204139c1837SPaolo Bonzini        break;
1205f6453695SRichard Henderson    default:
1206139c1837SPaolo Bonzini        break;
1207f6453695SRichard Henderson    }
1208f6453695SRichard Henderson
1209f6453695SRichard Henderson    switch (cond) {
1210139c1837SPaolo Bonzini    case TCG_COND_LE:
1211139c1837SPaolo Bonzini    case TCG_COND_LEU:
1212f6453695SRichard Henderson        /*
1213f6453695SRichard Henderson         * If we have a constant input, the most efficient way to implement
1214f6453695SRichard Henderson         * LE is by adding 1 and using LT.  Watch out for wrap around for LEU.
1215f6453695SRichard Henderson         * We don't need to care for this for LE because the constant input
1216f6453695SRichard Henderson         * is constrained to signed 12-bit, and 0x800 is representable in the
1217f6453695SRichard Henderson         * temporary register.
1218f6453695SRichard Henderson         */
1219f6453695SRichard Henderson        if (c2) {
1220f6453695SRichard Henderson            if (cond == TCG_COND_LEU) {
1221f6453695SRichard Henderson                /* unsigned <= -1 is true */
1222f6453695SRichard Henderson                if (arg2 == -1) {
1223f6453695SRichard Henderson                    tcg_out_movi(s, TCG_TYPE_REG, ret, !(flags & SETCOND_INV));
1224f6453695SRichard Henderson                    return ret;
1225f6453695SRichard Henderson                }
1226f6453695SRichard Henderson                cond = TCG_COND_LTU;
1227f6453695SRichard Henderson            } else {
1228f6453695SRichard Henderson                cond = TCG_COND_LT;
1229f6453695SRichard Henderson            }
1230f6453695SRichard Henderson            tcg_debug_assert(arg2 <= 0x7ff);
1231f6453695SRichard Henderson            if (++arg2 == 0x800) {
1232f6453695SRichard Henderson                tcg_out_movi(s, TCG_TYPE_REG, TCG_REG_TMP0, arg2);
1233f6453695SRichard Henderson                arg2 = TCG_REG_TMP0;
1234f6453695SRichard Henderson                c2 = false;
1235f6453695SRichard Henderson            }
1236f6453695SRichard Henderson        } else {
1237f6453695SRichard Henderson            TCGReg tmp = arg2;
1238f6453695SRichard Henderson            arg2 = arg1;
1239f6453695SRichard Henderson            arg1 = tmp;
1240f6453695SRichard Henderson            cond = tcg_swap_cond(cond);    /* LE -> GE */
1241f6453695SRichard Henderson            cond = tcg_invert_cond(cond);  /* GE -> LT */
1242f6453695SRichard Henderson            flags ^= SETCOND_INV;
1243f6453695SRichard Henderson        }
1244139c1837SPaolo Bonzini        break;
1245f6453695SRichard Henderson    default:
1246f6453695SRichard Henderson        break;
1247f6453695SRichard Henderson    }
1248f6453695SRichard Henderson
1249f6453695SRichard Henderson    switch (cond) {
1250f6453695SRichard Henderson    case TCG_COND_NE:
1251f6453695SRichard Henderson        flags |= SETCOND_NEZ;
1252f6453695SRichard Henderson        if (!c2) {
1253f6453695SRichard Henderson            tcg_out_opc_reg(s, OPC_XOR, ret, arg1, arg2);
1254f6453695SRichard Henderson        } else if (arg2 == 0) {
1255f6453695SRichard Henderson            ret = arg1;
1256f6453695SRichard Henderson        } else {
1257f6453695SRichard Henderson            tcg_out_opc_imm(s, OPC_XORI, ret, arg1, arg2);
1258f6453695SRichard Henderson        }
1259f6453695SRichard Henderson        break;
1260f6453695SRichard Henderson
1261f6453695SRichard Henderson    case TCG_COND_LT:
1262f6453695SRichard Henderson        if (c2) {
1263f6453695SRichard Henderson            tcg_out_opc_imm(s, OPC_SLTI, ret, arg1, arg2);
1264f6453695SRichard Henderson        } else {
1265f6453695SRichard Henderson            tcg_out_opc_reg(s, OPC_SLT, ret, arg1, arg2);
1266f6453695SRichard Henderson        }
1267f6453695SRichard Henderson        break;
1268f6453695SRichard Henderson
1269f6453695SRichard Henderson    case TCG_COND_LTU:
1270f6453695SRichard Henderson        if (c2) {
1271f6453695SRichard Henderson            tcg_out_opc_imm(s, OPC_SLTIU, ret, arg1, arg2);
1272f6453695SRichard Henderson        } else {
1273f6453695SRichard Henderson            tcg_out_opc_reg(s, OPC_SLTU, ret, arg1, arg2);
1274f6453695SRichard Henderson        }
1275f6453695SRichard Henderson        break;
1276f6453695SRichard Henderson
1277f6453695SRichard Henderson    default:
1278f6453695SRichard Henderson        g_assert_not_reached();
1279f6453695SRichard Henderson    }
1280f6453695SRichard Henderson
1281f6453695SRichard Henderson    return ret | flags;
1282f6453695SRichard Henderson}
1283f6453695SRichard Henderson
1284f6453695SRichard Hendersonstatic void tcg_out_setcond(TCGContext *s, TCGCond cond, TCGReg ret,
1285f6453695SRichard Henderson                            TCGReg arg1, tcg_target_long arg2, bool c2)
1286f6453695SRichard Henderson{
1287f6453695SRichard Henderson    int tmpflags = tcg_out_setcond_int(s, cond, ret, arg1, arg2, c2);
1288f6453695SRichard Henderson
1289f6453695SRichard Henderson    if (tmpflags != ret) {
1290f6453695SRichard Henderson        TCGReg tmp = tmpflags & ~SETCOND_FLAGS;
1291f6453695SRichard Henderson
1292f6453695SRichard Henderson        switch (tmpflags & SETCOND_FLAGS) {
1293f6453695SRichard Henderson        case SETCOND_INV:
1294f6453695SRichard Henderson            /* Intermediate result is boolean: simply invert. */
1295f6453695SRichard Henderson            tcg_out_opc_imm(s, OPC_XORI, ret, tmp, 1);
1296f6453695SRichard Henderson            break;
1297f6453695SRichard Henderson        case SETCOND_NEZ:
1298f6453695SRichard Henderson            /* Intermediate result is zero/non-zero: test != 0. */
1299f6453695SRichard Henderson            tcg_out_opc_reg(s, OPC_SLTU, ret, TCG_REG_ZERO, tmp);
1300f6453695SRichard Henderson            break;
1301f6453695SRichard Henderson        case SETCOND_NEZ | SETCOND_INV:
1302f6453695SRichard Henderson            /* Intermediate result is zero/non-zero: test == 0. */
1303f6453695SRichard Henderson            tcg_out_opc_imm(s, OPC_SLTIU, ret, tmp, 1);
1304139c1837SPaolo Bonzini            break;
1305139c1837SPaolo Bonzini        default:
1306139c1837SPaolo Bonzini            g_assert_not_reached();
1307f6453695SRichard Henderson        }
1308139c1837SPaolo Bonzini    }
1309139c1837SPaolo Bonzini}
1310139c1837SPaolo Bonzini
131141e4c0a9SRichard Hendersonstatic void tcg_out_negsetcond(TCGContext *s, TCGCond cond, TCGReg ret,
131241e4c0a9SRichard Henderson                               TCGReg arg1, tcg_target_long arg2, bool c2)
131341e4c0a9SRichard Henderson{
131441e4c0a9SRichard Henderson    int tmpflags;
131541e4c0a9SRichard Henderson    TCGReg tmp;
131641e4c0a9SRichard Henderson
131741e4c0a9SRichard Henderson    /* For LT/GE comparison against 0, replicate the sign bit. */
131841e4c0a9SRichard Henderson    if (c2 && arg2 == 0) {
131941e4c0a9SRichard Henderson        switch (cond) {
132041e4c0a9SRichard Henderson        case TCG_COND_GE:
132141e4c0a9SRichard Henderson            tcg_out_opc_imm(s, OPC_XORI, ret, arg1, -1);
132241e4c0a9SRichard Henderson            arg1 = ret;
132341e4c0a9SRichard Henderson            /* fall through */
132441e4c0a9SRichard Henderson        case TCG_COND_LT:
132541e4c0a9SRichard Henderson            tcg_out_opc_imm(s, OPC_SRAI, ret, arg1, TCG_TARGET_REG_BITS - 1);
132641e4c0a9SRichard Henderson            return;
132741e4c0a9SRichard Henderson        default:
132841e4c0a9SRichard Henderson            break;
132941e4c0a9SRichard Henderson        }
133041e4c0a9SRichard Henderson    }
133141e4c0a9SRichard Henderson
133241e4c0a9SRichard Henderson    tmpflags = tcg_out_setcond_int(s, cond, ret, arg1, arg2, c2);
133341e4c0a9SRichard Henderson    tmp = tmpflags & ~SETCOND_FLAGS;
133441e4c0a9SRichard Henderson
133541e4c0a9SRichard Henderson    /* If intermediate result is zero/non-zero: test != 0. */
133641e4c0a9SRichard Henderson    if (tmpflags & SETCOND_NEZ) {
133741e4c0a9SRichard Henderson        tcg_out_opc_reg(s, OPC_SLTU, ret, TCG_REG_ZERO, tmp);
133841e4c0a9SRichard Henderson        tmp = ret;
133941e4c0a9SRichard Henderson    }
134041e4c0a9SRichard Henderson
134141e4c0a9SRichard Henderson    /* Produce the 0/-1 result. */
134241e4c0a9SRichard Henderson    if (tmpflags & SETCOND_INV) {
134341e4c0a9SRichard Henderson        tcg_out_opc_imm(s, OPC_ADDI, ret, tmp, -1);
134441e4c0a9SRichard Henderson    } else {
134541e4c0a9SRichard Henderson        tcg_out_opc_reg(s, OPC_SUB, ret, TCG_REG_ZERO, tmp);
134641e4c0a9SRichard Henderson    }
134741e4c0a9SRichard Henderson}
134841e4c0a9SRichard Henderson
1349a18d783eSRichard Hendersonstatic void tcg_out_movcond_zicond(TCGContext *s, TCGReg ret, TCGReg test_ne,
1350a18d783eSRichard Henderson                                   int val1, bool c_val1,
1351a18d783eSRichard Henderson                                   int val2, bool c_val2)
1352a18d783eSRichard Henderson{
1353a18d783eSRichard Henderson    if (val1 == 0) {
1354a18d783eSRichard Henderson        if (c_val2) {
1355a18d783eSRichard Henderson            tcg_out_movi(s, TCG_TYPE_REG, TCG_REG_TMP1, val2);
1356a18d783eSRichard Henderson            val2 = TCG_REG_TMP1;
1357a18d783eSRichard Henderson        }
1358a18d783eSRichard Henderson        tcg_out_opc_reg(s, OPC_CZERO_NEZ, ret, val2, test_ne);
1359a18d783eSRichard Henderson        return;
1360a18d783eSRichard Henderson    }
1361a18d783eSRichard Henderson
1362a18d783eSRichard Henderson    if (val2 == 0) {
1363a18d783eSRichard Henderson        if (c_val1) {
1364a18d783eSRichard Henderson            tcg_out_movi(s, TCG_TYPE_REG, TCG_REG_TMP1, val1);
1365a18d783eSRichard Henderson            val1 = TCG_REG_TMP1;
1366a18d783eSRichard Henderson        }
1367a18d783eSRichard Henderson        tcg_out_opc_reg(s, OPC_CZERO_EQZ, ret, val1, test_ne);
1368a18d783eSRichard Henderson        return;
1369a18d783eSRichard Henderson    }
1370a18d783eSRichard Henderson
1371a18d783eSRichard Henderson    if (c_val2) {
1372a18d783eSRichard Henderson        if (c_val1) {
1373a18d783eSRichard Henderson            tcg_out_movi(s, TCG_TYPE_REG, TCG_REG_TMP1, val1 - val2);
1374a18d783eSRichard Henderson        } else {
1375a18d783eSRichard Henderson            tcg_out_opc_imm(s, OPC_ADDI, TCG_REG_TMP1, val1, -val2);
1376a18d783eSRichard Henderson        }
1377a18d783eSRichard Henderson        tcg_out_opc_reg(s, OPC_CZERO_EQZ, ret, TCG_REG_TMP1, test_ne);
1378a18d783eSRichard Henderson        tcg_out_opc_imm(s, OPC_ADDI, ret, ret, val2);
1379a18d783eSRichard Henderson        return;
1380a18d783eSRichard Henderson    }
1381a18d783eSRichard Henderson
1382a18d783eSRichard Henderson    if (c_val1) {
1383a18d783eSRichard Henderson        tcg_out_opc_imm(s, OPC_ADDI, TCG_REG_TMP1, val2, -val1);
1384a18d783eSRichard Henderson        tcg_out_opc_reg(s, OPC_CZERO_NEZ, ret, TCG_REG_TMP1, test_ne);
1385a18d783eSRichard Henderson        tcg_out_opc_imm(s, OPC_ADDI, ret, ret, val1);
1386a18d783eSRichard Henderson        return;
1387a18d783eSRichard Henderson    }
1388a18d783eSRichard Henderson
1389a18d783eSRichard Henderson    tcg_out_opc_reg(s, OPC_CZERO_NEZ, TCG_REG_TMP1, val2, test_ne);
1390a18d783eSRichard Henderson    tcg_out_opc_reg(s, OPC_CZERO_EQZ, TCG_REG_TMP0, val1, test_ne);
1391a18d783eSRichard Henderson    tcg_out_opc_reg(s, OPC_OR, ret, TCG_REG_TMP0, TCG_REG_TMP1);
1392a18d783eSRichard Henderson}
1393a18d783eSRichard Henderson
1394a18d783eSRichard Hendersonstatic void tcg_out_movcond_br1(TCGContext *s, TCGCond cond, TCGReg ret,
1395a18d783eSRichard Henderson                                TCGReg cmp1, TCGReg cmp2,
1396a18d783eSRichard Henderson                                int val, bool c_val)
1397a18d783eSRichard Henderson{
1398a18d783eSRichard Henderson    RISCVInsn op;
1399a18d783eSRichard Henderson    int disp = 8;
1400a18d783eSRichard Henderson
1401a18d783eSRichard Henderson    tcg_debug_assert((unsigned)cond < ARRAY_SIZE(tcg_brcond_to_riscv));
1402a18d783eSRichard Henderson    op = tcg_brcond_to_riscv[cond].op;
1403a18d783eSRichard Henderson    tcg_debug_assert(op != 0);
1404a18d783eSRichard Henderson
1405a18d783eSRichard Henderson    if (tcg_brcond_to_riscv[cond].swap) {
1406a18d783eSRichard Henderson        tcg_out_opc_branch(s, op, cmp2, cmp1, disp);
1407a18d783eSRichard Henderson    } else {
1408a18d783eSRichard Henderson        tcg_out_opc_branch(s, op, cmp1, cmp2, disp);
1409a18d783eSRichard Henderson    }
1410a18d783eSRichard Henderson    if (c_val) {
1411a18d783eSRichard Henderson        tcg_out_opc_imm(s, OPC_ADDI, ret, TCG_REG_ZERO, val);
1412a18d783eSRichard Henderson    } else {
1413a18d783eSRichard Henderson        tcg_out_opc_imm(s, OPC_ADDI, ret, val, 0);
1414a18d783eSRichard Henderson    }
1415a18d783eSRichard Henderson}
1416a18d783eSRichard Henderson
1417a18d783eSRichard Hendersonstatic void tcg_out_movcond_br2(TCGContext *s, TCGCond cond, TCGReg ret,
1418a18d783eSRichard Henderson                                TCGReg cmp1, TCGReg cmp2,
1419a18d783eSRichard Henderson                                int val1, bool c_val1,
1420a18d783eSRichard Henderson                                int val2, bool c_val2)
1421a18d783eSRichard Henderson{
1422a18d783eSRichard Henderson    TCGReg tmp;
1423a18d783eSRichard Henderson
1424a18d783eSRichard Henderson    /* TCG optimizer reorders to prefer ret matching val2. */
1425a18d783eSRichard Henderson    if (!c_val2 && ret == val2) {
1426a18d783eSRichard Henderson        cond = tcg_invert_cond(cond);
1427a18d783eSRichard Henderson        tcg_out_movcond_br1(s, cond, ret, cmp1, cmp2, val1, c_val1);
1428a18d783eSRichard Henderson        return;
1429a18d783eSRichard Henderson    }
1430a18d783eSRichard Henderson
1431a18d783eSRichard Henderson    if (!c_val1 && ret == val1) {
1432a18d783eSRichard Henderson        tcg_out_movcond_br1(s, cond, ret, cmp1, cmp2, val2, c_val2);
1433a18d783eSRichard Henderson        return;
1434a18d783eSRichard Henderson    }
1435a18d783eSRichard Henderson
1436a18d783eSRichard Henderson    tmp = (ret == cmp1 || ret == cmp2 ? TCG_REG_TMP1 : ret);
1437a18d783eSRichard Henderson    if (c_val1) {
1438a18d783eSRichard Henderson        tcg_out_movi(s, TCG_TYPE_REG, tmp, val1);
1439a18d783eSRichard Henderson    } else {
1440a18d783eSRichard Henderson        tcg_out_mov(s, TCG_TYPE_REG, tmp, val1);
1441a18d783eSRichard Henderson    }
1442a18d783eSRichard Henderson    tcg_out_movcond_br1(s, cond, tmp, cmp1, cmp2, val2, c_val2);
1443a18d783eSRichard Henderson    tcg_out_mov(s, TCG_TYPE_REG, ret, tmp);
1444a18d783eSRichard Henderson}
1445a18d783eSRichard Henderson
1446a18d783eSRichard Hendersonstatic void tcg_out_movcond(TCGContext *s, TCGCond cond, TCGReg ret,
1447a18d783eSRichard Henderson                            TCGReg cmp1, int cmp2, bool c_cmp2,
1448a18d783eSRichard Henderson                            TCGReg val1, bool c_val1,
1449a18d783eSRichard Henderson                            TCGReg val2, bool c_val2)
1450a18d783eSRichard Henderson{
1451a18d783eSRichard Henderson    int tmpflags;
1452a18d783eSRichard Henderson    TCGReg t;
1453a18d783eSRichard Henderson
1454b86c6ba6SRichard Henderson    if (!(cpuinfo & CPUINFO_ZICOND) && (!c_cmp2 || cmp2 == 0)) {
1455a18d783eSRichard Henderson        tcg_out_movcond_br2(s, cond, ret, cmp1, cmp2,
1456a18d783eSRichard Henderson                            val1, c_val1, val2, c_val2);
1457a18d783eSRichard Henderson        return;
1458a18d783eSRichard Henderson    }
1459a18d783eSRichard Henderson
1460a18d783eSRichard Henderson    tmpflags = tcg_out_setcond_int(s, cond, TCG_REG_TMP0, cmp1, cmp2, c_cmp2);
1461a18d783eSRichard Henderson    t = tmpflags & ~SETCOND_FLAGS;
1462a18d783eSRichard Henderson
1463b86c6ba6SRichard Henderson    if (cpuinfo & CPUINFO_ZICOND) {
1464a18d783eSRichard Henderson        if (tmpflags & SETCOND_INV) {
1465a18d783eSRichard Henderson            tcg_out_movcond_zicond(s, ret, t, val2, c_val2, val1, c_val1);
1466a18d783eSRichard Henderson        } else {
1467a18d783eSRichard Henderson            tcg_out_movcond_zicond(s, ret, t, val1, c_val1, val2, c_val2);
1468a18d783eSRichard Henderson        }
1469a18d783eSRichard Henderson    } else {
1470a18d783eSRichard Henderson        cond = tmpflags & SETCOND_INV ? TCG_COND_EQ : TCG_COND_NE;
1471a18d783eSRichard Henderson        tcg_out_movcond_br2(s, cond, ret, t, TCG_REG_ZERO,
1472a18d783eSRichard Henderson                            val1, c_val1, val2, c_val2);
1473a18d783eSRichard Henderson    }
1474a18d783eSRichard Henderson}
1475a18d783eSRichard Henderson
1476a30498fcSRichard Hendersonstatic void tcg_out_cltz(TCGContext *s, TCGType type, RISCVInsn insn,
1477a30498fcSRichard Henderson                         TCGReg ret, TCGReg src1, int src2, bool c_src2)
1478a30498fcSRichard Henderson{
1479a30498fcSRichard Henderson    tcg_out_opc_imm(s, insn, ret, src1, 0);
1480a30498fcSRichard Henderson
1481a30498fcSRichard Henderson    if (!c_src2 || src2 != (type == TCG_TYPE_I32 ? 32 : 64)) {
1482a30498fcSRichard Henderson        /*
1483a30498fcSRichard Henderson         * The requested zero result does not match the insn, so adjust.
1484a30498fcSRichard Henderson         * Note that constraints put 'ret' in a new register, so the
1485a30498fcSRichard Henderson         * computation above did not clobber either 'src1' or 'src2'.
1486a30498fcSRichard Henderson         */
1487a30498fcSRichard Henderson        tcg_out_movcond(s, TCG_COND_EQ, ret, src1, 0, true,
1488a30498fcSRichard Henderson                        src2, c_src2, ret, false);
1489a30498fcSRichard Henderson    }
1490a30498fcSRichard Henderson}
1491a30498fcSRichard Henderson
1492*a31768c0STANG Tianchengstatic void tcg_out_cmpsel(TCGContext *s, TCGType type, unsigned vece,
1493*a31768c0STANG Tiancheng                           TCGCond cond, TCGReg ret,
1494*a31768c0STANG Tiancheng                           TCGReg cmp1, TCGReg cmp2, bool c_cmp2,
1495*a31768c0STANG Tiancheng                           TCGReg val1, bool c_val1,
1496*a31768c0STANG Tiancheng                           TCGReg val2, bool c_val2)
1497*a31768c0STANG Tiancheng{
1498*a31768c0STANG Tiancheng    set_vtype_len_sew(s, type, vece);
1499*a31768c0STANG Tiancheng
1500*a31768c0STANG Tiancheng    /* Use only vmerge_vim if possible, by inverting the test. */
1501*a31768c0STANG Tiancheng    if (c_val2 && !c_val1) {
1502*a31768c0STANG Tiancheng        TCGArg temp = val1;
1503*a31768c0STANG Tiancheng        cond = tcg_invert_cond(cond);
1504*a31768c0STANG Tiancheng        val1 = val2;
1505*a31768c0STANG Tiancheng        val2 = temp;
1506*a31768c0STANG Tiancheng        c_val1 = true;
1507*a31768c0STANG Tiancheng        c_val2 = false;
1508*a31768c0STANG Tiancheng    }
1509*a31768c0STANG Tiancheng
1510*a31768c0STANG Tiancheng    /* Perform the comparison into V0 mask. */
1511*a31768c0STANG Tiancheng    if (c_cmp2) {
1512*a31768c0STANG Tiancheng        tcg_out_opc_vi(s, tcg_cmpcond_to_rvv_vi[cond].op, TCG_REG_V0, cmp1,
1513*a31768c0STANG Tiancheng                       cmp2 - tcg_cmpcond_to_rvv_vi[cond].adjust);
1514*a31768c0STANG Tiancheng    } else if (tcg_cmpcond_to_rvv_vv[cond].swap) {
1515*a31768c0STANG Tiancheng        tcg_out_opc_vv(s, tcg_cmpcond_to_rvv_vv[cond].op,
1516*a31768c0STANG Tiancheng                       TCG_REG_V0, cmp2, cmp1);
1517*a31768c0STANG Tiancheng    } else {
1518*a31768c0STANG Tiancheng        tcg_out_opc_vv(s, tcg_cmpcond_to_rvv_vv[cond].op,
1519*a31768c0STANG Tiancheng                       TCG_REG_V0, cmp1, cmp2);
1520*a31768c0STANG Tiancheng    }
1521*a31768c0STANG Tiancheng    if (c_val1) {
1522*a31768c0STANG Tiancheng        if (c_val2) {
1523*a31768c0STANG Tiancheng            tcg_out_opc_vi(s, OPC_VMV_V_I, ret, 0, val2);
1524*a31768c0STANG Tiancheng            val2 = ret;
1525*a31768c0STANG Tiancheng        }
1526*a31768c0STANG Tiancheng        /* vd[i] == v0.mask[i] ? imm : vs2[i] */
1527*a31768c0STANG Tiancheng        tcg_out_opc_vim_mask(s, OPC_VMERGE_VIM, ret, val2, val1);
1528*a31768c0STANG Tiancheng    } else {
1529*a31768c0STANG Tiancheng        /* vd[i] == v0.mask[i] ? vs1[i] : vs2[i] */
1530*a31768c0STANG Tiancheng        tcg_out_opc_vvm_mask(s, OPC_VMERGE_VVM, ret, val2, val1);
1531*a31768c0STANG Tiancheng    }
1532*a31768c0STANG Tiancheng}
1533*a31768c0STANG Tiancheng
1534f63e7089SHuang Shiyuanstatic void init_setting_vtype(TCGContext *s)
1535f63e7089SHuang Shiyuan{
1536f63e7089SHuang Shiyuan    s->riscv_cur_type = TCG_TYPE_COUNT;
1537f63e7089SHuang Shiyuan}
1538f63e7089SHuang Shiyuan
15392be7d76bSRichard Hendersonstatic void tcg_out_call_int(TCGContext *s, const tcg_insn_unit *arg, bool tail)
1540139c1837SPaolo Bonzini{
1541139c1837SPaolo Bonzini    TCGReg link = tail ? TCG_REG_ZERO : TCG_REG_RA;
1542139c1837SPaolo Bonzini    ptrdiff_t offset = tcg_pcrel_diff(s, arg);
1543139c1837SPaolo Bonzini    int ret;
1544139c1837SPaolo Bonzini
1545f63e7089SHuang Shiyuan    init_setting_vtype(s);
1546f63e7089SHuang Shiyuan
1547844d0442SRichard Henderson    tcg_debug_assert((offset & 1) == 0);
1548844d0442SRichard Henderson    if (offset == sextreg(offset, 0, 20)) {
1549139c1837SPaolo Bonzini        /* short jump: -2097150 to 2097152 */
1550139c1837SPaolo Bonzini        tcg_out_opc_jump(s, OPC_JAL, link, offset);
1551aeb6326eSRichard Henderson    } else if (offset == (int32_t)offset) {
1552139c1837SPaolo Bonzini        /* long jump: -2147483646 to 2147483648 */
1553139c1837SPaolo Bonzini        tcg_out_opc_upper(s, OPC_AUIPC, TCG_REG_TMP0, 0);
1554139c1837SPaolo Bonzini        tcg_out_opc_imm(s, OPC_JALR, link, TCG_REG_TMP0, 0);
1555844d0442SRichard Henderson        ret = reloc_call(s->code_ptr - 2, arg);
1556139c1837SPaolo Bonzini        tcg_debug_assert(ret == true);
1557aeb6326eSRichard Henderson    } else {
1558139c1837SPaolo Bonzini        /* far jump: 64-bit */
1559139c1837SPaolo Bonzini        tcg_target_long imm = sextreg((tcg_target_long)arg, 0, 12);
1560139c1837SPaolo Bonzini        tcg_target_long base = (tcg_target_long)arg - imm;
1561139c1837SPaolo Bonzini        tcg_out_movi(s, TCG_TYPE_PTR, TCG_REG_TMP0, base);
1562139c1837SPaolo Bonzini        tcg_out_opc_imm(s, OPC_JALR, link, TCG_REG_TMP0, imm);
1563139c1837SPaolo Bonzini    }
1564139c1837SPaolo Bonzini}
1565139c1837SPaolo Bonzini
1566cee44b03SRichard Hendersonstatic void tcg_out_call(TCGContext *s, const tcg_insn_unit *arg,
1567cee44b03SRichard Henderson                         const TCGHelperInfo *info)
1568139c1837SPaolo Bonzini{
1569139c1837SPaolo Bonzini    tcg_out_call_int(s, arg, false);
1570139c1837SPaolo Bonzini}
1571139c1837SPaolo Bonzini
1572139c1837SPaolo Bonzinistatic void tcg_out_mb(TCGContext *s, TCGArg a0)
1573139c1837SPaolo Bonzini{
1574139c1837SPaolo Bonzini    tcg_insn_unit insn = OPC_FENCE;
1575139c1837SPaolo Bonzini
1576139c1837SPaolo Bonzini    if (a0 & TCG_MO_LD_LD) {
1577139c1837SPaolo Bonzini        insn |= 0x02200000;
1578139c1837SPaolo Bonzini    }
1579139c1837SPaolo Bonzini    if (a0 & TCG_MO_ST_LD) {
1580139c1837SPaolo Bonzini        insn |= 0x01200000;
1581139c1837SPaolo Bonzini    }
1582139c1837SPaolo Bonzini    if (a0 & TCG_MO_LD_ST) {
1583139c1837SPaolo Bonzini        insn |= 0x02100000;
1584139c1837SPaolo Bonzini    }
1585139c1837SPaolo Bonzini    if (a0 & TCG_MO_ST_ST) {
1586139c1837SPaolo Bonzini        insn |= 0x02200000;
1587139c1837SPaolo Bonzini    }
1588139c1837SPaolo Bonzini    tcg_out32(s, insn);
1589139c1837SPaolo Bonzini}
1590139c1837SPaolo Bonzini
1591139c1837SPaolo Bonzini/*
1592139c1837SPaolo Bonzini * Load/store and TLB
1593139c1837SPaolo Bonzini */
1594139c1837SPaolo Bonzini
1595793f7381SRichard Hendersonstatic void tcg_out_goto(TCGContext *s, const tcg_insn_unit *target)
1596844d0442SRichard Henderson{
1597844d0442SRichard Henderson    tcg_out_opc_jump(s, OPC_JAL, TCG_REG_ZERO, 0);
1598844d0442SRichard Henderson    bool ok = reloc_jimm20(s->code_ptr - 1, target);
1599844d0442SRichard Henderson    tcg_debug_assert(ok);
1600844d0442SRichard Henderson}
1601844d0442SRichard Henderson
16027b880107SRichard Hendersonbool tcg_target_has_memory_bswap(MemOp memop)
16037b880107SRichard Henderson{
16047b880107SRichard Henderson    return false;
16057b880107SRichard Henderson}
16067b880107SRichard Henderson
160761b6daafSRichard Henderson/* We have three temps, we might as well expose them. */
160861b6daafSRichard Hendersonstatic const TCGLdstHelperParam ldst_helper_param = {
160961b6daafSRichard Henderson    .ntmp = 3, .tmp = { TCG_REG_TMP0, TCG_REG_TMP1, TCG_REG_TMP2 }
161061b6daafSRichard Henderson};
161161b6daafSRichard Henderson
1612139c1837SPaolo Bonzinistatic bool tcg_out_qemu_ld_slow_path(TCGContext *s, TCGLabelQemuLdst *l)
1613139c1837SPaolo Bonzini{
161461b6daafSRichard Henderson    MemOp opc = get_memop(l->oi);
1615139c1837SPaolo Bonzini
1616139c1837SPaolo Bonzini    /* resolve label address */
1617793f7381SRichard Henderson    if (!reloc_sbimm12(l->label_ptr[0], tcg_splitwx_to_rx(s->code_ptr))) {
1618139c1837SPaolo Bonzini        return false;
1619139c1837SPaolo Bonzini    }
1620139c1837SPaolo Bonzini
1621139c1837SPaolo Bonzini    /* call load helper */
162261b6daafSRichard Henderson    tcg_out_ld_helper_args(s, l, &ldst_helper_param);
1623cee44b03SRichard Henderson    tcg_out_call_int(s, qemu_ld_helpers[opc & MO_SSIZE], false);
162461b6daafSRichard Henderson    tcg_out_ld_helper_ret(s, l, true, &ldst_helper_param);
1625139c1837SPaolo Bonzini
1626139c1837SPaolo Bonzini    tcg_out_goto(s, l->raddr);
1627139c1837SPaolo Bonzini    return true;
1628139c1837SPaolo Bonzini}
1629139c1837SPaolo Bonzini
1630139c1837SPaolo Bonzinistatic bool tcg_out_qemu_st_slow_path(TCGContext *s, TCGLabelQemuLdst *l)
1631139c1837SPaolo Bonzini{
163261b6daafSRichard Henderson    MemOp opc = get_memop(l->oi);
1633139c1837SPaolo Bonzini
1634139c1837SPaolo Bonzini    /* resolve label address */
1635793f7381SRichard Henderson    if (!reloc_sbimm12(l->label_ptr[0], tcg_splitwx_to_rx(s->code_ptr))) {
1636139c1837SPaolo Bonzini        return false;
1637139c1837SPaolo Bonzini    }
1638139c1837SPaolo Bonzini
1639139c1837SPaolo Bonzini    /* call store helper */
164061b6daafSRichard Henderson    tcg_out_st_helper_args(s, l, &ldst_helper_param);
1641cee44b03SRichard Henderson    tcg_out_call_int(s, qemu_st_helpers[opc & MO_SIZE], false);
1642139c1837SPaolo Bonzini
1643139c1837SPaolo Bonzini    tcg_out_goto(s, l->raddr);
1644139c1837SPaolo Bonzini    return true;
1645139c1837SPaolo Bonzini}
1646139c1837SPaolo Bonzini
1647d0a9bb5eSRichard Henderson/* We expect to use a 12-bit negative offset from ENV.  */
1648d0a9bb5eSRichard Henderson#define MIN_TLB_MASK_TABLE_OFS  -(1 << 11)
1649d0a9bb5eSRichard Henderson
1650001dddfeSRichard Henderson/*
16517893e42dSPhilippe Mathieu-Daudé * For system-mode, perform the TLB load and compare.
16527893e42dSPhilippe Mathieu-Daudé * For user-mode, perform any required alignment tests.
1653001dddfeSRichard Henderson * In both cases, return a TCGLabelQemuLdst structure if the slow path
1654001dddfeSRichard Henderson * is required and fill in @h with the host address for the fast path.
1655001dddfeSRichard Henderson */
1656001dddfeSRichard Hendersonstatic TCGLabelQemuLdst *prepare_host_addr(TCGContext *s, TCGReg *pbase,
1657001dddfeSRichard Henderson                                           TCGReg addr_reg, MemOpIdx oi,
1658001dddfeSRichard Henderson                                           bool is_ld)
1659001dddfeSRichard Henderson{
16608aefe1fbSRichard Henderson    TCGType addr_type = s->addr_type;
1661001dddfeSRichard Henderson    TCGLabelQemuLdst *ldst = NULL;
1662001dddfeSRichard Henderson    MemOp opc = get_memop(oi);
166337e523f0SRichard Henderson    TCGAtomAlign aa;
166437e523f0SRichard Henderson    unsigned a_mask;
166537e523f0SRichard Henderson
166637e523f0SRichard Henderson    aa = atom_and_align_for_opc(s, opc, MO_ATOM_IFALIGN, false);
166737e523f0SRichard Henderson    a_mask = (1u << aa.align) - 1;
1668001dddfeSRichard Henderson
16694944d359SRichard Henderson    if (tcg_use_softmmu) {
1670001dddfeSRichard Henderson        unsigned s_bits = opc & MO_SIZE;
1671933b331bSRichard Henderson        unsigned s_mask = (1u << s_bits) - 1;
1672001dddfeSRichard Henderson        int mem_index = get_mmuidx(oi);
1673d0a9bb5eSRichard Henderson        int fast_ofs = tlb_mask_table_ofs(s, mem_index);
1674001dddfeSRichard Henderson        int mask_ofs = fast_ofs + offsetof(CPUTLBDescFast, mask);
1675001dddfeSRichard Henderson        int table_ofs = fast_ofs + offsetof(CPUTLBDescFast, table);
1676933b331bSRichard Henderson        int compare_mask;
1677933b331bSRichard Henderson        TCGReg addr_adj;
1678001dddfeSRichard Henderson
1679001dddfeSRichard Henderson        ldst = new_ldst_label(s);
1680001dddfeSRichard Henderson        ldst->is_ld = is_ld;
1681001dddfeSRichard Henderson        ldst->oi = oi;
1682001dddfeSRichard Henderson        ldst->addrlo_reg = addr_reg;
1683001dddfeSRichard Henderson
1684f63e7089SHuang Shiyuan        init_setting_vtype(s);
1685f63e7089SHuang Shiyuan
1686933b331bSRichard Henderson        tcg_out_ld(s, TCG_TYPE_PTR, TCG_REG_TMP0, TCG_AREG0, mask_ofs);
1687933b331bSRichard Henderson        tcg_out_ld(s, TCG_TYPE_PTR, TCG_REG_TMP1, TCG_AREG0, table_ofs);
1688001dddfeSRichard Henderson
1689001dddfeSRichard Henderson        tcg_out_opc_imm(s, OPC_SRLI, TCG_REG_TMP2, addr_reg,
1690aece72b7SRichard Henderson                        s->page_bits - CPU_TLB_ENTRY_BITS);
1691001dddfeSRichard Henderson        tcg_out_opc_reg(s, OPC_AND, TCG_REG_TMP2, TCG_REG_TMP2, TCG_REG_TMP0);
1692001dddfeSRichard Henderson        tcg_out_opc_reg(s, OPC_ADD, TCG_REG_TMP2, TCG_REG_TMP2, TCG_REG_TMP1);
1693001dddfeSRichard Henderson
1694933b331bSRichard Henderson        /*
16954944d359SRichard Henderson         * For aligned accesses, we check the first byte and include the
16964944d359SRichard Henderson         * alignment bits within the address.  For unaligned access, we
16974944d359SRichard Henderson         * check that we don't cross pages using the address of the last
16984944d359SRichard Henderson         * byte of the access.
1699933b331bSRichard Henderson         */
1700933b331bSRichard Henderson        addr_adj = addr_reg;
170137e523f0SRichard Henderson        if (a_mask < s_mask) {
1702933b331bSRichard Henderson            addr_adj = TCG_REG_TMP0;
17038aefe1fbSRichard Henderson            tcg_out_opc_imm(s, addr_type == TCG_TYPE_I32 ? OPC_ADDIW : OPC_ADDI,
1704933b331bSRichard Henderson                            addr_adj, addr_reg, s_mask - a_mask);
1705933b331bSRichard Henderson        }
1706aece72b7SRichard Henderson        compare_mask = s->page_mask | a_mask;
1707933b331bSRichard Henderson        if (compare_mask == sextreg(compare_mask, 0, 12)) {
1708933b331bSRichard Henderson            tcg_out_opc_imm(s, OPC_ANDI, TCG_REG_TMP1, addr_adj, compare_mask);
1709933b331bSRichard Henderson        } else {
17108aefe1fbSRichard Henderson            tcg_out_movi(s, addr_type, TCG_REG_TMP1, compare_mask);
1711933b331bSRichard Henderson            tcg_out_opc_reg(s, OPC_AND, TCG_REG_TMP1, TCG_REG_TMP1, addr_adj);
1712933b331bSRichard Henderson        }
1713933b331bSRichard Henderson
1714001dddfeSRichard Henderson        /* Load the tlb comparator and the addend.  */
1715238f4380SRichard Henderson        QEMU_BUILD_BUG_ON(HOST_BIG_ENDIAN);
17168aefe1fbSRichard Henderson        tcg_out_ld(s, addr_type, TCG_REG_TMP0, TCG_REG_TMP2,
1717001dddfeSRichard Henderson                   is_ld ? offsetof(CPUTLBEntry, addr_read)
1718001dddfeSRichard Henderson                         : offsetof(CPUTLBEntry, addr_write));
1719001dddfeSRichard Henderson        tcg_out_ld(s, TCG_TYPE_PTR, TCG_REG_TMP2, TCG_REG_TMP2,
1720001dddfeSRichard Henderson                   offsetof(CPUTLBEntry, addend));
1721001dddfeSRichard Henderson
1722001dddfeSRichard Henderson        /* Compare masked address with the TLB entry. */
1723001dddfeSRichard Henderson        ldst->label_ptr[0] = s->code_ptr;
1724001dddfeSRichard Henderson        tcg_out_opc_branch(s, OPC_BNE, TCG_REG_TMP0, TCG_REG_TMP1, 0);
1725001dddfeSRichard Henderson
1726001dddfeSRichard Henderson        /* TLB Hit - translate address using addend.  */
17278aefe1fbSRichard Henderson        if (addr_type != TCG_TYPE_I32) {
1728eda15159SRichard Henderson            tcg_out_opc_reg(s, OPC_ADD, TCG_REG_TMP0, addr_reg, TCG_REG_TMP2);
1729b86c6ba6SRichard Henderson        } else if (cpuinfo & CPUINFO_ZBA) {
17304944d359SRichard Henderson            tcg_out_opc_reg(s, OPC_ADD_UW, TCG_REG_TMP0,
17314944d359SRichard Henderson                            addr_reg, TCG_REG_TMP2);
1732eda15159SRichard Henderson        } else {
1733eda15159SRichard Henderson            tcg_out_ext32u(s, TCG_REG_TMP0, addr_reg);
17344944d359SRichard Henderson            tcg_out_opc_reg(s, OPC_ADD, TCG_REG_TMP0,
17354944d359SRichard Henderson                            TCG_REG_TMP0, TCG_REG_TMP2);
1736001dddfeSRichard Henderson        }
1737001dddfeSRichard Henderson        *pbase = TCG_REG_TMP0;
17384944d359SRichard Henderson    } else {
1739eda15159SRichard Henderson        TCGReg base;
1740eda15159SRichard Henderson
1741001dddfeSRichard Henderson        if (a_mask) {
1742001dddfeSRichard Henderson            ldst = new_ldst_label(s);
1743001dddfeSRichard Henderson            ldst->is_ld = is_ld;
1744001dddfeSRichard Henderson            ldst->oi = oi;
1745001dddfeSRichard Henderson            ldst->addrlo_reg = addr_reg;
1746001dddfeSRichard Henderson
1747f63e7089SHuang Shiyuan            init_setting_vtype(s);
1748f63e7089SHuang Shiyuan
174937e523f0SRichard Henderson            /* We are expecting alignment max 7, so we can always use andi. */
175037e523f0SRichard Henderson            tcg_debug_assert(a_mask == sextreg(a_mask, 0, 12));
1751001dddfeSRichard Henderson            tcg_out_opc_imm(s, OPC_ANDI, TCG_REG_TMP1, addr_reg, a_mask);
1752001dddfeSRichard Henderson
1753001dddfeSRichard Henderson            ldst->label_ptr[0] = s->code_ptr;
1754001dddfeSRichard Henderson            tcg_out_opc_branch(s, OPC_BNE, TCG_REG_TMP1, TCG_REG_ZERO, 0);
1755001dddfeSRichard Henderson        }
1756001dddfeSRichard Henderson
1757001dddfeSRichard Henderson        if (guest_base != 0) {
1758001dddfeSRichard Henderson            base = TCG_REG_TMP0;
17598aefe1fbSRichard Henderson            if (addr_type != TCG_TYPE_I32) {
17604944d359SRichard Henderson                tcg_out_opc_reg(s, OPC_ADD, base, addr_reg,
17614944d359SRichard Henderson                                TCG_GUEST_BASE_REG);
1762b86c6ba6SRichard Henderson            } else if (cpuinfo & CPUINFO_ZBA) {
17634944d359SRichard Henderson                tcg_out_opc_reg(s, OPC_ADD_UW, base, addr_reg,
17644944d359SRichard Henderson                                TCG_GUEST_BASE_REG);
1765eda15159SRichard Henderson            } else {
1766eda15159SRichard Henderson                tcg_out_ext32u(s, base, addr_reg);
1767eda15159SRichard Henderson                tcg_out_opc_reg(s, OPC_ADD, base, base, TCG_GUEST_BASE_REG);
1768eda15159SRichard Henderson            }
17698aefe1fbSRichard Henderson        } else if (addr_type != TCG_TYPE_I32) {
1770eda15159SRichard Henderson            base = addr_reg;
1771eda15159SRichard Henderson        } else {
1772eda15159SRichard Henderson            base = TCG_REG_TMP0;
1773eda15159SRichard Henderson            tcg_out_ext32u(s, base, addr_reg);
1774001dddfeSRichard Henderson        }
1775001dddfeSRichard Henderson        *pbase = base;
17764944d359SRichard Henderson    }
1777001dddfeSRichard Henderson
1778001dddfeSRichard Henderson    return ldst;
1779001dddfeSRichard Henderson}
1780001dddfeSRichard Henderson
1781aeb6326eSRichard Hendersonstatic void tcg_out_qemu_ld_direct(TCGContext *s, TCGReg val,
1782f7041977SRichard Henderson                                   TCGReg base, MemOp opc, TCGType type)
1783139c1837SPaolo Bonzini{
1784c86bd2dcSRichard Henderson    /* Byte swapping is left to middle-end expansion. */
1785c86bd2dcSRichard Henderson    tcg_debug_assert((opc & MO_BSWAP) == 0);
1786139c1837SPaolo Bonzini
1787139c1837SPaolo Bonzini    switch (opc & (MO_SSIZE)) {
1788139c1837SPaolo Bonzini    case MO_UB:
1789aeb6326eSRichard Henderson        tcg_out_opc_imm(s, OPC_LBU, val, base, 0);
1790139c1837SPaolo Bonzini        break;
1791139c1837SPaolo Bonzini    case MO_SB:
1792aeb6326eSRichard Henderson        tcg_out_opc_imm(s, OPC_LB, val, base, 0);
1793139c1837SPaolo Bonzini        break;
1794139c1837SPaolo Bonzini    case MO_UW:
1795aeb6326eSRichard Henderson        tcg_out_opc_imm(s, OPC_LHU, val, base, 0);
1796139c1837SPaolo Bonzini        break;
1797139c1837SPaolo Bonzini    case MO_SW:
1798aeb6326eSRichard Henderson        tcg_out_opc_imm(s, OPC_LH, val, base, 0);
1799139c1837SPaolo Bonzini        break;
1800139c1837SPaolo Bonzini    case MO_UL:
1801f7041977SRichard Henderson        if (type == TCG_TYPE_I64) {
1802aeb6326eSRichard Henderson            tcg_out_opc_imm(s, OPC_LWU, val, base, 0);
1803139c1837SPaolo Bonzini            break;
1804139c1837SPaolo Bonzini        }
1805139c1837SPaolo Bonzini        /* FALLTHRU */
1806139c1837SPaolo Bonzini    case MO_SL:
1807aeb6326eSRichard Henderson        tcg_out_opc_imm(s, OPC_LW, val, base, 0);
1808139c1837SPaolo Bonzini        break;
1809fc313c64SFrédéric Pétrot    case MO_UQ:
1810aeb6326eSRichard Henderson        tcg_out_opc_imm(s, OPC_LD, val, base, 0);
1811139c1837SPaolo Bonzini        break;
1812139c1837SPaolo Bonzini    default:
1813139c1837SPaolo Bonzini        g_assert_not_reached();
1814139c1837SPaolo Bonzini    }
1815139c1837SPaolo Bonzini}
1816139c1837SPaolo Bonzini
1817f7041977SRichard Hendersonstatic void tcg_out_qemu_ld(TCGContext *s, TCGReg data_reg, TCGReg addr_reg,
1818f7041977SRichard Henderson                            MemOpIdx oi, TCGType data_type)
1819139c1837SPaolo Bonzini{
1820001dddfeSRichard Henderson    TCGLabelQemuLdst *ldst;
18212e3a933aSRichard Henderson    TCGReg base;
1822139c1837SPaolo Bonzini
1823001dddfeSRichard Henderson    ldst = prepare_host_addr(s, &base, addr_reg, oi, true);
1824001dddfeSRichard Henderson    tcg_out_qemu_ld_direct(s, data_reg, base, get_memop(oi), data_type);
1825f7041977SRichard Henderson
1826001dddfeSRichard Henderson    if (ldst) {
1827001dddfeSRichard Henderson        ldst->type = data_type;
1828001dddfeSRichard Henderson        ldst->datalo_reg = data_reg;
1829001dddfeSRichard Henderson        ldst->raddr = tcg_splitwx_to_rx(s->code_ptr);
1830a3fb7c99SRichard Henderson    }
1831139c1837SPaolo Bonzini}
1832139c1837SPaolo Bonzini
1833aeb6326eSRichard Hendersonstatic void tcg_out_qemu_st_direct(TCGContext *s, TCGReg val,
1834139c1837SPaolo Bonzini                                   TCGReg base, MemOp opc)
1835139c1837SPaolo Bonzini{
1836c86bd2dcSRichard Henderson    /* Byte swapping is left to middle-end expansion. */
1837c86bd2dcSRichard Henderson    tcg_debug_assert((opc & MO_BSWAP) == 0);
1838139c1837SPaolo Bonzini
1839139c1837SPaolo Bonzini    switch (opc & (MO_SSIZE)) {
1840139c1837SPaolo Bonzini    case MO_8:
1841aeb6326eSRichard Henderson        tcg_out_opc_store(s, OPC_SB, base, val, 0);
1842139c1837SPaolo Bonzini        break;
1843139c1837SPaolo Bonzini    case MO_16:
1844aeb6326eSRichard Henderson        tcg_out_opc_store(s, OPC_SH, base, val, 0);
1845139c1837SPaolo Bonzini        break;
1846139c1837SPaolo Bonzini    case MO_32:
1847aeb6326eSRichard Henderson        tcg_out_opc_store(s, OPC_SW, base, val, 0);
1848139c1837SPaolo Bonzini        break;
1849139c1837SPaolo Bonzini    case MO_64:
1850aeb6326eSRichard Henderson        tcg_out_opc_store(s, OPC_SD, base, val, 0);
1851139c1837SPaolo Bonzini        break;
1852139c1837SPaolo Bonzini    default:
1853139c1837SPaolo Bonzini        g_assert_not_reached();
1854139c1837SPaolo Bonzini    }
1855139c1837SPaolo Bonzini}
1856139c1837SPaolo Bonzini
1857f7041977SRichard Hendersonstatic void tcg_out_qemu_st(TCGContext *s, TCGReg data_reg, TCGReg addr_reg,
1858f7041977SRichard Henderson                            MemOpIdx oi, TCGType data_type)
1859139c1837SPaolo Bonzini{
1860001dddfeSRichard Henderson    TCGLabelQemuLdst *ldst;
18612e3a933aSRichard Henderson    TCGReg base;
1862139c1837SPaolo Bonzini
1863001dddfeSRichard Henderson    ldst = prepare_host_addr(s, &base, addr_reg, oi, false);
1864001dddfeSRichard Henderson    tcg_out_qemu_st_direct(s, data_reg, base, get_memop(oi));
1865f7041977SRichard Henderson
1866001dddfeSRichard Henderson    if (ldst) {
1867001dddfeSRichard Henderson        ldst->type = data_type;
1868001dddfeSRichard Henderson        ldst->datalo_reg = data_reg;
1869001dddfeSRichard Henderson        ldst->raddr = tcg_splitwx_to_rx(s->code_ptr);
1870a3fb7c99SRichard Henderson    }
1871139c1837SPaolo Bonzini}
1872139c1837SPaolo Bonzini
1873793f7381SRichard Hendersonstatic const tcg_insn_unit *tb_ret_addr;
1874139c1837SPaolo Bonzini
1875b55a8d9dSRichard Hendersonstatic void tcg_out_exit_tb(TCGContext *s, uintptr_t a0)
1876b55a8d9dSRichard Henderson{
1877b55a8d9dSRichard Henderson    /* Reuse the zeroing that exists for goto_ptr.  */
1878b55a8d9dSRichard Henderson    if (a0 == 0) {
1879b55a8d9dSRichard Henderson        tcg_out_call_int(s, tcg_code_gen_epilogue, true);
1880b55a8d9dSRichard Henderson    } else {
1881b55a8d9dSRichard Henderson        tcg_out_movi(s, TCG_TYPE_PTR, TCG_REG_A0, a0);
1882b55a8d9dSRichard Henderson        tcg_out_call_int(s, tb_ret_addr, true);
1883b55a8d9dSRichard Henderson    }
1884b55a8d9dSRichard Henderson}
1885b55a8d9dSRichard Henderson
1886cf7d6b8eSRichard Hendersonstatic void tcg_out_goto_tb(TCGContext *s, int which)
1887cf7d6b8eSRichard Henderson{
1888493c9b19SRichard Henderson    /* Direct branch will be patched by tb_target_set_jmp_target. */
1889493c9b19SRichard Henderson    set_jmp_insn_offset(s, which);
1890493c9b19SRichard Henderson    tcg_out32(s, OPC_JAL);
1891493c9b19SRichard Henderson
1892493c9b19SRichard Henderson    /* When branch is out of range, fall through to indirect. */
1893cf7d6b8eSRichard Henderson    tcg_out_ld(s, TCG_TYPE_PTR, TCG_REG_TMP0, TCG_REG_ZERO,
1894cf7d6b8eSRichard Henderson               get_jmp_target_addr(s, which));
1895cf7d6b8eSRichard Henderson    tcg_out_opc_imm(s, OPC_JALR, TCG_REG_ZERO, TCG_REG_TMP0, 0);
1896cf7d6b8eSRichard Henderson    set_jmp_reset_offset(s, which);
1897cf7d6b8eSRichard Henderson}
1898cf7d6b8eSRichard Henderson
189990c0fee3SRichard Hendersonvoid tb_target_set_jmp_target(const TranslationBlock *tb, int n,
190090c0fee3SRichard Henderson                              uintptr_t jmp_rx, uintptr_t jmp_rw)
190190c0fee3SRichard Henderson{
1902493c9b19SRichard Henderson    uintptr_t addr = tb->jmp_target_addr[n];
1903493c9b19SRichard Henderson    ptrdiff_t offset = addr - jmp_rx;
1904493c9b19SRichard Henderson    tcg_insn_unit insn;
1905493c9b19SRichard Henderson
1906493c9b19SRichard Henderson    /* Either directly branch, or fall through to indirect branch. */
1907493c9b19SRichard Henderson    if (offset == sextreg(offset, 0, 20)) {
1908493c9b19SRichard Henderson        insn = encode_uj(OPC_JAL, TCG_REG_ZERO, offset);
1909493c9b19SRichard Henderson    } else {
1910493c9b19SRichard Henderson        insn = OPC_NOP;
1911493c9b19SRichard Henderson    }
1912493c9b19SRichard Henderson    qatomic_set((uint32_t *)jmp_rw, insn);
1913493c9b19SRichard Henderson    flush_idcache_range(jmp_rx, jmp_rw, 4);
191490c0fee3SRichard Henderson}
191590c0fee3SRichard Henderson
1916139c1837SPaolo Bonzinistatic void tcg_out_op(TCGContext *s, TCGOpcode opc,
19175e8892dbSMiroslav Rezanina                       const TCGArg args[TCG_MAX_OP_ARGS],
19185e8892dbSMiroslav Rezanina                       const int const_args[TCG_MAX_OP_ARGS])
1919139c1837SPaolo Bonzini{
1920139c1837SPaolo Bonzini    TCGArg a0 = args[0];
1921139c1837SPaolo Bonzini    TCGArg a1 = args[1];
1922139c1837SPaolo Bonzini    TCGArg a2 = args[2];
1923139c1837SPaolo Bonzini    int c2 = const_args[2];
1924139c1837SPaolo Bonzini
1925139c1837SPaolo Bonzini    switch (opc) {
1926139c1837SPaolo Bonzini    case INDEX_op_goto_ptr:
1927139c1837SPaolo Bonzini        tcg_out_opc_imm(s, OPC_JALR, TCG_REG_ZERO, a0, 0);
1928139c1837SPaolo Bonzini        break;
1929139c1837SPaolo Bonzini
1930139c1837SPaolo Bonzini    case INDEX_op_br:
1931139c1837SPaolo Bonzini        tcg_out_reloc(s, s->code_ptr, R_RISCV_JAL, arg_label(a0), 0);
1932139c1837SPaolo Bonzini        tcg_out_opc_jump(s, OPC_JAL, TCG_REG_ZERO, 0);
1933139c1837SPaolo Bonzini        break;
1934139c1837SPaolo Bonzini
1935139c1837SPaolo Bonzini    case INDEX_op_ld8u_i32:
1936139c1837SPaolo Bonzini    case INDEX_op_ld8u_i64:
1937139c1837SPaolo Bonzini        tcg_out_ldst(s, OPC_LBU, a0, a1, a2);
1938139c1837SPaolo Bonzini        break;
1939139c1837SPaolo Bonzini    case INDEX_op_ld8s_i32:
1940139c1837SPaolo Bonzini    case INDEX_op_ld8s_i64:
1941139c1837SPaolo Bonzini        tcg_out_ldst(s, OPC_LB, a0, a1, a2);
1942139c1837SPaolo Bonzini        break;
1943139c1837SPaolo Bonzini    case INDEX_op_ld16u_i32:
1944139c1837SPaolo Bonzini    case INDEX_op_ld16u_i64:
1945139c1837SPaolo Bonzini        tcg_out_ldst(s, OPC_LHU, a0, a1, a2);
1946139c1837SPaolo Bonzini        break;
1947139c1837SPaolo Bonzini    case INDEX_op_ld16s_i32:
1948139c1837SPaolo Bonzini    case INDEX_op_ld16s_i64:
1949139c1837SPaolo Bonzini        tcg_out_ldst(s, OPC_LH, a0, a1, a2);
1950139c1837SPaolo Bonzini        break;
1951139c1837SPaolo Bonzini    case INDEX_op_ld32u_i64:
1952139c1837SPaolo Bonzini        tcg_out_ldst(s, OPC_LWU, a0, a1, a2);
1953139c1837SPaolo Bonzini        break;
1954139c1837SPaolo Bonzini    case INDEX_op_ld_i32:
1955139c1837SPaolo Bonzini    case INDEX_op_ld32s_i64:
1956139c1837SPaolo Bonzini        tcg_out_ldst(s, OPC_LW, a0, a1, a2);
1957139c1837SPaolo Bonzini        break;
1958139c1837SPaolo Bonzini    case INDEX_op_ld_i64:
1959139c1837SPaolo Bonzini        tcg_out_ldst(s, OPC_LD, a0, a1, a2);
1960139c1837SPaolo Bonzini        break;
1961139c1837SPaolo Bonzini
1962139c1837SPaolo Bonzini    case INDEX_op_st8_i32:
1963139c1837SPaolo Bonzini    case INDEX_op_st8_i64:
1964139c1837SPaolo Bonzini        tcg_out_ldst(s, OPC_SB, a0, a1, a2);
1965139c1837SPaolo Bonzini        break;
1966139c1837SPaolo Bonzini    case INDEX_op_st16_i32:
1967139c1837SPaolo Bonzini    case INDEX_op_st16_i64:
1968139c1837SPaolo Bonzini        tcg_out_ldst(s, OPC_SH, a0, a1, a2);
1969139c1837SPaolo Bonzini        break;
1970139c1837SPaolo Bonzini    case INDEX_op_st_i32:
1971139c1837SPaolo Bonzini    case INDEX_op_st32_i64:
1972139c1837SPaolo Bonzini        tcg_out_ldst(s, OPC_SW, a0, a1, a2);
1973139c1837SPaolo Bonzini        break;
1974139c1837SPaolo Bonzini    case INDEX_op_st_i64:
1975139c1837SPaolo Bonzini        tcg_out_ldst(s, OPC_SD, a0, a1, a2);
1976139c1837SPaolo Bonzini        break;
1977139c1837SPaolo Bonzini
1978139c1837SPaolo Bonzini    case INDEX_op_add_i32:
1979139c1837SPaolo Bonzini        if (c2) {
1980139c1837SPaolo Bonzini            tcg_out_opc_imm(s, OPC_ADDIW, a0, a1, a2);
1981139c1837SPaolo Bonzini        } else {
1982139c1837SPaolo Bonzini            tcg_out_opc_reg(s, OPC_ADDW, a0, a1, a2);
1983139c1837SPaolo Bonzini        }
1984139c1837SPaolo Bonzini        break;
1985139c1837SPaolo Bonzini    case INDEX_op_add_i64:
1986139c1837SPaolo Bonzini        if (c2) {
1987139c1837SPaolo Bonzini            tcg_out_opc_imm(s, OPC_ADDI, a0, a1, a2);
1988139c1837SPaolo Bonzini        } else {
1989139c1837SPaolo Bonzini            tcg_out_opc_reg(s, OPC_ADD, a0, a1, a2);
1990139c1837SPaolo Bonzini        }
1991139c1837SPaolo Bonzini        break;
1992139c1837SPaolo Bonzini
1993139c1837SPaolo Bonzini    case INDEX_op_sub_i32:
1994139c1837SPaolo Bonzini        if (c2) {
1995139c1837SPaolo Bonzini            tcg_out_opc_imm(s, OPC_ADDIW, a0, a1, -a2);
1996139c1837SPaolo Bonzini        } else {
1997139c1837SPaolo Bonzini            tcg_out_opc_reg(s, OPC_SUBW, a0, a1, a2);
1998139c1837SPaolo Bonzini        }
1999139c1837SPaolo Bonzini        break;
2000139c1837SPaolo Bonzini    case INDEX_op_sub_i64:
2001139c1837SPaolo Bonzini        if (c2) {
2002139c1837SPaolo Bonzini            tcg_out_opc_imm(s, OPC_ADDI, a0, a1, -a2);
2003139c1837SPaolo Bonzini        } else {
2004139c1837SPaolo Bonzini            tcg_out_opc_reg(s, OPC_SUB, a0, a1, a2);
2005139c1837SPaolo Bonzini        }
2006139c1837SPaolo Bonzini        break;
2007139c1837SPaolo Bonzini
2008139c1837SPaolo Bonzini    case INDEX_op_and_i32:
2009139c1837SPaolo Bonzini    case INDEX_op_and_i64:
2010139c1837SPaolo Bonzini        if (c2) {
2011139c1837SPaolo Bonzini            tcg_out_opc_imm(s, OPC_ANDI, a0, a1, a2);
2012139c1837SPaolo Bonzini        } else {
2013139c1837SPaolo Bonzini            tcg_out_opc_reg(s, OPC_AND, a0, a1, a2);
2014139c1837SPaolo Bonzini        }
2015139c1837SPaolo Bonzini        break;
2016139c1837SPaolo Bonzini
2017139c1837SPaolo Bonzini    case INDEX_op_or_i32:
2018139c1837SPaolo Bonzini    case INDEX_op_or_i64:
2019139c1837SPaolo Bonzini        if (c2) {
2020139c1837SPaolo Bonzini            tcg_out_opc_imm(s, OPC_ORI, a0, a1, a2);
2021139c1837SPaolo Bonzini        } else {
2022139c1837SPaolo Bonzini            tcg_out_opc_reg(s, OPC_OR, a0, a1, a2);
2023139c1837SPaolo Bonzini        }
2024139c1837SPaolo Bonzini        break;
2025139c1837SPaolo Bonzini
2026139c1837SPaolo Bonzini    case INDEX_op_xor_i32:
2027139c1837SPaolo Bonzini    case INDEX_op_xor_i64:
2028139c1837SPaolo Bonzini        if (c2) {
2029139c1837SPaolo Bonzini            tcg_out_opc_imm(s, OPC_XORI, a0, a1, a2);
2030139c1837SPaolo Bonzini        } else {
2031139c1837SPaolo Bonzini            tcg_out_opc_reg(s, OPC_XOR, a0, a1, a2);
2032139c1837SPaolo Bonzini        }
2033139c1837SPaolo Bonzini        break;
2034139c1837SPaolo Bonzini
203599f4ec6eSRichard Henderson    case INDEX_op_andc_i32:
203699f4ec6eSRichard Henderson    case INDEX_op_andc_i64:
203799f4ec6eSRichard Henderson        if (c2) {
203899f4ec6eSRichard Henderson            tcg_out_opc_imm(s, OPC_ANDI, a0, a1, ~a2);
203999f4ec6eSRichard Henderson        } else {
204099f4ec6eSRichard Henderson            tcg_out_opc_reg(s, OPC_ANDN, a0, a1, a2);
204199f4ec6eSRichard Henderson        }
204299f4ec6eSRichard Henderson        break;
204399f4ec6eSRichard Henderson    case INDEX_op_orc_i32:
204499f4ec6eSRichard Henderson    case INDEX_op_orc_i64:
204599f4ec6eSRichard Henderson        if (c2) {
204699f4ec6eSRichard Henderson            tcg_out_opc_imm(s, OPC_ORI, a0, a1, ~a2);
204799f4ec6eSRichard Henderson        } else {
204899f4ec6eSRichard Henderson            tcg_out_opc_reg(s, OPC_ORN, a0, a1, a2);
204999f4ec6eSRichard Henderson        }
205099f4ec6eSRichard Henderson        break;
205199f4ec6eSRichard Henderson    case INDEX_op_eqv_i32:
205299f4ec6eSRichard Henderson    case INDEX_op_eqv_i64:
205399f4ec6eSRichard Henderson        if (c2) {
205499f4ec6eSRichard Henderson            tcg_out_opc_imm(s, OPC_XORI, a0, a1, ~a2);
205599f4ec6eSRichard Henderson        } else {
205699f4ec6eSRichard Henderson            tcg_out_opc_reg(s, OPC_XNOR, a0, a1, a2);
205799f4ec6eSRichard Henderson        }
205899f4ec6eSRichard Henderson        break;
205999f4ec6eSRichard Henderson
2060139c1837SPaolo Bonzini    case INDEX_op_not_i32:
2061139c1837SPaolo Bonzini    case INDEX_op_not_i64:
2062139c1837SPaolo Bonzini        tcg_out_opc_imm(s, OPC_XORI, a0, a1, -1);
2063139c1837SPaolo Bonzini        break;
2064139c1837SPaolo Bonzini
2065139c1837SPaolo Bonzini    case INDEX_op_neg_i32:
2066139c1837SPaolo Bonzini        tcg_out_opc_reg(s, OPC_SUBW, a0, TCG_REG_ZERO, a1);
2067139c1837SPaolo Bonzini        break;
2068139c1837SPaolo Bonzini    case INDEX_op_neg_i64:
2069139c1837SPaolo Bonzini        tcg_out_opc_reg(s, OPC_SUB, a0, TCG_REG_ZERO, a1);
2070139c1837SPaolo Bonzini        break;
2071139c1837SPaolo Bonzini
2072139c1837SPaolo Bonzini    case INDEX_op_mul_i32:
2073139c1837SPaolo Bonzini        tcg_out_opc_reg(s, OPC_MULW, a0, a1, a2);
2074139c1837SPaolo Bonzini        break;
2075139c1837SPaolo Bonzini    case INDEX_op_mul_i64:
2076139c1837SPaolo Bonzini        tcg_out_opc_reg(s, OPC_MUL, a0, a1, a2);
2077139c1837SPaolo Bonzini        break;
2078139c1837SPaolo Bonzini
2079139c1837SPaolo Bonzini    case INDEX_op_div_i32:
2080139c1837SPaolo Bonzini        tcg_out_opc_reg(s, OPC_DIVW, a0, a1, a2);
2081139c1837SPaolo Bonzini        break;
2082139c1837SPaolo Bonzini    case INDEX_op_div_i64:
2083139c1837SPaolo Bonzini        tcg_out_opc_reg(s, OPC_DIV, a0, a1, a2);
2084139c1837SPaolo Bonzini        break;
2085139c1837SPaolo Bonzini
2086139c1837SPaolo Bonzini    case INDEX_op_divu_i32:
2087139c1837SPaolo Bonzini        tcg_out_opc_reg(s, OPC_DIVUW, a0, a1, a2);
2088139c1837SPaolo Bonzini        break;
2089139c1837SPaolo Bonzini    case INDEX_op_divu_i64:
2090139c1837SPaolo Bonzini        tcg_out_opc_reg(s, OPC_DIVU, a0, a1, a2);
2091139c1837SPaolo Bonzini        break;
2092139c1837SPaolo Bonzini
2093139c1837SPaolo Bonzini    case INDEX_op_rem_i32:
2094139c1837SPaolo Bonzini        tcg_out_opc_reg(s, OPC_REMW, a0, a1, a2);
2095139c1837SPaolo Bonzini        break;
2096139c1837SPaolo Bonzini    case INDEX_op_rem_i64:
2097139c1837SPaolo Bonzini        tcg_out_opc_reg(s, OPC_REM, a0, a1, a2);
2098139c1837SPaolo Bonzini        break;
2099139c1837SPaolo Bonzini
2100139c1837SPaolo Bonzini    case INDEX_op_remu_i32:
2101139c1837SPaolo Bonzini        tcg_out_opc_reg(s, OPC_REMUW, a0, a1, a2);
2102139c1837SPaolo Bonzini        break;
2103139c1837SPaolo Bonzini    case INDEX_op_remu_i64:
2104139c1837SPaolo Bonzini        tcg_out_opc_reg(s, OPC_REMU, a0, a1, a2);
2105139c1837SPaolo Bonzini        break;
2106139c1837SPaolo Bonzini
2107139c1837SPaolo Bonzini    case INDEX_op_shl_i32:
2108139c1837SPaolo Bonzini        if (c2) {
2109d2f3066eSZihao Yu            tcg_out_opc_imm(s, OPC_SLLIW, a0, a1, a2 & 0x1f);
2110139c1837SPaolo Bonzini        } else {
2111139c1837SPaolo Bonzini            tcg_out_opc_reg(s, OPC_SLLW, a0, a1, a2);
2112139c1837SPaolo Bonzini        }
2113139c1837SPaolo Bonzini        break;
2114139c1837SPaolo Bonzini    case INDEX_op_shl_i64:
2115139c1837SPaolo Bonzini        if (c2) {
2116d2f3066eSZihao Yu            tcg_out_opc_imm(s, OPC_SLLI, a0, a1, a2 & 0x3f);
2117139c1837SPaolo Bonzini        } else {
2118139c1837SPaolo Bonzini            tcg_out_opc_reg(s, OPC_SLL, a0, a1, a2);
2119139c1837SPaolo Bonzini        }
2120139c1837SPaolo Bonzini        break;
2121139c1837SPaolo Bonzini
2122139c1837SPaolo Bonzini    case INDEX_op_shr_i32:
2123139c1837SPaolo Bonzini        if (c2) {
2124d2f3066eSZihao Yu            tcg_out_opc_imm(s, OPC_SRLIW, a0, a1, a2 & 0x1f);
2125139c1837SPaolo Bonzini        } else {
2126139c1837SPaolo Bonzini            tcg_out_opc_reg(s, OPC_SRLW, a0, a1, a2);
2127139c1837SPaolo Bonzini        }
2128139c1837SPaolo Bonzini        break;
2129139c1837SPaolo Bonzini    case INDEX_op_shr_i64:
2130139c1837SPaolo Bonzini        if (c2) {
2131d2f3066eSZihao Yu            tcg_out_opc_imm(s, OPC_SRLI, a0, a1, a2 & 0x3f);
2132139c1837SPaolo Bonzini        } else {
2133139c1837SPaolo Bonzini            tcg_out_opc_reg(s, OPC_SRL, a0, a1, a2);
2134139c1837SPaolo Bonzini        }
2135139c1837SPaolo Bonzini        break;
2136139c1837SPaolo Bonzini
2137139c1837SPaolo Bonzini    case INDEX_op_sar_i32:
2138139c1837SPaolo Bonzini        if (c2) {
2139d2f3066eSZihao Yu            tcg_out_opc_imm(s, OPC_SRAIW, a0, a1, a2 & 0x1f);
2140139c1837SPaolo Bonzini        } else {
2141139c1837SPaolo Bonzini            tcg_out_opc_reg(s, OPC_SRAW, a0, a1, a2);
2142139c1837SPaolo Bonzini        }
2143139c1837SPaolo Bonzini        break;
2144139c1837SPaolo Bonzini    case INDEX_op_sar_i64:
2145139c1837SPaolo Bonzini        if (c2) {
2146d2f3066eSZihao Yu            tcg_out_opc_imm(s, OPC_SRAI, a0, a1, a2 & 0x3f);
2147139c1837SPaolo Bonzini        } else {
2148139c1837SPaolo Bonzini            tcg_out_opc_reg(s, OPC_SRA, a0, a1, a2);
2149139c1837SPaolo Bonzini        }
2150139c1837SPaolo Bonzini        break;
2151139c1837SPaolo Bonzini
215219d016adSRichard Henderson    case INDEX_op_rotl_i32:
215319d016adSRichard Henderson        if (c2) {
215419d016adSRichard Henderson            tcg_out_opc_imm(s, OPC_RORIW, a0, a1, -a2 & 0x1f);
215519d016adSRichard Henderson        } else {
215619d016adSRichard Henderson            tcg_out_opc_reg(s, OPC_ROLW, a0, a1, a2);
215719d016adSRichard Henderson        }
215819d016adSRichard Henderson        break;
215919d016adSRichard Henderson    case INDEX_op_rotl_i64:
216019d016adSRichard Henderson        if (c2) {
216119d016adSRichard Henderson            tcg_out_opc_imm(s, OPC_RORI, a0, a1, -a2 & 0x3f);
216219d016adSRichard Henderson        } else {
216319d016adSRichard Henderson            tcg_out_opc_reg(s, OPC_ROL, a0, a1, a2);
216419d016adSRichard Henderson        }
216519d016adSRichard Henderson        break;
216619d016adSRichard Henderson
216719d016adSRichard Henderson    case INDEX_op_rotr_i32:
216819d016adSRichard Henderson        if (c2) {
216919d016adSRichard Henderson            tcg_out_opc_imm(s, OPC_RORIW, a0, a1, a2 & 0x1f);
217019d016adSRichard Henderson        } else {
217119d016adSRichard Henderson            tcg_out_opc_reg(s, OPC_RORW, a0, a1, a2);
217219d016adSRichard Henderson        }
217319d016adSRichard Henderson        break;
217419d016adSRichard Henderson    case INDEX_op_rotr_i64:
217519d016adSRichard Henderson        if (c2) {
217619d016adSRichard Henderson            tcg_out_opc_imm(s, OPC_RORI, a0, a1, a2 & 0x3f);
217719d016adSRichard Henderson        } else {
217819d016adSRichard Henderson            tcg_out_opc_reg(s, OPC_ROR, a0, a1, a2);
217919d016adSRichard Henderson        }
218019d016adSRichard Henderson        break;
218119d016adSRichard Henderson
21827b4d5274SRichard Henderson    case INDEX_op_bswap64_i64:
21837b4d5274SRichard Henderson        tcg_out_opc_imm(s, OPC_REV8, a0, a1, 0);
21847b4d5274SRichard Henderson        break;
21857b4d5274SRichard Henderson    case INDEX_op_bswap32_i32:
21867b4d5274SRichard Henderson        a2 = 0;
21877b4d5274SRichard Henderson        /* fall through */
21887b4d5274SRichard Henderson    case INDEX_op_bswap32_i64:
21897b4d5274SRichard Henderson        tcg_out_opc_imm(s, OPC_REV8, a0, a1, 0);
21907b4d5274SRichard Henderson        if (a2 & TCG_BSWAP_OZ) {
21917b4d5274SRichard Henderson            tcg_out_opc_imm(s, OPC_SRLI, a0, a0, 32);
21927b4d5274SRichard Henderson        } else {
21937b4d5274SRichard Henderson            tcg_out_opc_imm(s, OPC_SRAI, a0, a0, 32);
21947b4d5274SRichard Henderson        }
21957b4d5274SRichard Henderson        break;
21967b4d5274SRichard Henderson    case INDEX_op_bswap16_i64:
21977b4d5274SRichard Henderson    case INDEX_op_bswap16_i32:
21987b4d5274SRichard Henderson        tcg_out_opc_imm(s, OPC_REV8, a0, a1, 0);
21997b4d5274SRichard Henderson        if (a2 & TCG_BSWAP_OZ) {
22007b4d5274SRichard Henderson            tcg_out_opc_imm(s, OPC_SRLI, a0, a0, 48);
22017b4d5274SRichard Henderson        } else {
22027b4d5274SRichard Henderson            tcg_out_opc_imm(s, OPC_SRAI, a0, a0, 48);
22037b4d5274SRichard Henderson        }
22047b4d5274SRichard Henderson        break;
22057b4d5274SRichard Henderson
22060956ecdaSRichard Henderson    case INDEX_op_ctpop_i32:
22070956ecdaSRichard Henderson        tcg_out_opc_imm(s, OPC_CPOPW, a0, a1, 0);
22080956ecdaSRichard Henderson        break;
22090956ecdaSRichard Henderson    case INDEX_op_ctpop_i64:
22100956ecdaSRichard Henderson        tcg_out_opc_imm(s, OPC_CPOP, a0, a1, 0);
22110956ecdaSRichard Henderson        break;
22120956ecdaSRichard Henderson
2213a30498fcSRichard Henderson    case INDEX_op_clz_i32:
2214a30498fcSRichard Henderson        tcg_out_cltz(s, TCG_TYPE_I32, OPC_CLZW, a0, a1, a2, c2);
2215a30498fcSRichard Henderson        break;
2216a30498fcSRichard Henderson    case INDEX_op_clz_i64:
2217a30498fcSRichard Henderson        tcg_out_cltz(s, TCG_TYPE_I64, OPC_CLZ, a0, a1, a2, c2);
2218a30498fcSRichard Henderson        break;
2219a30498fcSRichard Henderson    case INDEX_op_ctz_i32:
2220a30498fcSRichard Henderson        tcg_out_cltz(s, TCG_TYPE_I32, OPC_CTZW, a0, a1, a2, c2);
2221a30498fcSRichard Henderson        break;
2222a30498fcSRichard Henderson    case INDEX_op_ctz_i64:
2223a30498fcSRichard Henderson        tcg_out_cltz(s, TCG_TYPE_I64, OPC_CTZ, a0, a1, a2, c2);
2224a30498fcSRichard Henderson        break;
2225a30498fcSRichard Henderson
2226139c1837SPaolo Bonzini    case INDEX_op_add2_i32:
2227139c1837SPaolo Bonzini        tcg_out_addsub2(s, a0, a1, a2, args[3], args[4], args[5],
2228139c1837SPaolo Bonzini                        const_args[4], const_args[5], false, true);
2229139c1837SPaolo Bonzini        break;
2230139c1837SPaolo Bonzini    case INDEX_op_add2_i64:
2231139c1837SPaolo Bonzini        tcg_out_addsub2(s, a0, a1, a2, args[3], args[4], args[5],
2232139c1837SPaolo Bonzini                        const_args[4], const_args[5], false, false);
2233139c1837SPaolo Bonzini        break;
2234139c1837SPaolo Bonzini    case INDEX_op_sub2_i32:
2235139c1837SPaolo Bonzini        tcg_out_addsub2(s, a0, a1, a2, args[3], args[4], args[5],
2236139c1837SPaolo Bonzini                        const_args[4], const_args[5], true, true);
2237139c1837SPaolo Bonzini        break;
2238139c1837SPaolo Bonzini    case INDEX_op_sub2_i64:
2239139c1837SPaolo Bonzini        tcg_out_addsub2(s, a0, a1, a2, args[3], args[4], args[5],
2240139c1837SPaolo Bonzini                        const_args[4], const_args[5], true, false);
2241139c1837SPaolo Bonzini        break;
2242139c1837SPaolo Bonzini
2243139c1837SPaolo Bonzini    case INDEX_op_brcond_i32:
2244139c1837SPaolo Bonzini    case INDEX_op_brcond_i64:
2245139c1837SPaolo Bonzini        tcg_out_brcond(s, a2, a0, a1, arg_label(args[3]));
2246139c1837SPaolo Bonzini        break;
2247139c1837SPaolo Bonzini
2248139c1837SPaolo Bonzini    case INDEX_op_setcond_i32:
2249139c1837SPaolo Bonzini    case INDEX_op_setcond_i64:
2250f6453695SRichard Henderson        tcg_out_setcond(s, args[3], a0, a1, a2, c2);
2251139c1837SPaolo Bonzini        break;
2252139c1837SPaolo Bonzini
225341e4c0a9SRichard Henderson    case INDEX_op_negsetcond_i32:
225441e4c0a9SRichard Henderson    case INDEX_op_negsetcond_i64:
225541e4c0a9SRichard Henderson        tcg_out_negsetcond(s, args[3], a0, a1, a2, c2);
225641e4c0a9SRichard Henderson        break;
225741e4c0a9SRichard Henderson
2258a18d783eSRichard Henderson    case INDEX_op_movcond_i32:
2259a18d783eSRichard Henderson    case INDEX_op_movcond_i64:
2260a18d783eSRichard Henderson        tcg_out_movcond(s, args[5], a0, a1, a2, c2,
2261a18d783eSRichard Henderson                        args[3], const_args[3], args[4], const_args[4]);
2262a18d783eSRichard Henderson        break;
2263a18d783eSRichard Henderson
2264fecccfccSRichard Henderson    case INDEX_op_qemu_ld_a32_i32:
2265fecccfccSRichard Henderson    case INDEX_op_qemu_ld_a64_i32:
2266f7041977SRichard Henderson        tcg_out_qemu_ld(s, a0, a1, a2, TCG_TYPE_I32);
2267139c1837SPaolo Bonzini        break;
2268fecccfccSRichard Henderson    case INDEX_op_qemu_ld_a32_i64:
2269fecccfccSRichard Henderson    case INDEX_op_qemu_ld_a64_i64:
2270f7041977SRichard Henderson        tcg_out_qemu_ld(s, a0, a1, a2, TCG_TYPE_I64);
2271139c1837SPaolo Bonzini        break;
2272fecccfccSRichard Henderson    case INDEX_op_qemu_st_a32_i32:
2273fecccfccSRichard Henderson    case INDEX_op_qemu_st_a64_i32:
2274f7041977SRichard Henderson        tcg_out_qemu_st(s, a0, a1, a2, TCG_TYPE_I32);
2275139c1837SPaolo Bonzini        break;
2276fecccfccSRichard Henderson    case INDEX_op_qemu_st_a32_i64:
2277fecccfccSRichard Henderson    case INDEX_op_qemu_st_a64_i64:
2278f7041977SRichard Henderson        tcg_out_qemu_st(s, a0, a1, a2, TCG_TYPE_I64);
2279139c1837SPaolo Bonzini        break;
2280139c1837SPaolo Bonzini
2281139c1837SPaolo Bonzini    case INDEX_op_extrh_i64_i32:
2282139c1837SPaolo Bonzini        tcg_out_opc_imm(s, OPC_SRAI, a0, a1, 32);
2283139c1837SPaolo Bonzini        break;
2284139c1837SPaolo Bonzini
2285139c1837SPaolo Bonzini    case INDEX_op_mulsh_i32:
2286139c1837SPaolo Bonzini    case INDEX_op_mulsh_i64:
2287139c1837SPaolo Bonzini        tcg_out_opc_reg(s, OPC_MULH, a0, a1, a2);
2288139c1837SPaolo Bonzini        break;
2289139c1837SPaolo Bonzini
2290139c1837SPaolo Bonzini    case INDEX_op_muluh_i32:
2291139c1837SPaolo Bonzini    case INDEX_op_muluh_i64:
2292139c1837SPaolo Bonzini        tcg_out_opc_reg(s, OPC_MULHU, a0, a1, a2);
2293139c1837SPaolo Bonzini        break;
2294139c1837SPaolo Bonzini
2295139c1837SPaolo Bonzini    case INDEX_op_mb:
2296139c1837SPaolo Bonzini        tcg_out_mb(s, a0);
2297139c1837SPaolo Bonzini        break;
2298139c1837SPaolo Bonzini
2299139c1837SPaolo Bonzini    case INDEX_op_mov_i32:  /* Always emitted via tcg_out_mov.  */
2300139c1837SPaolo Bonzini    case INDEX_op_mov_i64:
2301139c1837SPaolo Bonzini    case INDEX_op_call:     /* Always emitted via tcg_out_call.  */
2302b55a8d9dSRichard Henderson    case INDEX_op_exit_tb:  /* Always emitted via tcg_out_exit_tb.  */
2303cf7d6b8eSRichard Henderson    case INDEX_op_goto_tb:  /* Always emitted via tcg_out_goto_tb.  */
2304678155b2SRichard Henderson    case INDEX_op_ext8s_i32:  /* Always emitted via tcg_reg_alloc_op.  */
2305678155b2SRichard Henderson    case INDEX_op_ext8s_i64:
2306d0e66c89SRichard Henderson    case INDEX_op_ext8u_i32:
2307d0e66c89SRichard Henderson    case INDEX_op_ext8u_i64:
2308753e42eaSRichard Henderson    case INDEX_op_ext16s_i32:
2309753e42eaSRichard Henderson    case INDEX_op_ext16s_i64:
2310379afdffSRichard Henderson    case INDEX_op_ext16u_i32:
2311379afdffSRichard Henderson    case INDEX_op_ext16u_i64:
231252bf3398SRichard Henderson    case INDEX_op_ext32s_i64:
23139ecf5f61SRichard Henderson    case INDEX_op_ext32u_i64:
23149c6aa274SRichard Henderson    case INDEX_op_ext_i32_i64:
2315b9bfe000SRichard Henderson    case INDEX_op_extu_i32_i64:
2316b8b94ac6SRichard Henderson    case INDEX_op_extrl_i64_i32:
2317139c1837SPaolo Bonzini    default:
2318139c1837SPaolo Bonzini        g_assert_not_reached();
2319139c1837SPaolo Bonzini    }
2320139c1837SPaolo Bonzini}
2321139c1837SPaolo Bonzini
2322f63e7089SHuang Shiyuanstatic void tcg_out_vec_op(TCGContext *s, TCGOpcode opc,
2323f63e7089SHuang Shiyuan                           unsigned vecl, unsigned vece,
2324f63e7089SHuang Shiyuan                           const TCGArg args[TCG_MAX_OP_ARGS],
2325f63e7089SHuang Shiyuan                           const int const_args[TCG_MAX_OP_ARGS])
2326f63e7089SHuang Shiyuan{
2327f63e7089SHuang Shiyuan    TCGType type = vecl + TCG_TYPE_V64;
2328f63e7089SHuang Shiyuan    TCGArg a0, a1, a2;
23295a63f599STANG Tiancheng    int c2;
2330f63e7089SHuang Shiyuan
2331f63e7089SHuang Shiyuan    a0 = args[0];
2332f63e7089SHuang Shiyuan    a1 = args[1];
2333f63e7089SHuang Shiyuan    a2 = args[2];
23345a63f599STANG Tiancheng    c2 = const_args[2];
2335f63e7089SHuang Shiyuan
2336f63e7089SHuang Shiyuan    switch (opc) {
2337d4be6ee1STANG Tiancheng    case INDEX_op_dupm_vec:
2338d4be6ee1STANG Tiancheng        tcg_out_dupm_vec(s, type, vece, a0, a1, a2);
2339d4be6ee1STANG Tiancheng        break;
2340f63e7089SHuang Shiyuan    case INDEX_op_ld_vec:
2341f63e7089SHuang Shiyuan        tcg_out_ld(s, type, a0, a1, a2);
2342f63e7089SHuang Shiyuan        break;
2343f63e7089SHuang Shiyuan    case INDEX_op_st_vec:
2344f63e7089SHuang Shiyuan        tcg_out_st(s, type, a0, a1, a2);
2345f63e7089SHuang Shiyuan        break;
23465a63f599STANG Tiancheng    case INDEX_op_add_vec:
23475a63f599STANG Tiancheng        set_vtype_len_sew(s, type, vece);
23485a63f599STANG Tiancheng        tcg_out_opc_vv_vi(s, OPC_VADD_VV, OPC_VADD_VI, a0, a1, a2, c2);
23495a63f599STANG Tiancheng        break;
23505a63f599STANG Tiancheng    case INDEX_op_sub_vec:
23515a63f599STANG Tiancheng        set_vtype_len_sew(s, type, vece);
23525a63f599STANG Tiancheng        tcg_out_opc_vv(s, OPC_VSUB_VV, a0, a1, a2);
23535a63f599STANG Tiancheng        break;
23545a63f599STANG Tiancheng    case INDEX_op_and_vec:
23555a63f599STANG Tiancheng        set_vtype_len(s, type);
23565a63f599STANG Tiancheng        tcg_out_opc_vv_vi(s, OPC_VAND_VV, OPC_VAND_VI, a0, a1, a2, c2);
23575a63f599STANG Tiancheng        break;
23585a63f599STANG Tiancheng    case INDEX_op_or_vec:
23595a63f599STANG Tiancheng        set_vtype_len(s, type);
23605a63f599STANG Tiancheng        tcg_out_opc_vv_vi(s, OPC_VOR_VV, OPC_VOR_VI, a0, a1, a2, c2);
23615a63f599STANG Tiancheng        break;
23625a63f599STANG Tiancheng    case INDEX_op_xor_vec:
23635a63f599STANG Tiancheng        set_vtype_len(s, type);
23645a63f599STANG Tiancheng        tcg_out_opc_vv_vi(s, OPC_VXOR_VV, OPC_VXOR_VI, a0, a1, a2, c2);
23655a63f599STANG Tiancheng        break;
23665a63f599STANG Tiancheng    case INDEX_op_not_vec:
23675a63f599STANG Tiancheng        set_vtype_len(s, type);
23685a63f599STANG Tiancheng        tcg_out_opc_vi(s, OPC_VXOR_VI, a0, a1, -1);
23695a63f599STANG Tiancheng        break;
2370*a31768c0STANG Tiancheng    case INDEX_op_cmp_vec:
2371*a31768c0STANG Tiancheng        tcg_out_cmpsel(s, type, vece, args[3], a0, a1, a2, c2,
2372*a31768c0STANG Tiancheng                       -1, true, 0, true);
2373*a31768c0STANG Tiancheng        break;
2374*a31768c0STANG Tiancheng    case INDEX_op_cmpsel_vec:
2375*a31768c0STANG Tiancheng        tcg_out_cmpsel(s, type, vece, args[5], a0, a1, a2, c2,
2376*a31768c0STANG Tiancheng                       args[3], const_args[3], args[4], const_args[4]);
2377*a31768c0STANG Tiancheng        break;
2378f63e7089SHuang Shiyuan    case INDEX_op_mov_vec: /* Always emitted via tcg_out_mov.  */
2379f63e7089SHuang Shiyuan    case INDEX_op_dup_vec: /* Always emitted via tcg_out_dup_vec.  */
2380f63e7089SHuang Shiyuan    default:
2381f63e7089SHuang Shiyuan        g_assert_not_reached();
2382f63e7089SHuang Shiyuan    }
2383f63e7089SHuang Shiyuan}
2384f63e7089SHuang Shiyuan
2385f63e7089SHuang Shiyuanvoid tcg_expand_vec_op(TCGOpcode opc, TCGType type, unsigned vece,
2386f63e7089SHuang Shiyuan                       TCGArg a0, ...)
2387f63e7089SHuang Shiyuan{
2388f63e7089SHuang Shiyuan    g_assert_not_reached();
2389f63e7089SHuang Shiyuan}
2390f63e7089SHuang Shiyuan
2391f63e7089SHuang Shiyuanint tcg_can_emit_vec_op(TCGOpcode opc, TCGType type, unsigned vece)
2392f63e7089SHuang Shiyuan{
2393f63e7089SHuang Shiyuan    switch (opc) {
23945a63f599STANG Tiancheng    case INDEX_op_add_vec:
23955a63f599STANG Tiancheng    case INDEX_op_sub_vec:
23965a63f599STANG Tiancheng    case INDEX_op_and_vec:
23975a63f599STANG Tiancheng    case INDEX_op_or_vec:
23985a63f599STANG Tiancheng    case INDEX_op_xor_vec:
23995a63f599STANG Tiancheng    case INDEX_op_not_vec:
2400*a31768c0STANG Tiancheng    case INDEX_op_cmp_vec:
2401*a31768c0STANG Tiancheng    case INDEX_op_cmpsel_vec:
24025a63f599STANG Tiancheng        return 1;
2403f63e7089SHuang Shiyuan    default:
2404f63e7089SHuang Shiyuan        return 0;
2405f63e7089SHuang Shiyuan    }
2406f63e7089SHuang Shiyuan}
2407f63e7089SHuang Shiyuan
2408665be288SRichard Hendersonstatic TCGConstraintSetIndex tcg_target_op_def(TCGOpcode op)
2409139c1837SPaolo Bonzini{
2410139c1837SPaolo Bonzini    switch (op) {
2411139c1837SPaolo Bonzini    case INDEX_op_goto_ptr:
2412665be288SRichard Henderson        return C_O0_I1(r);
2413139c1837SPaolo Bonzini
2414139c1837SPaolo Bonzini    case INDEX_op_ld8u_i32:
2415139c1837SPaolo Bonzini    case INDEX_op_ld8s_i32:
2416139c1837SPaolo Bonzini    case INDEX_op_ld16u_i32:
2417139c1837SPaolo Bonzini    case INDEX_op_ld16s_i32:
2418139c1837SPaolo Bonzini    case INDEX_op_ld_i32:
2419139c1837SPaolo Bonzini    case INDEX_op_not_i32:
2420139c1837SPaolo Bonzini    case INDEX_op_neg_i32:
2421139c1837SPaolo Bonzini    case INDEX_op_ld8u_i64:
2422139c1837SPaolo Bonzini    case INDEX_op_ld8s_i64:
2423139c1837SPaolo Bonzini    case INDEX_op_ld16u_i64:
2424139c1837SPaolo Bonzini    case INDEX_op_ld16s_i64:
2425139c1837SPaolo Bonzini    case INDEX_op_ld32s_i64:
2426139c1837SPaolo Bonzini    case INDEX_op_ld32u_i64:
2427139c1837SPaolo Bonzini    case INDEX_op_ld_i64:
2428139c1837SPaolo Bonzini    case INDEX_op_not_i64:
2429139c1837SPaolo Bonzini    case INDEX_op_neg_i64:
2430139c1837SPaolo Bonzini    case INDEX_op_ext8u_i32:
2431139c1837SPaolo Bonzini    case INDEX_op_ext8u_i64:
2432139c1837SPaolo Bonzini    case INDEX_op_ext16u_i32:
2433139c1837SPaolo Bonzini    case INDEX_op_ext16u_i64:
2434139c1837SPaolo Bonzini    case INDEX_op_ext32u_i64:
2435139c1837SPaolo Bonzini    case INDEX_op_extu_i32_i64:
2436139c1837SPaolo Bonzini    case INDEX_op_ext8s_i32:
2437139c1837SPaolo Bonzini    case INDEX_op_ext8s_i64:
2438139c1837SPaolo Bonzini    case INDEX_op_ext16s_i32:
2439139c1837SPaolo Bonzini    case INDEX_op_ext16s_i64:
2440139c1837SPaolo Bonzini    case INDEX_op_ext32s_i64:
2441139c1837SPaolo Bonzini    case INDEX_op_extrl_i64_i32:
2442139c1837SPaolo Bonzini    case INDEX_op_extrh_i64_i32:
2443139c1837SPaolo Bonzini    case INDEX_op_ext_i32_i64:
24447b4d5274SRichard Henderson    case INDEX_op_bswap16_i32:
24457b4d5274SRichard Henderson    case INDEX_op_bswap32_i32:
24467b4d5274SRichard Henderson    case INDEX_op_bswap16_i64:
24477b4d5274SRichard Henderson    case INDEX_op_bswap32_i64:
24487b4d5274SRichard Henderson    case INDEX_op_bswap64_i64:
24490956ecdaSRichard Henderson    case INDEX_op_ctpop_i32:
24500956ecdaSRichard Henderson    case INDEX_op_ctpop_i64:
2451665be288SRichard Henderson        return C_O1_I1(r, r);
2452139c1837SPaolo Bonzini
2453139c1837SPaolo Bonzini    case INDEX_op_st8_i32:
2454139c1837SPaolo Bonzini    case INDEX_op_st16_i32:
2455139c1837SPaolo Bonzini    case INDEX_op_st_i32:
2456139c1837SPaolo Bonzini    case INDEX_op_st8_i64:
2457139c1837SPaolo Bonzini    case INDEX_op_st16_i64:
2458139c1837SPaolo Bonzini    case INDEX_op_st32_i64:
2459139c1837SPaolo Bonzini    case INDEX_op_st_i64:
2460665be288SRichard Henderson        return C_O0_I2(rZ, r);
2461139c1837SPaolo Bonzini
2462139c1837SPaolo Bonzini    case INDEX_op_add_i32:
2463139c1837SPaolo Bonzini    case INDEX_op_and_i32:
2464139c1837SPaolo Bonzini    case INDEX_op_or_i32:
2465139c1837SPaolo Bonzini    case INDEX_op_xor_i32:
2466139c1837SPaolo Bonzini    case INDEX_op_add_i64:
2467139c1837SPaolo Bonzini    case INDEX_op_and_i64:
2468139c1837SPaolo Bonzini    case INDEX_op_or_i64:
2469139c1837SPaolo Bonzini    case INDEX_op_xor_i64:
2470f6453695SRichard Henderson    case INDEX_op_setcond_i32:
2471f6453695SRichard Henderson    case INDEX_op_setcond_i64:
247241e4c0a9SRichard Henderson    case INDEX_op_negsetcond_i32:
247341e4c0a9SRichard Henderson    case INDEX_op_negsetcond_i64:
2474665be288SRichard Henderson        return C_O1_I2(r, r, rI);
2475139c1837SPaolo Bonzini
247699f4ec6eSRichard Henderson    case INDEX_op_andc_i32:
247799f4ec6eSRichard Henderson    case INDEX_op_andc_i64:
247899f4ec6eSRichard Henderson    case INDEX_op_orc_i32:
247999f4ec6eSRichard Henderson    case INDEX_op_orc_i64:
248099f4ec6eSRichard Henderson    case INDEX_op_eqv_i32:
248199f4ec6eSRichard Henderson    case INDEX_op_eqv_i64:
248299f4ec6eSRichard Henderson        return C_O1_I2(r, r, rJ);
248399f4ec6eSRichard Henderson
2484139c1837SPaolo Bonzini    case INDEX_op_sub_i32:
2485139c1837SPaolo Bonzini    case INDEX_op_sub_i64:
2486665be288SRichard Henderson        return C_O1_I2(r, rZ, rN);
2487139c1837SPaolo Bonzini
2488139c1837SPaolo Bonzini    case INDEX_op_mul_i32:
2489139c1837SPaolo Bonzini    case INDEX_op_mulsh_i32:
2490139c1837SPaolo Bonzini    case INDEX_op_muluh_i32:
2491139c1837SPaolo Bonzini    case INDEX_op_div_i32:
2492139c1837SPaolo Bonzini    case INDEX_op_divu_i32:
2493139c1837SPaolo Bonzini    case INDEX_op_rem_i32:
2494139c1837SPaolo Bonzini    case INDEX_op_remu_i32:
2495139c1837SPaolo Bonzini    case INDEX_op_mul_i64:
2496139c1837SPaolo Bonzini    case INDEX_op_mulsh_i64:
2497139c1837SPaolo Bonzini    case INDEX_op_muluh_i64:
2498139c1837SPaolo Bonzini    case INDEX_op_div_i64:
2499139c1837SPaolo Bonzini    case INDEX_op_divu_i64:
2500139c1837SPaolo Bonzini    case INDEX_op_rem_i64:
2501139c1837SPaolo Bonzini    case INDEX_op_remu_i64:
2502665be288SRichard Henderson        return C_O1_I2(r, rZ, rZ);
2503139c1837SPaolo Bonzini
2504139c1837SPaolo Bonzini    case INDEX_op_shl_i32:
2505139c1837SPaolo Bonzini    case INDEX_op_shr_i32:
2506139c1837SPaolo Bonzini    case INDEX_op_sar_i32:
250719d016adSRichard Henderson    case INDEX_op_rotl_i32:
250819d016adSRichard Henderson    case INDEX_op_rotr_i32:
2509139c1837SPaolo Bonzini    case INDEX_op_shl_i64:
2510139c1837SPaolo Bonzini    case INDEX_op_shr_i64:
2511139c1837SPaolo Bonzini    case INDEX_op_sar_i64:
251219d016adSRichard Henderson    case INDEX_op_rotl_i64:
251319d016adSRichard Henderson    case INDEX_op_rotr_i64:
2514665be288SRichard Henderson        return C_O1_I2(r, r, ri);
2515139c1837SPaolo Bonzini
2516a30498fcSRichard Henderson    case INDEX_op_clz_i32:
2517a30498fcSRichard Henderson    case INDEX_op_clz_i64:
2518a30498fcSRichard Henderson    case INDEX_op_ctz_i32:
2519a30498fcSRichard Henderson    case INDEX_op_ctz_i64:
2520a30498fcSRichard Henderson        return C_N1_I2(r, r, rM);
2521a30498fcSRichard Henderson
2522139c1837SPaolo Bonzini    case INDEX_op_brcond_i32:
2523139c1837SPaolo Bonzini    case INDEX_op_brcond_i64:
2524665be288SRichard Henderson        return C_O0_I2(rZ, rZ);
2525139c1837SPaolo Bonzini
2526a18d783eSRichard Henderson    case INDEX_op_movcond_i32:
2527a18d783eSRichard Henderson    case INDEX_op_movcond_i64:
2528a18d783eSRichard Henderson        return C_O1_I4(r, r, rI, rM, rM);
2529a18d783eSRichard Henderson
2530139c1837SPaolo Bonzini    case INDEX_op_add2_i32:
2531139c1837SPaolo Bonzini    case INDEX_op_add2_i64:
2532139c1837SPaolo Bonzini    case INDEX_op_sub2_i32:
2533139c1837SPaolo Bonzini    case INDEX_op_sub2_i64:
2534665be288SRichard Henderson        return C_O2_I4(r, r, rZ, rZ, rM, rM);
2535139c1837SPaolo Bonzini
2536fecccfccSRichard Henderson    case INDEX_op_qemu_ld_a32_i32:
2537fecccfccSRichard Henderson    case INDEX_op_qemu_ld_a64_i32:
2538fecccfccSRichard Henderson    case INDEX_op_qemu_ld_a32_i64:
2539fecccfccSRichard Henderson    case INDEX_op_qemu_ld_a64_i64:
2540f0f43534SRichard Henderson        return C_O1_I1(r, r);
2541fecccfccSRichard Henderson    case INDEX_op_qemu_st_a32_i32:
2542fecccfccSRichard Henderson    case INDEX_op_qemu_st_a64_i32:
2543fecccfccSRichard Henderson    case INDEX_op_qemu_st_a32_i64:
2544fecccfccSRichard Henderson    case INDEX_op_qemu_st_a64_i64:
2545f0f43534SRichard Henderson        return C_O0_I2(rZ, r);
2546139c1837SPaolo Bonzini
2547f63e7089SHuang Shiyuan    case INDEX_op_st_vec:
2548f63e7089SHuang Shiyuan        return C_O0_I2(v, r);
2549d4be6ee1STANG Tiancheng    case INDEX_op_dup_vec:
2550d4be6ee1STANG Tiancheng    case INDEX_op_dupm_vec:
2551f63e7089SHuang Shiyuan    case INDEX_op_ld_vec:
2552f63e7089SHuang Shiyuan        return C_O1_I1(v, r);
25535a63f599STANG Tiancheng    case INDEX_op_not_vec:
25545a63f599STANG Tiancheng        return C_O1_I1(v, v);
25555a63f599STANG Tiancheng    case INDEX_op_add_vec:
25565a63f599STANG Tiancheng    case INDEX_op_and_vec:
25575a63f599STANG Tiancheng    case INDEX_op_or_vec:
25585a63f599STANG Tiancheng    case INDEX_op_xor_vec:
25595a63f599STANG Tiancheng        return C_O1_I2(v, v, vK);
25605a63f599STANG Tiancheng    case INDEX_op_sub_vec:
25615a63f599STANG Tiancheng        return C_O1_I2(v, v, v);
2562*a31768c0STANG Tiancheng    case INDEX_op_cmp_vec:
2563*a31768c0STANG Tiancheng        return C_O1_I2(v, v, vL);
2564*a31768c0STANG Tiancheng    case INDEX_op_cmpsel_vec:
2565*a31768c0STANG Tiancheng        return C_O1_I4(v, v, vL, vK, vK);
2566139c1837SPaolo Bonzini    default:
2567665be288SRichard Henderson        g_assert_not_reached();
2568139c1837SPaolo Bonzini    }
2569139c1837SPaolo Bonzini}
2570139c1837SPaolo Bonzini
2571139c1837SPaolo Bonzinistatic const int tcg_target_callee_save_regs[] = {
2572139c1837SPaolo Bonzini    TCG_REG_S0,       /* used for the global env (TCG_AREG0) */
2573139c1837SPaolo Bonzini    TCG_REG_S1,
2574139c1837SPaolo Bonzini    TCG_REG_S2,
2575139c1837SPaolo Bonzini    TCG_REG_S3,
2576139c1837SPaolo Bonzini    TCG_REG_S4,
2577139c1837SPaolo Bonzini    TCG_REG_S5,
2578139c1837SPaolo Bonzini    TCG_REG_S6,
2579139c1837SPaolo Bonzini    TCG_REG_S7,
2580139c1837SPaolo Bonzini    TCG_REG_S8,
2581139c1837SPaolo Bonzini    TCG_REG_S9,
2582139c1837SPaolo Bonzini    TCG_REG_S10,
2583139c1837SPaolo Bonzini    TCG_REG_S11,
2584139c1837SPaolo Bonzini    TCG_REG_RA,       /* should be last for ABI compliance */
2585139c1837SPaolo Bonzini};
2586139c1837SPaolo Bonzini
2587139c1837SPaolo Bonzini/* Stack frame parameters.  */
2588139c1837SPaolo Bonzini#define REG_SIZE   (TCG_TARGET_REG_BITS / 8)
2589139c1837SPaolo Bonzini#define SAVE_SIZE  ((int)ARRAY_SIZE(tcg_target_callee_save_regs) * REG_SIZE)
2590139c1837SPaolo Bonzini#define TEMP_SIZE  (CPU_TEMP_BUF_NLONGS * (int)sizeof(long))
2591139c1837SPaolo Bonzini#define FRAME_SIZE ((TCG_STATIC_CALL_ARGS_SIZE + TEMP_SIZE + SAVE_SIZE \
2592139c1837SPaolo Bonzini                     + TCG_TARGET_STACK_ALIGN - 1) \
2593139c1837SPaolo Bonzini                    & -TCG_TARGET_STACK_ALIGN)
2594139c1837SPaolo Bonzini#define SAVE_OFS   (TCG_STATIC_CALL_ARGS_SIZE + TEMP_SIZE)
2595139c1837SPaolo Bonzini
2596139c1837SPaolo Bonzini/* We're expecting to be able to use an immediate for frame allocation.  */
2597139c1837SPaolo BonziniQEMU_BUILD_BUG_ON(FRAME_SIZE > 0x7ff);
2598139c1837SPaolo Bonzini
2599139c1837SPaolo Bonzini/* Generate global QEMU prologue and epilogue code */
2600139c1837SPaolo Bonzinistatic void tcg_target_qemu_prologue(TCGContext *s)
2601139c1837SPaolo Bonzini{
2602139c1837SPaolo Bonzini    int i;
2603139c1837SPaolo Bonzini
2604139c1837SPaolo Bonzini    tcg_set_frame(s, TCG_REG_SP, TCG_STATIC_CALL_ARGS_SIZE, TEMP_SIZE);
2605139c1837SPaolo Bonzini
2606139c1837SPaolo Bonzini    /* TB prologue */
2607139c1837SPaolo Bonzini    tcg_out_opc_imm(s, OPC_ADDI, TCG_REG_SP, TCG_REG_SP, -FRAME_SIZE);
2608139c1837SPaolo Bonzini    for (i = 0; i < ARRAY_SIZE(tcg_target_callee_save_regs); i++) {
2609139c1837SPaolo Bonzini        tcg_out_st(s, TCG_TYPE_REG, tcg_target_callee_save_regs[i],
2610139c1837SPaolo Bonzini                   TCG_REG_SP, SAVE_OFS + i * REG_SIZE);
2611139c1837SPaolo Bonzini    }
2612139c1837SPaolo Bonzini
26134944d359SRichard Henderson    if (!tcg_use_softmmu && guest_base) {
2614139c1837SPaolo Bonzini        tcg_out_movi(s, TCG_TYPE_PTR, TCG_GUEST_BASE_REG, guest_base);
2615139c1837SPaolo Bonzini        tcg_regset_set_reg(s->reserved_regs, TCG_GUEST_BASE_REG);
2616cf0ed30eSRichard Henderson    }
2617139c1837SPaolo Bonzini
2618139c1837SPaolo Bonzini    /* Call generated code */
2619139c1837SPaolo Bonzini    tcg_out_mov(s, TCG_TYPE_PTR, TCG_AREG0, tcg_target_call_iarg_regs[0]);
2620139c1837SPaolo Bonzini    tcg_out_opc_imm(s, OPC_JALR, TCG_REG_ZERO, tcg_target_call_iarg_regs[1], 0);
2621139c1837SPaolo Bonzini
2622139c1837SPaolo Bonzini    /* Return path for goto_ptr. Set return value to 0 */
2623c8bc1168SRichard Henderson    tcg_code_gen_epilogue = tcg_splitwx_to_rx(s->code_ptr);
2624139c1837SPaolo Bonzini    tcg_out_mov(s, TCG_TYPE_REG, TCG_REG_A0, TCG_REG_ZERO);
2625139c1837SPaolo Bonzini
2626139c1837SPaolo Bonzini    /* TB epilogue */
2627793f7381SRichard Henderson    tb_ret_addr = tcg_splitwx_to_rx(s->code_ptr);
2628139c1837SPaolo Bonzini    for (i = 0; i < ARRAY_SIZE(tcg_target_callee_save_regs); i++) {
2629139c1837SPaolo Bonzini        tcg_out_ld(s, TCG_TYPE_REG, tcg_target_callee_save_regs[i],
2630139c1837SPaolo Bonzini                   TCG_REG_SP, SAVE_OFS + i * REG_SIZE);
2631139c1837SPaolo Bonzini    }
2632139c1837SPaolo Bonzini
2633139c1837SPaolo Bonzini    tcg_out_opc_imm(s, OPC_ADDI, TCG_REG_SP, TCG_REG_SP, FRAME_SIZE);
2634139c1837SPaolo Bonzini    tcg_out_opc_imm(s, OPC_JALR, TCG_REG_ZERO, TCG_REG_RA, 0);
2635139c1837SPaolo Bonzini}
2636139c1837SPaolo Bonzini
26379358fbbfSRichard Hendersonstatic void tcg_out_tb_start(TCGContext *s)
26389358fbbfSRichard Henderson{
2639f63e7089SHuang Shiyuan    init_setting_vtype(s);
2640f63e7089SHuang Shiyuan}
2641f63e7089SHuang Shiyuan
2642f63e7089SHuang Shiyuanstatic bool vtype_check(unsigned vtype)
2643f63e7089SHuang Shiyuan{
2644f63e7089SHuang Shiyuan    unsigned long tmp;
2645f63e7089SHuang Shiyuan
2646f63e7089SHuang Shiyuan    /* vsetvl tmp, zero, vtype */
2647f63e7089SHuang Shiyuan    asm(".insn r 0x57, 7, 0x40, %0, zero, %1" : "=r"(tmp) : "r"(vtype));
2648f63e7089SHuang Shiyuan    return tmp != 0;
2649f63e7089SHuang Shiyuan}
2650f63e7089SHuang Shiyuan
2651f63e7089SHuang Shiyuanstatic void probe_frac_lmul_1(TCGType type, MemOp vsew)
2652f63e7089SHuang Shiyuan{
2653f63e7089SHuang Shiyuan    VsetCache *p = &riscv_vset_cache[type - TCG_TYPE_V64][vsew];
2654f63e7089SHuang Shiyuan    unsigned avl = tcg_type_size(type) >> vsew;
2655f63e7089SHuang Shiyuan    int lmul = type - riscv_lg2_vlenb;
2656f63e7089SHuang Shiyuan    unsigned vtype = encode_vtype(true, true, vsew, lmul & 7);
2657f63e7089SHuang Shiyuan    bool lmul_eq_avl = true;
2658f63e7089SHuang Shiyuan
2659f63e7089SHuang Shiyuan    /* Guaranteed by Zve64x. */
2660f63e7089SHuang Shiyuan    assert(lmul < 3);
2661f63e7089SHuang Shiyuan
2662f63e7089SHuang Shiyuan    /*
2663f63e7089SHuang Shiyuan     * For LMUL < -3, the host vector size is so large that TYPE
2664f63e7089SHuang Shiyuan     * is smaller than the minimum 1/8 fraction.
2665f63e7089SHuang Shiyuan     *
2666f63e7089SHuang Shiyuan     * For other fractional LMUL settings, implementations must
2667f63e7089SHuang Shiyuan     * support SEW settings between SEW_MIN and LMUL * ELEN, inclusive.
2668f63e7089SHuang Shiyuan     * So if ELEN = 64, LMUL = 1/2, then SEW will support e8, e16, e32,
2669f63e7089SHuang Shiyuan     * but e64 may not be supported. In other words, the hardware only
2670f63e7089SHuang Shiyuan     * guarantees SEW_MIN <= SEW <= LMUL * ELEN.  Check.
2671f63e7089SHuang Shiyuan     */
2672f63e7089SHuang Shiyuan    if (lmul < 0 && (lmul < -3 || !vtype_check(vtype))) {
2673f63e7089SHuang Shiyuan        vtype = encode_vtype(true, true, vsew, VLMUL_M1);
2674f63e7089SHuang Shiyuan        lmul_eq_avl = false;
2675f63e7089SHuang Shiyuan    }
2676f63e7089SHuang Shiyuan
2677f63e7089SHuang Shiyuan    if (avl < 32) {
2678f63e7089SHuang Shiyuan        p->vset_insn = encode_vseti(OPC_VSETIVLI, TCG_REG_ZERO, avl, vtype);
2679f63e7089SHuang Shiyuan    } else if (lmul_eq_avl) {
2680f63e7089SHuang Shiyuan        /* rd != 0 and rs1 == 0 uses vlmax */
2681f63e7089SHuang Shiyuan        p->vset_insn = encode_vset(OPC_VSETVLI, TCG_REG_TMP0, TCG_REG_ZERO, vtype);
2682f63e7089SHuang Shiyuan    } else {
2683f63e7089SHuang Shiyuan        p->movi_insn = encode_i(OPC_ADDI, TCG_REG_TMP0, TCG_REG_ZERO, avl);
2684f63e7089SHuang Shiyuan        p->vset_insn = encode_vset(OPC_VSETVLI, TCG_REG_ZERO, TCG_REG_TMP0, vtype);
2685f63e7089SHuang Shiyuan    }
2686f63e7089SHuang Shiyuan}
2687f63e7089SHuang Shiyuan
2688f63e7089SHuang Shiyuanstatic void probe_frac_lmul(void)
2689f63e7089SHuang Shiyuan{
2690f63e7089SHuang Shiyuan    /* Match riscv_lg2_vlenb to TCG_TYPE_V64. */
2691f63e7089SHuang Shiyuan    QEMU_BUILD_BUG_ON(TCG_TYPE_V64 != 3);
2692f63e7089SHuang Shiyuan
2693f63e7089SHuang Shiyuan    for (TCGType t = TCG_TYPE_V64; t <= TCG_TYPE_V256; t++) {
2694f63e7089SHuang Shiyuan        for (MemOp e = MO_8; e <= MO_64; e++) {
2695f63e7089SHuang Shiyuan            probe_frac_lmul_1(t, e);
2696f63e7089SHuang Shiyuan        }
2697f63e7089SHuang Shiyuan    }
26989358fbbfSRichard Henderson}
26999358fbbfSRichard Henderson
2700139c1837SPaolo Bonzinistatic void tcg_target_init(TCGContext *s)
2701139c1837SPaolo Bonzini{
2702139c1837SPaolo Bonzini    tcg_target_available_regs[TCG_TYPE_I32] = 0xffffffff;
2703139c1837SPaolo Bonzini    tcg_target_available_regs[TCG_TYPE_I64] = 0xffffffff;
2704139c1837SPaolo Bonzini
2705f63e7089SHuang Shiyuan    tcg_target_call_clobber_regs = -1;
2706139c1837SPaolo Bonzini    tcg_regset_reset_reg(tcg_target_call_clobber_regs, TCG_REG_S0);
2707139c1837SPaolo Bonzini    tcg_regset_reset_reg(tcg_target_call_clobber_regs, TCG_REG_S1);
2708139c1837SPaolo Bonzini    tcg_regset_reset_reg(tcg_target_call_clobber_regs, TCG_REG_S2);
2709139c1837SPaolo Bonzini    tcg_regset_reset_reg(tcg_target_call_clobber_regs, TCG_REG_S3);
2710139c1837SPaolo Bonzini    tcg_regset_reset_reg(tcg_target_call_clobber_regs, TCG_REG_S4);
2711139c1837SPaolo Bonzini    tcg_regset_reset_reg(tcg_target_call_clobber_regs, TCG_REG_S5);
2712139c1837SPaolo Bonzini    tcg_regset_reset_reg(tcg_target_call_clobber_regs, TCG_REG_S6);
2713139c1837SPaolo Bonzini    tcg_regset_reset_reg(tcg_target_call_clobber_regs, TCG_REG_S7);
2714139c1837SPaolo Bonzini    tcg_regset_reset_reg(tcg_target_call_clobber_regs, TCG_REG_S8);
2715139c1837SPaolo Bonzini    tcg_regset_reset_reg(tcg_target_call_clobber_regs, TCG_REG_S9);
2716139c1837SPaolo Bonzini    tcg_regset_reset_reg(tcg_target_call_clobber_regs, TCG_REG_S10);
2717139c1837SPaolo Bonzini    tcg_regset_reset_reg(tcg_target_call_clobber_regs, TCG_REG_S11);
2718139c1837SPaolo Bonzini
2719139c1837SPaolo Bonzini    s->reserved_regs = 0;
2720139c1837SPaolo Bonzini    tcg_regset_set_reg(s->reserved_regs, TCG_REG_ZERO);
2721139c1837SPaolo Bonzini    tcg_regset_set_reg(s->reserved_regs, TCG_REG_TMP0);
2722139c1837SPaolo Bonzini    tcg_regset_set_reg(s->reserved_regs, TCG_REG_TMP1);
2723139c1837SPaolo Bonzini    tcg_regset_set_reg(s->reserved_regs, TCG_REG_TMP2);
2724139c1837SPaolo Bonzini    tcg_regset_set_reg(s->reserved_regs, TCG_REG_SP);
2725139c1837SPaolo Bonzini    tcg_regset_set_reg(s->reserved_regs, TCG_REG_GP);
2726139c1837SPaolo Bonzini    tcg_regset_set_reg(s->reserved_regs, TCG_REG_TP);
2727f63e7089SHuang Shiyuan
2728f63e7089SHuang Shiyuan    if (cpuinfo & CPUINFO_ZVE64X) {
2729f63e7089SHuang Shiyuan        switch (riscv_lg2_vlenb) {
2730f63e7089SHuang Shiyuan        case TCG_TYPE_V64:
2731f63e7089SHuang Shiyuan            tcg_target_available_regs[TCG_TYPE_V64] = ALL_VECTOR_REGS;
2732f63e7089SHuang Shiyuan            tcg_target_available_regs[TCG_TYPE_V128] = ALL_DVECTOR_REG_GROUPS;
2733f63e7089SHuang Shiyuan            tcg_target_available_regs[TCG_TYPE_V256] = ALL_QVECTOR_REG_GROUPS;
2734f63e7089SHuang Shiyuan            s->reserved_regs |= (~ALL_QVECTOR_REG_GROUPS & ALL_VECTOR_REGS);
2735f63e7089SHuang Shiyuan            break;
2736f63e7089SHuang Shiyuan        case TCG_TYPE_V128:
2737f63e7089SHuang Shiyuan            tcg_target_available_regs[TCG_TYPE_V64] = ALL_VECTOR_REGS;
2738f63e7089SHuang Shiyuan            tcg_target_available_regs[TCG_TYPE_V128] = ALL_VECTOR_REGS;
2739f63e7089SHuang Shiyuan            tcg_target_available_regs[TCG_TYPE_V256] = ALL_DVECTOR_REG_GROUPS;
2740f63e7089SHuang Shiyuan            s->reserved_regs |= (~ALL_DVECTOR_REG_GROUPS & ALL_VECTOR_REGS);
2741f63e7089SHuang Shiyuan            break;
2742f63e7089SHuang Shiyuan        default:
2743f63e7089SHuang Shiyuan            /* Guaranteed by Zve64x. */
2744f63e7089SHuang Shiyuan            tcg_debug_assert(riscv_lg2_vlenb >= TCG_TYPE_V256);
2745f63e7089SHuang Shiyuan            tcg_target_available_regs[TCG_TYPE_V64] = ALL_VECTOR_REGS;
2746f63e7089SHuang Shiyuan            tcg_target_available_regs[TCG_TYPE_V128] = ALL_VECTOR_REGS;
2747f63e7089SHuang Shiyuan            tcg_target_available_regs[TCG_TYPE_V256] = ALL_VECTOR_REGS;
2748f63e7089SHuang Shiyuan            break;
2749f63e7089SHuang Shiyuan        }
2750f63e7089SHuang Shiyuan        tcg_regset_set_reg(s->reserved_regs, TCG_REG_V0);
2751f63e7089SHuang Shiyuan        probe_frac_lmul();
2752f63e7089SHuang Shiyuan    }
2753139c1837SPaolo Bonzini}
2754139c1837SPaolo Bonzini
2755139c1837SPaolo Bonzinitypedef struct {
2756139c1837SPaolo Bonzini    DebugFrameHeader h;
2757139c1837SPaolo Bonzini    uint8_t fde_def_cfa[4];
2758139c1837SPaolo Bonzini    uint8_t fde_reg_ofs[ARRAY_SIZE(tcg_target_callee_save_regs) * 2];
2759139c1837SPaolo Bonzini} DebugFrame;
2760139c1837SPaolo Bonzini
2761139c1837SPaolo Bonzini#define ELF_HOST_MACHINE EM_RISCV
2762139c1837SPaolo Bonzini
2763139c1837SPaolo Bonzinistatic const DebugFrame debug_frame = {
2764139c1837SPaolo Bonzini    .h.cie.len = sizeof(DebugFrameCIE) - 4, /* length after .len member */
2765139c1837SPaolo Bonzini    .h.cie.id = -1,
2766139c1837SPaolo Bonzini    .h.cie.version = 1,
2767139c1837SPaolo Bonzini    .h.cie.code_align = 1,
2768139c1837SPaolo Bonzini    .h.cie.data_align = -(TCG_TARGET_REG_BITS / 8) & 0x7f, /* sleb128 */
2769139c1837SPaolo Bonzini    .h.cie.return_column = TCG_REG_RA,
2770139c1837SPaolo Bonzini
2771139c1837SPaolo Bonzini    /* Total FDE size does not include the "len" member.  */
2772139c1837SPaolo Bonzini    .h.fde.len = sizeof(DebugFrame) - offsetof(DebugFrame, h.fde.cie_offset),
2773139c1837SPaolo Bonzini
2774139c1837SPaolo Bonzini    .fde_def_cfa = {
2775139c1837SPaolo Bonzini        12, TCG_REG_SP,                 /* DW_CFA_def_cfa sp, ... */
2776139c1837SPaolo Bonzini        (FRAME_SIZE & 0x7f) | 0x80,     /* ... uleb128 FRAME_SIZE */
2777139c1837SPaolo Bonzini        (FRAME_SIZE >> 7)
2778139c1837SPaolo Bonzini    },
2779139c1837SPaolo Bonzini    .fde_reg_ofs = {
2780139c1837SPaolo Bonzini        0x80 + 9,  12,                  /* DW_CFA_offset, s1,  -96 */
2781139c1837SPaolo Bonzini        0x80 + 18, 11,                  /* DW_CFA_offset, s2,  -88 */
2782139c1837SPaolo Bonzini        0x80 + 19, 10,                  /* DW_CFA_offset, s3,  -80 */
2783139c1837SPaolo Bonzini        0x80 + 20, 9,                   /* DW_CFA_offset, s4,  -72 */
2784139c1837SPaolo Bonzini        0x80 + 21, 8,                   /* DW_CFA_offset, s5,  -64 */
2785139c1837SPaolo Bonzini        0x80 + 22, 7,                   /* DW_CFA_offset, s6,  -56 */
2786139c1837SPaolo Bonzini        0x80 + 23, 6,                   /* DW_CFA_offset, s7,  -48 */
2787139c1837SPaolo Bonzini        0x80 + 24, 5,                   /* DW_CFA_offset, s8,  -40 */
2788139c1837SPaolo Bonzini        0x80 + 25, 4,                   /* DW_CFA_offset, s9,  -32 */
2789139c1837SPaolo Bonzini        0x80 + 26, 3,                   /* DW_CFA_offset, s10, -24 */
2790139c1837SPaolo Bonzini        0x80 + 27, 2,                   /* DW_CFA_offset, s11, -16 */
2791139c1837SPaolo Bonzini        0x80 + 1 , 1,                   /* DW_CFA_offset, ra,  -8 */
2792139c1837SPaolo Bonzini    }
2793139c1837SPaolo Bonzini};
2794139c1837SPaolo Bonzini
2795755bf9e5SRichard Hendersonvoid tcg_register_jit(const void *buf, size_t buf_size)
2796139c1837SPaolo Bonzini{
2797139c1837SPaolo Bonzini    tcg_register_jit_int(buf, buf_size, &debug_frame, sizeof(debug_frame));
2798139c1837SPaolo Bonzini}
2799