xref: /openbmc/qemu/tcg/riscv/tcg-target.c.inc (revision f63e7089b49e0aa031e0247fad7b22b8d650a3fb)
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] = {
35*f63e7089SHuang Shiyuan    "zero", "ra",  "sp",  "gp",  "tp",  "t0",  "t1",  "t2",
36*f63e7089SHuang Shiyuan    "s0",   "s1",  "a0",  "a1",  "a2",  "a3",  "a4",  "a5",
37*f63e7089SHuang Shiyuan    "a6",   "a7",  "s2",  "s3",  "s4",  "s5",  "s6",  "s7",
38*f63e7089SHuang Shiyuan    "s8",   "s9",  "s10", "s11", "t3",  "t4",  "t5",  "t6",
39*f63e7089SHuang Shiyuan    "v0",   "v1",  "v2",  "v3",  "v4",  "v5",  "v6",  "v7",
40*f63e7089SHuang Shiyuan    "v8",   "v9",  "v10", "v11", "v12", "v13", "v14", "v15",
41*f63e7089SHuang Shiyuan    "v16",  "v17", "v18", "v19", "v20", "v21", "v22", "v23",
42*f63e7089SHuang 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,
79*f63e7089SHuang Shiyuan
80*f63e7089SHuang Shiyuan    /* Vector registers and TCG_REG_V0 reserved for mask. */
81*f63e7089SHuang Shiyuan    TCG_REG_V1,  TCG_REG_V2,  TCG_REG_V3,  TCG_REG_V4,
82*f63e7089SHuang Shiyuan    TCG_REG_V5,  TCG_REG_V6,  TCG_REG_V7,  TCG_REG_V8,
83*f63e7089SHuang Shiyuan    TCG_REG_V9,  TCG_REG_V10, TCG_REG_V11, TCG_REG_V12,
84*f63e7089SHuang Shiyuan    TCG_REG_V13, TCG_REG_V14, TCG_REG_V15, TCG_REG_V16,
85*f63e7089SHuang Shiyuan    TCG_REG_V17, TCG_REG_V18, TCG_REG_V19, TCG_REG_V20,
86*f63e7089SHuang Shiyuan    TCG_REG_V21, TCG_REG_V22, TCG_REG_V23, TCG_REG_V24,
87*f63e7089SHuang Shiyuan    TCG_REG_V25, TCG_REG_V26, TCG_REG_V27, TCG_REG_V28,
88*f63e7089SHuang 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
114139c1837SPaolo Bonzini
115fc63a4c5SRichard Henderson#define ALL_GENERAL_REGS   MAKE_64BIT_MASK(0, 32)
116*f63e7089SHuang Shiyuan#define ALL_VECTOR_REGS    MAKE_64BIT_MASK(32, 32)
117*f63e7089SHuang Shiyuan#define ALL_DVECTOR_REG_GROUPS 0x5555555500000000
118*f63e7089SHuang Shiyuan#define ALL_QVECTOR_REG_GROUPS 0x1111111100000000
119fc63a4c5SRichard Henderson
120aeb6326eSRichard Henderson#define sextreg  sextract64
121139c1837SPaolo Bonzini
122139c1837SPaolo Bonzini/* test if a constant matches the constraint */
12321e9a8aeSRichard Hendersonstatic bool tcg_target_const_match(int64_t val, int ct,
12421e9a8aeSRichard Henderson                                   TCGType type, TCGCond cond, int vece)
125139c1837SPaolo Bonzini{
126139c1837SPaolo Bonzini    if (ct & TCG_CT_CONST) {
127139c1837SPaolo Bonzini        return 1;
128139c1837SPaolo Bonzini    }
129139c1837SPaolo Bonzini    if ((ct & TCG_CT_CONST_ZERO) && val == 0) {
130139c1837SPaolo Bonzini        return 1;
131139c1837SPaolo Bonzini    }
13262722763SRichard Henderson    /*
13362722763SRichard Henderson     * Sign extended from 12 bits: [-0x800, 0x7ff].
13462722763SRichard Henderson     * Used for most arithmetic, as this is the isa field.
13562722763SRichard Henderson     */
13662722763SRichard Henderson    if ((ct & TCG_CT_CONST_S12) && val >= -0x800 && val <= 0x7ff) {
137139c1837SPaolo Bonzini        return 1;
138139c1837SPaolo Bonzini    }
13962722763SRichard Henderson    /*
14062722763SRichard Henderson     * Sign extended from 12 bits, negated: [-0x7ff, 0x800].
14162722763SRichard Henderson     * Used for subtraction, where a constant must be handled by ADDI.
14262722763SRichard Henderson     */
14362722763SRichard Henderson    if ((ct & TCG_CT_CONST_N12) && val >= -0x7ff && val <= 0x800) {
144139c1837SPaolo Bonzini        return 1;
145139c1837SPaolo Bonzini    }
14662722763SRichard Henderson    /*
14762722763SRichard Henderson     * Sign extended from 12 bits, +/- matching: [-0x7ff, 0x7ff].
148a18d783eSRichard Henderson     * Used by addsub2 and movcond, which may need the negative value,
14962722763SRichard Henderson     * and requires the modified constant to be representable.
15062722763SRichard Henderson     */
15162722763SRichard Henderson    if ((ct & TCG_CT_CONST_M12) && val >= -0x7ff && val <= 0x7ff) {
152139c1837SPaolo Bonzini        return 1;
153139c1837SPaolo Bonzini    }
15499f4ec6eSRichard Henderson    /*
15599f4ec6eSRichard Henderson     * Inverse of sign extended from 12 bits: ~[-0x800, 0x7ff].
15699f4ec6eSRichard Henderson     * Used to map ANDN back to ANDI, etc.
15799f4ec6eSRichard Henderson     */
15899f4ec6eSRichard Henderson    if ((ct & TCG_CT_CONST_J12) && ~val >= -0x800 && ~val <= 0x7ff) {
15999f4ec6eSRichard Henderson        return 1;
16099f4ec6eSRichard Henderson    }
161139c1837SPaolo Bonzini    return 0;
162139c1837SPaolo Bonzini}
163139c1837SPaolo Bonzini
164139c1837SPaolo Bonzini/*
165139c1837SPaolo Bonzini * RISC-V Base ISA opcodes (IM)
166139c1837SPaolo Bonzini */
167139c1837SPaolo Bonzini
168*f63e7089SHuang Shiyuan#define V_OPIVV (0x0 << 12)
169*f63e7089SHuang Shiyuan#define V_OPFVV (0x1 << 12)
170*f63e7089SHuang Shiyuan#define V_OPMVV (0x2 << 12)
171*f63e7089SHuang Shiyuan#define V_OPIVI (0x3 << 12)
172*f63e7089SHuang Shiyuan#define V_OPIVX (0x4 << 12)
173*f63e7089SHuang Shiyuan#define V_OPFVF (0x5 << 12)
174*f63e7089SHuang Shiyuan#define V_OPMVX (0x6 << 12)
175*f63e7089SHuang Shiyuan#define V_OPCFG (0x7 << 12)
176*f63e7089SHuang Shiyuan
177*f63e7089SHuang Shiyuan/* NF <= 7 && NF >= 0 */
178*f63e7089SHuang Shiyuan#define V_NF(x) (x << 29)
179*f63e7089SHuang Shiyuan#define V_UNIT_STRIDE (0x0 << 20)
180*f63e7089SHuang Shiyuan#define V_UNIT_STRIDE_WHOLE_REG (0x8 << 20)
181*f63e7089SHuang Shiyuan
182*f63e7089SHuang Shiyuantypedef enum {
183*f63e7089SHuang Shiyuan    VLMUL_M1 = 0, /* LMUL=1 */
184*f63e7089SHuang Shiyuan    VLMUL_M2,     /* LMUL=2 */
185*f63e7089SHuang Shiyuan    VLMUL_M4,     /* LMUL=4 */
186*f63e7089SHuang Shiyuan    VLMUL_M8,     /* LMUL=8 */
187*f63e7089SHuang Shiyuan    VLMUL_RESERVED,
188*f63e7089SHuang Shiyuan    VLMUL_MF8,    /* LMUL=1/8 */
189*f63e7089SHuang Shiyuan    VLMUL_MF4,    /* LMUL=1/4 */
190*f63e7089SHuang Shiyuan    VLMUL_MF2,    /* LMUL=1/2 */
191*f63e7089SHuang Shiyuan} RISCVVlmul;
192*f63e7089SHuang Shiyuan
193139c1837SPaolo Bonzinitypedef enum {
194139c1837SPaolo Bonzini    OPC_ADD = 0x33,
195139c1837SPaolo Bonzini    OPC_ADDI = 0x13,
196139c1837SPaolo Bonzini    OPC_AND = 0x7033,
197139c1837SPaolo Bonzini    OPC_ANDI = 0x7013,
198139c1837SPaolo Bonzini    OPC_AUIPC = 0x17,
199139c1837SPaolo Bonzini    OPC_BEQ = 0x63,
200139c1837SPaolo Bonzini    OPC_BGE = 0x5063,
201139c1837SPaolo Bonzini    OPC_BGEU = 0x7063,
202139c1837SPaolo Bonzini    OPC_BLT = 0x4063,
203139c1837SPaolo Bonzini    OPC_BLTU = 0x6063,
204139c1837SPaolo Bonzini    OPC_BNE = 0x1063,
205139c1837SPaolo Bonzini    OPC_DIV = 0x2004033,
206139c1837SPaolo Bonzini    OPC_DIVU = 0x2005033,
207139c1837SPaolo Bonzini    OPC_JAL = 0x6f,
208139c1837SPaolo Bonzini    OPC_JALR = 0x67,
209139c1837SPaolo Bonzini    OPC_LB = 0x3,
210139c1837SPaolo Bonzini    OPC_LBU = 0x4003,
211139c1837SPaolo Bonzini    OPC_LD = 0x3003,
212139c1837SPaolo Bonzini    OPC_LH = 0x1003,
213139c1837SPaolo Bonzini    OPC_LHU = 0x5003,
214139c1837SPaolo Bonzini    OPC_LUI = 0x37,
215139c1837SPaolo Bonzini    OPC_LW = 0x2003,
216139c1837SPaolo Bonzini    OPC_LWU = 0x6003,
217139c1837SPaolo Bonzini    OPC_MUL = 0x2000033,
218139c1837SPaolo Bonzini    OPC_MULH = 0x2001033,
219139c1837SPaolo Bonzini    OPC_MULHSU = 0x2002033,
220139c1837SPaolo Bonzini    OPC_MULHU = 0x2003033,
221139c1837SPaolo Bonzini    OPC_OR = 0x6033,
222139c1837SPaolo Bonzini    OPC_ORI = 0x6013,
223139c1837SPaolo Bonzini    OPC_REM = 0x2006033,
224139c1837SPaolo Bonzini    OPC_REMU = 0x2007033,
225139c1837SPaolo Bonzini    OPC_SB = 0x23,
226139c1837SPaolo Bonzini    OPC_SD = 0x3023,
227139c1837SPaolo Bonzini    OPC_SH = 0x1023,
228139c1837SPaolo Bonzini    OPC_SLL = 0x1033,
229139c1837SPaolo Bonzini    OPC_SLLI = 0x1013,
230139c1837SPaolo Bonzini    OPC_SLT = 0x2033,
231139c1837SPaolo Bonzini    OPC_SLTI = 0x2013,
232139c1837SPaolo Bonzini    OPC_SLTIU = 0x3013,
233139c1837SPaolo Bonzini    OPC_SLTU = 0x3033,
234139c1837SPaolo Bonzini    OPC_SRA = 0x40005033,
235139c1837SPaolo Bonzini    OPC_SRAI = 0x40005013,
236139c1837SPaolo Bonzini    OPC_SRL = 0x5033,
237139c1837SPaolo Bonzini    OPC_SRLI = 0x5013,
238139c1837SPaolo Bonzini    OPC_SUB = 0x40000033,
239139c1837SPaolo Bonzini    OPC_SW = 0x2023,
240139c1837SPaolo Bonzini    OPC_XOR = 0x4033,
241139c1837SPaolo Bonzini    OPC_XORI = 0x4013,
242139c1837SPaolo Bonzini
243139c1837SPaolo Bonzini    OPC_ADDIW = 0x1b,
244139c1837SPaolo Bonzini    OPC_ADDW = 0x3b,
245139c1837SPaolo Bonzini    OPC_DIVUW = 0x200503b,
246139c1837SPaolo Bonzini    OPC_DIVW = 0x200403b,
247139c1837SPaolo Bonzini    OPC_MULW = 0x200003b,
248139c1837SPaolo Bonzini    OPC_REMUW = 0x200703b,
249139c1837SPaolo Bonzini    OPC_REMW = 0x200603b,
250139c1837SPaolo Bonzini    OPC_SLLIW = 0x101b,
251139c1837SPaolo Bonzini    OPC_SLLW = 0x103b,
252139c1837SPaolo Bonzini    OPC_SRAIW = 0x4000501b,
253139c1837SPaolo Bonzini    OPC_SRAW = 0x4000503b,
254139c1837SPaolo Bonzini    OPC_SRLIW = 0x501b,
255139c1837SPaolo Bonzini    OPC_SRLW = 0x503b,
256139c1837SPaolo Bonzini    OPC_SUBW = 0x4000003b,
257139c1837SPaolo Bonzini
258139c1837SPaolo Bonzini    OPC_FENCE = 0x0000000f,
2599ae958e4SRichard Henderson    OPC_NOP   = OPC_ADDI,   /* nop = addi r0,r0,0 */
2609e3e0bc6SRichard Henderson
2619e3e0bc6SRichard Henderson    /* Zba: Bit manipulation extension, address generation */
2629e3e0bc6SRichard Henderson    OPC_ADD_UW = 0x0800003b,
2639e3e0bc6SRichard Henderson
2644daad8d9SMichael Tokarev    /* Zbb: Bit manipulation extension, basic bit manipulation */
2659e3e0bc6SRichard Henderson    OPC_ANDN   = 0x40007033,
2669e3e0bc6SRichard Henderson    OPC_CLZ    = 0x60001013,
2679e3e0bc6SRichard Henderson    OPC_CLZW   = 0x6000101b,
2689e3e0bc6SRichard Henderson    OPC_CPOP   = 0x60201013,
2699e3e0bc6SRichard Henderson    OPC_CPOPW  = 0x6020101b,
2709e3e0bc6SRichard Henderson    OPC_CTZ    = 0x60101013,
2719e3e0bc6SRichard Henderson    OPC_CTZW   = 0x6010101b,
2729e3e0bc6SRichard Henderson    OPC_ORN    = 0x40006033,
2739e3e0bc6SRichard Henderson    OPC_REV8   = 0x6b805013,
2749e3e0bc6SRichard Henderson    OPC_ROL    = 0x60001033,
2759e3e0bc6SRichard Henderson    OPC_ROLW   = 0x6000103b,
2769e3e0bc6SRichard Henderson    OPC_ROR    = 0x60005033,
2779e3e0bc6SRichard Henderson    OPC_RORW   = 0x6000503b,
2789e3e0bc6SRichard Henderson    OPC_RORI   = 0x60005013,
2799e3e0bc6SRichard Henderson    OPC_RORIW  = 0x6000501b,
2809e3e0bc6SRichard Henderson    OPC_SEXT_B = 0x60401013,
2819e3e0bc6SRichard Henderson    OPC_SEXT_H = 0x60501013,
2829e3e0bc6SRichard Henderson    OPC_XNOR   = 0x40004033,
2839e3e0bc6SRichard Henderson    OPC_ZEXT_H = 0x0800403b,
2849e3e0bc6SRichard Henderson
2859e3e0bc6SRichard Henderson    /* Zicond: integer conditional operations */
2869e3e0bc6SRichard Henderson    OPC_CZERO_EQZ = 0x0e005033,
2879e3e0bc6SRichard Henderson    OPC_CZERO_NEZ = 0x0e007033,
288*f63e7089SHuang Shiyuan
289*f63e7089SHuang Shiyuan    /* V: Vector extension 1.0 */
290*f63e7089SHuang Shiyuan    OPC_VSETVLI  = 0x57 | V_OPCFG,
291*f63e7089SHuang Shiyuan    OPC_VSETIVLI = 0xc0000057 | V_OPCFG,
292*f63e7089SHuang Shiyuan    OPC_VSETVL   = 0x80000057 | V_OPCFG,
293*f63e7089SHuang Shiyuan
294*f63e7089SHuang Shiyuan    OPC_VLE8_V  = 0x7 | V_UNIT_STRIDE,
295*f63e7089SHuang Shiyuan    OPC_VLE16_V = 0x5007 | V_UNIT_STRIDE,
296*f63e7089SHuang Shiyuan    OPC_VLE32_V = 0x6007 | V_UNIT_STRIDE,
297*f63e7089SHuang Shiyuan    OPC_VLE64_V = 0x7007 | V_UNIT_STRIDE,
298*f63e7089SHuang Shiyuan    OPC_VSE8_V  = 0x27 | V_UNIT_STRIDE,
299*f63e7089SHuang Shiyuan    OPC_VSE16_V = 0x5027 | V_UNIT_STRIDE,
300*f63e7089SHuang Shiyuan    OPC_VSE32_V = 0x6027 | V_UNIT_STRIDE,
301*f63e7089SHuang Shiyuan    OPC_VSE64_V = 0x7027 | V_UNIT_STRIDE,
302*f63e7089SHuang Shiyuan
303*f63e7089SHuang Shiyuan    OPC_VL1RE64_V = 0x2007007 | V_UNIT_STRIDE_WHOLE_REG | V_NF(0),
304*f63e7089SHuang Shiyuan    OPC_VL2RE64_V = 0x2007007 | V_UNIT_STRIDE_WHOLE_REG | V_NF(1),
305*f63e7089SHuang Shiyuan    OPC_VL4RE64_V = 0x2007007 | V_UNIT_STRIDE_WHOLE_REG | V_NF(3),
306*f63e7089SHuang Shiyuan    OPC_VL8RE64_V = 0x2007007 | V_UNIT_STRIDE_WHOLE_REG | V_NF(7),
307*f63e7089SHuang Shiyuan
308*f63e7089SHuang Shiyuan    OPC_VS1R_V = 0x2000027 | V_UNIT_STRIDE_WHOLE_REG | V_NF(0),
309*f63e7089SHuang Shiyuan    OPC_VS2R_V = 0x2000027 | V_UNIT_STRIDE_WHOLE_REG | V_NF(1),
310*f63e7089SHuang Shiyuan    OPC_VS4R_V = 0x2000027 | V_UNIT_STRIDE_WHOLE_REG | V_NF(3),
311*f63e7089SHuang Shiyuan    OPC_VS8R_V = 0x2000027 | V_UNIT_STRIDE_WHOLE_REG | V_NF(7),
312139c1837SPaolo Bonzini} RISCVInsn;
313139c1837SPaolo Bonzini
314139c1837SPaolo Bonzini/*
315139c1837SPaolo Bonzini * RISC-V immediate and instruction encoders (excludes 16-bit RVC)
316139c1837SPaolo Bonzini */
317139c1837SPaolo Bonzini
318139c1837SPaolo Bonzini/* Type-R */
319139c1837SPaolo Bonzini
320139c1837SPaolo Bonzinistatic int32_t encode_r(RISCVInsn opc, TCGReg rd, TCGReg rs1, TCGReg rs2)
321139c1837SPaolo Bonzini{
322139c1837SPaolo Bonzini    return opc | (rd & 0x1f) << 7 | (rs1 & 0x1f) << 15 | (rs2 & 0x1f) << 20;
323139c1837SPaolo Bonzini}
324139c1837SPaolo Bonzini
325139c1837SPaolo Bonzini/* Type-I */
326139c1837SPaolo Bonzini
327139c1837SPaolo Bonzinistatic int32_t encode_imm12(uint32_t imm)
328139c1837SPaolo Bonzini{
329139c1837SPaolo Bonzini    return (imm & 0xfff) << 20;
330139c1837SPaolo Bonzini}
331139c1837SPaolo Bonzini
332139c1837SPaolo Bonzinistatic int32_t encode_i(RISCVInsn opc, TCGReg rd, TCGReg rs1, uint32_t imm)
333139c1837SPaolo Bonzini{
334139c1837SPaolo Bonzini    return opc | (rd & 0x1f) << 7 | (rs1 & 0x1f) << 15 | encode_imm12(imm);
335139c1837SPaolo Bonzini}
336139c1837SPaolo Bonzini
337139c1837SPaolo Bonzini/* Type-S */
338139c1837SPaolo Bonzini
339139c1837SPaolo Bonzinistatic int32_t encode_simm12(uint32_t imm)
340139c1837SPaolo Bonzini{
341139c1837SPaolo Bonzini    int32_t ret = 0;
342139c1837SPaolo Bonzini
343139c1837SPaolo Bonzini    ret |= (imm & 0xFE0) << 20;
344139c1837SPaolo Bonzini    ret |= (imm & 0x1F) << 7;
345139c1837SPaolo Bonzini
346139c1837SPaolo Bonzini    return ret;
347139c1837SPaolo Bonzini}
348139c1837SPaolo Bonzini
349139c1837SPaolo Bonzinistatic int32_t encode_s(RISCVInsn opc, TCGReg rs1, TCGReg rs2, uint32_t imm)
350139c1837SPaolo Bonzini{
351139c1837SPaolo Bonzini    return opc | (rs1 & 0x1f) << 15 | (rs2 & 0x1f) << 20 | encode_simm12(imm);
352139c1837SPaolo Bonzini}
353139c1837SPaolo Bonzini
354139c1837SPaolo Bonzini/* Type-SB */
355139c1837SPaolo Bonzini
356139c1837SPaolo Bonzinistatic int32_t encode_sbimm12(uint32_t imm)
357139c1837SPaolo Bonzini{
358139c1837SPaolo Bonzini    int32_t ret = 0;
359139c1837SPaolo Bonzini
360139c1837SPaolo Bonzini    ret |= (imm & 0x1000) << 19;
361139c1837SPaolo Bonzini    ret |= (imm & 0x7e0) << 20;
362139c1837SPaolo Bonzini    ret |= (imm & 0x1e) << 7;
363139c1837SPaolo Bonzini    ret |= (imm & 0x800) >> 4;
364139c1837SPaolo Bonzini
365139c1837SPaolo Bonzini    return ret;
366139c1837SPaolo Bonzini}
367139c1837SPaolo Bonzini
368139c1837SPaolo Bonzinistatic int32_t encode_sb(RISCVInsn opc, TCGReg rs1, TCGReg rs2, uint32_t imm)
369139c1837SPaolo Bonzini{
370139c1837SPaolo Bonzini    return opc | (rs1 & 0x1f) << 15 | (rs2 & 0x1f) << 20 | encode_sbimm12(imm);
371139c1837SPaolo Bonzini}
372139c1837SPaolo Bonzini
373139c1837SPaolo Bonzini/* Type-U */
374139c1837SPaolo Bonzini
375139c1837SPaolo Bonzinistatic int32_t encode_uimm20(uint32_t imm)
376139c1837SPaolo Bonzini{
377139c1837SPaolo Bonzini    return imm & 0xfffff000;
378139c1837SPaolo Bonzini}
379139c1837SPaolo Bonzini
380139c1837SPaolo Bonzinistatic int32_t encode_u(RISCVInsn opc, TCGReg rd, uint32_t imm)
381139c1837SPaolo Bonzini{
382139c1837SPaolo Bonzini    return opc | (rd & 0x1f) << 7 | encode_uimm20(imm);
383139c1837SPaolo Bonzini}
384139c1837SPaolo Bonzini
385139c1837SPaolo Bonzini/* Type-UJ */
386139c1837SPaolo Bonzini
387139c1837SPaolo Bonzinistatic int32_t encode_ujimm20(uint32_t imm)
388139c1837SPaolo Bonzini{
389139c1837SPaolo Bonzini    int32_t ret = 0;
390139c1837SPaolo Bonzini
391139c1837SPaolo Bonzini    ret |= (imm & 0x0007fe) << (21 - 1);
392139c1837SPaolo Bonzini    ret |= (imm & 0x000800) << (20 - 11);
393139c1837SPaolo Bonzini    ret |= (imm & 0x0ff000) << (12 - 12);
394139c1837SPaolo Bonzini    ret |= (imm & 0x100000) << (31 - 20);
395139c1837SPaolo Bonzini
396139c1837SPaolo Bonzini    return ret;
397139c1837SPaolo Bonzini}
398139c1837SPaolo Bonzini
399139c1837SPaolo Bonzinistatic int32_t encode_uj(RISCVInsn opc, TCGReg rd, uint32_t imm)
400139c1837SPaolo Bonzini{
401139c1837SPaolo Bonzini    return opc | (rd & 0x1f) << 7 | encode_ujimm20(imm);
402139c1837SPaolo Bonzini}
403139c1837SPaolo Bonzini
404*f63e7089SHuang Shiyuan/* Type-OPIVV/OPMVV/OPIVX/OPMVX, Vector load and store */
405*f63e7089SHuang Shiyuan
406*f63e7089SHuang Shiyuanstatic int32_t encode_v(RISCVInsn opc, TCGReg d, TCGReg s1,
407*f63e7089SHuang Shiyuan                        TCGReg s2, bool vm)
408*f63e7089SHuang Shiyuan{
409*f63e7089SHuang Shiyuan    return opc | (d & 0x1f) << 7 | (s1 & 0x1f) << 15 |
410*f63e7089SHuang Shiyuan           (s2 & 0x1f) << 20 | (vm << 25);
411*f63e7089SHuang Shiyuan}
412*f63e7089SHuang Shiyuan
413*f63e7089SHuang Shiyuan/* Vector vtype */
414*f63e7089SHuang Shiyuan
415*f63e7089SHuang Shiyuanstatic uint32_t encode_vtype(bool vta, bool vma,
416*f63e7089SHuang Shiyuan                            MemOp vsew, RISCVVlmul vlmul)
417*f63e7089SHuang Shiyuan{
418*f63e7089SHuang Shiyuan    return vma << 7 | vta << 6 | vsew << 3 | vlmul;
419*f63e7089SHuang Shiyuan}
420*f63e7089SHuang Shiyuan
421*f63e7089SHuang Shiyuanstatic int32_t encode_vset(RISCVInsn opc, TCGReg rd,
422*f63e7089SHuang Shiyuan                           TCGArg rs1, uint32_t vtype)
423*f63e7089SHuang Shiyuan{
424*f63e7089SHuang Shiyuan    return opc | (rd & 0x1f) << 7 | (rs1 & 0x1f) << 15 | (vtype & 0x7ff) << 20;
425*f63e7089SHuang Shiyuan}
426*f63e7089SHuang Shiyuan
427*f63e7089SHuang Shiyuanstatic int32_t encode_vseti(RISCVInsn opc, TCGReg rd,
428*f63e7089SHuang Shiyuan                            uint32_t uimm, uint32_t vtype)
429*f63e7089SHuang Shiyuan{
430*f63e7089SHuang Shiyuan    return opc | (rd & 0x1f) << 7 | (uimm & 0x1f) << 15 | (vtype & 0x3ff) << 20;
431*f63e7089SHuang Shiyuan}
432*f63e7089SHuang Shiyuan
433139c1837SPaolo Bonzini/*
434139c1837SPaolo Bonzini * RISC-V instruction emitters
435139c1837SPaolo Bonzini */
436139c1837SPaolo Bonzini
437139c1837SPaolo Bonzinistatic void tcg_out_opc_reg(TCGContext *s, RISCVInsn opc,
438139c1837SPaolo Bonzini                            TCGReg rd, TCGReg rs1, TCGReg rs2)
439139c1837SPaolo Bonzini{
440139c1837SPaolo Bonzini    tcg_out32(s, encode_r(opc, rd, rs1, rs2));
441139c1837SPaolo Bonzini}
442139c1837SPaolo Bonzini
443139c1837SPaolo Bonzinistatic void tcg_out_opc_imm(TCGContext *s, RISCVInsn opc,
444139c1837SPaolo Bonzini                            TCGReg rd, TCGReg rs1, TCGArg imm)
445139c1837SPaolo Bonzini{
446139c1837SPaolo Bonzini    tcg_out32(s, encode_i(opc, rd, rs1, imm));
447139c1837SPaolo Bonzini}
448139c1837SPaolo Bonzini
449139c1837SPaolo Bonzinistatic void tcg_out_opc_store(TCGContext *s, RISCVInsn opc,
450139c1837SPaolo Bonzini                              TCGReg rs1, TCGReg rs2, uint32_t imm)
451139c1837SPaolo Bonzini{
452139c1837SPaolo Bonzini    tcg_out32(s, encode_s(opc, rs1, rs2, imm));
453139c1837SPaolo Bonzini}
454139c1837SPaolo Bonzini
455139c1837SPaolo Bonzinistatic void tcg_out_opc_branch(TCGContext *s, RISCVInsn opc,
456139c1837SPaolo Bonzini                               TCGReg rs1, TCGReg rs2, uint32_t imm)
457139c1837SPaolo Bonzini{
458139c1837SPaolo Bonzini    tcg_out32(s, encode_sb(opc, rs1, rs2, imm));
459139c1837SPaolo Bonzini}
460139c1837SPaolo Bonzini
461139c1837SPaolo Bonzinistatic void tcg_out_opc_upper(TCGContext *s, RISCVInsn opc,
462139c1837SPaolo Bonzini                              TCGReg rd, uint32_t imm)
463139c1837SPaolo Bonzini{
464139c1837SPaolo Bonzini    tcg_out32(s, encode_u(opc, rd, imm));
465139c1837SPaolo Bonzini}
466139c1837SPaolo Bonzini
467139c1837SPaolo Bonzinistatic void tcg_out_opc_jump(TCGContext *s, RISCVInsn opc,
468139c1837SPaolo Bonzini                             TCGReg rd, uint32_t imm)
469139c1837SPaolo Bonzini{
470139c1837SPaolo Bonzini    tcg_out32(s, encode_uj(opc, rd, imm));
471139c1837SPaolo Bonzini}
472139c1837SPaolo Bonzini
473139c1837SPaolo Bonzinistatic void tcg_out_nop_fill(tcg_insn_unit *p, int count)
474139c1837SPaolo Bonzini{
475139c1837SPaolo Bonzini    int i;
476139c1837SPaolo Bonzini    for (i = 0; i < count; ++i) {
4779ae958e4SRichard Henderson        p[i] = OPC_NOP;
478139c1837SPaolo Bonzini    }
479139c1837SPaolo Bonzini}
480139c1837SPaolo Bonzini
481139c1837SPaolo Bonzini/*
482139c1837SPaolo Bonzini * Relocations
483139c1837SPaolo Bonzini */
484139c1837SPaolo Bonzini
485793f7381SRichard Hendersonstatic bool reloc_sbimm12(tcg_insn_unit *src_rw, const tcg_insn_unit *target)
486139c1837SPaolo Bonzini{
487793f7381SRichard Henderson    const tcg_insn_unit *src_rx = tcg_splitwx_to_rx(src_rw);
488793f7381SRichard Henderson    intptr_t offset = (intptr_t)target - (intptr_t)src_rx;
489139c1837SPaolo Bonzini
490844d0442SRichard Henderson    tcg_debug_assert((offset & 1) == 0);
491844d0442SRichard Henderson    if (offset == sextreg(offset, 0, 12)) {
492793f7381SRichard Henderson        *src_rw |= encode_sbimm12(offset);
493139c1837SPaolo Bonzini        return true;
494139c1837SPaolo Bonzini    }
495139c1837SPaolo Bonzini
496139c1837SPaolo Bonzini    return false;
497139c1837SPaolo Bonzini}
498139c1837SPaolo Bonzini
499793f7381SRichard Hendersonstatic bool reloc_jimm20(tcg_insn_unit *src_rw, const tcg_insn_unit *target)
500139c1837SPaolo Bonzini{
501793f7381SRichard Henderson    const tcg_insn_unit *src_rx = tcg_splitwx_to_rx(src_rw);
502793f7381SRichard Henderson    intptr_t offset = (intptr_t)target - (intptr_t)src_rx;
503139c1837SPaolo Bonzini
504844d0442SRichard Henderson    tcg_debug_assert((offset & 1) == 0);
505844d0442SRichard Henderson    if (offset == sextreg(offset, 0, 20)) {
506793f7381SRichard Henderson        *src_rw |= encode_ujimm20(offset);
507139c1837SPaolo Bonzini        return true;
508139c1837SPaolo Bonzini    }
509139c1837SPaolo Bonzini
510139c1837SPaolo Bonzini    return false;
511139c1837SPaolo Bonzini}
512139c1837SPaolo Bonzini
513793f7381SRichard Hendersonstatic bool reloc_call(tcg_insn_unit *src_rw, const tcg_insn_unit *target)
514139c1837SPaolo Bonzini{
515793f7381SRichard Henderson    const tcg_insn_unit *src_rx = tcg_splitwx_to_rx(src_rw);
516793f7381SRichard Henderson    intptr_t offset = (intptr_t)target - (intptr_t)src_rx;
517139c1837SPaolo Bonzini    int32_t lo = sextreg(offset, 0, 12);
518139c1837SPaolo Bonzini    int32_t hi = offset - lo;
519139c1837SPaolo Bonzini
520139c1837SPaolo Bonzini    if (offset == hi + lo) {
521793f7381SRichard Henderson        src_rw[0] |= encode_uimm20(hi);
522793f7381SRichard Henderson        src_rw[1] |= encode_imm12(lo);
523139c1837SPaolo Bonzini        return true;
524139c1837SPaolo Bonzini    }
525139c1837SPaolo Bonzini
526139c1837SPaolo Bonzini    return false;
527139c1837SPaolo Bonzini}
528139c1837SPaolo Bonzini
529139c1837SPaolo Bonzinistatic bool patch_reloc(tcg_insn_unit *code_ptr, int type,
530139c1837SPaolo Bonzini                        intptr_t value, intptr_t addend)
531139c1837SPaolo Bonzini{
532139c1837SPaolo Bonzini    tcg_debug_assert(addend == 0);
533139c1837SPaolo Bonzini    switch (type) {
534139c1837SPaolo Bonzini    case R_RISCV_BRANCH:
535139c1837SPaolo Bonzini        return reloc_sbimm12(code_ptr, (tcg_insn_unit *)value);
536139c1837SPaolo Bonzini    case R_RISCV_JAL:
537139c1837SPaolo Bonzini        return reloc_jimm20(code_ptr, (tcg_insn_unit *)value);
538139c1837SPaolo Bonzini    case R_RISCV_CALL:
539139c1837SPaolo Bonzini        return reloc_call(code_ptr, (tcg_insn_unit *)value);
540139c1837SPaolo Bonzini    default:
5414b6a52d0SRichard Henderson        g_assert_not_reached();
542139c1837SPaolo Bonzini    }
543139c1837SPaolo Bonzini}
544139c1837SPaolo Bonzini
545139c1837SPaolo Bonzini/*
546*f63e7089SHuang Shiyuan * RISC-V vector instruction emitters
547*f63e7089SHuang Shiyuan */
548*f63e7089SHuang Shiyuan
549*f63e7089SHuang Shiyuantypedef struct VsetCache {
550*f63e7089SHuang Shiyuan    uint32_t movi_insn;
551*f63e7089SHuang Shiyuan    uint32_t vset_insn;
552*f63e7089SHuang Shiyuan} VsetCache;
553*f63e7089SHuang Shiyuan
554*f63e7089SHuang Shiyuanstatic VsetCache riscv_vset_cache[3][4];
555*f63e7089SHuang Shiyuan
556*f63e7089SHuang Shiyuanstatic void set_vtype(TCGContext *s, TCGType type, MemOp vsew)
557*f63e7089SHuang Shiyuan{
558*f63e7089SHuang Shiyuan    const VsetCache *p = &riscv_vset_cache[type - TCG_TYPE_V64][vsew];
559*f63e7089SHuang Shiyuan
560*f63e7089SHuang Shiyuan    s->riscv_cur_type = type;
561*f63e7089SHuang Shiyuan    s->riscv_cur_vsew = vsew;
562*f63e7089SHuang Shiyuan
563*f63e7089SHuang Shiyuan    if (p->movi_insn) {
564*f63e7089SHuang Shiyuan        tcg_out32(s, p->movi_insn);
565*f63e7089SHuang Shiyuan    }
566*f63e7089SHuang Shiyuan    tcg_out32(s, p->vset_insn);
567*f63e7089SHuang Shiyuan}
568*f63e7089SHuang Shiyuan
569*f63e7089SHuang Shiyuanstatic MemOp set_vtype_len(TCGContext *s, TCGType type)
570*f63e7089SHuang Shiyuan{
571*f63e7089SHuang Shiyuan    if (type != s->riscv_cur_type) {
572*f63e7089SHuang Shiyuan        set_vtype(s, type, MO_64);
573*f63e7089SHuang Shiyuan    }
574*f63e7089SHuang Shiyuan    return s->riscv_cur_vsew;
575*f63e7089SHuang Shiyuan}
576*f63e7089SHuang Shiyuan
577*f63e7089SHuang Shiyuan/*
578139c1837SPaolo Bonzini * TCG intrinsics
579139c1837SPaolo Bonzini */
580139c1837SPaolo Bonzini
581139c1837SPaolo Bonzinistatic bool tcg_out_mov(TCGContext *s, TCGType type, TCGReg ret, TCGReg arg)
582139c1837SPaolo Bonzini{
583139c1837SPaolo Bonzini    if (ret == arg) {
584139c1837SPaolo Bonzini        return true;
585139c1837SPaolo Bonzini    }
586139c1837SPaolo Bonzini    switch (type) {
587139c1837SPaolo Bonzini    case TCG_TYPE_I32:
588139c1837SPaolo Bonzini    case TCG_TYPE_I64:
589139c1837SPaolo Bonzini        tcg_out_opc_imm(s, OPC_ADDI, ret, arg, 0);
590139c1837SPaolo Bonzini        break;
591139c1837SPaolo Bonzini    default:
592139c1837SPaolo Bonzini        g_assert_not_reached();
593139c1837SPaolo Bonzini    }
594139c1837SPaolo Bonzini    return true;
595139c1837SPaolo Bonzini}
596139c1837SPaolo Bonzini
597139c1837SPaolo Bonzinistatic void tcg_out_movi(TCGContext *s, TCGType type, TCGReg rd,
598139c1837SPaolo Bonzini                         tcg_target_long val)
599139c1837SPaolo Bonzini{
600139c1837SPaolo Bonzini    tcg_target_long lo, hi, tmp;
601139c1837SPaolo Bonzini    int shift, ret;
602139c1837SPaolo Bonzini
603aeb6326eSRichard Henderson    if (type == TCG_TYPE_I32) {
604139c1837SPaolo Bonzini        val = (int32_t)val;
605139c1837SPaolo Bonzini    }
606139c1837SPaolo Bonzini
607139c1837SPaolo Bonzini    lo = sextreg(val, 0, 12);
608139c1837SPaolo Bonzini    if (val == lo) {
609139c1837SPaolo Bonzini        tcg_out_opc_imm(s, OPC_ADDI, rd, TCG_REG_ZERO, lo);
610139c1837SPaolo Bonzini        return;
611139c1837SPaolo Bonzini    }
612139c1837SPaolo Bonzini
613139c1837SPaolo Bonzini    hi = val - lo;
614aeb6326eSRichard Henderson    if (val == (int32_t)val) {
615139c1837SPaolo Bonzini        tcg_out_opc_upper(s, OPC_LUI, rd, hi);
616139c1837SPaolo Bonzini        if (lo != 0) {
617139c1837SPaolo Bonzini            tcg_out_opc_imm(s, OPC_ADDIW, rd, rd, lo);
618139c1837SPaolo Bonzini        }
619139c1837SPaolo Bonzini        return;
620139c1837SPaolo Bonzini    }
621139c1837SPaolo Bonzini
622139c1837SPaolo Bonzini    tmp = tcg_pcrel_diff(s, (void *)val);
623139c1837SPaolo Bonzini    if (tmp == (int32_t)tmp) {
624139c1837SPaolo Bonzini        tcg_out_opc_upper(s, OPC_AUIPC, rd, 0);
625139c1837SPaolo Bonzini        tcg_out_opc_imm(s, OPC_ADDI, rd, rd, 0);
626793f7381SRichard Henderson        ret = reloc_call(s->code_ptr - 2, (const tcg_insn_unit *)val);
627139c1837SPaolo Bonzini        tcg_debug_assert(ret == true);
628139c1837SPaolo Bonzini        return;
629139c1837SPaolo Bonzini    }
630139c1837SPaolo Bonzini
631139c1837SPaolo Bonzini    /* Look for a single 20-bit section.  */
632139c1837SPaolo Bonzini    shift = ctz64(val);
633139c1837SPaolo Bonzini    tmp = val >> shift;
634139c1837SPaolo Bonzini    if (tmp == sextreg(tmp, 0, 20)) {
635139c1837SPaolo Bonzini        tcg_out_opc_upper(s, OPC_LUI, rd, tmp << 12);
636139c1837SPaolo Bonzini        if (shift > 12) {
637139c1837SPaolo Bonzini            tcg_out_opc_imm(s, OPC_SLLI, rd, rd, shift - 12);
638139c1837SPaolo Bonzini        } else {
639139c1837SPaolo Bonzini            tcg_out_opc_imm(s, OPC_SRAI, rd, rd, 12 - shift);
640139c1837SPaolo Bonzini        }
641139c1837SPaolo Bonzini        return;
642139c1837SPaolo Bonzini    }
643139c1837SPaolo Bonzini
644139c1837SPaolo Bonzini    /* Look for a few high zero bits, with lots of bits set in the middle.  */
645139c1837SPaolo Bonzini    shift = clz64(val);
646139c1837SPaolo Bonzini    tmp = val << shift;
647139c1837SPaolo Bonzini    if (tmp == sextreg(tmp, 12, 20) << 12) {
648139c1837SPaolo Bonzini        tcg_out_opc_upper(s, OPC_LUI, rd, tmp);
649139c1837SPaolo Bonzini        tcg_out_opc_imm(s, OPC_SRLI, rd, rd, shift);
650139c1837SPaolo Bonzini        return;
651139c1837SPaolo Bonzini    } else if (tmp == sextreg(tmp, 0, 12)) {
652139c1837SPaolo Bonzini        tcg_out_opc_imm(s, OPC_ADDI, rd, TCG_REG_ZERO, tmp);
653139c1837SPaolo Bonzini        tcg_out_opc_imm(s, OPC_SRLI, rd, rd, shift);
654139c1837SPaolo Bonzini        return;
655139c1837SPaolo Bonzini    }
656139c1837SPaolo Bonzini
657139c1837SPaolo Bonzini    /* Drop into the constant pool.  */
658139c1837SPaolo Bonzini    new_pool_label(s, val, R_RISCV_CALL, s->code_ptr, 0);
659139c1837SPaolo Bonzini    tcg_out_opc_upper(s, OPC_AUIPC, rd, 0);
660139c1837SPaolo Bonzini    tcg_out_opc_imm(s, OPC_LD, rd, rd, 0);
661139c1837SPaolo Bonzini}
662139c1837SPaolo Bonzini
663767c2503SRichard Hendersonstatic bool tcg_out_xchg(TCGContext *s, TCGType type, TCGReg r1, TCGReg r2)
664767c2503SRichard Henderson{
665767c2503SRichard Henderson    return false;
666767c2503SRichard Henderson}
667767c2503SRichard Henderson
6686a6d772eSRichard Hendersonstatic void tcg_out_addi_ptr(TCGContext *s, TCGReg rd, TCGReg rs,
6696a6d772eSRichard Henderson                             tcg_target_long imm)
6706a6d772eSRichard Henderson{
6716a6d772eSRichard Henderson    /* This function is only used for passing structs by reference. */
6726a6d772eSRichard Henderson    g_assert_not_reached();
6736a6d772eSRichard Henderson}
6746a6d772eSRichard Henderson
675139c1837SPaolo Bonzinistatic void tcg_out_ext8u(TCGContext *s, TCGReg ret, TCGReg arg)
676139c1837SPaolo Bonzini{
677139c1837SPaolo Bonzini    tcg_out_opc_imm(s, OPC_ANDI, ret, arg, 0xff);
678139c1837SPaolo Bonzini}
679139c1837SPaolo Bonzini
680139c1837SPaolo Bonzinistatic void tcg_out_ext16u(TCGContext *s, TCGReg ret, TCGReg arg)
681139c1837SPaolo Bonzini{
682b86c6ba6SRichard Henderson    if (cpuinfo & CPUINFO_ZBB) {
683d1c3f4e9SRichard Henderson        tcg_out_opc_reg(s, OPC_ZEXT_H, ret, arg, TCG_REG_ZERO);
684d1c3f4e9SRichard Henderson    } else {
685139c1837SPaolo Bonzini        tcg_out_opc_imm(s, OPC_SLLIW, ret, arg, 16);
686139c1837SPaolo Bonzini        tcg_out_opc_imm(s, OPC_SRLIW, ret, ret, 16);
687139c1837SPaolo Bonzini    }
688d1c3f4e9SRichard Henderson}
689139c1837SPaolo Bonzini
690139c1837SPaolo Bonzinistatic void tcg_out_ext32u(TCGContext *s, TCGReg ret, TCGReg arg)
691139c1837SPaolo Bonzini{
692b86c6ba6SRichard Henderson    if (cpuinfo & CPUINFO_ZBA) {
693d1c3f4e9SRichard Henderson        tcg_out_opc_reg(s, OPC_ADD_UW, ret, arg, TCG_REG_ZERO);
694d1c3f4e9SRichard Henderson    } else {
695139c1837SPaolo Bonzini        tcg_out_opc_imm(s, OPC_SLLI, ret, arg, 32);
696139c1837SPaolo Bonzini        tcg_out_opc_imm(s, OPC_SRLI, ret, ret, 32);
697139c1837SPaolo Bonzini    }
698d1c3f4e9SRichard Henderson}
699139c1837SPaolo Bonzini
700678155b2SRichard Hendersonstatic void tcg_out_ext8s(TCGContext *s, TCGType type, TCGReg ret, TCGReg arg)
701139c1837SPaolo Bonzini{
702b86c6ba6SRichard Henderson    if (cpuinfo & CPUINFO_ZBB) {
703d1c3f4e9SRichard Henderson        tcg_out_opc_imm(s, OPC_SEXT_B, ret, arg, 0);
704d1c3f4e9SRichard Henderson    } else {
705139c1837SPaolo Bonzini        tcg_out_opc_imm(s, OPC_SLLIW, ret, arg, 24);
706139c1837SPaolo Bonzini        tcg_out_opc_imm(s, OPC_SRAIW, ret, ret, 24);
707139c1837SPaolo Bonzini    }
708d1c3f4e9SRichard Henderson}
709139c1837SPaolo Bonzini
710753e42eaSRichard Hendersonstatic void tcg_out_ext16s(TCGContext *s, TCGType type, TCGReg ret, TCGReg arg)
711139c1837SPaolo Bonzini{
712b86c6ba6SRichard Henderson    if (cpuinfo & CPUINFO_ZBB) {
713d1c3f4e9SRichard Henderson        tcg_out_opc_imm(s, OPC_SEXT_H, ret, arg, 0);
714d1c3f4e9SRichard Henderson    } else {
715139c1837SPaolo Bonzini        tcg_out_opc_imm(s, OPC_SLLIW, ret, arg, 16);
716139c1837SPaolo Bonzini        tcg_out_opc_imm(s, OPC_SRAIW, ret, ret, 16);
717139c1837SPaolo Bonzini    }
718d1c3f4e9SRichard Henderson}
719139c1837SPaolo Bonzini
720139c1837SPaolo Bonzinistatic void tcg_out_ext32s(TCGContext *s, TCGReg ret, TCGReg arg)
721139c1837SPaolo Bonzini{
722139c1837SPaolo Bonzini    tcg_out_opc_imm(s, OPC_ADDIW, ret, arg, 0);
723139c1837SPaolo Bonzini}
724139c1837SPaolo Bonzini
7259c6aa274SRichard Hendersonstatic void tcg_out_exts_i32_i64(TCGContext *s, TCGReg ret, TCGReg arg)
7269c6aa274SRichard Henderson{
7273ea9be33SRichard Henderson    if (ret != arg) {
7289c6aa274SRichard Henderson        tcg_out_ext32s(s, ret, arg);
7299c6aa274SRichard Henderson    }
7303ea9be33SRichard Henderson}
7319c6aa274SRichard Henderson
732b9bfe000SRichard Hendersonstatic void tcg_out_extu_i32_i64(TCGContext *s, TCGReg ret, TCGReg arg)
733b9bfe000SRichard Henderson{
734b9bfe000SRichard Henderson    tcg_out_ext32u(s, ret, arg);
735b9bfe000SRichard Henderson}
736b9bfe000SRichard Henderson
737b8b94ac6SRichard Hendersonstatic void tcg_out_extrl_i64_i32(TCGContext *s, TCGReg ret, TCGReg arg)
738b8b94ac6SRichard Henderson{
739b8b94ac6SRichard Henderson    tcg_out_ext32s(s, ret, arg);
740b8b94ac6SRichard Henderson}
741b8b94ac6SRichard Henderson
742139c1837SPaolo Bonzinistatic void tcg_out_ldst(TCGContext *s, RISCVInsn opc, TCGReg data,
743139c1837SPaolo Bonzini                         TCGReg addr, intptr_t offset)
744139c1837SPaolo Bonzini{
745139c1837SPaolo Bonzini    intptr_t imm12 = sextreg(offset, 0, 12);
746139c1837SPaolo Bonzini
747139c1837SPaolo Bonzini    if (offset != imm12) {
7489d9db413SRichard Henderson        intptr_t diff = tcg_pcrel_diff(s, (void *)offset);
749139c1837SPaolo Bonzini
750139c1837SPaolo Bonzini        if (addr == TCG_REG_ZERO && diff == (int32_t)diff) {
751139c1837SPaolo Bonzini            imm12 = sextreg(diff, 0, 12);
752139c1837SPaolo Bonzini            tcg_out_opc_upper(s, OPC_AUIPC, TCG_REG_TMP2, diff - imm12);
753139c1837SPaolo Bonzini        } else {
754139c1837SPaolo Bonzini            tcg_out_movi(s, TCG_TYPE_PTR, TCG_REG_TMP2, offset - imm12);
755139c1837SPaolo Bonzini            if (addr != TCG_REG_ZERO) {
756139c1837SPaolo Bonzini                tcg_out_opc_reg(s, OPC_ADD, TCG_REG_TMP2, TCG_REG_TMP2, addr);
757139c1837SPaolo Bonzini            }
758139c1837SPaolo Bonzini        }
759139c1837SPaolo Bonzini        addr = TCG_REG_TMP2;
760139c1837SPaolo Bonzini    }
761139c1837SPaolo Bonzini
762139c1837SPaolo Bonzini    switch (opc) {
763139c1837SPaolo Bonzini    case OPC_SB:
764139c1837SPaolo Bonzini    case OPC_SH:
765139c1837SPaolo Bonzini    case OPC_SW:
766139c1837SPaolo Bonzini    case OPC_SD:
767139c1837SPaolo Bonzini        tcg_out_opc_store(s, opc, addr, data, imm12);
768139c1837SPaolo Bonzini        break;
769139c1837SPaolo Bonzini    case OPC_LB:
770139c1837SPaolo Bonzini    case OPC_LBU:
771139c1837SPaolo Bonzini    case OPC_LH:
772139c1837SPaolo Bonzini    case OPC_LHU:
773139c1837SPaolo Bonzini    case OPC_LW:
774139c1837SPaolo Bonzini    case OPC_LWU:
775139c1837SPaolo Bonzini    case OPC_LD:
776139c1837SPaolo Bonzini        tcg_out_opc_imm(s, opc, data, addr, imm12);
777139c1837SPaolo Bonzini        break;
778139c1837SPaolo Bonzini    default:
779139c1837SPaolo Bonzini        g_assert_not_reached();
780139c1837SPaolo Bonzini    }
781139c1837SPaolo Bonzini}
782139c1837SPaolo Bonzini
783*f63e7089SHuang Shiyuanstatic void tcg_out_vec_ldst(TCGContext *s, RISCVInsn opc, TCGReg data,
784*f63e7089SHuang Shiyuan                             TCGReg addr, intptr_t offset)
785*f63e7089SHuang Shiyuan{
786*f63e7089SHuang Shiyuan    tcg_debug_assert(data >= TCG_REG_V0);
787*f63e7089SHuang Shiyuan    tcg_debug_assert(addr < TCG_REG_V0);
788*f63e7089SHuang Shiyuan
789*f63e7089SHuang Shiyuan    if (offset) {
790*f63e7089SHuang Shiyuan        tcg_debug_assert(addr != TCG_REG_ZERO);
791*f63e7089SHuang Shiyuan        if (offset == sextreg(offset, 0, 12)) {
792*f63e7089SHuang Shiyuan            tcg_out_opc_imm(s, OPC_ADDI, TCG_REG_TMP0, addr, offset);
793*f63e7089SHuang Shiyuan        } else {
794*f63e7089SHuang Shiyuan            tcg_out_movi(s, TCG_TYPE_PTR, TCG_REG_TMP0, offset);
795*f63e7089SHuang Shiyuan            tcg_out_opc_reg(s, OPC_ADD, TCG_REG_TMP0, TCG_REG_TMP0, addr);
796*f63e7089SHuang Shiyuan        }
797*f63e7089SHuang Shiyuan        addr = TCG_REG_TMP0;
798*f63e7089SHuang Shiyuan    }
799*f63e7089SHuang Shiyuan    tcg_out32(s, encode_v(opc, data, addr, 0, true));
800*f63e7089SHuang Shiyuan}
801*f63e7089SHuang Shiyuan
802139c1837SPaolo Bonzinistatic void tcg_out_ld(TCGContext *s, TCGType type, TCGReg arg,
803139c1837SPaolo Bonzini                       TCGReg arg1, intptr_t arg2)
804139c1837SPaolo Bonzini{
805*f63e7089SHuang Shiyuan    RISCVInsn insn;
806*f63e7089SHuang Shiyuan
807*f63e7089SHuang Shiyuan    switch (type) {
808*f63e7089SHuang Shiyuan    case TCG_TYPE_I32:
809*f63e7089SHuang Shiyuan        tcg_out_ldst(s, OPC_LW, arg, arg1, arg2);
810*f63e7089SHuang Shiyuan        break;
811*f63e7089SHuang Shiyuan    case TCG_TYPE_I64:
812*f63e7089SHuang Shiyuan        tcg_out_ldst(s, OPC_LD, arg, arg1, arg2);
813*f63e7089SHuang Shiyuan        break;
814*f63e7089SHuang Shiyuan    case TCG_TYPE_V64:
815*f63e7089SHuang Shiyuan    case TCG_TYPE_V128:
816*f63e7089SHuang Shiyuan    case TCG_TYPE_V256:
817*f63e7089SHuang Shiyuan        if (type >= riscv_lg2_vlenb) {
818*f63e7089SHuang Shiyuan            static const RISCVInsn whole_reg_ld[] = {
819*f63e7089SHuang Shiyuan                OPC_VL1RE64_V, OPC_VL2RE64_V, OPC_VL4RE64_V, OPC_VL8RE64_V
820*f63e7089SHuang Shiyuan            };
821*f63e7089SHuang Shiyuan            unsigned idx = type - riscv_lg2_vlenb;
822*f63e7089SHuang Shiyuan
823*f63e7089SHuang Shiyuan            tcg_debug_assert(idx < ARRAY_SIZE(whole_reg_ld));
824*f63e7089SHuang Shiyuan            insn = whole_reg_ld[idx];
825*f63e7089SHuang Shiyuan        } else {
826*f63e7089SHuang Shiyuan            static const RISCVInsn unit_stride_ld[] = {
827*f63e7089SHuang Shiyuan                OPC_VLE8_V, OPC_VLE16_V, OPC_VLE32_V, OPC_VLE64_V
828*f63e7089SHuang Shiyuan            };
829*f63e7089SHuang Shiyuan            MemOp prev_vsew = set_vtype_len(s, type);
830*f63e7089SHuang Shiyuan
831*f63e7089SHuang Shiyuan            tcg_debug_assert(prev_vsew < ARRAY_SIZE(unit_stride_ld));
832*f63e7089SHuang Shiyuan            insn = unit_stride_ld[prev_vsew];
833*f63e7089SHuang Shiyuan        }
834*f63e7089SHuang Shiyuan        tcg_out_vec_ldst(s, insn, arg, arg1, arg2);
835*f63e7089SHuang Shiyuan        break;
836*f63e7089SHuang Shiyuan    default:
837*f63e7089SHuang Shiyuan        g_assert_not_reached();
838*f63e7089SHuang Shiyuan    }
839139c1837SPaolo Bonzini}
840139c1837SPaolo Bonzini
841139c1837SPaolo Bonzinistatic void tcg_out_st(TCGContext *s, TCGType type, TCGReg arg,
842139c1837SPaolo Bonzini                       TCGReg arg1, intptr_t arg2)
843139c1837SPaolo Bonzini{
844*f63e7089SHuang Shiyuan    RISCVInsn insn;
845*f63e7089SHuang Shiyuan
846*f63e7089SHuang Shiyuan    switch (type) {
847*f63e7089SHuang Shiyuan    case TCG_TYPE_I32:
848*f63e7089SHuang Shiyuan        tcg_out_ldst(s, OPC_SW, arg, arg1, arg2);
849*f63e7089SHuang Shiyuan        break;
850*f63e7089SHuang Shiyuan    case TCG_TYPE_I64:
851*f63e7089SHuang Shiyuan        tcg_out_ldst(s, OPC_SD, arg, arg1, arg2);
852*f63e7089SHuang Shiyuan        break;
853*f63e7089SHuang Shiyuan    case TCG_TYPE_V64:
854*f63e7089SHuang Shiyuan    case TCG_TYPE_V128:
855*f63e7089SHuang Shiyuan    case TCG_TYPE_V256:
856*f63e7089SHuang Shiyuan        if (type >= riscv_lg2_vlenb) {
857*f63e7089SHuang Shiyuan            static const RISCVInsn whole_reg_st[] = {
858*f63e7089SHuang Shiyuan                OPC_VS1R_V, OPC_VS2R_V, OPC_VS4R_V, OPC_VS8R_V
859*f63e7089SHuang Shiyuan            };
860*f63e7089SHuang Shiyuan            unsigned idx = type - riscv_lg2_vlenb;
861*f63e7089SHuang Shiyuan
862*f63e7089SHuang Shiyuan            tcg_debug_assert(idx < ARRAY_SIZE(whole_reg_st));
863*f63e7089SHuang Shiyuan            insn = whole_reg_st[idx];
864*f63e7089SHuang Shiyuan        } else {
865*f63e7089SHuang Shiyuan            static const RISCVInsn unit_stride_st[] = {
866*f63e7089SHuang Shiyuan                OPC_VSE8_V, OPC_VSE16_V, OPC_VSE32_V, OPC_VSE64_V
867*f63e7089SHuang Shiyuan            };
868*f63e7089SHuang Shiyuan            MemOp prev_vsew = set_vtype_len(s, type);
869*f63e7089SHuang Shiyuan
870*f63e7089SHuang Shiyuan            tcg_debug_assert(prev_vsew < ARRAY_SIZE(unit_stride_st));
871*f63e7089SHuang Shiyuan            insn = unit_stride_st[prev_vsew];
872*f63e7089SHuang Shiyuan        }
873*f63e7089SHuang Shiyuan        tcg_out_vec_ldst(s, insn, arg, arg1, arg2);
874*f63e7089SHuang Shiyuan        break;
875*f63e7089SHuang Shiyuan    default:
876*f63e7089SHuang Shiyuan        g_assert_not_reached();
877*f63e7089SHuang Shiyuan    }
878139c1837SPaolo Bonzini}
879139c1837SPaolo Bonzini
880139c1837SPaolo Bonzinistatic bool tcg_out_sti(TCGContext *s, TCGType type, TCGArg val,
881139c1837SPaolo Bonzini                        TCGReg base, intptr_t ofs)
882139c1837SPaolo Bonzini{
883139c1837SPaolo Bonzini    if (val == 0) {
884139c1837SPaolo Bonzini        tcg_out_st(s, type, TCG_REG_ZERO, base, ofs);
885139c1837SPaolo Bonzini        return true;
886139c1837SPaolo Bonzini    }
887139c1837SPaolo Bonzini    return false;
888139c1837SPaolo Bonzini}
889139c1837SPaolo Bonzini
890139c1837SPaolo Bonzinistatic void tcg_out_addsub2(TCGContext *s,
891139c1837SPaolo Bonzini                            TCGReg rl, TCGReg rh,
892139c1837SPaolo Bonzini                            TCGReg al, TCGReg ah,
893139c1837SPaolo Bonzini                            TCGArg bl, TCGArg bh,
894139c1837SPaolo Bonzini                            bool cbl, bool cbh, bool is_sub, bool is32bit)
895139c1837SPaolo Bonzini{
896139c1837SPaolo Bonzini    const RISCVInsn opc_add = is32bit ? OPC_ADDW : OPC_ADD;
897139c1837SPaolo Bonzini    const RISCVInsn opc_addi = is32bit ? OPC_ADDIW : OPC_ADDI;
898139c1837SPaolo Bonzini    const RISCVInsn opc_sub = is32bit ? OPC_SUBW : OPC_SUB;
899139c1837SPaolo Bonzini    TCGReg th = TCG_REG_TMP1;
900139c1837SPaolo Bonzini
901139c1837SPaolo Bonzini    /* If we have a negative constant such that negating it would
902139c1837SPaolo Bonzini       make the high part zero, we can (usually) eliminate one insn.  */
903139c1837SPaolo Bonzini    if (cbl && cbh && bh == -1 && bl != 0) {
904139c1837SPaolo Bonzini        bl = -bl;
905139c1837SPaolo Bonzini        bh = 0;
906139c1837SPaolo Bonzini        is_sub = !is_sub;
907139c1837SPaolo Bonzini    }
908139c1837SPaolo Bonzini
909139c1837SPaolo Bonzini    /* By operating on the high part first, we get to use the final
910139c1837SPaolo Bonzini       carry operation to move back from the temporary.  */
911139c1837SPaolo Bonzini    if (!cbh) {
912139c1837SPaolo Bonzini        tcg_out_opc_reg(s, (is_sub ? opc_sub : opc_add), th, ah, bh);
913139c1837SPaolo Bonzini    } else if (bh != 0 || ah == rl) {
914139c1837SPaolo Bonzini        tcg_out_opc_imm(s, opc_addi, th, ah, (is_sub ? -bh : bh));
915139c1837SPaolo Bonzini    } else {
916139c1837SPaolo Bonzini        th = ah;
917139c1837SPaolo Bonzini    }
918139c1837SPaolo Bonzini
919139c1837SPaolo Bonzini    /* Note that tcg optimization should eliminate the bl == 0 case.  */
920139c1837SPaolo Bonzini    if (is_sub) {
921139c1837SPaolo Bonzini        if (cbl) {
922139c1837SPaolo Bonzini            tcg_out_opc_imm(s, OPC_SLTIU, TCG_REG_TMP0, al, bl);
923139c1837SPaolo Bonzini            tcg_out_opc_imm(s, opc_addi, rl, al, -bl);
924139c1837SPaolo Bonzini        } else {
925139c1837SPaolo Bonzini            tcg_out_opc_reg(s, OPC_SLTU, TCG_REG_TMP0, al, bl);
926139c1837SPaolo Bonzini            tcg_out_opc_reg(s, opc_sub, rl, al, bl);
927139c1837SPaolo Bonzini        }
928139c1837SPaolo Bonzini        tcg_out_opc_reg(s, opc_sub, rh, th, TCG_REG_TMP0);
929139c1837SPaolo Bonzini    } else {
930139c1837SPaolo Bonzini        if (cbl) {
931139c1837SPaolo Bonzini            tcg_out_opc_imm(s, opc_addi, rl, al, bl);
932139c1837SPaolo Bonzini            tcg_out_opc_imm(s, OPC_SLTIU, TCG_REG_TMP0, rl, bl);
9339b246685SRichard Henderson        } else if (al == bl) {
9349b246685SRichard Henderson            /*
9359b246685SRichard Henderson             * If the input regs overlap, this is a simple doubling
9369b246685SRichard Henderson             * and carry-out is the input msb.  This special case is
9379b246685SRichard Henderson             * required when the output reg overlaps the input,
9389b246685SRichard Henderson             * but we might as well use it always.
9399b246685SRichard Henderson             */
940139c1837SPaolo Bonzini            tcg_out_opc_imm(s, OPC_SLTI, TCG_REG_TMP0, al, 0);
9419b246685SRichard Henderson            tcg_out_opc_reg(s, opc_add, rl, al, al);
942139c1837SPaolo Bonzini        } else {
943139c1837SPaolo Bonzini            tcg_out_opc_reg(s, opc_add, rl, al, bl);
944139c1837SPaolo Bonzini            tcg_out_opc_reg(s, OPC_SLTU, TCG_REG_TMP0,
945139c1837SPaolo Bonzini                            rl, (rl == bl ? al : bl));
946139c1837SPaolo Bonzini        }
947139c1837SPaolo Bonzini        tcg_out_opc_reg(s, opc_add, rh, th, TCG_REG_TMP0);
948139c1837SPaolo Bonzini    }
949139c1837SPaolo Bonzini}
950139c1837SPaolo Bonzini
951*f63e7089SHuang Shiyuanstatic bool tcg_out_dup_vec(TCGContext *s, TCGType type, unsigned vece,
952*f63e7089SHuang Shiyuan                                   TCGReg dst, TCGReg src)
953*f63e7089SHuang Shiyuan{
954*f63e7089SHuang Shiyuan    return false;
955*f63e7089SHuang Shiyuan}
956*f63e7089SHuang Shiyuan
957*f63e7089SHuang Shiyuanstatic bool tcg_out_dupm_vec(TCGContext *s, TCGType type, unsigned vece,
958*f63e7089SHuang Shiyuan                                    TCGReg dst, TCGReg base, intptr_t offset)
959*f63e7089SHuang Shiyuan{
960*f63e7089SHuang Shiyuan    return false;
961*f63e7089SHuang Shiyuan}
962*f63e7089SHuang Shiyuan
963*f63e7089SHuang Shiyuanstatic void tcg_out_dupi_vec(TCGContext *s, TCGType type, unsigned vece,
964*f63e7089SHuang Shiyuan                                    TCGReg dst, int64_t arg)
965*f63e7089SHuang Shiyuan{
966*f63e7089SHuang Shiyuan}
967*f63e7089SHuang Shiyuan
968139c1837SPaolo Bonzinistatic const struct {
969139c1837SPaolo Bonzini    RISCVInsn op;
970139c1837SPaolo Bonzini    bool swap;
971139c1837SPaolo Bonzini} tcg_brcond_to_riscv[] = {
972139c1837SPaolo Bonzini    [TCG_COND_EQ] =  { OPC_BEQ,  false },
973139c1837SPaolo Bonzini    [TCG_COND_NE] =  { OPC_BNE,  false },
974139c1837SPaolo Bonzini    [TCG_COND_LT] =  { OPC_BLT,  false },
975139c1837SPaolo Bonzini    [TCG_COND_GE] =  { OPC_BGE,  false },
976139c1837SPaolo Bonzini    [TCG_COND_LE] =  { OPC_BGE,  true  },
977139c1837SPaolo Bonzini    [TCG_COND_GT] =  { OPC_BLT,  true  },
978139c1837SPaolo Bonzini    [TCG_COND_LTU] = { OPC_BLTU, false },
979139c1837SPaolo Bonzini    [TCG_COND_GEU] = { OPC_BGEU, false },
980139c1837SPaolo Bonzini    [TCG_COND_LEU] = { OPC_BGEU, true  },
981139c1837SPaolo Bonzini    [TCG_COND_GTU] = { OPC_BLTU, true  }
982139c1837SPaolo Bonzini};
983139c1837SPaolo Bonzini
984139c1837SPaolo Bonzinistatic void tcg_out_brcond(TCGContext *s, TCGCond cond, TCGReg arg1,
985139c1837SPaolo Bonzini                           TCGReg arg2, TCGLabel *l)
986139c1837SPaolo Bonzini{
987139c1837SPaolo Bonzini    RISCVInsn op = tcg_brcond_to_riscv[cond].op;
988139c1837SPaolo Bonzini
989139c1837SPaolo Bonzini    tcg_debug_assert(op != 0);
990139c1837SPaolo Bonzini
991139c1837SPaolo Bonzini    if (tcg_brcond_to_riscv[cond].swap) {
992139c1837SPaolo Bonzini        TCGReg t = arg1;
993139c1837SPaolo Bonzini        arg1 = arg2;
994139c1837SPaolo Bonzini        arg2 = t;
995139c1837SPaolo Bonzini    }
996139c1837SPaolo Bonzini
997139c1837SPaolo Bonzini    tcg_out_reloc(s, s->code_ptr, R_RISCV_BRANCH, l, 0);
998139c1837SPaolo Bonzini    tcg_out_opc_branch(s, op, arg1, arg2, 0);
999139c1837SPaolo Bonzini}
1000139c1837SPaolo Bonzini
1001f6453695SRichard Henderson#define SETCOND_INV    TCG_TARGET_NB_REGS
1002f6453695SRichard Henderson#define SETCOND_NEZ    (SETCOND_INV << 1)
1003f6453695SRichard Henderson#define SETCOND_FLAGS  (SETCOND_INV | SETCOND_NEZ)
1004f6453695SRichard Henderson
1005f6453695SRichard Hendersonstatic int tcg_out_setcond_int(TCGContext *s, TCGCond cond, TCGReg ret,
1006f6453695SRichard Henderson                               TCGReg arg1, tcg_target_long arg2, bool c2)
1007139c1837SPaolo Bonzini{
1008f6453695SRichard Henderson    int flags = 0;
1009f6453695SRichard Henderson
1010139c1837SPaolo Bonzini    switch (cond) {
1011f6453695SRichard Henderson    case TCG_COND_EQ:    /* -> NE  */
1012f6453695SRichard Henderson    case TCG_COND_GE:    /* -> LT  */
1013f6453695SRichard Henderson    case TCG_COND_GEU:   /* -> LTU */
1014f6453695SRichard Henderson    case TCG_COND_GT:    /* -> LE  */
1015f6453695SRichard Henderson    case TCG_COND_GTU:   /* -> LEU */
1016f6453695SRichard Henderson        cond = tcg_invert_cond(cond);
1017f6453695SRichard Henderson        flags ^= SETCOND_INV;
1018139c1837SPaolo Bonzini        break;
1019f6453695SRichard Henderson    default:
1020139c1837SPaolo Bonzini        break;
1021f6453695SRichard Henderson    }
1022f6453695SRichard Henderson
1023f6453695SRichard Henderson    switch (cond) {
1024139c1837SPaolo Bonzini    case TCG_COND_LE:
1025139c1837SPaolo Bonzini    case TCG_COND_LEU:
1026f6453695SRichard Henderson        /*
1027f6453695SRichard Henderson         * If we have a constant input, the most efficient way to implement
1028f6453695SRichard Henderson         * LE is by adding 1 and using LT.  Watch out for wrap around for LEU.
1029f6453695SRichard Henderson         * We don't need to care for this for LE because the constant input
1030f6453695SRichard Henderson         * is constrained to signed 12-bit, and 0x800 is representable in the
1031f6453695SRichard Henderson         * temporary register.
1032f6453695SRichard Henderson         */
1033f6453695SRichard Henderson        if (c2) {
1034f6453695SRichard Henderson            if (cond == TCG_COND_LEU) {
1035f6453695SRichard Henderson                /* unsigned <= -1 is true */
1036f6453695SRichard Henderson                if (arg2 == -1) {
1037f6453695SRichard Henderson                    tcg_out_movi(s, TCG_TYPE_REG, ret, !(flags & SETCOND_INV));
1038f6453695SRichard Henderson                    return ret;
1039f6453695SRichard Henderson                }
1040f6453695SRichard Henderson                cond = TCG_COND_LTU;
1041f6453695SRichard Henderson            } else {
1042f6453695SRichard Henderson                cond = TCG_COND_LT;
1043f6453695SRichard Henderson            }
1044f6453695SRichard Henderson            tcg_debug_assert(arg2 <= 0x7ff);
1045f6453695SRichard Henderson            if (++arg2 == 0x800) {
1046f6453695SRichard Henderson                tcg_out_movi(s, TCG_TYPE_REG, TCG_REG_TMP0, arg2);
1047f6453695SRichard Henderson                arg2 = TCG_REG_TMP0;
1048f6453695SRichard Henderson                c2 = false;
1049f6453695SRichard Henderson            }
1050f6453695SRichard Henderson        } else {
1051f6453695SRichard Henderson            TCGReg tmp = arg2;
1052f6453695SRichard Henderson            arg2 = arg1;
1053f6453695SRichard Henderson            arg1 = tmp;
1054f6453695SRichard Henderson            cond = tcg_swap_cond(cond);    /* LE -> GE */
1055f6453695SRichard Henderson            cond = tcg_invert_cond(cond);  /* GE -> LT */
1056f6453695SRichard Henderson            flags ^= SETCOND_INV;
1057f6453695SRichard Henderson        }
1058139c1837SPaolo Bonzini        break;
1059f6453695SRichard Henderson    default:
1060f6453695SRichard Henderson        break;
1061f6453695SRichard Henderson    }
1062f6453695SRichard Henderson
1063f6453695SRichard Henderson    switch (cond) {
1064f6453695SRichard Henderson    case TCG_COND_NE:
1065f6453695SRichard Henderson        flags |= SETCOND_NEZ;
1066f6453695SRichard Henderson        if (!c2) {
1067f6453695SRichard Henderson            tcg_out_opc_reg(s, OPC_XOR, ret, arg1, arg2);
1068f6453695SRichard Henderson        } else if (arg2 == 0) {
1069f6453695SRichard Henderson            ret = arg1;
1070f6453695SRichard Henderson        } else {
1071f6453695SRichard Henderson            tcg_out_opc_imm(s, OPC_XORI, ret, arg1, arg2);
1072f6453695SRichard Henderson        }
1073f6453695SRichard Henderson        break;
1074f6453695SRichard Henderson
1075f6453695SRichard Henderson    case TCG_COND_LT:
1076f6453695SRichard Henderson        if (c2) {
1077f6453695SRichard Henderson            tcg_out_opc_imm(s, OPC_SLTI, ret, arg1, arg2);
1078f6453695SRichard Henderson        } else {
1079f6453695SRichard Henderson            tcg_out_opc_reg(s, OPC_SLT, ret, arg1, arg2);
1080f6453695SRichard Henderson        }
1081f6453695SRichard Henderson        break;
1082f6453695SRichard Henderson
1083f6453695SRichard Henderson    case TCG_COND_LTU:
1084f6453695SRichard Henderson        if (c2) {
1085f6453695SRichard Henderson            tcg_out_opc_imm(s, OPC_SLTIU, ret, arg1, arg2);
1086f6453695SRichard Henderson        } else {
1087f6453695SRichard Henderson            tcg_out_opc_reg(s, OPC_SLTU, ret, arg1, arg2);
1088f6453695SRichard Henderson        }
1089f6453695SRichard Henderson        break;
1090f6453695SRichard Henderson
1091f6453695SRichard Henderson    default:
1092f6453695SRichard Henderson        g_assert_not_reached();
1093f6453695SRichard Henderson    }
1094f6453695SRichard Henderson
1095f6453695SRichard Henderson    return ret | flags;
1096f6453695SRichard Henderson}
1097f6453695SRichard Henderson
1098f6453695SRichard Hendersonstatic void tcg_out_setcond(TCGContext *s, TCGCond cond, TCGReg ret,
1099f6453695SRichard Henderson                            TCGReg arg1, tcg_target_long arg2, bool c2)
1100f6453695SRichard Henderson{
1101f6453695SRichard Henderson    int tmpflags = tcg_out_setcond_int(s, cond, ret, arg1, arg2, c2);
1102f6453695SRichard Henderson
1103f6453695SRichard Henderson    if (tmpflags != ret) {
1104f6453695SRichard Henderson        TCGReg tmp = tmpflags & ~SETCOND_FLAGS;
1105f6453695SRichard Henderson
1106f6453695SRichard Henderson        switch (tmpflags & SETCOND_FLAGS) {
1107f6453695SRichard Henderson        case SETCOND_INV:
1108f6453695SRichard Henderson            /* Intermediate result is boolean: simply invert. */
1109f6453695SRichard Henderson            tcg_out_opc_imm(s, OPC_XORI, ret, tmp, 1);
1110f6453695SRichard Henderson            break;
1111f6453695SRichard Henderson        case SETCOND_NEZ:
1112f6453695SRichard Henderson            /* Intermediate result is zero/non-zero: test != 0. */
1113f6453695SRichard Henderson            tcg_out_opc_reg(s, OPC_SLTU, ret, TCG_REG_ZERO, tmp);
1114f6453695SRichard Henderson            break;
1115f6453695SRichard Henderson        case SETCOND_NEZ | SETCOND_INV:
1116f6453695SRichard Henderson            /* Intermediate result is zero/non-zero: test == 0. */
1117f6453695SRichard Henderson            tcg_out_opc_imm(s, OPC_SLTIU, ret, tmp, 1);
1118139c1837SPaolo Bonzini            break;
1119139c1837SPaolo Bonzini        default:
1120139c1837SPaolo Bonzini            g_assert_not_reached();
1121f6453695SRichard Henderson        }
1122139c1837SPaolo Bonzini    }
1123139c1837SPaolo Bonzini}
1124139c1837SPaolo Bonzini
112541e4c0a9SRichard Hendersonstatic void tcg_out_negsetcond(TCGContext *s, TCGCond cond, TCGReg ret,
112641e4c0a9SRichard Henderson                               TCGReg arg1, tcg_target_long arg2, bool c2)
112741e4c0a9SRichard Henderson{
112841e4c0a9SRichard Henderson    int tmpflags;
112941e4c0a9SRichard Henderson    TCGReg tmp;
113041e4c0a9SRichard Henderson
113141e4c0a9SRichard Henderson    /* For LT/GE comparison against 0, replicate the sign bit. */
113241e4c0a9SRichard Henderson    if (c2 && arg2 == 0) {
113341e4c0a9SRichard Henderson        switch (cond) {
113441e4c0a9SRichard Henderson        case TCG_COND_GE:
113541e4c0a9SRichard Henderson            tcg_out_opc_imm(s, OPC_XORI, ret, arg1, -1);
113641e4c0a9SRichard Henderson            arg1 = ret;
113741e4c0a9SRichard Henderson            /* fall through */
113841e4c0a9SRichard Henderson        case TCG_COND_LT:
113941e4c0a9SRichard Henderson            tcg_out_opc_imm(s, OPC_SRAI, ret, arg1, TCG_TARGET_REG_BITS - 1);
114041e4c0a9SRichard Henderson            return;
114141e4c0a9SRichard Henderson        default:
114241e4c0a9SRichard Henderson            break;
114341e4c0a9SRichard Henderson        }
114441e4c0a9SRichard Henderson    }
114541e4c0a9SRichard Henderson
114641e4c0a9SRichard Henderson    tmpflags = tcg_out_setcond_int(s, cond, ret, arg1, arg2, c2);
114741e4c0a9SRichard Henderson    tmp = tmpflags & ~SETCOND_FLAGS;
114841e4c0a9SRichard Henderson
114941e4c0a9SRichard Henderson    /* If intermediate result is zero/non-zero: test != 0. */
115041e4c0a9SRichard Henderson    if (tmpflags & SETCOND_NEZ) {
115141e4c0a9SRichard Henderson        tcg_out_opc_reg(s, OPC_SLTU, ret, TCG_REG_ZERO, tmp);
115241e4c0a9SRichard Henderson        tmp = ret;
115341e4c0a9SRichard Henderson    }
115441e4c0a9SRichard Henderson
115541e4c0a9SRichard Henderson    /* Produce the 0/-1 result. */
115641e4c0a9SRichard Henderson    if (tmpflags & SETCOND_INV) {
115741e4c0a9SRichard Henderson        tcg_out_opc_imm(s, OPC_ADDI, ret, tmp, -1);
115841e4c0a9SRichard Henderson    } else {
115941e4c0a9SRichard Henderson        tcg_out_opc_reg(s, OPC_SUB, ret, TCG_REG_ZERO, tmp);
116041e4c0a9SRichard Henderson    }
116141e4c0a9SRichard Henderson}
116241e4c0a9SRichard Henderson
1163a18d783eSRichard Hendersonstatic void tcg_out_movcond_zicond(TCGContext *s, TCGReg ret, TCGReg test_ne,
1164a18d783eSRichard Henderson                                   int val1, bool c_val1,
1165a18d783eSRichard Henderson                                   int val2, bool c_val2)
1166a18d783eSRichard Henderson{
1167a18d783eSRichard Henderson    if (val1 == 0) {
1168a18d783eSRichard Henderson        if (c_val2) {
1169a18d783eSRichard Henderson            tcg_out_movi(s, TCG_TYPE_REG, TCG_REG_TMP1, val2);
1170a18d783eSRichard Henderson            val2 = TCG_REG_TMP1;
1171a18d783eSRichard Henderson        }
1172a18d783eSRichard Henderson        tcg_out_opc_reg(s, OPC_CZERO_NEZ, ret, val2, test_ne);
1173a18d783eSRichard Henderson        return;
1174a18d783eSRichard Henderson    }
1175a18d783eSRichard Henderson
1176a18d783eSRichard Henderson    if (val2 == 0) {
1177a18d783eSRichard Henderson        if (c_val1) {
1178a18d783eSRichard Henderson            tcg_out_movi(s, TCG_TYPE_REG, TCG_REG_TMP1, val1);
1179a18d783eSRichard Henderson            val1 = TCG_REG_TMP1;
1180a18d783eSRichard Henderson        }
1181a18d783eSRichard Henderson        tcg_out_opc_reg(s, OPC_CZERO_EQZ, ret, val1, test_ne);
1182a18d783eSRichard Henderson        return;
1183a18d783eSRichard Henderson    }
1184a18d783eSRichard Henderson
1185a18d783eSRichard Henderson    if (c_val2) {
1186a18d783eSRichard Henderson        if (c_val1) {
1187a18d783eSRichard Henderson            tcg_out_movi(s, TCG_TYPE_REG, TCG_REG_TMP1, val1 - val2);
1188a18d783eSRichard Henderson        } else {
1189a18d783eSRichard Henderson            tcg_out_opc_imm(s, OPC_ADDI, TCG_REG_TMP1, val1, -val2);
1190a18d783eSRichard Henderson        }
1191a18d783eSRichard Henderson        tcg_out_opc_reg(s, OPC_CZERO_EQZ, ret, TCG_REG_TMP1, test_ne);
1192a18d783eSRichard Henderson        tcg_out_opc_imm(s, OPC_ADDI, ret, ret, val2);
1193a18d783eSRichard Henderson        return;
1194a18d783eSRichard Henderson    }
1195a18d783eSRichard Henderson
1196a18d783eSRichard Henderson    if (c_val1) {
1197a18d783eSRichard Henderson        tcg_out_opc_imm(s, OPC_ADDI, TCG_REG_TMP1, val2, -val1);
1198a18d783eSRichard Henderson        tcg_out_opc_reg(s, OPC_CZERO_NEZ, ret, TCG_REG_TMP1, test_ne);
1199a18d783eSRichard Henderson        tcg_out_opc_imm(s, OPC_ADDI, ret, ret, val1);
1200a18d783eSRichard Henderson        return;
1201a18d783eSRichard Henderson    }
1202a18d783eSRichard Henderson
1203a18d783eSRichard Henderson    tcg_out_opc_reg(s, OPC_CZERO_NEZ, TCG_REG_TMP1, val2, test_ne);
1204a18d783eSRichard Henderson    tcg_out_opc_reg(s, OPC_CZERO_EQZ, TCG_REG_TMP0, val1, test_ne);
1205a18d783eSRichard Henderson    tcg_out_opc_reg(s, OPC_OR, ret, TCG_REG_TMP0, TCG_REG_TMP1);
1206a18d783eSRichard Henderson}
1207a18d783eSRichard Henderson
1208a18d783eSRichard Hendersonstatic void tcg_out_movcond_br1(TCGContext *s, TCGCond cond, TCGReg ret,
1209a18d783eSRichard Henderson                                TCGReg cmp1, TCGReg cmp2,
1210a18d783eSRichard Henderson                                int val, bool c_val)
1211a18d783eSRichard Henderson{
1212a18d783eSRichard Henderson    RISCVInsn op;
1213a18d783eSRichard Henderson    int disp = 8;
1214a18d783eSRichard Henderson
1215a18d783eSRichard Henderson    tcg_debug_assert((unsigned)cond < ARRAY_SIZE(tcg_brcond_to_riscv));
1216a18d783eSRichard Henderson    op = tcg_brcond_to_riscv[cond].op;
1217a18d783eSRichard Henderson    tcg_debug_assert(op != 0);
1218a18d783eSRichard Henderson
1219a18d783eSRichard Henderson    if (tcg_brcond_to_riscv[cond].swap) {
1220a18d783eSRichard Henderson        tcg_out_opc_branch(s, op, cmp2, cmp1, disp);
1221a18d783eSRichard Henderson    } else {
1222a18d783eSRichard Henderson        tcg_out_opc_branch(s, op, cmp1, cmp2, disp);
1223a18d783eSRichard Henderson    }
1224a18d783eSRichard Henderson    if (c_val) {
1225a18d783eSRichard Henderson        tcg_out_opc_imm(s, OPC_ADDI, ret, TCG_REG_ZERO, val);
1226a18d783eSRichard Henderson    } else {
1227a18d783eSRichard Henderson        tcg_out_opc_imm(s, OPC_ADDI, ret, val, 0);
1228a18d783eSRichard Henderson    }
1229a18d783eSRichard Henderson}
1230a18d783eSRichard Henderson
1231a18d783eSRichard Hendersonstatic void tcg_out_movcond_br2(TCGContext *s, TCGCond cond, TCGReg ret,
1232a18d783eSRichard Henderson                                TCGReg cmp1, TCGReg cmp2,
1233a18d783eSRichard Henderson                                int val1, bool c_val1,
1234a18d783eSRichard Henderson                                int val2, bool c_val2)
1235a18d783eSRichard Henderson{
1236a18d783eSRichard Henderson    TCGReg tmp;
1237a18d783eSRichard Henderson
1238a18d783eSRichard Henderson    /* TCG optimizer reorders to prefer ret matching val2. */
1239a18d783eSRichard Henderson    if (!c_val2 && ret == val2) {
1240a18d783eSRichard Henderson        cond = tcg_invert_cond(cond);
1241a18d783eSRichard Henderson        tcg_out_movcond_br1(s, cond, ret, cmp1, cmp2, val1, c_val1);
1242a18d783eSRichard Henderson        return;
1243a18d783eSRichard Henderson    }
1244a18d783eSRichard Henderson
1245a18d783eSRichard Henderson    if (!c_val1 && ret == val1) {
1246a18d783eSRichard Henderson        tcg_out_movcond_br1(s, cond, ret, cmp1, cmp2, val2, c_val2);
1247a18d783eSRichard Henderson        return;
1248a18d783eSRichard Henderson    }
1249a18d783eSRichard Henderson
1250a18d783eSRichard Henderson    tmp = (ret == cmp1 || ret == cmp2 ? TCG_REG_TMP1 : ret);
1251a18d783eSRichard Henderson    if (c_val1) {
1252a18d783eSRichard Henderson        tcg_out_movi(s, TCG_TYPE_REG, tmp, val1);
1253a18d783eSRichard Henderson    } else {
1254a18d783eSRichard Henderson        tcg_out_mov(s, TCG_TYPE_REG, tmp, val1);
1255a18d783eSRichard Henderson    }
1256a18d783eSRichard Henderson    tcg_out_movcond_br1(s, cond, tmp, cmp1, cmp2, val2, c_val2);
1257a18d783eSRichard Henderson    tcg_out_mov(s, TCG_TYPE_REG, ret, tmp);
1258a18d783eSRichard Henderson}
1259a18d783eSRichard Henderson
1260a18d783eSRichard Hendersonstatic void tcg_out_movcond(TCGContext *s, TCGCond cond, TCGReg ret,
1261a18d783eSRichard Henderson                            TCGReg cmp1, int cmp2, bool c_cmp2,
1262a18d783eSRichard Henderson                            TCGReg val1, bool c_val1,
1263a18d783eSRichard Henderson                            TCGReg val2, bool c_val2)
1264a18d783eSRichard Henderson{
1265a18d783eSRichard Henderson    int tmpflags;
1266a18d783eSRichard Henderson    TCGReg t;
1267a18d783eSRichard Henderson
1268b86c6ba6SRichard Henderson    if (!(cpuinfo & CPUINFO_ZICOND) && (!c_cmp2 || cmp2 == 0)) {
1269a18d783eSRichard Henderson        tcg_out_movcond_br2(s, cond, ret, cmp1, cmp2,
1270a18d783eSRichard Henderson                            val1, c_val1, val2, c_val2);
1271a18d783eSRichard Henderson        return;
1272a18d783eSRichard Henderson    }
1273a18d783eSRichard Henderson
1274a18d783eSRichard Henderson    tmpflags = tcg_out_setcond_int(s, cond, TCG_REG_TMP0, cmp1, cmp2, c_cmp2);
1275a18d783eSRichard Henderson    t = tmpflags & ~SETCOND_FLAGS;
1276a18d783eSRichard Henderson
1277b86c6ba6SRichard Henderson    if (cpuinfo & CPUINFO_ZICOND) {
1278a18d783eSRichard Henderson        if (tmpflags & SETCOND_INV) {
1279a18d783eSRichard Henderson            tcg_out_movcond_zicond(s, ret, t, val2, c_val2, val1, c_val1);
1280a18d783eSRichard Henderson        } else {
1281a18d783eSRichard Henderson            tcg_out_movcond_zicond(s, ret, t, val1, c_val1, val2, c_val2);
1282a18d783eSRichard Henderson        }
1283a18d783eSRichard Henderson    } else {
1284a18d783eSRichard Henderson        cond = tmpflags & SETCOND_INV ? TCG_COND_EQ : TCG_COND_NE;
1285a18d783eSRichard Henderson        tcg_out_movcond_br2(s, cond, ret, t, TCG_REG_ZERO,
1286a18d783eSRichard Henderson                            val1, c_val1, val2, c_val2);
1287a18d783eSRichard Henderson    }
1288a18d783eSRichard Henderson}
1289a18d783eSRichard Henderson
1290a30498fcSRichard Hendersonstatic void tcg_out_cltz(TCGContext *s, TCGType type, RISCVInsn insn,
1291a30498fcSRichard Henderson                         TCGReg ret, TCGReg src1, int src2, bool c_src2)
1292a30498fcSRichard Henderson{
1293a30498fcSRichard Henderson    tcg_out_opc_imm(s, insn, ret, src1, 0);
1294a30498fcSRichard Henderson
1295a30498fcSRichard Henderson    if (!c_src2 || src2 != (type == TCG_TYPE_I32 ? 32 : 64)) {
1296a30498fcSRichard Henderson        /*
1297a30498fcSRichard Henderson         * The requested zero result does not match the insn, so adjust.
1298a30498fcSRichard Henderson         * Note that constraints put 'ret' in a new register, so the
1299a30498fcSRichard Henderson         * computation above did not clobber either 'src1' or 'src2'.
1300a30498fcSRichard Henderson         */
1301a30498fcSRichard Henderson        tcg_out_movcond(s, TCG_COND_EQ, ret, src1, 0, true,
1302a30498fcSRichard Henderson                        src2, c_src2, ret, false);
1303a30498fcSRichard Henderson    }
1304a30498fcSRichard Henderson}
1305a30498fcSRichard Henderson
1306*f63e7089SHuang Shiyuanstatic void init_setting_vtype(TCGContext *s)
1307*f63e7089SHuang Shiyuan{
1308*f63e7089SHuang Shiyuan    s->riscv_cur_type = TCG_TYPE_COUNT;
1309*f63e7089SHuang Shiyuan}
1310*f63e7089SHuang Shiyuan
13112be7d76bSRichard Hendersonstatic void tcg_out_call_int(TCGContext *s, const tcg_insn_unit *arg, bool tail)
1312139c1837SPaolo Bonzini{
1313139c1837SPaolo Bonzini    TCGReg link = tail ? TCG_REG_ZERO : TCG_REG_RA;
1314139c1837SPaolo Bonzini    ptrdiff_t offset = tcg_pcrel_diff(s, arg);
1315139c1837SPaolo Bonzini    int ret;
1316139c1837SPaolo Bonzini
1317*f63e7089SHuang Shiyuan    init_setting_vtype(s);
1318*f63e7089SHuang Shiyuan
1319844d0442SRichard Henderson    tcg_debug_assert((offset & 1) == 0);
1320844d0442SRichard Henderson    if (offset == sextreg(offset, 0, 20)) {
1321139c1837SPaolo Bonzini        /* short jump: -2097150 to 2097152 */
1322139c1837SPaolo Bonzini        tcg_out_opc_jump(s, OPC_JAL, link, offset);
1323aeb6326eSRichard Henderson    } else if (offset == (int32_t)offset) {
1324139c1837SPaolo Bonzini        /* long jump: -2147483646 to 2147483648 */
1325139c1837SPaolo Bonzini        tcg_out_opc_upper(s, OPC_AUIPC, TCG_REG_TMP0, 0);
1326139c1837SPaolo Bonzini        tcg_out_opc_imm(s, OPC_JALR, link, TCG_REG_TMP0, 0);
1327844d0442SRichard Henderson        ret = reloc_call(s->code_ptr - 2, arg);
1328139c1837SPaolo Bonzini        tcg_debug_assert(ret == true);
1329aeb6326eSRichard Henderson    } else {
1330139c1837SPaolo Bonzini        /* far jump: 64-bit */
1331139c1837SPaolo Bonzini        tcg_target_long imm = sextreg((tcg_target_long)arg, 0, 12);
1332139c1837SPaolo Bonzini        tcg_target_long base = (tcg_target_long)arg - imm;
1333139c1837SPaolo Bonzini        tcg_out_movi(s, TCG_TYPE_PTR, TCG_REG_TMP0, base);
1334139c1837SPaolo Bonzini        tcg_out_opc_imm(s, OPC_JALR, link, TCG_REG_TMP0, imm);
1335139c1837SPaolo Bonzini    }
1336139c1837SPaolo Bonzini}
1337139c1837SPaolo Bonzini
1338cee44b03SRichard Hendersonstatic void tcg_out_call(TCGContext *s, const tcg_insn_unit *arg,
1339cee44b03SRichard Henderson                         const TCGHelperInfo *info)
1340139c1837SPaolo Bonzini{
1341139c1837SPaolo Bonzini    tcg_out_call_int(s, arg, false);
1342139c1837SPaolo Bonzini}
1343139c1837SPaolo Bonzini
1344139c1837SPaolo Bonzinistatic void tcg_out_mb(TCGContext *s, TCGArg a0)
1345139c1837SPaolo Bonzini{
1346139c1837SPaolo Bonzini    tcg_insn_unit insn = OPC_FENCE;
1347139c1837SPaolo Bonzini
1348139c1837SPaolo Bonzini    if (a0 & TCG_MO_LD_LD) {
1349139c1837SPaolo Bonzini        insn |= 0x02200000;
1350139c1837SPaolo Bonzini    }
1351139c1837SPaolo Bonzini    if (a0 & TCG_MO_ST_LD) {
1352139c1837SPaolo Bonzini        insn |= 0x01200000;
1353139c1837SPaolo Bonzini    }
1354139c1837SPaolo Bonzini    if (a0 & TCG_MO_LD_ST) {
1355139c1837SPaolo Bonzini        insn |= 0x02100000;
1356139c1837SPaolo Bonzini    }
1357139c1837SPaolo Bonzini    if (a0 & TCG_MO_ST_ST) {
1358139c1837SPaolo Bonzini        insn |= 0x02200000;
1359139c1837SPaolo Bonzini    }
1360139c1837SPaolo Bonzini    tcg_out32(s, insn);
1361139c1837SPaolo Bonzini}
1362139c1837SPaolo Bonzini
1363139c1837SPaolo Bonzini/*
1364139c1837SPaolo Bonzini * Load/store and TLB
1365139c1837SPaolo Bonzini */
1366139c1837SPaolo Bonzini
1367793f7381SRichard Hendersonstatic void tcg_out_goto(TCGContext *s, const tcg_insn_unit *target)
1368844d0442SRichard Henderson{
1369844d0442SRichard Henderson    tcg_out_opc_jump(s, OPC_JAL, TCG_REG_ZERO, 0);
1370844d0442SRichard Henderson    bool ok = reloc_jimm20(s->code_ptr - 1, target);
1371844d0442SRichard Henderson    tcg_debug_assert(ok);
1372844d0442SRichard Henderson}
1373844d0442SRichard Henderson
13747b880107SRichard Hendersonbool tcg_target_has_memory_bswap(MemOp memop)
13757b880107SRichard Henderson{
13767b880107SRichard Henderson    return false;
13777b880107SRichard Henderson}
13787b880107SRichard Henderson
137961b6daafSRichard Henderson/* We have three temps, we might as well expose them. */
138061b6daafSRichard Hendersonstatic const TCGLdstHelperParam ldst_helper_param = {
138161b6daafSRichard Henderson    .ntmp = 3, .tmp = { TCG_REG_TMP0, TCG_REG_TMP1, TCG_REG_TMP2 }
138261b6daafSRichard Henderson};
138361b6daafSRichard Henderson
1384139c1837SPaolo Bonzinistatic bool tcg_out_qemu_ld_slow_path(TCGContext *s, TCGLabelQemuLdst *l)
1385139c1837SPaolo Bonzini{
138661b6daafSRichard Henderson    MemOp opc = get_memop(l->oi);
1387139c1837SPaolo Bonzini
1388139c1837SPaolo Bonzini    /* resolve label address */
1389793f7381SRichard Henderson    if (!reloc_sbimm12(l->label_ptr[0], tcg_splitwx_to_rx(s->code_ptr))) {
1390139c1837SPaolo Bonzini        return false;
1391139c1837SPaolo Bonzini    }
1392139c1837SPaolo Bonzini
1393139c1837SPaolo Bonzini    /* call load helper */
139461b6daafSRichard Henderson    tcg_out_ld_helper_args(s, l, &ldst_helper_param);
1395cee44b03SRichard Henderson    tcg_out_call_int(s, qemu_ld_helpers[opc & MO_SSIZE], false);
139661b6daafSRichard Henderson    tcg_out_ld_helper_ret(s, l, true, &ldst_helper_param);
1397139c1837SPaolo Bonzini
1398139c1837SPaolo Bonzini    tcg_out_goto(s, l->raddr);
1399139c1837SPaolo Bonzini    return true;
1400139c1837SPaolo Bonzini}
1401139c1837SPaolo Bonzini
1402139c1837SPaolo Bonzinistatic bool tcg_out_qemu_st_slow_path(TCGContext *s, TCGLabelQemuLdst *l)
1403139c1837SPaolo Bonzini{
140461b6daafSRichard Henderson    MemOp opc = get_memop(l->oi);
1405139c1837SPaolo Bonzini
1406139c1837SPaolo Bonzini    /* resolve label address */
1407793f7381SRichard Henderson    if (!reloc_sbimm12(l->label_ptr[0], tcg_splitwx_to_rx(s->code_ptr))) {
1408139c1837SPaolo Bonzini        return false;
1409139c1837SPaolo Bonzini    }
1410139c1837SPaolo Bonzini
1411139c1837SPaolo Bonzini    /* call store helper */
141261b6daafSRichard Henderson    tcg_out_st_helper_args(s, l, &ldst_helper_param);
1413cee44b03SRichard Henderson    tcg_out_call_int(s, qemu_st_helpers[opc & MO_SIZE], false);
1414139c1837SPaolo Bonzini
1415139c1837SPaolo Bonzini    tcg_out_goto(s, l->raddr);
1416139c1837SPaolo Bonzini    return true;
1417139c1837SPaolo Bonzini}
1418139c1837SPaolo Bonzini
1419d0a9bb5eSRichard Henderson/* We expect to use a 12-bit negative offset from ENV.  */
1420d0a9bb5eSRichard Henderson#define MIN_TLB_MASK_TABLE_OFS  -(1 << 11)
1421d0a9bb5eSRichard Henderson
1422001dddfeSRichard Henderson/*
14237893e42dSPhilippe Mathieu-Daudé * For system-mode, perform the TLB load and compare.
14247893e42dSPhilippe Mathieu-Daudé * For user-mode, perform any required alignment tests.
1425001dddfeSRichard Henderson * In both cases, return a TCGLabelQemuLdst structure if the slow path
1426001dddfeSRichard Henderson * is required and fill in @h with the host address for the fast path.
1427001dddfeSRichard Henderson */
1428001dddfeSRichard Hendersonstatic TCGLabelQemuLdst *prepare_host_addr(TCGContext *s, TCGReg *pbase,
1429001dddfeSRichard Henderson                                           TCGReg addr_reg, MemOpIdx oi,
1430001dddfeSRichard Henderson                                           bool is_ld)
1431001dddfeSRichard Henderson{
14328aefe1fbSRichard Henderson    TCGType addr_type = s->addr_type;
1433001dddfeSRichard Henderson    TCGLabelQemuLdst *ldst = NULL;
1434001dddfeSRichard Henderson    MemOp opc = get_memop(oi);
143537e523f0SRichard Henderson    TCGAtomAlign aa;
143637e523f0SRichard Henderson    unsigned a_mask;
143737e523f0SRichard Henderson
143837e523f0SRichard Henderson    aa = atom_and_align_for_opc(s, opc, MO_ATOM_IFALIGN, false);
143937e523f0SRichard Henderson    a_mask = (1u << aa.align) - 1;
1440001dddfeSRichard Henderson
14414944d359SRichard Henderson    if (tcg_use_softmmu) {
1442001dddfeSRichard Henderson        unsigned s_bits = opc & MO_SIZE;
1443933b331bSRichard Henderson        unsigned s_mask = (1u << s_bits) - 1;
1444001dddfeSRichard Henderson        int mem_index = get_mmuidx(oi);
1445d0a9bb5eSRichard Henderson        int fast_ofs = tlb_mask_table_ofs(s, mem_index);
1446001dddfeSRichard Henderson        int mask_ofs = fast_ofs + offsetof(CPUTLBDescFast, mask);
1447001dddfeSRichard Henderson        int table_ofs = fast_ofs + offsetof(CPUTLBDescFast, table);
1448933b331bSRichard Henderson        int compare_mask;
1449933b331bSRichard Henderson        TCGReg addr_adj;
1450001dddfeSRichard Henderson
1451001dddfeSRichard Henderson        ldst = new_ldst_label(s);
1452001dddfeSRichard Henderson        ldst->is_ld = is_ld;
1453001dddfeSRichard Henderson        ldst->oi = oi;
1454001dddfeSRichard Henderson        ldst->addrlo_reg = addr_reg;
1455001dddfeSRichard Henderson
1456*f63e7089SHuang Shiyuan        init_setting_vtype(s);
1457*f63e7089SHuang Shiyuan
1458933b331bSRichard Henderson        tcg_out_ld(s, TCG_TYPE_PTR, TCG_REG_TMP0, TCG_AREG0, mask_ofs);
1459933b331bSRichard Henderson        tcg_out_ld(s, TCG_TYPE_PTR, TCG_REG_TMP1, TCG_AREG0, table_ofs);
1460001dddfeSRichard Henderson
1461001dddfeSRichard Henderson        tcg_out_opc_imm(s, OPC_SRLI, TCG_REG_TMP2, addr_reg,
1462aece72b7SRichard Henderson                        s->page_bits - CPU_TLB_ENTRY_BITS);
1463001dddfeSRichard Henderson        tcg_out_opc_reg(s, OPC_AND, TCG_REG_TMP2, TCG_REG_TMP2, TCG_REG_TMP0);
1464001dddfeSRichard Henderson        tcg_out_opc_reg(s, OPC_ADD, TCG_REG_TMP2, TCG_REG_TMP2, TCG_REG_TMP1);
1465001dddfeSRichard Henderson
1466933b331bSRichard Henderson        /*
14674944d359SRichard Henderson         * For aligned accesses, we check the first byte and include the
14684944d359SRichard Henderson         * alignment bits within the address.  For unaligned access, we
14694944d359SRichard Henderson         * check that we don't cross pages using the address of the last
14704944d359SRichard Henderson         * byte of the access.
1471933b331bSRichard Henderson         */
1472933b331bSRichard Henderson        addr_adj = addr_reg;
147337e523f0SRichard Henderson        if (a_mask < s_mask) {
1474933b331bSRichard Henderson            addr_adj = TCG_REG_TMP0;
14758aefe1fbSRichard Henderson            tcg_out_opc_imm(s, addr_type == TCG_TYPE_I32 ? OPC_ADDIW : OPC_ADDI,
1476933b331bSRichard Henderson                            addr_adj, addr_reg, s_mask - a_mask);
1477933b331bSRichard Henderson        }
1478aece72b7SRichard Henderson        compare_mask = s->page_mask | a_mask;
1479933b331bSRichard Henderson        if (compare_mask == sextreg(compare_mask, 0, 12)) {
1480933b331bSRichard Henderson            tcg_out_opc_imm(s, OPC_ANDI, TCG_REG_TMP1, addr_adj, compare_mask);
1481933b331bSRichard Henderson        } else {
14828aefe1fbSRichard Henderson            tcg_out_movi(s, addr_type, TCG_REG_TMP1, compare_mask);
1483933b331bSRichard Henderson            tcg_out_opc_reg(s, OPC_AND, TCG_REG_TMP1, TCG_REG_TMP1, addr_adj);
1484933b331bSRichard Henderson        }
1485933b331bSRichard Henderson
1486001dddfeSRichard Henderson        /* Load the tlb comparator and the addend.  */
1487238f4380SRichard Henderson        QEMU_BUILD_BUG_ON(HOST_BIG_ENDIAN);
14888aefe1fbSRichard Henderson        tcg_out_ld(s, addr_type, TCG_REG_TMP0, TCG_REG_TMP2,
1489001dddfeSRichard Henderson                   is_ld ? offsetof(CPUTLBEntry, addr_read)
1490001dddfeSRichard Henderson                         : offsetof(CPUTLBEntry, addr_write));
1491001dddfeSRichard Henderson        tcg_out_ld(s, TCG_TYPE_PTR, TCG_REG_TMP2, TCG_REG_TMP2,
1492001dddfeSRichard Henderson                   offsetof(CPUTLBEntry, addend));
1493001dddfeSRichard Henderson
1494001dddfeSRichard Henderson        /* Compare masked address with the TLB entry. */
1495001dddfeSRichard Henderson        ldst->label_ptr[0] = s->code_ptr;
1496001dddfeSRichard Henderson        tcg_out_opc_branch(s, OPC_BNE, TCG_REG_TMP0, TCG_REG_TMP1, 0);
1497001dddfeSRichard Henderson
1498001dddfeSRichard Henderson        /* TLB Hit - translate address using addend.  */
14998aefe1fbSRichard Henderson        if (addr_type != TCG_TYPE_I32) {
1500eda15159SRichard Henderson            tcg_out_opc_reg(s, OPC_ADD, TCG_REG_TMP0, addr_reg, TCG_REG_TMP2);
1501b86c6ba6SRichard Henderson        } else if (cpuinfo & CPUINFO_ZBA) {
15024944d359SRichard Henderson            tcg_out_opc_reg(s, OPC_ADD_UW, TCG_REG_TMP0,
15034944d359SRichard Henderson                            addr_reg, TCG_REG_TMP2);
1504eda15159SRichard Henderson        } else {
1505eda15159SRichard Henderson            tcg_out_ext32u(s, TCG_REG_TMP0, addr_reg);
15064944d359SRichard Henderson            tcg_out_opc_reg(s, OPC_ADD, TCG_REG_TMP0,
15074944d359SRichard Henderson                            TCG_REG_TMP0, TCG_REG_TMP2);
1508001dddfeSRichard Henderson        }
1509001dddfeSRichard Henderson        *pbase = TCG_REG_TMP0;
15104944d359SRichard Henderson    } else {
1511eda15159SRichard Henderson        TCGReg base;
1512eda15159SRichard Henderson
1513001dddfeSRichard Henderson        if (a_mask) {
1514001dddfeSRichard Henderson            ldst = new_ldst_label(s);
1515001dddfeSRichard Henderson            ldst->is_ld = is_ld;
1516001dddfeSRichard Henderson            ldst->oi = oi;
1517001dddfeSRichard Henderson            ldst->addrlo_reg = addr_reg;
1518001dddfeSRichard Henderson
1519*f63e7089SHuang Shiyuan            init_setting_vtype(s);
1520*f63e7089SHuang Shiyuan
152137e523f0SRichard Henderson            /* We are expecting alignment max 7, so we can always use andi. */
152237e523f0SRichard Henderson            tcg_debug_assert(a_mask == sextreg(a_mask, 0, 12));
1523001dddfeSRichard Henderson            tcg_out_opc_imm(s, OPC_ANDI, TCG_REG_TMP1, addr_reg, a_mask);
1524001dddfeSRichard Henderson
1525001dddfeSRichard Henderson            ldst->label_ptr[0] = s->code_ptr;
1526001dddfeSRichard Henderson            tcg_out_opc_branch(s, OPC_BNE, TCG_REG_TMP1, TCG_REG_ZERO, 0);
1527001dddfeSRichard Henderson        }
1528001dddfeSRichard Henderson
1529001dddfeSRichard Henderson        if (guest_base != 0) {
1530001dddfeSRichard Henderson            base = TCG_REG_TMP0;
15318aefe1fbSRichard Henderson            if (addr_type != TCG_TYPE_I32) {
15324944d359SRichard Henderson                tcg_out_opc_reg(s, OPC_ADD, base, addr_reg,
15334944d359SRichard Henderson                                TCG_GUEST_BASE_REG);
1534b86c6ba6SRichard Henderson            } else if (cpuinfo & CPUINFO_ZBA) {
15354944d359SRichard Henderson                tcg_out_opc_reg(s, OPC_ADD_UW, base, addr_reg,
15364944d359SRichard Henderson                                TCG_GUEST_BASE_REG);
1537eda15159SRichard Henderson            } else {
1538eda15159SRichard Henderson                tcg_out_ext32u(s, base, addr_reg);
1539eda15159SRichard Henderson                tcg_out_opc_reg(s, OPC_ADD, base, base, TCG_GUEST_BASE_REG);
1540eda15159SRichard Henderson            }
15418aefe1fbSRichard Henderson        } else if (addr_type != TCG_TYPE_I32) {
1542eda15159SRichard Henderson            base = addr_reg;
1543eda15159SRichard Henderson        } else {
1544eda15159SRichard Henderson            base = TCG_REG_TMP0;
1545eda15159SRichard Henderson            tcg_out_ext32u(s, base, addr_reg);
1546001dddfeSRichard Henderson        }
1547001dddfeSRichard Henderson        *pbase = base;
15484944d359SRichard Henderson    }
1549001dddfeSRichard Henderson
1550001dddfeSRichard Henderson    return ldst;
1551001dddfeSRichard Henderson}
1552001dddfeSRichard Henderson
1553aeb6326eSRichard Hendersonstatic void tcg_out_qemu_ld_direct(TCGContext *s, TCGReg val,
1554f7041977SRichard Henderson                                   TCGReg base, MemOp opc, TCGType type)
1555139c1837SPaolo Bonzini{
1556c86bd2dcSRichard Henderson    /* Byte swapping is left to middle-end expansion. */
1557c86bd2dcSRichard Henderson    tcg_debug_assert((opc & MO_BSWAP) == 0);
1558139c1837SPaolo Bonzini
1559139c1837SPaolo Bonzini    switch (opc & (MO_SSIZE)) {
1560139c1837SPaolo Bonzini    case MO_UB:
1561aeb6326eSRichard Henderson        tcg_out_opc_imm(s, OPC_LBU, val, base, 0);
1562139c1837SPaolo Bonzini        break;
1563139c1837SPaolo Bonzini    case MO_SB:
1564aeb6326eSRichard Henderson        tcg_out_opc_imm(s, OPC_LB, val, base, 0);
1565139c1837SPaolo Bonzini        break;
1566139c1837SPaolo Bonzini    case MO_UW:
1567aeb6326eSRichard Henderson        tcg_out_opc_imm(s, OPC_LHU, val, base, 0);
1568139c1837SPaolo Bonzini        break;
1569139c1837SPaolo Bonzini    case MO_SW:
1570aeb6326eSRichard Henderson        tcg_out_opc_imm(s, OPC_LH, val, base, 0);
1571139c1837SPaolo Bonzini        break;
1572139c1837SPaolo Bonzini    case MO_UL:
1573f7041977SRichard Henderson        if (type == TCG_TYPE_I64) {
1574aeb6326eSRichard Henderson            tcg_out_opc_imm(s, OPC_LWU, val, base, 0);
1575139c1837SPaolo Bonzini            break;
1576139c1837SPaolo Bonzini        }
1577139c1837SPaolo Bonzini        /* FALLTHRU */
1578139c1837SPaolo Bonzini    case MO_SL:
1579aeb6326eSRichard Henderson        tcg_out_opc_imm(s, OPC_LW, val, base, 0);
1580139c1837SPaolo Bonzini        break;
1581fc313c64SFrédéric Pétrot    case MO_UQ:
1582aeb6326eSRichard Henderson        tcg_out_opc_imm(s, OPC_LD, val, base, 0);
1583139c1837SPaolo Bonzini        break;
1584139c1837SPaolo Bonzini    default:
1585139c1837SPaolo Bonzini        g_assert_not_reached();
1586139c1837SPaolo Bonzini    }
1587139c1837SPaolo Bonzini}
1588139c1837SPaolo Bonzini
1589f7041977SRichard Hendersonstatic void tcg_out_qemu_ld(TCGContext *s, TCGReg data_reg, TCGReg addr_reg,
1590f7041977SRichard Henderson                            MemOpIdx oi, TCGType data_type)
1591139c1837SPaolo Bonzini{
1592001dddfeSRichard Henderson    TCGLabelQemuLdst *ldst;
15932e3a933aSRichard Henderson    TCGReg base;
1594139c1837SPaolo Bonzini
1595001dddfeSRichard Henderson    ldst = prepare_host_addr(s, &base, addr_reg, oi, true);
1596001dddfeSRichard Henderson    tcg_out_qemu_ld_direct(s, data_reg, base, get_memop(oi), data_type);
1597f7041977SRichard Henderson
1598001dddfeSRichard Henderson    if (ldst) {
1599001dddfeSRichard Henderson        ldst->type = data_type;
1600001dddfeSRichard Henderson        ldst->datalo_reg = data_reg;
1601001dddfeSRichard Henderson        ldst->raddr = tcg_splitwx_to_rx(s->code_ptr);
1602a3fb7c99SRichard Henderson    }
1603139c1837SPaolo Bonzini}
1604139c1837SPaolo Bonzini
1605aeb6326eSRichard Hendersonstatic void tcg_out_qemu_st_direct(TCGContext *s, TCGReg val,
1606139c1837SPaolo Bonzini                                   TCGReg base, MemOp opc)
1607139c1837SPaolo Bonzini{
1608c86bd2dcSRichard Henderson    /* Byte swapping is left to middle-end expansion. */
1609c86bd2dcSRichard Henderson    tcg_debug_assert((opc & MO_BSWAP) == 0);
1610139c1837SPaolo Bonzini
1611139c1837SPaolo Bonzini    switch (opc & (MO_SSIZE)) {
1612139c1837SPaolo Bonzini    case MO_8:
1613aeb6326eSRichard Henderson        tcg_out_opc_store(s, OPC_SB, base, val, 0);
1614139c1837SPaolo Bonzini        break;
1615139c1837SPaolo Bonzini    case MO_16:
1616aeb6326eSRichard Henderson        tcg_out_opc_store(s, OPC_SH, base, val, 0);
1617139c1837SPaolo Bonzini        break;
1618139c1837SPaolo Bonzini    case MO_32:
1619aeb6326eSRichard Henderson        tcg_out_opc_store(s, OPC_SW, base, val, 0);
1620139c1837SPaolo Bonzini        break;
1621139c1837SPaolo Bonzini    case MO_64:
1622aeb6326eSRichard Henderson        tcg_out_opc_store(s, OPC_SD, base, val, 0);
1623139c1837SPaolo Bonzini        break;
1624139c1837SPaolo Bonzini    default:
1625139c1837SPaolo Bonzini        g_assert_not_reached();
1626139c1837SPaolo Bonzini    }
1627139c1837SPaolo Bonzini}
1628139c1837SPaolo Bonzini
1629f7041977SRichard Hendersonstatic void tcg_out_qemu_st(TCGContext *s, TCGReg data_reg, TCGReg addr_reg,
1630f7041977SRichard Henderson                            MemOpIdx oi, TCGType data_type)
1631139c1837SPaolo Bonzini{
1632001dddfeSRichard Henderson    TCGLabelQemuLdst *ldst;
16332e3a933aSRichard Henderson    TCGReg base;
1634139c1837SPaolo Bonzini
1635001dddfeSRichard Henderson    ldst = prepare_host_addr(s, &base, addr_reg, oi, false);
1636001dddfeSRichard Henderson    tcg_out_qemu_st_direct(s, data_reg, base, get_memop(oi));
1637f7041977SRichard Henderson
1638001dddfeSRichard Henderson    if (ldst) {
1639001dddfeSRichard Henderson        ldst->type = data_type;
1640001dddfeSRichard Henderson        ldst->datalo_reg = data_reg;
1641001dddfeSRichard Henderson        ldst->raddr = tcg_splitwx_to_rx(s->code_ptr);
1642a3fb7c99SRichard Henderson    }
1643139c1837SPaolo Bonzini}
1644139c1837SPaolo Bonzini
1645793f7381SRichard Hendersonstatic const tcg_insn_unit *tb_ret_addr;
1646139c1837SPaolo Bonzini
1647b55a8d9dSRichard Hendersonstatic void tcg_out_exit_tb(TCGContext *s, uintptr_t a0)
1648b55a8d9dSRichard Henderson{
1649b55a8d9dSRichard Henderson    /* Reuse the zeroing that exists for goto_ptr.  */
1650b55a8d9dSRichard Henderson    if (a0 == 0) {
1651b55a8d9dSRichard Henderson        tcg_out_call_int(s, tcg_code_gen_epilogue, true);
1652b55a8d9dSRichard Henderson    } else {
1653b55a8d9dSRichard Henderson        tcg_out_movi(s, TCG_TYPE_PTR, TCG_REG_A0, a0);
1654b55a8d9dSRichard Henderson        tcg_out_call_int(s, tb_ret_addr, true);
1655b55a8d9dSRichard Henderson    }
1656b55a8d9dSRichard Henderson}
1657b55a8d9dSRichard Henderson
1658cf7d6b8eSRichard Hendersonstatic void tcg_out_goto_tb(TCGContext *s, int which)
1659cf7d6b8eSRichard Henderson{
1660493c9b19SRichard Henderson    /* Direct branch will be patched by tb_target_set_jmp_target. */
1661493c9b19SRichard Henderson    set_jmp_insn_offset(s, which);
1662493c9b19SRichard Henderson    tcg_out32(s, OPC_JAL);
1663493c9b19SRichard Henderson
1664493c9b19SRichard Henderson    /* When branch is out of range, fall through to indirect. */
1665cf7d6b8eSRichard Henderson    tcg_out_ld(s, TCG_TYPE_PTR, TCG_REG_TMP0, TCG_REG_ZERO,
1666cf7d6b8eSRichard Henderson               get_jmp_target_addr(s, which));
1667cf7d6b8eSRichard Henderson    tcg_out_opc_imm(s, OPC_JALR, TCG_REG_ZERO, TCG_REG_TMP0, 0);
1668cf7d6b8eSRichard Henderson    set_jmp_reset_offset(s, which);
1669cf7d6b8eSRichard Henderson}
1670cf7d6b8eSRichard Henderson
167190c0fee3SRichard Hendersonvoid tb_target_set_jmp_target(const TranslationBlock *tb, int n,
167290c0fee3SRichard Henderson                              uintptr_t jmp_rx, uintptr_t jmp_rw)
167390c0fee3SRichard Henderson{
1674493c9b19SRichard Henderson    uintptr_t addr = tb->jmp_target_addr[n];
1675493c9b19SRichard Henderson    ptrdiff_t offset = addr - jmp_rx;
1676493c9b19SRichard Henderson    tcg_insn_unit insn;
1677493c9b19SRichard Henderson
1678493c9b19SRichard Henderson    /* Either directly branch, or fall through to indirect branch. */
1679493c9b19SRichard Henderson    if (offset == sextreg(offset, 0, 20)) {
1680493c9b19SRichard Henderson        insn = encode_uj(OPC_JAL, TCG_REG_ZERO, offset);
1681493c9b19SRichard Henderson    } else {
1682493c9b19SRichard Henderson        insn = OPC_NOP;
1683493c9b19SRichard Henderson    }
1684493c9b19SRichard Henderson    qatomic_set((uint32_t *)jmp_rw, insn);
1685493c9b19SRichard Henderson    flush_idcache_range(jmp_rx, jmp_rw, 4);
168690c0fee3SRichard Henderson}
168790c0fee3SRichard Henderson
1688139c1837SPaolo Bonzinistatic void tcg_out_op(TCGContext *s, TCGOpcode opc,
16895e8892dbSMiroslav Rezanina                       const TCGArg args[TCG_MAX_OP_ARGS],
16905e8892dbSMiroslav Rezanina                       const int const_args[TCG_MAX_OP_ARGS])
1691139c1837SPaolo Bonzini{
1692139c1837SPaolo Bonzini    TCGArg a0 = args[0];
1693139c1837SPaolo Bonzini    TCGArg a1 = args[1];
1694139c1837SPaolo Bonzini    TCGArg a2 = args[2];
1695139c1837SPaolo Bonzini    int c2 = const_args[2];
1696139c1837SPaolo Bonzini
1697139c1837SPaolo Bonzini    switch (opc) {
1698139c1837SPaolo Bonzini    case INDEX_op_goto_ptr:
1699139c1837SPaolo Bonzini        tcg_out_opc_imm(s, OPC_JALR, TCG_REG_ZERO, a0, 0);
1700139c1837SPaolo Bonzini        break;
1701139c1837SPaolo Bonzini
1702139c1837SPaolo Bonzini    case INDEX_op_br:
1703139c1837SPaolo Bonzini        tcg_out_reloc(s, s->code_ptr, R_RISCV_JAL, arg_label(a0), 0);
1704139c1837SPaolo Bonzini        tcg_out_opc_jump(s, OPC_JAL, TCG_REG_ZERO, 0);
1705139c1837SPaolo Bonzini        break;
1706139c1837SPaolo Bonzini
1707139c1837SPaolo Bonzini    case INDEX_op_ld8u_i32:
1708139c1837SPaolo Bonzini    case INDEX_op_ld8u_i64:
1709139c1837SPaolo Bonzini        tcg_out_ldst(s, OPC_LBU, a0, a1, a2);
1710139c1837SPaolo Bonzini        break;
1711139c1837SPaolo Bonzini    case INDEX_op_ld8s_i32:
1712139c1837SPaolo Bonzini    case INDEX_op_ld8s_i64:
1713139c1837SPaolo Bonzini        tcg_out_ldst(s, OPC_LB, a0, a1, a2);
1714139c1837SPaolo Bonzini        break;
1715139c1837SPaolo Bonzini    case INDEX_op_ld16u_i32:
1716139c1837SPaolo Bonzini    case INDEX_op_ld16u_i64:
1717139c1837SPaolo Bonzini        tcg_out_ldst(s, OPC_LHU, a0, a1, a2);
1718139c1837SPaolo Bonzini        break;
1719139c1837SPaolo Bonzini    case INDEX_op_ld16s_i32:
1720139c1837SPaolo Bonzini    case INDEX_op_ld16s_i64:
1721139c1837SPaolo Bonzini        tcg_out_ldst(s, OPC_LH, a0, a1, a2);
1722139c1837SPaolo Bonzini        break;
1723139c1837SPaolo Bonzini    case INDEX_op_ld32u_i64:
1724139c1837SPaolo Bonzini        tcg_out_ldst(s, OPC_LWU, a0, a1, a2);
1725139c1837SPaolo Bonzini        break;
1726139c1837SPaolo Bonzini    case INDEX_op_ld_i32:
1727139c1837SPaolo Bonzini    case INDEX_op_ld32s_i64:
1728139c1837SPaolo Bonzini        tcg_out_ldst(s, OPC_LW, a0, a1, a2);
1729139c1837SPaolo Bonzini        break;
1730139c1837SPaolo Bonzini    case INDEX_op_ld_i64:
1731139c1837SPaolo Bonzini        tcg_out_ldst(s, OPC_LD, a0, a1, a2);
1732139c1837SPaolo Bonzini        break;
1733139c1837SPaolo Bonzini
1734139c1837SPaolo Bonzini    case INDEX_op_st8_i32:
1735139c1837SPaolo Bonzini    case INDEX_op_st8_i64:
1736139c1837SPaolo Bonzini        tcg_out_ldst(s, OPC_SB, a0, a1, a2);
1737139c1837SPaolo Bonzini        break;
1738139c1837SPaolo Bonzini    case INDEX_op_st16_i32:
1739139c1837SPaolo Bonzini    case INDEX_op_st16_i64:
1740139c1837SPaolo Bonzini        tcg_out_ldst(s, OPC_SH, a0, a1, a2);
1741139c1837SPaolo Bonzini        break;
1742139c1837SPaolo Bonzini    case INDEX_op_st_i32:
1743139c1837SPaolo Bonzini    case INDEX_op_st32_i64:
1744139c1837SPaolo Bonzini        tcg_out_ldst(s, OPC_SW, a0, a1, a2);
1745139c1837SPaolo Bonzini        break;
1746139c1837SPaolo Bonzini    case INDEX_op_st_i64:
1747139c1837SPaolo Bonzini        tcg_out_ldst(s, OPC_SD, a0, a1, a2);
1748139c1837SPaolo Bonzini        break;
1749139c1837SPaolo Bonzini
1750139c1837SPaolo Bonzini    case INDEX_op_add_i32:
1751139c1837SPaolo Bonzini        if (c2) {
1752139c1837SPaolo Bonzini            tcg_out_opc_imm(s, OPC_ADDIW, a0, a1, a2);
1753139c1837SPaolo Bonzini        } else {
1754139c1837SPaolo Bonzini            tcg_out_opc_reg(s, OPC_ADDW, a0, a1, a2);
1755139c1837SPaolo Bonzini        }
1756139c1837SPaolo Bonzini        break;
1757139c1837SPaolo Bonzini    case INDEX_op_add_i64:
1758139c1837SPaolo Bonzini        if (c2) {
1759139c1837SPaolo Bonzini            tcg_out_opc_imm(s, OPC_ADDI, a0, a1, a2);
1760139c1837SPaolo Bonzini        } else {
1761139c1837SPaolo Bonzini            tcg_out_opc_reg(s, OPC_ADD, a0, a1, a2);
1762139c1837SPaolo Bonzini        }
1763139c1837SPaolo Bonzini        break;
1764139c1837SPaolo Bonzini
1765139c1837SPaolo Bonzini    case INDEX_op_sub_i32:
1766139c1837SPaolo Bonzini        if (c2) {
1767139c1837SPaolo Bonzini            tcg_out_opc_imm(s, OPC_ADDIW, a0, a1, -a2);
1768139c1837SPaolo Bonzini        } else {
1769139c1837SPaolo Bonzini            tcg_out_opc_reg(s, OPC_SUBW, a0, a1, a2);
1770139c1837SPaolo Bonzini        }
1771139c1837SPaolo Bonzini        break;
1772139c1837SPaolo Bonzini    case INDEX_op_sub_i64:
1773139c1837SPaolo Bonzini        if (c2) {
1774139c1837SPaolo Bonzini            tcg_out_opc_imm(s, OPC_ADDI, a0, a1, -a2);
1775139c1837SPaolo Bonzini        } else {
1776139c1837SPaolo Bonzini            tcg_out_opc_reg(s, OPC_SUB, a0, a1, a2);
1777139c1837SPaolo Bonzini        }
1778139c1837SPaolo Bonzini        break;
1779139c1837SPaolo Bonzini
1780139c1837SPaolo Bonzini    case INDEX_op_and_i32:
1781139c1837SPaolo Bonzini    case INDEX_op_and_i64:
1782139c1837SPaolo Bonzini        if (c2) {
1783139c1837SPaolo Bonzini            tcg_out_opc_imm(s, OPC_ANDI, a0, a1, a2);
1784139c1837SPaolo Bonzini        } else {
1785139c1837SPaolo Bonzini            tcg_out_opc_reg(s, OPC_AND, a0, a1, a2);
1786139c1837SPaolo Bonzini        }
1787139c1837SPaolo Bonzini        break;
1788139c1837SPaolo Bonzini
1789139c1837SPaolo Bonzini    case INDEX_op_or_i32:
1790139c1837SPaolo Bonzini    case INDEX_op_or_i64:
1791139c1837SPaolo Bonzini        if (c2) {
1792139c1837SPaolo Bonzini            tcg_out_opc_imm(s, OPC_ORI, a0, a1, a2);
1793139c1837SPaolo Bonzini        } else {
1794139c1837SPaolo Bonzini            tcg_out_opc_reg(s, OPC_OR, a0, a1, a2);
1795139c1837SPaolo Bonzini        }
1796139c1837SPaolo Bonzini        break;
1797139c1837SPaolo Bonzini
1798139c1837SPaolo Bonzini    case INDEX_op_xor_i32:
1799139c1837SPaolo Bonzini    case INDEX_op_xor_i64:
1800139c1837SPaolo Bonzini        if (c2) {
1801139c1837SPaolo Bonzini            tcg_out_opc_imm(s, OPC_XORI, a0, a1, a2);
1802139c1837SPaolo Bonzini        } else {
1803139c1837SPaolo Bonzini            tcg_out_opc_reg(s, OPC_XOR, a0, a1, a2);
1804139c1837SPaolo Bonzini        }
1805139c1837SPaolo Bonzini        break;
1806139c1837SPaolo Bonzini
180799f4ec6eSRichard Henderson    case INDEX_op_andc_i32:
180899f4ec6eSRichard Henderson    case INDEX_op_andc_i64:
180999f4ec6eSRichard Henderson        if (c2) {
181099f4ec6eSRichard Henderson            tcg_out_opc_imm(s, OPC_ANDI, a0, a1, ~a2);
181199f4ec6eSRichard Henderson        } else {
181299f4ec6eSRichard Henderson            tcg_out_opc_reg(s, OPC_ANDN, a0, a1, a2);
181399f4ec6eSRichard Henderson        }
181499f4ec6eSRichard Henderson        break;
181599f4ec6eSRichard Henderson    case INDEX_op_orc_i32:
181699f4ec6eSRichard Henderson    case INDEX_op_orc_i64:
181799f4ec6eSRichard Henderson        if (c2) {
181899f4ec6eSRichard Henderson            tcg_out_opc_imm(s, OPC_ORI, a0, a1, ~a2);
181999f4ec6eSRichard Henderson        } else {
182099f4ec6eSRichard Henderson            tcg_out_opc_reg(s, OPC_ORN, a0, a1, a2);
182199f4ec6eSRichard Henderson        }
182299f4ec6eSRichard Henderson        break;
182399f4ec6eSRichard Henderson    case INDEX_op_eqv_i32:
182499f4ec6eSRichard Henderson    case INDEX_op_eqv_i64:
182599f4ec6eSRichard Henderson        if (c2) {
182699f4ec6eSRichard Henderson            tcg_out_opc_imm(s, OPC_XORI, a0, a1, ~a2);
182799f4ec6eSRichard Henderson        } else {
182899f4ec6eSRichard Henderson            tcg_out_opc_reg(s, OPC_XNOR, a0, a1, a2);
182999f4ec6eSRichard Henderson        }
183099f4ec6eSRichard Henderson        break;
183199f4ec6eSRichard Henderson
1832139c1837SPaolo Bonzini    case INDEX_op_not_i32:
1833139c1837SPaolo Bonzini    case INDEX_op_not_i64:
1834139c1837SPaolo Bonzini        tcg_out_opc_imm(s, OPC_XORI, a0, a1, -1);
1835139c1837SPaolo Bonzini        break;
1836139c1837SPaolo Bonzini
1837139c1837SPaolo Bonzini    case INDEX_op_neg_i32:
1838139c1837SPaolo Bonzini        tcg_out_opc_reg(s, OPC_SUBW, a0, TCG_REG_ZERO, a1);
1839139c1837SPaolo Bonzini        break;
1840139c1837SPaolo Bonzini    case INDEX_op_neg_i64:
1841139c1837SPaolo Bonzini        tcg_out_opc_reg(s, OPC_SUB, a0, TCG_REG_ZERO, a1);
1842139c1837SPaolo Bonzini        break;
1843139c1837SPaolo Bonzini
1844139c1837SPaolo Bonzini    case INDEX_op_mul_i32:
1845139c1837SPaolo Bonzini        tcg_out_opc_reg(s, OPC_MULW, a0, a1, a2);
1846139c1837SPaolo Bonzini        break;
1847139c1837SPaolo Bonzini    case INDEX_op_mul_i64:
1848139c1837SPaolo Bonzini        tcg_out_opc_reg(s, OPC_MUL, a0, a1, a2);
1849139c1837SPaolo Bonzini        break;
1850139c1837SPaolo Bonzini
1851139c1837SPaolo Bonzini    case INDEX_op_div_i32:
1852139c1837SPaolo Bonzini        tcg_out_opc_reg(s, OPC_DIVW, a0, a1, a2);
1853139c1837SPaolo Bonzini        break;
1854139c1837SPaolo Bonzini    case INDEX_op_div_i64:
1855139c1837SPaolo Bonzini        tcg_out_opc_reg(s, OPC_DIV, a0, a1, a2);
1856139c1837SPaolo Bonzini        break;
1857139c1837SPaolo Bonzini
1858139c1837SPaolo Bonzini    case INDEX_op_divu_i32:
1859139c1837SPaolo Bonzini        tcg_out_opc_reg(s, OPC_DIVUW, a0, a1, a2);
1860139c1837SPaolo Bonzini        break;
1861139c1837SPaolo Bonzini    case INDEX_op_divu_i64:
1862139c1837SPaolo Bonzini        tcg_out_opc_reg(s, OPC_DIVU, a0, a1, a2);
1863139c1837SPaolo Bonzini        break;
1864139c1837SPaolo Bonzini
1865139c1837SPaolo Bonzini    case INDEX_op_rem_i32:
1866139c1837SPaolo Bonzini        tcg_out_opc_reg(s, OPC_REMW, a0, a1, a2);
1867139c1837SPaolo Bonzini        break;
1868139c1837SPaolo Bonzini    case INDEX_op_rem_i64:
1869139c1837SPaolo Bonzini        tcg_out_opc_reg(s, OPC_REM, a0, a1, a2);
1870139c1837SPaolo Bonzini        break;
1871139c1837SPaolo Bonzini
1872139c1837SPaolo Bonzini    case INDEX_op_remu_i32:
1873139c1837SPaolo Bonzini        tcg_out_opc_reg(s, OPC_REMUW, a0, a1, a2);
1874139c1837SPaolo Bonzini        break;
1875139c1837SPaolo Bonzini    case INDEX_op_remu_i64:
1876139c1837SPaolo Bonzini        tcg_out_opc_reg(s, OPC_REMU, a0, a1, a2);
1877139c1837SPaolo Bonzini        break;
1878139c1837SPaolo Bonzini
1879139c1837SPaolo Bonzini    case INDEX_op_shl_i32:
1880139c1837SPaolo Bonzini        if (c2) {
1881d2f3066eSZihao Yu            tcg_out_opc_imm(s, OPC_SLLIW, a0, a1, a2 & 0x1f);
1882139c1837SPaolo Bonzini        } else {
1883139c1837SPaolo Bonzini            tcg_out_opc_reg(s, OPC_SLLW, a0, a1, a2);
1884139c1837SPaolo Bonzini        }
1885139c1837SPaolo Bonzini        break;
1886139c1837SPaolo Bonzini    case INDEX_op_shl_i64:
1887139c1837SPaolo Bonzini        if (c2) {
1888d2f3066eSZihao Yu            tcg_out_opc_imm(s, OPC_SLLI, a0, a1, a2 & 0x3f);
1889139c1837SPaolo Bonzini        } else {
1890139c1837SPaolo Bonzini            tcg_out_opc_reg(s, OPC_SLL, a0, a1, a2);
1891139c1837SPaolo Bonzini        }
1892139c1837SPaolo Bonzini        break;
1893139c1837SPaolo Bonzini
1894139c1837SPaolo Bonzini    case INDEX_op_shr_i32:
1895139c1837SPaolo Bonzini        if (c2) {
1896d2f3066eSZihao Yu            tcg_out_opc_imm(s, OPC_SRLIW, a0, a1, a2 & 0x1f);
1897139c1837SPaolo Bonzini        } else {
1898139c1837SPaolo Bonzini            tcg_out_opc_reg(s, OPC_SRLW, a0, a1, a2);
1899139c1837SPaolo Bonzini        }
1900139c1837SPaolo Bonzini        break;
1901139c1837SPaolo Bonzini    case INDEX_op_shr_i64:
1902139c1837SPaolo Bonzini        if (c2) {
1903d2f3066eSZihao Yu            tcg_out_opc_imm(s, OPC_SRLI, a0, a1, a2 & 0x3f);
1904139c1837SPaolo Bonzini        } else {
1905139c1837SPaolo Bonzini            tcg_out_opc_reg(s, OPC_SRL, a0, a1, a2);
1906139c1837SPaolo Bonzini        }
1907139c1837SPaolo Bonzini        break;
1908139c1837SPaolo Bonzini
1909139c1837SPaolo Bonzini    case INDEX_op_sar_i32:
1910139c1837SPaolo Bonzini        if (c2) {
1911d2f3066eSZihao Yu            tcg_out_opc_imm(s, OPC_SRAIW, a0, a1, a2 & 0x1f);
1912139c1837SPaolo Bonzini        } else {
1913139c1837SPaolo Bonzini            tcg_out_opc_reg(s, OPC_SRAW, a0, a1, a2);
1914139c1837SPaolo Bonzini        }
1915139c1837SPaolo Bonzini        break;
1916139c1837SPaolo Bonzini    case INDEX_op_sar_i64:
1917139c1837SPaolo Bonzini        if (c2) {
1918d2f3066eSZihao Yu            tcg_out_opc_imm(s, OPC_SRAI, a0, a1, a2 & 0x3f);
1919139c1837SPaolo Bonzini        } else {
1920139c1837SPaolo Bonzini            tcg_out_opc_reg(s, OPC_SRA, a0, a1, a2);
1921139c1837SPaolo Bonzini        }
1922139c1837SPaolo Bonzini        break;
1923139c1837SPaolo Bonzini
192419d016adSRichard Henderson    case INDEX_op_rotl_i32:
192519d016adSRichard Henderson        if (c2) {
192619d016adSRichard Henderson            tcg_out_opc_imm(s, OPC_RORIW, a0, a1, -a2 & 0x1f);
192719d016adSRichard Henderson        } else {
192819d016adSRichard Henderson            tcg_out_opc_reg(s, OPC_ROLW, a0, a1, a2);
192919d016adSRichard Henderson        }
193019d016adSRichard Henderson        break;
193119d016adSRichard Henderson    case INDEX_op_rotl_i64:
193219d016adSRichard Henderson        if (c2) {
193319d016adSRichard Henderson            tcg_out_opc_imm(s, OPC_RORI, a0, a1, -a2 & 0x3f);
193419d016adSRichard Henderson        } else {
193519d016adSRichard Henderson            tcg_out_opc_reg(s, OPC_ROL, a0, a1, a2);
193619d016adSRichard Henderson        }
193719d016adSRichard Henderson        break;
193819d016adSRichard Henderson
193919d016adSRichard Henderson    case INDEX_op_rotr_i32:
194019d016adSRichard Henderson        if (c2) {
194119d016adSRichard Henderson            tcg_out_opc_imm(s, OPC_RORIW, a0, a1, a2 & 0x1f);
194219d016adSRichard Henderson        } else {
194319d016adSRichard Henderson            tcg_out_opc_reg(s, OPC_RORW, a0, a1, a2);
194419d016adSRichard Henderson        }
194519d016adSRichard Henderson        break;
194619d016adSRichard Henderson    case INDEX_op_rotr_i64:
194719d016adSRichard Henderson        if (c2) {
194819d016adSRichard Henderson            tcg_out_opc_imm(s, OPC_RORI, a0, a1, a2 & 0x3f);
194919d016adSRichard Henderson        } else {
195019d016adSRichard Henderson            tcg_out_opc_reg(s, OPC_ROR, a0, a1, a2);
195119d016adSRichard Henderson        }
195219d016adSRichard Henderson        break;
195319d016adSRichard Henderson
19547b4d5274SRichard Henderson    case INDEX_op_bswap64_i64:
19557b4d5274SRichard Henderson        tcg_out_opc_imm(s, OPC_REV8, a0, a1, 0);
19567b4d5274SRichard Henderson        break;
19577b4d5274SRichard Henderson    case INDEX_op_bswap32_i32:
19587b4d5274SRichard Henderson        a2 = 0;
19597b4d5274SRichard Henderson        /* fall through */
19607b4d5274SRichard Henderson    case INDEX_op_bswap32_i64:
19617b4d5274SRichard Henderson        tcg_out_opc_imm(s, OPC_REV8, a0, a1, 0);
19627b4d5274SRichard Henderson        if (a2 & TCG_BSWAP_OZ) {
19637b4d5274SRichard Henderson            tcg_out_opc_imm(s, OPC_SRLI, a0, a0, 32);
19647b4d5274SRichard Henderson        } else {
19657b4d5274SRichard Henderson            tcg_out_opc_imm(s, OPC_SRAI, a0, a0, 32);
19667b4d5274SRichard Henderson        }
19677b4d5274SRichard Henderson        break;
19687b4d5274SRichard Henderson    case INDEX_op_bswap16_i64:
19697b4d5274SRichard Henderson    case INDEX_op_bswap16_i32:
19707b4d5274SRichard Henderson        tcg_out_opc_imm(s, OPC_REV8, a0, a1, 0);
19717b4d5274SRichard Henderson        if (a2 & TCG_BSWAP_OZ) {
19727b4d5274SRichard Henderson            tcg_out_opc_imm(s, OPC_SRLI, a0, a0, 48);
19737b4d5274SRichard Henderson        } else {
19747b4d5274SRichard Henderson            tcg_out_opc_imm(s, OPC_SRAI, a0, a0, 48);
19757b4d5274SRichard Henderson        }
19767b4d5274SRichard Henderson        break;
19777b4d5274SRichard Henderson
19780956ecdaSRichard Henderson    case INDEX_op_ctpop_i32:
19790956ecdaSRichard Henderson        tcg_out_opc_imm(s, OPC_CPOPW, a0, a1, 0);
19800956ecdaSRichard Henderson        break;
19810956ecdaSRichard Henderson    case INDEX_op_ctpop_i64:
19820956ecdaSRichard Henderson        tcg_out_opc_imm(s, OPC_CPOP, a0, a1, 0);
19830956ecdaSRichard Henderson        break;
19840956ecdaSRichard Henderson
1985a30498fcSRichard Henderson    case INDEX_op_clz_i32:
1986a30498fcSRichard Henderson        tcg_out_cltz(s, TCG_TYPE_I32, OPC_CLZW, a0, a1, a2, c2);
1987a30498fcSRichard Henderson        break;
1988a30498fcSRichard Henderson    case INDEX_op_clz_i64:
1989a30498fcSRichard Henderson        tcg_out_cltz(s, TCG_TYPE_I64, OPC_CLZ, a0, a1, a2, c2);
1990a30498fcSRichard Henderson        break;
1991a30498fcSRichard Henderson    case INDEX_op_ctz_i32:
1992a30498fcSRichard Henderson        tcg_out_cltz(s, TCG_TYPE_I32, OPC_CTZW, a0, a1, a2, c2);
1993a30498fcSRichard Henderson        break;
1994a30498fcSRichard Henderson    case INDEX_op_ctz_i64:
1995a30498fcSRichard Henderson        tcg_out_cltz(s, TCG_TYPE_I64, OPC_CTZ, a0, a1, a2, c2);
1996a30498fcSRichard Henderson        break;
1997a30498fcSRichard Henderson
1998139c1837SPaolo Bonzini    case INDEX_op_add2_i32:
1999139c1837SPaolo Bonzini        tcg_out_addsub2(s, a0, a1, a2, args[3], args[4], args[5],
2000139c1837SPaolo Bonzini                        const_args[4], const_args[5], false, true);
2001139c1837SPaolo Bonzini        break;
2002139c1837SPaolo Bonzini    case INDEX_op_add2_i64:
2003139c1837SPaolo Bonzini        tcg_out_addsub2(s, a0, a1, a2, args[3], args[4], args[5],
2004139c1837SPaolo Bonzini                        const_args[4], const_args[5], false, false);
2005139c1837SPaolo Bonzini        break;
2006139c1837SPaolo Bonzini    case INDEX_op_sub2_i32:
2007139c1837SPaolo Bonzini        tcg_out_addsub2(s, a0, a1, a2, args[3], args[4], args[5],
2008139c1837SPaolo Bonzini                        const_args[4], const_args[5], true, true);
2009139c1837SPaolo Bonzini        break;
2010139c1837SPaolo Bonzini    case INDEX_op_sub2_i64:
2011139c1837SPaolo Bonzini        tcg_out_addsub2(s, a0, a1, a2, args[3], args[4], args[5],
2012139c1837SPaolo Bonzini                        const_args[4], const_args[5], true, false);
2013139c1837SPaolo Bonzini        break;
2014139c1837SPaolo Bonzini
2015139c1837SPaolo Bonzini    case INDEX_op_brcond_i32:
2016139c1837SPaolo Bonzini    case INDEX_op_brcond_i64:
2017139c1837SPaolo Bonzini        tcg_out_brcond(s, a2, a0, a1, arg_label(args[3]));
2018139c1837SPaolo Bonzini        break;
2019139c1837SPaolo Bonzini
2020139c1837SPaolo Bonzini    case INDEX_op_setcond_i32:
2021139c1837SPaolo Bonzini    case INDEX_op_setcond_i64:
2022f6453695SRichard Henderson        tcg_out_setcond(s, args[3], a0, a1, a2, c2);
2023139c1837SPaolo Bonzini        break;
2024139c1837SPaolo Bonzini
202541e4c0a9SRichard Henderson    case INDEX_op_negsetcond_i32:
202641e4c0a9SRichard Henderson    case INDEX_op_negsetcond_i64:
202741e4c0a9SRichard Henderson        tcg_out_negsetcond(s, args[3], a0, a1, a2, c2);
202841e4c0a9SRichard Henderson        break;
202941e4c0a9SRichard Henderson
2030a18d783eSRichard Henderson    case INDEX_op_movcond_i32:
2031a18d783eSRichard Henderson    case INDEX_op_movcond_i64:
2032a18d783eSRichard Henderson        tcg_out_movcond(s, args[5], a0, a1, a2, c2,
2033a18d783eSRichard Henderson                        args[3], const_args[3], args[4], const_args[4]);
2034a18d783eSRichard Henderson        break;
2035a18d783eSRichard Henderson
2036fecccfccSRichard Henderson    case INDEX_op_qemu_ld_a32_i32:
2037fecccfccSRichard Henderson    case INDEX_op_qemu_ld_a64_i32:
2038f7041977SRichard Henderson        tcg_out_qemu_ld(s, a0, a1, a2, TCG_TYPE_I32);
2039139c1837SPaolo Bonzini        break;
2040fecccfccSRichard Henderson    case INDEX_op_qemu_ld_a32_i64:
2041fecccfccSRichard Henderson    case INDEX_op_qemu_ld_a64_i64:
2042f7041977SRichard Henderson        tcg_out_qemu_ld(s, a0, a1, a2, TCG_TYPE_I64);
2043139c1837SPaolo Bonzini        break;
2044fecccfccSRichard Henderson    case INDEX_op_qemu_st_a32_i32:
2045fecccfccSRichard Henderson    case INDEX_op_qemu_st_a64_i32:
2046f7041977SRichard Henderson        tcg_out_qemu_st(s, a0, a1, a2, TCG_TYPE_I32);
2047139c1837SPaolo Bonzini        break;
2048fecccfccSRichard Henderson    case INDEX_op_qemu_st_a32_i64:
2049fecccfccSRichard Henderson    case INDEX_op_qemu_st_a64_i64:
2050f7041977SRichard Henderson        tcg_out_qemu_st(s, a0, a1, a2, TCG_TYPE_I64);
2051139c1837SPaolo Bonzini        break;
2052139c1837SPaolo Bonzini
2053139c1837SPaolo Bonzini    case INDEX_op_extrh_i64_i32:
2054139c1837SPaolo Bonzini        tcg_out_opc_imm(s, OPC_SRAI, a0, a1, 32);
2055139c1837SPaolo Bonzini        break;
2056139c1837SPaolo Bonzini
2057139c1837SPaolo Bonzini    case INDEX_op_mulsh_i32:
2058139c1837SPaolo Bonzini    case INDEX_op_mulsh_i64:
2059139c1837SPaolo Bonzini        tcg_out_opc_reg(s, OPC_MULH, a0, a1, a2);
2060139c1837SPaolo Bonzini        break;
2061139c1837SPaolo Bonzini
2062139c1837SPaolo Bonzini    case INDEX_op_muluh_i32:
2063139c1837SPaolo Bonzini    case INDEX_op_muluh_i64:
2064139c1837SPaolo Bonzini        tcg_out_opc_reg(s, OPC_MULHU, a0, a1, a2);
2065139c1837SPaolo Bonzini        break;
2066139c1837SPaolo Bonzini
2067139c1837SPaolo Bonzini    case INDEX_op_mb:
2068139c1837SPaolo Bonzini        tcg_out_mb(s, a0);
2069139c1837SPaolo Bonzini        break;
2070139c1837SPaolo Bonzini
2071139c1837SPaolo Bonzini    case INDEX_op_mov_i32:  /* Always emitted via tcg_out_mov.  */
2072139c1837SPaolo Bonzini    case INDEX_op_mov_i64:
2073139c1837SPaolo Bonzini    case INDEX_op_call:     /* Always emitted via tcg_out_call.  */
2074b55a8d9dSRichard Henderson    case INDEX_op_exit_tb:  /* Always emitted via tcg_out_exit_tb.  */
2075cf7d6b8eSRichard Henderson    case INDEX_op_goto_tb:  /* Always emitted via tcg_out_goto_tb.  */
2076678155b2SRichard Henderson    case INDEX_op_ext8s_i32:  /* Always emitted via tcg_reg_alloc_op.  */
2077678155b2SRichard Henderson    case INDEX_op_ext8s_i64:
2078d0e66c89SRichard Henderson    case INDEX_op_ext8u_i32:
2079d0e66c89SRichard Henderson    case INDEX_op_ext8u_i64:
2080753e42eaSRichard Henderson    case INDEX_op_ext16s_i32:
2081753e42eaSRichard Henderson    case INDEX_op_ext16s_i64:
2082379afdffSRichard Henderson    case INDEX_op_ext16u_i32:
2083379afdffSRichard Henderson    case INDEX_op_ext16u_i64:
208452bf3398SRichard Henderson    case INDEX_op_ext32s_i64:
20859ecf5f61SRichard Henderson    case INDEX_op_ext32u_i64:
20869c6aa274SRichard Henderson    case INDEX_op_ext_i32_i64:
2087b9bfe000SRichard Henderson    case INDEX_op_extu_i32_i64:
2088b8b94ac6SRichard Henderson    case INDEX_op_extrl_i64_i32:
2089139c1837SPaolo Bonzini    default:
2090139c1837SPaolo Bonzini        g_assert_not_reached();
2091139c1837SPaolo Bonzini    }
2092139c1837SPaolo Bonzini}
2093139c1837SPaolo Bonzini
2094*f63e7089SHuang Shiyuanstatic void tcg_out_vec_op(TCGContext *s, TCGOpcode opc,
2095*f63e7089SHuang Shiyuan                           unsigned vecl, unsigned vece,
2096*f63e7089SHuang Shiyuan                           const TCGArg args[TCG_MAX_OP_ARGS],
2097*f63e7089SHuang Shiyuan                           const int const_args[TCG_MAX_OP_ARGS])
2098*f63e7089SHuang Shiyuan{
2099*f63e7089SHuang Shiyuan    TCGType type = vecl + TCG_TYPE_V64;
2100*f63e7089SHuang Shiyuan    TCGArg a0, a1, a2;
2101*f63e7089SHuang Shiyuan
2102*f63e7089SHuang Shiyuan    a0 = args[0];
2103*f63e7089SHuang Shiyuan    a1 = args[1];
2104*f63e7089SHuang Shiyuan    a2 = args[2];
2105*f63e7089SHuang Shiyuan
2106*f63e7089SHuang Shiyuan    switch (opc) {
2107*f63e7089SHuang Shiyuan    case INDEX_op_ld_vec:
2108*f63e7089SHuang Shiyuan        tcg_out_ld(s, type, a0, a1, a2);
2109*f63e7089SHuang Shiyuan        break;
2110*f63e7089SHuang Shiyuan    case INDEX_op_st_vec:
2111*f63e7089SHuang Shiyuan        tcg_out_st(s, type, a0, a1, a2);
2112*f63e7089SHuang Shiyuan        break;
2113*f63e7089SHuang Shiyuan    case INDEX_op_mov_vec: /* Always emitted via tcg_out_mov.  */
2114*f63e7089SHuang Shiyuan    case INDEX_op_dup_vec: /* Always emitted via tcg_out_dup_vec.  */
2115*f63e7089SHuang Shiyuan    default:
2116*f63e7089SHuang Shiyuan        g_assert_not_reached();
2117*f63e7089SHuang Shiyuan    }
2118*f63e7089SHuang Shiyuan}
2119*f63e7089SHuang Shiyuan
2120*f63e7089SHuang Shiyuanvoid tcg_expand_vec_op(TCGOpcode opc, TCGType type, unsigned vece,
2121*f63e7089SHuang Shiyuan                       TCGArg a0, ...)
2122*f63e7089SHuang Shiyuan{
2123*f63e7089SHuang Shiyuan    g_assert_not_reached();
2124*f63e7089SHuang Shiyuan}
2125*f63e7089SHuang Shiyuan
2126*f63e7089SHuang Shiyuanint tcg_can_emit_vec_op(TCGOpcode opc, TCGType type, unsigned vece)
2127*f63e7089SHuang Shiyuan{
2128*f63e7089SHuang Shiyuan    switch (opc) {
2129*f63e7089SHuang Shiyuan    default:
2130*f63e7089SHuang Shiyuan        return 0;
2131*f63e7089SHuang Shiyuan    }
2132*f63e7089SHuang Shiyuan}
2133*f63e7089SHuang Shiyuan
2134665be288SRichard Hendersonstatic TCGConstraintSetIndex tcg_target_op_def(TCGOpcode op)
2135139c1837SPaolo Bonzini{
2136139c1837SPaolo Bonzini    switch (op) {
2137139c1837SPaolo Bonzini    case INDEX_op_goto_ptr:
2138665be288SRichard Henderson        return C_O0_I1(r);
2139139c1837SPaolo Bonzini
2140139c1837SPaolo Bonzini    case INDEX_op_ld8u_i32:
2141139c1837SPaolo Bonzini    case INDEX_op_ld8s_i32:
2142139c1837SPaolo Bonzini    case INDEX_op_ld16u_i32:
2143139c1837SPaolo Bonzini    case INDEX_op_ld16s_i32:
2144139c1837SPaolo Bonzini    case INDEX_op_ld_i32:
2145139c1837SPaolo Bonzini    case INDEX_op_not_i32:
2146139c1837SPaolo Bonzini    case INDEX_op_neg_i32:
2147139c1837SPaolo Bonzini    case INDEX_op_ld8u_i64:
2148139c1837SPaolo Bonzini    case INDEX_op_ld8s_i64:
2149139c1837SPaolo Bonzini    case INDEX_op_ld16u_i64:
2150139c1837SPaolo Bonzini    case INDEX_op_ld16s_i64:
2151139c1837SPaolo Bonzini    case INDEX_op_ld32s_i64:
2152139c1837SPaolo Bonzini    case INDEX_op_ld32u_i64:
2153139c1837SPaolo Bonzini    case INDEX_op_ld_i64:
2154139c1837SPaolo Bonzini    case INDEX_op_not_i64:
2155139c1837SPaolo Bonzini    case INDEX_op_neg_i64:
2156139c1837SPaolo Bonzini    case INDEX_op_ext8u_i32:
2157139c1837SPaolo Bonzini    case INDEX_op_ext8u_i64:
2158139c1837SPaolo Bonzini    case INDEX_op_ext16u_i32:
2159139c1837SPaolo Bonzini    case INDEX_op_ext16u_i64:
2160139c1837SPaolo Bonzini    case INDEX_op_ext32u_i64:
2161139c1837SPaolo Bonzini    case INDEX_op_extu_i32_i64:
2162139c1837SPaolo Bonzini    case INDEX_op_ext8s_i32:
2163139c1837SPaolo Bonzini    case INDEX_op_ext8s_i64:
2164139c1837SPaolo Bonzini    case INDEX_op_ext16s_i32:
2165139c1837SPaolo Bonzini    case INDEX_op_ext16s_i64:
2166139c1837SPaolo Bonzini    case INDEX_op_ext32s_i64:
2167139c1837SPaolo Bonzini    case INDEX_op_extrl_i64_i32:
2168139c1837SPaolo Bonzini    case INDEX_op_extrh_i64_i32:
2169139c1837SPaolo Bonzini    case INDEX_op_ext_i32_i64:
21707b4d5274SRichard Henderson    case INDEX_op_bswap16_i32:
21717b4d5274SRichard Henderson    case INDEX_op_bswap32_i32:
21727b4d5274SRichard Henderson    case INDEX_op_bswap16_i64:
21737b4d5274SRichard Henderson    case INDEX_op_bswap32_i64:
21747b4d5274SRichard Henderson    case INDEX_op_bswap64_i64:
21750956ecdaSRichard Henderson    case INDEX_op_ctpop_i32:
21760956ecdaSRichard Henderson    case INDEX_op_ctpop_i64:
2177665be288SRichard Henderson        return C_O1_I1(r, r);
2178139c1837SPaolo Bonzini
2179139c1837SPaolo Bonzini    case INDEX_op_st8_i32:
2180139c1837SPaolo Bonzini    case INDEX_op_st16_i32:
2181139c1837SPaolo Bonzini    case INDEX_op_st_i32:
2182139c1837SPaolo Bonzini    case INDEX_op_st8_i64:
2183139c1837SPaolo Bonzini    case INDEX_op_st16_i64:
2184139c1837SPaolo Bonzini    case INDEX_op_st32_i64:
2185139c1837SPaolo Bonzini    case INDEX_op_st_i64:
2186665be288SRichard Henderson        return C_O0_I2(rZ, r);
2187139c1837SPaolo Bonzini
2188139c1837SPaolo Bonzini    case INDEX_op_add_i32:
2189139c1837SPaolo Bonzini    case INDEX_op_and_i32:
2190139c1837SPaolo Bonzini    case INDEX_op_or_i32:
2191139c1837SPaolo Bonzini    case INDEX_op_xor_i32:
2192139c1837SPaolo Bonzini    case INDEX_op_add_i64:
2193139c1837SPaolo Bonzini    case INDEX_op_and_i64:
2194139c1837SPaolo Bonzini    case INDEX_op_or_i64:
2195139c1837SPaolo Bonzini    case INDEX_op_xor_i64:
2196f6453695SRichard Henderson    case INDEX_op_setcond_i32:
2197f6453695SRichard Henderson    case INDEX_op_setcond_i64:
219841e4c0a9SRichard Henderson    case INDEX_op_negsetcond_i32:
219941e4c0a9SRichard Henderson    case INDEX_op_negsetcond_i64:
2200665be288SRichard Henderson        return C_O1_I2(r, r, rI);
2201139c1837SPaolo Bonzini
220299f4ec6eSRichard Henderson    case INDEX_op_andc_i32:
220399f4ec6eSRichard Henderson    case INDEX_op_andc_i64:
220499f4ec6eSRichard Henderson    case INDEX_op_orc_i32:
220599f4ec6eSRichard Henderson    case INDEX_op_orc_i64:
220699f4ec6eSRichard Henderson    case INDEX_op_eqv_i32:
220799f4ec6eSRichard Henderson    case INDEX_op_eqv_i64:
220899f4ec6eSRichard Henderson        return C_O1_I2(r, r, rJ);
220999f4ec6eSRichard Henderson
2210139c1837SPaolo Bonzini    case INDEX_op_sub_i32:
2211139c1837SPaolo Bonzini    case INDEX_op_sub_i64:
2212665be288SRichard Henderson        return C_O1_I2(r, rZ, rN);
2213139c1837SPaolo Bonzini
2214139c1837SPaolo Bonzini    case INDEX_op_mul_i32:
2215139c1837SPaolo Bonzini    case INDEX_op_mulsh_i32:
2216139c1837SPaolo Bonzini    case INDEX_op_muluh_i32:
2217139c1837SPaolo Bonzini    case INDEX_op_div_i32:
2218139c1837SPaolo Bonzini    case INDEX_op_divu_i32:
2219139c1837SPaolo Bonzini    case INDEX_op_rem_i32:
2220139c1837SPaolo Bonzini    case INDEX_op_remu_i32:
2221139c1837SPaolo Bonzini    case INDEX_op_mul_i64:
2222139c1837SPaolo Bonzini    case INDEX_op_mulsh_i64:
2223139c1837SPaolo Bonzini    case INDEX_op_muluh_i64:
2224139c1837SPaolo Bonzini    case INDEX_op_div_i64:
2225139c1837SPaolo Bonzini    case INDEX_op_divu_i64:
2226139c1837SPaolo Bonzini    case INDEX_op_rem_i64:
2227139c1837SPaolo Bonzini    case INDEX_op_remu_i64:
2228665be288SRichard Henderson        return C_O1_I2(r, rZ, rZ);
2229139c1837SPaolo Bonzini
2230139c1837SPaolo Bonzini    case INDEX_op_shl_i32:
2231139c1837SPaolo Bonzini    case INDEX_op_shr_i32:
2232139c1837SPaolo Bonzini    case INDEX_op_sar_i32:
223319d016adSRichard Henderson    case INDEX_op_rotl_i32:
223419d016adSRichard Henderson    case INDEX_op_rotr_i32:
2235139c1837SPaolo Bonzini    case INDEX_op_shl_i64:
2236139c1837SPaolo Bonzini    case INDEX_op_shr_i64:
2237139c1837SPaolo Bonzini    case INDEX_op_sar_i64:
223819d016adSRichard Henderson    case INDEX_op_rotl_i64:
223919d016adSRichard Henderson    case INDEX_op_rotr_i64:
2240665be288SRichard Henderson        return C_O1_I2(r, r, ri);
2241139c1837SPaolo Bonzini
2242a30498fcSRichard Henderson    case INDEX_op_clz_i32:
2243a30498fcSRichard Henderson    case INDEX_op_clz_i64:
2244a30498fcSRichard Henderson    case INDEX_op_ctz_i32:
2245a30498fcSRichard Henderson    case INDEX_op_ctz_i64:
2246a30498fcSRichard Henderson        return C_N1_I2(r, r, rM);
2247a30498fcSRichard Henderson
2248139c1837SPaolo Bonzini    case INDEX_op_brcond_i32:
2249139c1837SPaolo Bonzini    case INDEX_op_brcond_i64:
2250665be288SRichard Henderson        return C_O0_I2(rZ, rZ);
2251139c1837SPaolo Bonzini
2252a18d783eSRichard Henderson    case INDEX_op_movcond_i32:
2253a18d783eSRichard Henderson    case INDEX_op_movcond_i64:
2254a18d783eSRichard Henderson        return C_O1_I4(r, r, rI, rM, rM);
2255a18d783eSRichard Henderson
2256139c1837SPaolo Bonzini    case INDEX_op_add2_i32:
2257139c1837SPaolo Bonzini    case INDEX_op_add2_i64:
2258139c1837SPaolo Bonzini    case INDEX_op_sub2_i32:
2259139c1837SPaolo Bonzini    case INDEX_op_sub2_i64:
2260665be288SRichard Henderson        return C_O2_I4(r, r, rZ, rZ, rM, rM);
2261139c1837SPaolo Bonzini
2262fecccfccSRichard Henderson    case INDEX_op_qemu_ld_a32_i32:
2263fecccfccSRichard Henderson    case INDEX_op_qemu_ld_a64_i32:
2264fecccfccSRichard Henderson    case INDEX_op_qemu_ld_a32_i64:
2265fecccfccSRichard Henderson    case INDEX_op_qemu_ld_a64_i64:
2266f0f43534SRichard Henderson        return C_O1_I1(r, r);
2267fecccfccSRichard Henderson    case INDEX_op_qemu_st_a32_i32:
2268fecccfccSRichard Henderson    case INDEX_op_qemu_st_a64_i32:
2269fecccfccSRichard Henderson    case INDEX_op_qemu_st_a32_i64:
2270fecccfccSRichard Henderson    case INDEX_op_qemu_st_a64_i64:
2271f0f43534SRichard Henderson        return C_O0_I2(rZ, r);
2272139c1837SPaolo Bonzini
2273*f63e7089SHuang Shiyuan    case INDEX_op_st_vec:
2274*f63e7089SHuang Shiyuan        return C_O0_I2(v, r);
2275*f63e7089SHuang Shiyuan    case INDEX_op_ld_vec:
2276*f63e7089SHuang Shiyuan        return C_O1_I1(v, r);
2277139c1837SPaolo Bonzini    default:
2278665be288SRichard Henderson        g_assert_not_reached();
2279139c1837SPaolo Bonzini    }
2280139c1837SPaolo Bonzini}
2281139c1837SPaolo Bonzini
2282139c1837SPaolo Bonzinistatic const int tcg_target_callee_save_regs[] = {
2283139c1837SPaolo Bonzini    TCG_REG_S0,       /* used for the global env (TCG_AREG0) */
2284139c1837SPaolo Bonzini    TCG_REG_S1,
2285139c1837SPaolo Bonzini    TCG_REG_S2,
2286139c1837SPaolo Bonzini    TCG_REG_S3,
2287139c1837SPaolo Bonzini    TCG_REG_S4,
2288139c1837SPaolo Bonzini    TCG_REG_S5,
2289139c1837SPaolo Bonzini    TCG_REG_S6,
2290139c1837SPaolo Bonzini    TCG_REG_S7,
2291139c1837SPaolo Bonzini    TCG_REG_S8,
2292139c1837SPaolo Bonzini    TCG_REG_S9,
2293139c1837SPaolo Bonzini    TCG_REG_S10,
2294139c1837SPaolo Bonzini    TCG_REG_S11,
2295139c1837SPaolo Bonzini    TCG_REG_RA,       /* should be last for ABI compliance */
2296139c1837SPaolo Bonzini};
2297139c1837SPaolo Bonzini
2298139c1837SPaolo Bonzini/* Stack frame parameters.  */
2299139c1837SPaolo Bonzini#define REG_SIZE   (TCG_TARGET_REG_BITS / 8)
2300139c1837SPaolo Bonzini#define SAVE_SIZE  ((int)ARRAY_SIZE(tcg_target_callee_save_regs) * REG_SIZE)
2301139c1837SPaolo Bonzini#define TEMP_SIZE  (CPU_TEMP_BUF_NLONGS * (int)sizeof(long))
2302139c1837SPaolo Bonzini#define FRAME_SIZE ((TCG_STATIC_CALL_ARGS_SIZE + TEMP_SIZE + SAVE_SIZE \
2303139c1837SPaolo Bonzini                     + TCG_TARGET_STACK_ALIGN - 1) \
2304139c1837SPaolo Bonzini                    & -TCG_TARGET_STACK_ALIGN)
2305139c1837SPaolo Bonzini#define SAVE_OFS   (TCG_STATIC_CALL_ARGS_SIZE + TEMP_SIZE)
2306139c1837SPaolo Bonzini
2307139c1837SPaolo Bonzini/* We're expecting to be able to use an immediate for frame allocation.  */
2308139c1837SPaolo BonziniQEMU_BUILD_BUG_ON(FRAME_SIZE > 0x7ff);
2309139c1837SPaolo Bonzini
2310139c1837SPaolo Bonzini/* Generate global QEMU prologue and epilogue code */
2311139c1837SPaolo Bonzinistatic void tcg_target_qemu_prologue(TCGContext *s)
2312139c1837SPaolo Bonzini{
2313139c1837SPaolo Bonzini    int i;
2314139c1837SPaolo Bonzini
2315139c1837SPaolo Bonzini    tcg_set_frame(s, TCG_REG_SP, TCG_STATIC_CALL_ARGS_SIZE, TEMP_SIZE);
2316139c1837SPaolo Bonzini
2317139c1837SPaolo Bonzini    /* TB prologue */
2318139c1837SPaolo Bonzini    tcg_out_opc_imm(s, OPC_ADDI, TCG_REG_SP, TCG_REG_SP, -FRAME_SIZE);
2319139c1837SPaolo Bonzini    for (i = 0; i < ARRAY_SIZE(tcg_target_callee_save_regs); i++) {
2320139c1837SPaolo Bonzini        tcg_out_st(s, TCG_TYPE_REG, tcg_target_callee_save_regs[i],
2321139c1837SPaolo Bonzini                   TCG_REG_SP, SAVE_OFS + i * REG_SIZE);
2322139c1837SPaolo Bonzini    }
2323139c1837SPaolo Bonzini
23244944d359SRichard Henderson    if (!tcg_use_softmmu && guest_base) {
2325139c1837SPaolo Bonzini        tcg_out_movi(s, TCG_TYPE_PTR, TCG_GUEST_BASE_REG, guest_base);
2326139c1837SPaolo Bonzini        tcg_regset_set_reg(s->reserved_regs, TCG_GUEST_BASE_REG);
2327cf0ed30eSRichard Henderson    }
2328139c1837SPaolo Bonzini
2329139c1837SPaolo Bonzini    /* Call generated code */
2330139c1837SPaolo Bonzini    tcg_out_mov(s, TCG_TYPE_PTR, TCG_AREG0, tcg_target_call_iarg_regs[0]);
2331139c1837SPaolo Bonzini    tcg_out_opc_imm(s, OPC_JALR, TCG_REG_ZERO, tcg_target_call_iarg_regs[1], 0);
2332139c1837SPaolo Bonzini
2333139c1837SPaolo Bonzini    /* Return path for goto_ptr. Set return value to 0 */
2334c8bc1168SRichard Henderson    tcg_code_gen_epilogue = tcg_splitwx_to_rx(s->code_ptr);
2335139c1837SPaolo Bonzini    tcg_out_mov(s, TCG_TYPE_REG, TCG_REG_A0, TCG_REG_ZERO);
2336139c1837SPaolo Bonzini
2337139c1837SPaolo Bonzini    /* TB epilogue */
2338793f7381SRichard Henderson    tb_ret_addr = tcg_splitwx_to_rx(s->code_ptr);
2339139c1837SPaolo Bonzini    for (i = 0; i < ARRAY_SIZE(tcg_target_callee_save_regs); i++) {
2340139c1837SPaolo Bonzini        tcg_out_ld(s, TCG_TYPE_REG, tcg_target_callee_save_regs[i],
2341139c1837SPaolo Bonzini                   TCG_REG_SP, SAVE_OFS + i * REG_SIZE);
2342139c1837SPaolo Bonzini    }
2343139c1837SPaolo Bonzini
2344139c1837SPaolo Bonzini    tcg_out_opc_imm(s, OPC_ADDI, TCG_REG_SP, TCG_REG_SP, FRAME_SIZE);
2345139c1837SPaolo Bonzini    tcg_out_opc_imm(s, OPC_JALR, TCG_REG_ZERO, TCG_REG_RA, 0);
2346139c1837SPaolo Bonzini}
2347139c1837SPaolo Bonzini
23489358fbbfSRichard Hendersonstatic void tcg_out_tb_start(TCGContext *s)
23499358fbbfSRichard Henderson{
2350*f63e7089SHuang Shiyuan    init_setting_vtype(s);
2351*f63e7089SHuang Shiyuan}
2352*f63e7089SHuang Shiyuan
2353*f63e7089SHuang Shiyuanstatic bool vtype_check(unsigned vtype)
2354*f63e7089SHuang Shiyuan{
2355*f63e7089SHuang Shiyuan    unsigned long tmp;
2356*f63e7089SHuang Shiyuan
2357*f63e7089SHuang Shiyuan    /* vsetvl tmp, zero, vtype */
2358*f63e7089SHuang Shiyuan    asm(".insn r 0x57, 7, 0x40, %0, zero, %1" : "=r"(tmp) : "r"(vtype));
2359*f63e7089SHuang Shiyuan    return tmp != 0;
2360*f63e7089SHuang Shiyuan}
2361*f63e7089SHuang Shiyuan
2362*f63e7089SHuang Shiyuanstatic void probe_frac_lmul_1(TCGType type, MemOp vsew)
2363*f63e7089SHuang Shiyuan{
2364*f63e7089SHuang Shiyuan    VsetCache *p = &riscv_vset_cache[type - TCG_TYPE_V64][vsew];
2365*f63e7089SHuang Shiyuan    unsigned avl = tcg_type_size(type) >> vsew;
2366*f63e7089SHuang Shiyuan    int lmul = type - riscv_lg2_vlenb;
2367*f63e7089SHuang Shiyuan    unsigned vtype = encode_vtype(true, true, vsew, lmul & 7);
2368*f63e7089SHuang Shiyuan    bool lmul_eq_avl = true;
2369*f63e7089SHuang Shiyuan
2370*f63e7089SHuang Shiyuan    /* Guaranteed by Zve64x. */
2371*f63e7089SHuang Shiyuan    assert(lmul < 3);
2372*f63e7089SHuang Shiyuan
2373*f63e7089SHuang Shiyuan    /*
2374*f63e7089SHuang Shiyuan     * For LMUL < -3, the host vector size is so large that TYPE
2375*f63e7089SHuang Shiyuan     * is smaller than the minimum 1/8 fraction.
2376*f63e7089SHuang Shiyuan     *
2377*f63e7089SHuang Shiyuan     * For other fractional LMUL settings, implementations must
2378*f63e7089SHuang Shiyuan     * support SEW settings between SEW_MIN and LMUL * ELEN, inclusive.
2379*f63e7089SHuang Shiyuan     * So if ELEN = 64, LMUL = 1/2, then SEW will support e8, e16, e32,
2380*f63e7089SHuang Shiyuan     * but e64 may not be supported. In other words, the hardware only
2381*f63e7089SHuang Shiyuan     * guarantees SEW_MIN <= SEW <= LMUL * ELEN.  Check.
2382*f63e7089SHuang Shiyuan     */
2383*f63e7089SHuang Shiyuan    if (lmul < 0 && (lmul < -3 || !vtype_check(vtype))) {
2384*f63e7089SHuang Shiyuan        vtype = encode_vtype(true, true, vsew, VLMUL_M1);
2385*f63e7089SHuang Shiyuan        lmul_eq_avl = false;
2386*f63e7089SHuang Shiyuan    }
2387*f63e7089SHuang Shiyuan
2388*f63e7089SHuang Shiyuan    if (avl < 32) {
2389*f63e7089SHuang Shiyuan        p->vset_insn = encode_vseti(OPC_VSETIVLI, TCG_REG_ZERO, avl, vtype);
2390*f63e7089SHuang Shiyuan    } else if (lmul_eq_avl) {
2391*f63e7089SHuang Shiyuan        /* rd != 0 and rs1 == 0 uses vlmax */
2392*f63e7089SHuang Shiyuan        p->vset_insn = encode_vset(OPC_VSETVLI, TCG_REG_TMP0, TCG_REG_ZERO, vtype);
2393*f63e7089SHuang Shiyuan    } else {
2394*f63e7089SHuang Shiyuan        p->movi_insn = encode_i(OPC_ADDI, TCG_REG_TMP0, TCG_REG_ZERO, avl);
2395*f63e7089SHuang Shiyuan        p->vset_insn = encode_vset(OPC_VSETVLI, TCG_REG_ZERO, TCG_REG_TMP0, vtype);
2396*f63e7089SHuang Shiyuan    }
2397*f63e7089SHuang Shiyuan}
2398*f63e7089SHuang Shiyuan
2399*f63e7089SHuang Shiyuanstatic void probe_frac_lmul(void)
2400*f63e7089SHuang Shiyuan{
2401*f63e7089SHuang Shiyuan    /* Match riscv_lg2_vlenb to TCG_TYPE_V64. */
2402*f63e7089SHuang Shiyuan    QEMU_BUILD_BUG_ON(TCG_TYPE_V64 != 3);
2403*f63e7089SHuang Shiyuan
2404*f63e7089SHuang Shiyuan    for (TCGType t = TCG_TYPE_V64; t <= TCG_TYPE_V256; t++) {
2405*f63e7089SHuang Shiyuan        for (MemOp e = MO_8; e <= MO_64; e++) {
2406*f63e7089SHuang Shiyuan            probe_frac_lmul_1(t, e);
2407*f63e7089SHuang Shiyuan        }
2408*f63e7089SHuang Shiyuan    }
24099358fbbfSRichard Henderson}
24109358fbbfSRichard Henderson
2411139c1837SPaolo Bonzinistatic void tcg_target_init(TCGContext *s)
2412139c1837SPaolo Bonzini{
2413139c1837SPaolo Bonzini    tcg_target_available_regs[TCG_TYPE_I32] = 0xffffffff;
2414139c1837SPaolo Bonzini    tcg_target_available_regs[TCG_TYPE_I64] = 0xffffffff;
2415139c1837SPaolo Bonzini
2416*f63e7089SHuang Shiyuan    tcg_target_call_clobber_regs = -1;
2417139c1837SPaolo Bonzini    tcg_regset_reset_reg(tcg_target_call_clobber_regs, TCG_REG_S0);
2418139c1837SPaolo Bonzini    tcg_regset_reset_reg(tcg_target_call_clobber_regs, TCG_REG_S1);
2419139c1837SPaolo Bonzini    tcg_regset_reset_reg(tcg_target_call_clobber_regs, TCG_REG_S2);
2420139c1837SPaolo Bonzini    tcg_regset_reset_reg(tcg_target_call_clobber_regs, TCG_REG_S3);
2421139c1837SPaolo Bonzini    tcg_regset_reset_reg(tcg_target_call_clobber_regs, TCG_REG_S4);
2422139c1837SPaolo Bonzini    tcg_regset_reset_reg(tcg_target_call_clobber_regs, TCG_REG_S5);
2423139c1837SPaolo Bonzini    tcg_regset_reset_reg(tcg_target_call_clobber_regs, TCG_REG_S6);
2424139c1837SPaolo Bonzini    tcg_regset_reset_reg(tcg_target_call_clobber_regs, TCG_REG_S7);
2425139c1837SPaolo Bonzini    tcg_regset_reset_reg(tcg_target_call_clobber_regs, TCG_REG_S8);
2426139c1837SPaolo Bonzini    tcg_regset_reset_reg(tcg_target_call_clobber_regs, TCG_REG_S9);
2427139c1837SPaolo Bonzini    tcg_regset_reset_reg(tcg_target_call_clobber_regs, TCG_REG_S10);
2428139c1837SPaolo Bonzini    tcg_regset_reset_reg(tcg_target_call_clobber_regs, TCG_REG_S11);
2429139c1837SPaolo Bonzini
2430139c1837SPaolo Bonzini    s->reserved_regs = 0;
2431139c1837SPaolo Bonzini    tcg_regset_set_reg(s->reserved_regs, TCG_REG_ZERO);
2432139c1837SPaolo Bonzini    tcg_regset_set_reg(s->reserved_regs, TCG_REG_TMP0);
2433139c1837SPaolo Bonzini    tcg_regset_set_reg(s->reserved_regs, TCG_REG_TMP1);
2434139c1837SPaolo Bonzini    tcg_regset_set_reg(s->reserved_regs, TCG_REG_TMP2);
2435139c1837SPaolo Bonzini    tcg_regset_set_reg(s->reserved_regs, TCG_REG_SP);
2436139c1837SPaolo Bonzini    tcg_regset_set_reg(s->reserved_regs, TCG_REG_GP);
2437139c1837SPaolo Bonzini    tcg_regset_set_reg(s->reserved_regs, TCG_REG_TP);
2438*f63e7089SHuang Shiyuan
2439*f63e7089SHuang Shiyuan    if (cpuinfo & CPUINFO_ZVE64X) {
2440*f63e7089SHuang Shiyuan        switch (riscv_lg2_vlenb) {
2441*f63e7089SHuang Shiyuan        case TCG_TYPE_V64:
2442*f63e7089SHuang Shiyuan            tcg_target_available_regs[TCG_TYPE_V64] = ALL_VECTOR_REGS;
2443*f63e7089SHuang Shiyuan            tcg_target_available_regs[TCG_TYPE_V128] = ALL_DVECTOR_REG_GROUPS;
2444*f63e7089SHuang Shiyuan            tcg_target_available_regs[TCG_TYPE_V256] = ALL_QVECTOR_REG_GROUPS;
2445*f63e7089SHuang Shiyuan            s->reserved_regs |= (~ALL_QVECTOR_REG_GROUPS & ALL_VECTOR_REGS);
2446*f63e7089SHuang Shiyuan            break;
2447*f63e7089SHuang Shiyuan        case TCG_TYPE_V128:
2448*f63e7089SHuang Shiyuan            tcg_target_available_regs[TCG_TYPE_V64] = ALL_VECTOR_REGS;
2449*f63e7089SHuang Shiyuan            tcg_target_available_regs[TCG_TYPE_V128] = ALL_VECTOR_REGS;
2450*f63e7089SHuang Shiyuan            tcg_target_available_regs[TCG_TYPE_V256] = ALL_DVECTOR_REG_GROUPS;
2451*f63e7089SHuang Shiyuan            s->reserved_regs |= (~ALL_DVECTOR_REG_GROUPS & ALL_VECTOR_REGS);
2452*f63e7089SHuang Shiyuan            break;
2453*f63e7089SHuang Shiyuan        default:
2454*f63e7089SHuang Shiyuan            /* Guaranteed by Zve64x. */
2455*f63e7089SHuang Shiyuan            tcg_debug_assert(riscv_lg2_vlenb >= TCG_TYPE_V256);
2456*f63e7089SHuang Shiyuan            tcg_target_available_regs[TCG_TYPE_V64] = ALL_VECTOR_REGS;
2457*f63e7089SHuang Shiyuan            tcg_target_available_regs[TCG_TYPE_V128] = ALL_VECTOR_REGS;
2458*f63e7089SHuang Shiyuan            tcg_target_available_regs[TCG_TYPE_V256] = ALL_VECTOR_REGS;
2459*f63e7089SHuang Shiyuan            break;
2460*f63e7089SHuang Shiyuan        }
2461*f63e7089SHuang Shiyuan        tcg_regset_set_reg(s->reserved_regs, TCG_REG_V0);
2462*f63e7089SHuang Shiyuan        probe_frac_lmul();
2463*f63e7089SHuang Shiyuan    }
2464139c1837SPaolo Bonzini}
2465139c1837SPaolo Bonzini
2466139c1837SPaolo Bonzinitypedef struct {
2467139c1837SPaolo Bonzini    DebugFrameHeader h;
2468139c1837SPaolo Bonzini    uint8_t fde_def_cfa[4];
2469139c1837SPaolo Bonzini    uint8_t fde_reg_ofs[ARRAY_SIZE(tcg_target_callee_save_regs) * 2];
2470139c1837SPaolo Bonzini} DebugFrame;
2471139c1837SPaolo Bonzini
2472139c1837SPaolo Bonzini#define ELF_HOST_MACHINE EM_RISCV
2473139c1837SPaolo Bonzini
2474139c1837SPaolo Bonzinistatic const DebugFrame debug_frame = {
2475139c1837SPaolo Bonzini    .h.cie.len = sizeof(DebugFrameCIE) - 4, /* length after .len member */
2476139c1837SPaolo Bonzini    .h.cie.id = -1,
2477139c1837SPaolo Bonzini    .h.cie.version = 1,
2478139c1837SPaolo Bonzini    .h.cie.code_align = 1,
2479139c1837SPaolo Bonzini    .h.cie.data_align = -(TCG_TARGET_REG_BITS / 8) & 0x7f, /* sleb128 */
2480139c1837SPaolo Bonzini    .h.cie.return_column = TCG_REG_RA,
2481139c1837SPaolo Bonzini
2482139c1837SPaolo Bonzini    /* Total FDE size does not include the "len" member.  */
2483139c1837SPaolo Bonzini    .h.fde.len = sizeof(DebugFrame) - offsetof(DebugFrame, h.fde.cie_offset),
2484139c1837SPaolo Bonzini
2485139c1837SPaolo Bonzini    .fde_def_cfa = {
2486139c1837SPaolo Bonzini        12, TCG_REG_SP,                 /* DW_CFA_def_cfa sp, ... */
2487139c1837SPaolo Bonzini        (FRAME_SIZE & 0x7f) | 0x80,     /* ... uleb128 FRAME_SIZE */
2488139c1837SPaolo Bonzini        (FRAME_SIZE >> 7)
2489139c1837SPaolo Bonzini    },
2490139c1837SPaolo Bonzini    .fde_reg_ofs = {
2491139c1837SPaolo Bonzini        0x80 + 9,  12,                  /* DW_CFA_offset, s1,  -96 */
2492139c1837SPaolo Bonzini        0x80 + 18, 11,                  /* DW_CFA_offset, s2,  -88 */
2493139c1837SPaolo Bonzini        0x80 + 19, 10,                  /* DW_CFA_offset, s3,  -80 */
2494139c1837SPaolo Bonzini        0x80 + 20, 9,                   /* DW_CFA_offset, s4,  -72 */
2495139c1837SPaolo Bonzini        0x80 + 21, 8,                   /* DW_CFA_offset, s5,  -64 */
2496139c1837SPaolo Bonzini        0x80 + 22, 7,                   /* DW_CFA_offset, s6,  -56 */
2497139c1837SPaolo Bonzini        0x80 + 23, 6,                   /* DW_CFA_offset, s7,  -48 */
2498139c1837SPaolo Bonzini        0x80 + 24, 5,                   /* DW_CFA_offset, s8,  -40 */
2499139c1837SPaolo Bonzini        0x80 + 25, 4,                   /* DW_CFA_offset, s9,  -32 */
2500139c1837SPaolo Bonzini        0x80 + 26, 3,                   /* DW_CFA_offset, s10, -24 */
2501139c1837SPaolo Bonzini        0x80 + 27, 2,                   /* DW_CFA_offset, s11, -16 */
2502139c1837SPaolo Bonzini        0x80 + 1 , 1,                   /* DW_CFA_offset, ra,  -8 */
2503139c1837SPaolo Bonzini    }
2504139c1837SPaolo Bonzini};
2505139c1837SPaolo Bonzini
2506755bf9e5SRichard Hendersonvoid tcg_register_jit(const void *buf, size_t buf_size)
2507139c1837SPaolo Bonzini{
2508139c1837SPaolo Bonzini    tcg_register_jit_int(buf, buf_size, &debug_frame, sizeof(debug_frame));
2509139c1837SPaolo Bonzini}
2510