xref: /openbmc/qemu/tcg/riscv/tcg-target.c.inc (revision 665be288ace26027bf941d6a2eafa0ecb92009e0)
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
30139c1837SPaolo Bonzini#include "../tcg-pool.c.inc"
31139c1837SPaolo Bonzini
32139c1837SPaolo Bonzini#ifdef CONFIG_DEBUG_TCG
33139c1837SPaolo Bonzinistatic const char * const tcg_target_reg_names[TCG_TARGET_NB_REGS] = {
34139c1837SPaolo Bonzini    "zero",
35139c1837SPaolo Bonzini    "ra",
36139c1837SPaolo Bonzini    "sp",
37139c1837SPaolo Bonzini    "gp",
38139c1837SPaolo Bonzini    "tp",
39139c1837SPaolo Bonzini    "t0",
40139c1837SPaolo Bonzini    "t1",
41139c1837SPaolo Bonzini    "t2",
42139c1837SPaolo Bonzini    "s0",
43139c1837SPaolo Bonzini    "s1",
44139c1837SPaolo Bonzini    "a0",
45139c1837SPaolo Bonzini    "a1",
46139c1837SPaolo Bonzini    "a2",
47139c1837SPaolo Bonzini    "a3",
48139c1837SPaolo Bonzini    "a4",
49139c1837SPaolo Bonzini    "a5",
50139c1837SPaolo Bonzini    "a6",
51139c1837SPaolo Bonzini    "a7",
52139c1837SPaolo Bonzini    "s2",
53139c1837SPaolo Bonzini    "s3",
54139c1837SPaolo Bonzini    "s4",
55139c1837SPaolo Bonzini    "s5",
56139c1837SPaolo Bonzini    "s6",
57139c1837SPaolo Bonzini    "s7",
58139c1837SPaolo Bonzini    "s8",
59139c1837SPaolo Bonzini    "s9",
60139c1837SPaolo Bonzini    "s10",
61139c1837SPaolo Bonzini    "s11",
62139c1837SPaolo Bonzini    "t3",
63139c1837SPaolo Bonzini    "t4",
64139c1837SPaolo Bonzini    "t5",
65139c1837SPaolo Bonzini    "t6"
66139c1837SPaolo Bonzini};
67139c1837SPaolo Bonzini#endif
68139c1837SPaolo Bonzini
69139c1837SPaolo Bonzinistatic const int tcg_target_reg_alloc_order[] = {
70139c1837SPaolo Bonzini    /* Call saved registers */
71139c1837SPaolo Bonzini    /* TCG_REG_S0 reservered for TCG_AREG0 */
72139c1837SPaolo Bonzini    TCG_REG_S1,
73139c1837SPaolo Bonzini    TCG_REG_S2,
74139c1837SPaolo Bonzini    TCG_REG_S3,
75139c1837SPaolo Bonzini    TCG_REG_S4,
76139c1837SPaolo Bonzini    TCG_REG_S5,
77139c1837SPaolo Bonzini    TCG_REG_S6,
78139c1837SPaolo Bonzini    TCG_REG_S7,
79139c1837SPaolo Bonzini    TCG_REG_S8,
80139c1837SPaolo Bonzini    TCG_REG_S9,
81139c1837SPaolo Bonzini    TCG_REG_S10,
82139c1837SPaolo Bonzini    TCG_REG_S11,
83139c1837SPaolo Bonzini
84139c1837SPaolo Bonzini    /* Call clobbered registers */
85139c1837SPaolo Bonzini    TCG_REG_T0,
86139c1837SPaolo Bonzini    TCG_REG_T1,
87139c1837SPaolo Bonzini    TCG_REG_T2,
88139c1837SPaolo Bonzini    TCG_REG_T3,
89139c1837SPaolo Bonzini    TCG_REG_T4,
90139c1837SPaolo Bonzini    TCG_REG_T5,
91139c1837SPaolo Bonzini    TCG_REG_T6,
92139c1837SPaolo Bonzini
93139c1837SPaolo Bonzini    /* Argument registers */
94139c1837SPaolo Bonzini    TCG_REG_A0,
95139c1837SPaolo Bonzini    TCG_REG_A1,
96139c1837SPaolo Bonzini    TCG_REG_A2,
97139c1837SPaolo Bonzini    TCG_REG_A3,
98139c1837SPaolo Bonzini    TCG_REG_A4,
99139c1837SPaolo Bonzini    TCG_REG_A5,
100139c1837SPaolo Bonzini    TCG_REG_A6,
101139c1837SPaolo Bonzini    TCG_REG_A7,
102139c1837SPaolo Bonzini};
103139c1837SPaolo Bonzini
104139c1837SPaolo Bonzinistatic const int tcg_target_call_iarg_regs[] = {
105139c1837SPaolo Bonzini    TCG_REG_A0,
106139c1837SPaolo Bonzini    TCG_REG_A1,
107139c1837SPaolo Bonzini    TCG_REG_A2,
108139c1837SPaolo Bonzini    TCG_REG_A3,
109139c1837SPaolo Bonzini    TCG_REG_A4,
110139c1837SPaolo Bonzini    TCG_REG_A5,
111139c1837SPaolo Bonzini    TCG_REG_A6,
112139c1837SPaolo Bonzini    TCG_REG_A7,
113139c1837SPaolo Bonzini};
114139c1837SPaolo Bonzini
115139c1837SPaolo Bonzinistatic const int tcg_target_call_oarg_regs[] = {
116139c1837SPaolo Bonzini    TCG_REG_A0,
117139c1837SPaolo Bonzini    TCG_REG_A1,
118139c1837SPaolo Bonzini};
119139c1837SPaolo Bonzini
120139c1837SPaolo Bonzini#define TCG_CT_CONST_ZERO  0x100
121139c1837SPaolo Bonzini#define TCG_CT_CONST_S12   0x200
122139c1837SPaolo Bonzini#define TCG_CT_CONST_N12   0x400
123139c1837SPaolo Bonzini#define TCG_CT_CONST_M12   0x800
124139c1837SPaolo Bonzini
125fc63a4c5SRichard Henderson#define ALL_GENERAL_REGS      MAKE_64BIT_MASK(0, 32)
126fc63a4c5SRichard Henderson/*
127fc63a4c5SRichard Henderson * For softmmu, we need to avoid conflicts with the first 5
128fc63a4c5SRichard Henderson * argument registers to call the helper.  Some of these are
129fc63a4c5SRichard Henderson * also used for the tlb lookup.
130fc63a4c5SRichard Henderson */
131fc63a4c5SRichard Henderson#ifdef CONFIG_SOFTMMU
132fc63a4c5SRichard Henderson#define SOFTMMU_RESERVE_REGS  MAKE_64BIT_MASK(TCG_REG_A0, 5)
133fc63a4c5SRichard Henderson#else
134fc63a4c5SRichard Henderson#define SOFTMMU_RESERVE_REGS  0
135fc63a4c5SRichard Henderson#endif
136fc63a4c5SRichard Henderson
137fc63a4c5SRichard Henderson
138139c1837SPaolo Bonzinistatic inline tcg_target_long sextreg(tcg_target_long val, int pos, int len)
139139c1837SPaolo Bonzini{
140139c1837SPaolo Bonzini    if (TCG_TARGET_REG_BITS == 32) {
141139c1837SPaolo Bonzini        return sextract32(val, pos, len);
142139c1837SPaolo Bonzini    } else {
143139c1837SPaolo Bonzini        return sextract64(val, pos, len);
144139c1837SPaolo Bonzini    }
145139c1837SPaolo Bonzini}
146139c1837SPaolo Bonzini
147139c1837SPaolo Bonzini/* test if a constant matches the constraint */
148139c1837SPaolo Bonzinistatic int tcg_target_const_match(tcg_target_long val, TCGType type,
149139c1837SPaolo Bonzini                                  const TCGArgConstraint *arg_ct)
150139c1837SPaolo Bonzini{
151139c1837SPaolo Bonzini    int ct = arg_ct->ct;
152139c1837SPaolo Bonzini    if (ct & TCG_CT_CONST) {
153139c1837SPaolo Bonzini        return 1;
154139c1837SPaolo Bonzini    }
155139c1837SPaolo Bonzini    if ((ct & TCG_CT_CONST_ZERO) && val == 0) {
156139c1837SPaolo Bonzini        return 1;
157139c1837SPaolo Bonzini    }
158139c1837SPaolo Bonzini    if ((ct & TCG_CT_CONST_S12) && val == sextreg(val, 0, 12)) {
159139c1837SPaolo Bonzini        return 1;
160139c1837SPaolo Bonzini    }
161139c1837SPaolo Bonzini    if ((ct & TCG_CT_CONST_N12) && -val == sextreg(-val, 0, 12)) {
162139c1837SPaolo Bonzini        return 1;
163139c1837SPaolo Bonzini    }
164139c1837SPaolo Bonzini    if ((ct & TCG_CT_CONST_M12) && val >= -0xfff && val <= 0xfff) {
165139c1837SPaolo Bonzini        return 1;
166139c1837SPaolo Bonzini    }
167139c1837SPaolo Bonzini    return 0;
168139c1837SPaolo Bonzini}
169139c1837SPaolo Bonzini
170139c1837SPaolo Bonzini/*
171139c1837SPaolo Bonzini * RISC-V Base ISA opcodes (IM)
172139c1837SPaolo Bonzini */
173139c1837SPaolo Bonzini
174139c1837SPaolo Bonzinitypedef enum {
175139c1837SPaolo Bonzini    OPC_ADD = 0x33,
176139c1837SPaolo Bonzini    OPC_ADDI = 0x13,
177139c1837SPaolo Bonzini    OPC_AND = 0x7033,
178139c1837SPaolo Bonzini    OPC_ANDI = 0x7013,
179139c1837SPaolo Bonzini    OPC_AUIPC = 0x17,
180139c1837SPaolo Bonzini    OPC_BEQ = 0x63,
181139c1837SPaolo Bonzini    OPC_BGE = 0x5063,
182139c1837SPaolo Bonzini    OPC_BGEU = 0x7063,
183139c1837SPaolo Bonzini    OPC_BLT = 0x4063,
184139c1837SPaolo Bonzini    OPC_BLTU = 0x6063,
185139c1837SPaolo Bonzini    OPC_BNE = 0x1063,
186139c1837SPaolo Bonzini    OPC_DIV = 0x2004033,
187139c1837SPaolo Bonzini    OPC_DIVU = 0x2005033,
188139c1837SPaolo Bonzini    OPC_JAL = 0x6f,
189139c1837SPaolo Bonzini    OPC_JALR = 0x67,
190139c1837SPaolo Bonzini    OPC_LB = 0x3,
191139c1837SPaolo Bonzini    OPC_LBU = 0x4003,
192139c1837SPaolo Bonzini    OPC_LD = 0x3003,
193139c1837SPaolo Bonzini    OPC_LH = 0x1003,
194139c1837SPaolo Bonzini    OPC_LHU = 0x5003,
195139c1837SPaolo Bonzini    OPC_LUI = 0x37,
196139c1837SPaolo Bonzini    OPC_LW = 0x2003,
197139c1837SPaolo Bonzini    OPC_LWU = 0x6003,
198139c1837SPaolo Bonzini    OPC_MUL = 0x2000033,
199139c1837SPaolo Bonzini    OPC_MULH = 0x2001033,
200139c1837SPaolo Bonzini    OPC_MULHSU = 0x2002033,
201139c1837SPaolo Bonzini    OPC_MULHU = 0x2003033,
202139c1837SPaolo Bonzini    OPC_OR = 0x6033,
203139c1837SPaolo Bonzini    OPC_ORI = 0x6013,
204139c1837SPaolo Bonzini    OPC_REM = 0x2006033,
205139c1837SPaolo Bonzini    OPC_REMU = 0x2007033,
206139c1837SPaolo Bonzini    OPC_SB = 0x23,
207139c1837SPaolo Bonzini    OPC_SD = 0x3023,
208139c1837SPaolo Bonzini    OPC_SH = 0x1023,
209139c1837SPaolo Bonzini    OPC_SLL = 0x1033,
210139c1837SPaolo Bonzini    OPC_SLLI = 0x1013,
211139c1837SPaolo Bonzini    OPC_SLT = 0x2033,
212139c1837SPaolo Bonzini    OPC_SLTI = 0x2013,
213139c1837SPaolo Bonzini    OPC_SLTIU = 0x3013,
214139c1837SPaolo Bonzini    OPC_SLTU = 0x3033,
215139c1837SPaolo Bonzini    OPC_SRA = 0x40005033,
216139c1837SPaolo Bonzini    OPC_SRAI = 0x40005013,
217139c1837SPaolo Bonzini    OPC_SRL = 0x5033,
218139c1837SPaolo Bonzini    OPC_SRLI = 0x5013,
219139c1837SPaolo Bonzini    OPC_SUB = 0x40000033,
220139c1837SPaolo Bonzini    OPC_SW = 0x2023,
221139c1837SPaolo Bonzini    OPC_XOR = 0x4033,
222139c1837SPaolo Bonzini    OPC_XORI = 0x4013,
223139c1837SPaolo Bonzini
224139c1837SPaolo Bonzini#if TCG_TARGET_REG_BITS == 64
225139c1837SPaolo Bonzini    OPC_ADDIW = 0x1b,
226139c1837SPaolo Bonzini    OPC_ADDW = 0x3b,
227139c1837SPaolo Bonzini    OPC_DIVUW = 0x200503b,
228139c1837SPaolo Bonzini    OPC_DIVW = 0x200403b,
229139c1837SPaolo Bonzini    OPC_MULW = 0x200003b,
230139c1837SPaolo Bonzini    OPC_REMUW = 0x200703b,
231139c1837SPaolo Bonzini    OPC_REMW = 0x200603b,
232139c1837SPaolo Bonzini    OPC_SLLIW = 0x101b,
233139c1837SPaolo Bonzini    OPC_SLLW = 0x103b,
234139c1837SPaolo Bonzini    OPC_SRAIW = 0x4000501b,
235139c1837SPaolo Bonzini    OPC_SRAW = 0x4000503b,
236139c1837SPaolo Bonzini    OPC_SRLIW = 0x501b,
237139c1837SPaolo Bonzini    OPC_SRLW = 0x503b,
238139c1837SPaolo Bonzini    OPC_SUBW = 0x4000003b,
239139c1837SPaolo Bonzini#else
240139c1837SPaolo Bonzini    /* Simplify code throughout by defining aliases for RV32.  */
241139c1837SPaolo Bonzini    OPC_ADDIW = OPC_ADDI,
242139c1837SPaolo Bonzini    OPC_ADDW = OPC_ADD,
243139c1837SPaolo Bonzini    OPC_DIVUW = OPC_DIVU,
244139c1837SPaolo Bonzini    OPC_DIVW = OPC_DIV,
245139c1837SPaolo Bonzini    OPC_MULW = OPC_MUL,
246139c1837SPaolo Bonzini    OPC_REMUW = OPC_REMU,
247139c1837SPaolo Bonzini    OPC_REMW = OPC_REM,
248139c1837SPaolo Bonzini    OPC_SLLIW = OPC_SLLI,
249139c1837SPaolo Bonzini    OPC_SLLW = OPC_SLL,
250139c1837SPaolo Bonzini    OPC_SRAIW = OPC_SRAI,
251139c1837SPaolo Bonzini    OPC_SRAW = OPC_SRA,
252139c1837SPaolo Bonzini    OPC_SRLIW = OPC_SRLI,
253139c1837SPaolo Bonzini    OPC_SRLW = OPC_SRL,
254139c1837SPaolo Bonzini    OPC_SUBW = OPC_SUB,
255139c1837SPaolo Bonzini#endif
256139c1837SPaolo Bonzini
257139c1837SPaolo Bonzini    OPC_FENCE = 0x0000000f,
258139c1837SPaolo Bonzini} RISCVInsn;
259139c1837SPaolo Bonzini
260139c1837SPaolo Bonzini/*
261139c1837SPaolo Bonzini * RISC-V immediate and instruction encoders (excludes 16-bit RVC)
262139c1837SPaolo Bonzini */
263139c1837SPaolo Bonzini
264139c1837SPaolo Bonzini/* Type-R */
265139c1837SPaolo Bonzini
266139c1837SPaolo Bonzinistatic int32_t encode_r(RISCVInsn opc, TCGReg rd, TCGReg rs1, TCGReg rs2)
267139c1837SPaolo Bonzini{
268139c1837SPaolo Bonzini    return opc | (rd & 0x1f) << 7 | (rs1 & 0x1f) << 15 | (rs2 & 0x1f) << 20;
269139c1837SPaolo Bonzini}
270139c1837SPaolo Bonzini
271139c1837SPaolo Bonzini/* Type-I */
272139c1837SPaolo Bonzini
273139c1837SPaolo Bonzinistatic int32_t encode_imm12(uint32_t imm)
274139c1837SPaolo Bonzini{
275139c1837SPaolo Bonzini    return (imm & 0xfff) << 20;
276139c1837SPaolo Bonzini}
277139c1837SPaolo Bonzini
278139c1837SPaolo Bonzinistatic int32_t encode_i(RISCVInsn opc, TCGReg rd, TCGReg rs1, uint32_t imm)
279139c1837SPaolo Bonzini{
280139c1837SPaolo Bonzini    return opc | (rd & 0x1f) << 7 | (rs1 & 0x1f) << 15 | encode_imm12(imm);
281139c1837SPaolo Bonzini}
282139c1837SPaolo Bonzini
283139c1837SPaolo Bonzini/* Type-S */
284139c1837SPaolo Bonzini
285139c1837SPaolo Bonzinistatic int32_t encode_simm12(uint32_t imm)
286139c1837SPaolo Bonzini{
287139c1837SPaolo Bonzini    int32_t ret = 0;
288139c1837SPaolo Bonzini
289139c1837SPaolo Bonzini    ret |= (imm & 0xFE0) << 20;
290139c1837SPaolo Bonzini    ret |= (imm & 0x1F) << 7;
291139c1837SPaolo Bonzini
292139c1837SPaolo Bonzini    return ret;
293139c1837SPaolo Bonzini}
294139c1837SPaolo Bonzini
295139c1837SPaolo Bonzinistatic int32_t encode_s(RISCVInsn opc, TCGReg rs1, TCGReg rs2, uint32_t imm)
296139c1837SPaolo Bonzini{
297139c1837SPaolo Bonzini    return opc | (rs1 & 0x1f) << 15 | (rs2 & 0x1f) << 20 | encode_simm12(imm);
298139c1837SPaolo Bonzini}
299139c1837SPaolo Bonzini
300139c1837SPaolo Bonzini/* Type-SB */
301139c1837SPaolo Bonzini
302139c1837SPaolo Bonzinistatic int32_t encode_sbimm12(uint32_t imm)
303139c1837SPaolo Bonzini{
304139c1837SPaolo Bonzini    int32_t ret = 0;
305139c1837SPaolo Bonzini
306139c1837SPaolo Bonzini    ret |= (imm & 0x1000) << 19;
307139c1837SPaolo Bonzini    ret |= (imm & 0x7e0) << 20;
308139c1837SPaolo Bonzini    ret |= (imm & 0x1e) << 7;
309139c1837SPaolo Bonzini    ret |= (imm & 0x800) >> 4;
310139c1837SPaolo Bonzini
311139c1837SPaolo Bonzini    return ret;
312139c1837SPaolo Bonzini}
313139c1837SPaolo Bonzini
314139c1837SPaolo Bonzinistatic int32_t encode_sb(RISCVInsn opc, TCGReg rs1, TCGReg rs2, uint32_t imm)
315139c1837SPaolo Bonzini{
316139c1837SPaolo Bonzini    return opc | (rs1 & 0x1f) << 15 | (rs2 & 0x1f) << 20 | encode_sbimm12(imm);
317139c1837SPaolo Bonzini}
318139c1837SPaolo Bonzini
319139c1837SPaolo Bonzini/* Type-U */
320139c1837SPaolo Bonzini
321139c1837SPaolo Bonzinistatic int32_t encode_uimm20(uint32_t imm)
322139c1837SPaolo Bonzini{
323139c1837SPaolo Bonzini    return imm & 0xfffff000;
324139c1837SPaolo Bonzini}
325139c1837SPaolo Bonzini
326139c1837SPaolo Bonzinistatic int32_t encode_u(RISCVInsn opc, TCGReg rd, uint32_t imm)
327139c1837SPaolo Bonzini{
328139c1837SPaolo Bonzini    return opc | (rd & 0x1f) << 7 | encode_uimm20(imm);
329139c1837SPaolo Bonzini}
330139c1837SPaolo Bonzini
331139c1837SPaolo Bonzini/* Type-UJ */
332139c1837SPaolo Bonzini
333139c1837SPaolo Bonzinistatic int32_t encode_ujimm20(uint32_t imm)
334139c1837SPaolo Bonzini{
335139c1837SPaolo Bonzini    int32_t ret = 0;
336139c1837SPaolo Bonzini
337139c1837SPaolo Bonzini    ret |= (imm & 0x0007fe) << (21 - 1);
338139c1837SPaolo Bonzini    ret |= (imm & 0x000800) << (20 - 11);
339139c1837SPaolo Bonzini    ret |= (imm & 0x0ff000) << (12 - 12);
340139c1837SPaolo Bonzini    ret |= (imm & 0x100000) << (31 - 20);
341139c1837SPaolo Bonzini
342139c1837SPaolo Bonzini    return ret;
343139c1837SPaolo Bonzini}
344139c1837SPaolo Bonzini
345139c1837SPaolo Bonzinistatic int32_t encode_uj(RISCVInsn opc, TCGReg rd, uint32_t imm)
346139c1837SPaolo Bonzini{
347139c1837SPaolo Bonzini    return opc | (rd & 0x1f) << 7 | encode_ujimm20(imm);
348139c1837SPaolo Bonzini}
349139c1837SPaolo Bonzini
350139c1837SPaolo Bonzini/*
351139c1837SPaolo Bonzini * RISC-V instruction emitters
352139c1837SPaolo Bonzini */
353139c1837SPaolo Bonzini
354139c1837SPaolo Bonzinistatic void tcg_out_opc_reg(TCGContext *s, RISCVInsn opc,
355139c1837SPaolo Bonzini                            TCGReg rd, TCGReg rs1, TCGReg rs2)
356139c1837SPaolo Bonzini{
357139c1837SPaolo Bonzini    tcg_out32(s, encode_r(opc, rd, rs1, rs2));
358139c1837SPaolo Bonzini}
359139c1837SPaolo Bonzini
360139c1837SPaolo Bonzinistatic void tcg_out_opc_imm(TCGContext *s, RISCVInsn opc,
361139c1837SPaolo Bonzini                            TCGReg rd, TCGReg rs1, TCGArg imm)
362139c1837SPaolo Bonzini{
363139c1837SPaolo Bonzini    tcg_out32(s, encode_i(opc, rd, rs1, imm));
364139c1837SPaolo Bonzini}
365139c1837SPaolo Bonzini
366139c1837SPaolo Bonzinistatic void tcg_out_opc_store(TCGContext *s, RISCVInsn opc,
367139c1837SPaolo Bonzini                              TCGReg rs1, TCGReg rs2, uint32_t imm)
368139c1837SPaolo Bonzini{
369139c1837SPaolo Bonzini    tcg_out32(s, encode_s(opc, rs1, rs2, imm));
370139c1837SPaolo Bonzini}
371139c1837SPaolo Bonzini
372139c1837SPaolo Bonzinistatic void tcg_out_opc_branch(TCGContext *s, RISCVInsn opc,
373139c1837SPaolo Bonzini                               TCGReg rs1, TCGReg rs2, uint32_t imm)
374139c1837SPaolo Bonzini{
375139c1837SPaolo Bonzini    tcg_out32(s, encode_sb(opc, rs1, rs2, imm));
376139c1837SPaolo Bonzini}
377139c1837SPaolo Bonzini
378139c1837SPaolo Bonzinistatic void tcg_out_opc_upper(TCGContext *s, RISCVInsn opc,
379139c1837SPaolo Bonzini                              TCGReg rd, uint32_t imm)
380139c1837SPaolo Bonzini{
381139c1837SPaolo Bonzini    tcg_out32(s, encode_u(opc, rd, imm));
382139c1837SPaolo Bonzini}
383139c1837SPaolo Bonzini
384139c1837SPaolo Bonzinistatic void tcg_out_opc_jump(TCGContext *s, RISCVInsn opc,
385139c1837SPaolo Bonzini                             TCGReg rd, uint32_t imm)
386139c1837SPaolo Bonzini{
387139c1837SPaolo Bonzini    tcg_out32(s, encode_uj(opc, rd, imm));
388139c1837SPaolo Bonzini}
389139c1837SPaolo Bonzini
390139c1837SPaolo Bonzinistatic void tcg_out_nop_fill(tcg_insn_unit *p, int count)
391139c1837SPaolo Bonzini{
392139c1837SPaolo Bonzini    int i;
393139c1837SPaolo Bonzini    for (i = 0; i < count; ++i) {
394139c1837SPaolo Bonzini        p[i] = encode_i(OPC_ADDI, TCG_REG_ZERO, TCG_REG_ZERO, 0);
395139c1837SPaolo Bonzini    }
396139c1837SPaolo Bonzini}
397139c1837SPaolo Bonzini
398139c1837SPaolo Bonzini/*
399139c1837SPaolo Bonzini * Relocations
400139c1837SPaolo Bonzini */
401139c1837SPaolo Bonzini
402793f7381SRichard Hendersonstatic bool reloc_sbimm12(tcg_insn_unit *src_rw, const tcg_insn_unit *target)
403139c1837SPaolo Bonzini{
404793f7381SRichard Henderson    const tcg_insn_unit *src_rx = tcg_splitwx_to_rx(src_rw);
405793f7381SRichard Henderson    intptr_t offset = (intptr_t)target - (intptr_t)src_rx;
406139c1837SPaolo Bonzini
407844d0442SRichard Henderson    tcg_debug_assert((offset & 1) == 0);
408844d0442SRichard Henderson    if (offset == sextreg(offset, 0, 12)) {
409793f7381SRichard Henderson        *src_rw |= encode_sbimm12(offset);
410139c1837SPaolo Bonzini        return true;
411139c1837SPaolo Bonzini    }
412139c1837SPaolo Bonzini
413139c1837SPaolo Bonzini    return false;
414139c1837SPaolo Bonzini}
415139c1837SPaolo Bonzini
416793f7381SRichard Hendersonstatic bool reloc_jimm20(tcg_insn_unit *src_rw, const tcg_insn_unit *target)
417139c1837SPaolo Bonzini{
418793f7381SRichard Henderson    const tcg_insn_unit *src_rx = tcg_splitwx_to_rx(src_rw);
419793f7381SRichard Henderson    intptr_t offset = (intptr_t)target - (intptr_t)src_rx;
420139c1837SPaolo Bonzini
421844d0442SRichard Henderson    tcg_debug_assert((offset & 1) == 0);
422844d0442SRichard Henderson    if (offset == sextreg(offset, 0, 20)) {
423793f7381SRichard Henderson        *src_rw |= encode_ujimm20(offset);
424139c1837SPaolo Bonzini        return true;
425139c1837SPaolo Bonzini    }
426139c1837SPaolo Bonzini
427139c1837SPaolo Bonzini    return false;
428139c1837SPaolo Bonzini}
429139c1837SPaolo Bonzini
430793f7381SRichard Hendersonstatic bool reloc_call(tcg_insn_unit *src_rw, const tcg_insn_unit *target)
431139c1837SPaolo Bonzini{
432793f7381SRichard Henderson    const tcg_insn_unit *src_rx = tcg_splitwx_to_rx(src_rw);
433793f7381SRichard Henderson    intptr_t offset = (intptr_t)target - (intptr_t)src_rx;
434139c1837SPaolo Bonzini    int32_t lo = sextreg(offset, 0, 12);
435139c1837SPaolo Bonzini    int32_t hi = offset - lo;
436139c1837SPaolo Bonzini
437139c1837SPaolo Bonzini    if (offset == hi + lo) {
438793f7381SRichard Henderson        src_rw[0] |= encode_uimm20(hi);
439793f7381SRichard Henderson        src_rw[1] |= encode_imm12(lo);
440139c1837SPaolo Bonzini        return true;
441139c1837SPaolo Bonzini    }
442139c1837SPaolo Bonzini
443139c1837SPaolo Bonzini    return false;
444139c1837SPaolo Bonzini}
445139c1837SPaolo Bonzini
446139c1837SPaolo Bonzinistatic bool patch_reloc(tcg_insn_unit *code_ptr, int type,
447139c1837SPaolo Bonzini                        intptr_t value, intptr_t addend)
448139c1837SPaolo Bonzini{
449139c1837SPaolo Bonzini    tcg_debug_assert(addend == 0);
450139c1837SPaolo Bonzini    switch (type) {
451139c1837SPaolo Bonzini    case R_RISCV_BRANCH:
452139c1837SPaolo Bonzini        return reloc_sbimm12(code_ptr, (tcg_insn_unit *)value);
453139c1837SPaolo Bonzini    case R_RISCV_JAL:
454139c1837SPaolo Bonzini        return reloc_jimm20(code_ptr, (tcg_insn_unit *)value);
455139c1837SPaolo Bonzini    case R_RISCV_CALL:
456139c1837SPaolo Bonzini        return reloc_call(code_ptr, (tcg_insn_unit *)value);
457139c1837SPaolo Bonzini    default:
4584b6a52d0SRichard Henderson        g_assert_not_reached();
459139c1837SPaolo Bonzini    }
460139c1837SPaolo Bonzini}
461139c1837SPaolo Bonzini
462139c1837SPaolo Bonzini/*
463139c1837SPaolo Bonzini * TCG intrinsics
464139c1837SPaolo Bonzini */
465139c1837SPaolo Bonzini
466139c1837SPaolo Bonzinistatic bool tcg_out_mov(TCGContext *s, TCGType type, TCGReg ret, TCGReg arg)
467139c1837SPaolo Bonzini{
468139c1837SPaolo Bonzini    if (ret == arg) {
469139c1837SPaolo Bonzini        return true;
470139c1837SPaolo Bonzini    }
471139c1837SPaolo Bonzini    switch (type) {
472139c1837SPaolo Bonzini    case TCG_TYPE_I32:
473139c1837SPaolo Bonzini    case TCG_TYPE_I64:
474139c1837SPaolo Bonzini        tcg_out_opc_imm(s, OPC_ADDI, ret, arg, 0);
475139c1837SPaolo Bonzini        break;
476139c1837SPaolo Bonzini    default:
477139c1837SPaolo Bonzini        g_assert_not_reached();
478139c1837SPaolo Bonzini    }
479139c1837SPaolo Bonzini    return true;
480139c1837SPaolo Bonzini}
481139c1837SPaolo Bonzini
482139c1837SPaolo Bonzinistatic void tcg_out_movi(TCGContext *s, TCGType type, TCGReg rd,
483139c1837SPaolo Bonzini                         tcg_target_long val)
484139c1837SPaolo Bonzini{
485139c1837SPaolo Bonzini    tcg_target_long lo, hi, tmp;
486139c1837SPaolo Bonzini    int shift, ret;
487139c1837SPaolo Bonzini
488139c1837SPaolo Bonzini    if (TCG_TARGET_REG_BITS == 64 && type == TCG_TYPE_I32) {
489139c1837SPaolo Bonzini        val = (int32_t)val;
490139c1837SPaolo Bonzini    }
491139c1837SPaolo Bonzini
492139c1837SPaolo Bonzini    lo = sextreg(val, 0, 12);
493139c1837SPaolo Bonzini    if (val == lo) {
494139c1837SPaolo Bonzini        tcg_out_opc_imm(s, OPC_ADDI, rd, TCG_REG_ZERO, lo);
495139c1837SPaolo Bonzini        return;
496139c1837SPaolo Bonzini    }
497139c1837SPaolo Bonzini
498139c1837SPaolo Bonzini    hi = val - lo;
499139c1837SPaolo Bonzini    if (TCG_TARGET_REG_BITS == 32 || val == (int32_t)val) {
500139c1837SPaolo Bonzini        tcg_out_opc_upper(s, OPC_LUI, rd, hi);
501139c1837SPaolo Bonzini        if (lo != 0) {
502139c1837SPaolo Bonzini            tcg_out_opc_imm(s, OPC_ADDIW, rd, rd, lo);
503139c1837SPaolo Bonzini        }
504139c1837SPaolo Bonzini        return;
505139c1837SPaolo Bonzini    }
506139c1837SPaolo Bonzini
507139c1837SPaolo Bonzini    /* We can only be here if TCG_TARGET_REG_BITS != 32 */
508139c1837SPaolo Bonzini    tmp = tcg_pcrel_diff(s, (void *)val);
509139c1837SPaolo Bonzini    if (tmp == (int32_t)tmp) {
510139c1837SPaolo Bonzini        tcg_out_opc_upper(s, OPC_AUIPC, rd, 0);
511139c1837SPaolo Bonzini        tcg_out_opc_imm(s, OPC_ADDI, rd, rd, 0);
512793f7381SRichard Henderson        ret = reloc_call(s->code_ptr - 2, (const tcg_insn_unit *)val);
513139c1837SPaolo Bonzini        tcg_debug_assert(ret == true);
514139c1837SPaolo Bonzini        return;
515139c1837SPaolo Bonzini    }
516139c1837SPaolo Bonzini
517139c1837SPaolo Bonzini    /* Look for a single 20-bit section.  */
518139c1837SPaolo Bonzini    shift = ctz64(val);
519139c1837SPaolo Bonzini    tmp = val >> shift;
520139c1837SPaolo Bonzini    if (tmp == sextreg(tmp, 0, 20)) {
521139c1837SPaolo Bonzini        tcg_out_opc_upper(s, OPC_LUI, rd, tmp << 12);
522139c1837SPaolo Bonzini        if (shift > 12) {
523139c1837SPaolo Bonzini            tcg_out_opc_imm(s, OPC_SLLI, rd, rd, shift - 12);
524139c1837SPaolo Bonzini        } else {
525139c1837SPaolo Bonzini            tcg_out_opc_imm(s, OPC_SRAI, rd, rd, 12 - shift);
526139c1837SPaolo Bonzini        }
527139c1837SPaolo Bonzini        return;
528139c1837SPaolo Bonzini    }
529139c1837SPaolo Bonzini
530139c1837SPaolo Bonzini    /* Look for a few high zero bits, with lots of bits set in the middle.  */
531139c1837SPaolo Bonzini    shift = clz64(val);
532139c1837SPaolo Bonzini    tmp = val << shift;
533139c1837SPaolo Bonzini    if (tmp == sextreg(tmp, 12, 20) << 12) {
534139c1837SPaolo Bonzini        tcg_out_opc_upper(s, OPC_LUI, rd, tmp);
535139c1837SPaolo Bonzini        tcg_out_opc_imm(s, OPC_SRLI, rd, rd, shift);
536139c1837SPaolo Bonzini        return;
537139c1837SPaolo Bonzini    } else if (tmp == sextreg(tmp, 0, 12)) {
538139c1837SPaolo Bonzini        tcg_out_opc_imm(s, OPC_ADDI, rd, TCG_REG_ZERO, tmp);
539139c1837SPaolo Bonzini        tcg_out_opc_imm(s, OPC_SRLI, rd, rd, shift);
540139c1837SPaolo Bonzini        return;
541139c1837SPaolo Bonzini    }
542139c1837SPaolo Bonzini
543139c1837SPaolo Bonzini    /* Drop into the constant pool.  */
544139c1837SPaolo Bonzini    new_pool_label(s, val, R_RISCV_CALL, s->code_ptr, 0);
545139c1837SPaolo Bonzini    tcg_out_opc_upper(s, OPC_AUIPC, rd, 0);
546139c1837SPaolo Bonzini    tcg_out_opc_imm(s, OPC_LD, rd, rd, 0);
547139c1837SPaolo Bonzini}
548139c1837SPaolo Bonzini
549139c1837SPaolo Bonzinistatic void tcg_out_ext8u(TCGContext *s, TCGReg ret, TCGReg arg)
550139c1837SPaolo Bonzini{
551139c1837SPaolo Bonzini    tcg_out_opc_imm(s, OPC_ANDI, ret, arg, 0xff);
552139c1837SPaolo Bonzini}
553139c1837SPaolo Bonzini
554139c1837SPaolo Bonzinistatic void tcg_out_ext16u(TCGContext *s, TCGReg ret, TCGReg arg)
555139c1837SPaolo Bonzini{
556139c1837SPaolo Bonzini    tcg_out_opc_imm(s, OPC_SLLIW, ret, arg, 16);
557139c1837SPaolo Bonzini    tcg_out_opc_imm(s, OPC_SRLIW, ret, ret, 16);
558139c1837SPaolo Bonzini}
559139c1837SPaolo Bonzini
560139c1837SPaolo Bonzinistatic void tcg_out_ext32u(TCGContext *s, TCGReg ret, TCGReg arg)
561139c1837SPaolo Bonzini{
562139c1837SPaolo Bonzini    tcg_out_opc_imm(s, OPC_SLLI, ret, arg, 32);
563139c1837SPaolo Bonzini    tcg_out_opc_imm(s, OPC_SRLI, ret, ret, 32);
564139c1837SPaolo Bonzini}
565139c1837SPaolo Bonzini
566139c1837SPaolo Bonzinistatic void tcg_out_ext8s(TCGContext *s, TCGReg ret, TCGReg arg)
567139c1837SPaolo Bonzini{
568139c1837SPaolo Bonzini    tcg_out_opc_imm(s, OPC_SLLIW, ret, arg, 24);
569139c1837SPaolo Bonzini    tcg_out_opc_imm(s, OPC_SRAIW, ret, ret, 24);
570139c1837SPaolo Bonzini}
571139c1837SPaolo Bonzini
572139c1837SPaolo Bonzinistatic void tcg_out_ext16s(TCGContext *s, TCGReg ret, TCGReg arg)
573139c1837SPaolo Bonzini{
574139c1837SPaolo Bonzini    tcg_out_opc_imm(s, OPC_SLLIW, ret, arg, 16);
575139c1837SPaolo Bonzini    tcg_out_opc_imm(s, OPC_SRAIW, ret, ret, 16);
576139c1837SPaolo Bonzini}
577139c1837SPaolo Bonzini
578139c1837SPaolo Bonzinistatic void tcg_out_ext32s(TCGContext *s, TCGReg ret, TCGReg arg)
579139c1837SPaolo Bonzini{
580139c1837SPaolo Bonzini    tcg_out_opc_imm(s, OPC_ADDIW, ret, arg, 0);
581139c1837SPaolo Bonzini}
582139c1837SPaolo Bonzini
583139c1837SPaolo Bonzinistatic void tcg_out_ldst(TCGContext *s, RISCVInsn opc, TCGReg data,
584139c1837SPaolo Bonzini                         TCGReg addr, intptr_t offset)
585139c1837SPaolo Bonzini{
586139c1837SPaolo Bonzini    intptr_t imm12 = sextreg(offset, 0, 12);
587139c1837SPaolo Bonzini
588139c1837SPaolo Bonzini    if (offset != imm12) {
589139c1837SPaolo Bonzini        intptr_t diff = offset - (uintptr_t)s->code_ptr;
590139c1837SPaolo Bonzini
591139c1837SPaolo Bonzini        if (addr == TCG_REG_ZERO && diff == (int32_t)diff) {
592139c1837SPaolo Bonzini            imm12 = sextreg(diff, 0, 12);
593139c1837SPaolo Bonzini            tcg_out_opc_upper(s, OPC_AUIPC, TCG_REG_TMP2, diff - imm12);
594139c1837SPaolo Bonzini        } else {
595139c1837SPaolo Bonzini            tcg_out_movi(s, TCG_TYPE_PTR, TCG_REG_TMP2, offset - imm12);
596139c1837SPaolo Bonzini            if (addr != TCG_REG_ZERO) {
597139c1837SPaolo Bonzini                tcg_out_opc_reg(s, OPC_ADD, TCG_REG_TMP2, TCG_REG_TMP2, addr);
598139c1837SPaolo Bonzini            }
599139c1837SPaolo Bonzini        }
600139c1837SPaolo Bonzini        addr = TCG_REG_TMP2;
601139c1837SPaolo Bonzini    }
602139c1837SPaolo Bonzini
603139c1837SPaolo Bonzini    switch (opc) {
604139c1837SPaolo Bonzini    case OPC_SB:
605139c1837SPaolo Bonzini    case OPC_SH:
606139c1837SPaolo Bonzini    case OPC_SW:
607139c1837SPaolo Bonzini    case OPC_SD:
608139c1837SPaolo Bonzini        tcg_out_opc_store(s, opc, addr, data, imm12);
609139c1837SPaolo Bonzini        break;
610139c1837SPaolo Bonzini    case OPC_LB:
611139c1837SPaolo Bonzini    case OPC_LBU:
612139c1837SPaolo Bonzini    case OPC_LH:
613139c1837SPaolo Bonzini    case OPC_LHU:
614139c1837SPaolo Bonzini    case OPC_LW:
615139c1837SPaolo Bonzini    case OPC_LWU:
616139c1837SPaolo Bonzini    case OPC_LD:
617139c1837SPaolo Bonzini        tcg_out_opc_imm(s, opc, data, addr, imm12);
618139c1837SPaolo Bonzini        break;
619139c1837SPaolo Bonzini    default:
620139c1837SPaolo Bonzini        g_assert_not_reached();
621139c1837SPaolo Bonzini    }
622139c1837SPaolo Bonzini}
623139c1837SPaolo Bonzini
624139c1837SPaolo Bonzinistatic void tcg_out_ld(TCGContext *s, TCGType type, TCGReg arg,
625139c1837SPaolo Bonzini                       TCGReg arg1, intptr_t arg2)
626139c1837SPaolo Bonzini{
627139c1837SPaolo Bonzini    bool is32bit = (TCG_TARGET_REG_BITS == 32 || type == TCG_TYPE_I32);
628139c1837SPaolo Bonzini    tcg_out_ldst(s, is32bit ? OPC_LW : OPC_LD, arg, arg1, arg2);
629139c1837SPaolo Bonzini}
630139c1837SPaolo Bonzini
631139c1837SPaolo Bonzinistatic void tcg_out_st(TCGContext *s, TCGType type, TCGReg arg,
632139c1837SPaolo Bonzini                       TCGReg arg1, intptr_t arg2)
633139c1837SPaolo Bonzini{
634139c1837SPaolo Bonzini    bool is32bit = (TCG_TARGET_REG_BITS == 32 || type == TCG_TYPE_I32);
635139c1837SPaolo Bonzini    tcg_out_ldst(s, is32bit ? OPC_SW : OPC_SD, arg, arg1, arg2);
636139c1837SPaolo Bonzini}
637139c1837SPaolo Bonzini
638139c1837SPaolo Bonzinistatic bool tcg_out_sti(TCGContext *s, TCGType type, TCGArg val,
639139c1837SPaolo Bonzini                        TCGReg base, intptr_t ofs)
640139c1837SPaolo Bonzini{
641139c1837SPaolo Bonzini    if (val == 0) {
642139c1837SPaolo Bonzini        tcg_out_st(s, type, TCG_REG_ZERO, base, ofs);
643139c1837SPaolo Bonzini        return true;
644139c1837SPaolo Bonzini    }
645139c1837SPaolo Bonzini    return false;
646139c1837SPaolo Bonzini}
647139c1837SPaolo Bonzini
648139c1837SPaolo Bonzinistatic void tcg_out_addsub2(TCGContext *s,
649139c1837SPaolo Bonzini                            TCGReg rl, TCGReg rh,
650139c1837SPaolo Bonzini                            TCGReg al, TCGReg ah,
651139c1837SPaolo Bonzini                            TCGArg bl, TCGArg bh,
652139c1837SPaolo Bonzini                            bool cbl, bool cbh, bool is_sub, bool is32bit)
653139c1837SPaolo Bonzini{
654139c1837SPaolo Bonzini    const RISCVInsn opc_add = is32bit ? OPC_ADDW : OPC_ADD;
655139c1837SPaolo Bonzini    const RISCVInsn opc_addi = is32bit ? OPC_ADDIW : OPC_ADDI;
656139c1837SPaolo Bonzini    const RISCVInsn opc_sub = is32bit ? OPC_SUBW : OPC_SUB;
657139c1837SPaolo Bonzini    TCGReg th = TCG_REG_TMP1;
658139c1837SPaolo Bonzini
659139c1837SPaolo Bonzini    /* If we have a negative constant such that negating it would
660139c1837SPaolo Bonzini       make the high part zero, we can (usually) eliminate one insn.  */
661139c1837SPaolo Bonzini    if (cbl && cbh && bh == -1 && bl != 0) {
662139c1837SPaolo Bonzini        bl = -bl;
663139c1837SPaolo Bonzini        bh = 0;
664139c1837SPaolo Bonzini        is_sub = !is_sub;
665139c1837SPaolo Bonzini    }
666139c1837SPaolo Bonzini
667139c1837SPaolo Bonzini    /* By operating on the high part first, we get to use the final
668139c1837SPaolo Bonzini       carry operation to move back from the temporary.  */
669139c1837SPaolo Bonzini    if (!cbh) {
670139c1837SPaolo Bonzini        tcg_out_opc_reg(s, (is_sub ? opc_sub : opc_add), th, ah, bh);
671139c1837SPaolo Bonzini    } else if (bh != 0 || ah == rl) {
672139c1837SPaolo Bonzini        tcg_out_opc_imm(s, opc_addi, th, ah, (is_sub ? -bh : bh));
673139c1837SPaolo Bonzini    } else {
674139c1837SPaolo Bonzini        th = ah;
675139c1837SPaolo Bonzini    }
676139c1837SPaolo Bonzini
677139c1837SPaolo Bonzini    /* Note that tcg optimization should eliminate the bl == 0 case.  */
678139c1837SPaolo Bonzini    if (is_sub) {
679139c1837SPaolo Bonzini        if (cbl) {
680139c1837SPaolo Bonzini            tcg_out_opc_imm(s, OPC_SLTIU, TCG_REG_TMP0, al, bl);
681139c1837SPaolo Bonzini            tcg_out_opc_imm(s, opc_addi, rl, al, -bl);
682139c1837SPaolo Bonzini        } else {
683139c1837SPaolo Bonzini            tcg_out_opc_reg(s, OPC_SLTU, TCG_REG_TMP0, al, bl);
684139c1837SPaolo Bonzini            tcg_out_opc_reg(s, opc_sub, rl, al, bl);
685139c1837SPaolo Bonzini        }
686139c1837SPaolo Bonzini        tcg_out_opc_reg(s, opc_sub, rh, th, TCG_REG_TMP0);
687139c1837SPaolo Bonzini    } else {
688139c1837SPaolo Bonzini        if (cbl) {
689139c1837SPaolo Bonzini            tcg_out_opc_imm(s, opc_addi, rl, al, bl);
690139c1837SPaolo Bonzini            tcg_out_opc_imm(s, OPC_SLTIU, TCG_REG_TMP0, rl, bl);
691139c1837SPaolo Bonzini        } else if (rl == al && rl == bl) {
692139c1837SPaolo Bonzini            tcg_out_opc_imm(s, OPC_SLTI, TCG_REG_TMP0, al, 0);
693139c1837SPaolo Bonzini            tcg_out_opc_reg(s, opc_addi, rl, al, bl);
694139c1837SPaolo Bonzini        } else {
695139c1837SPaolo Bonzini            tcg_out_opc_reg(s, opc_add, rl, al, bl);
696139c1837SPaolo Bonzini            tcg_out_opc_reg(s, OPC_SLTU, TCG_REG_TMP0,
697139c1837SPaolo Bonzini                            rl, (rl == bl ? al : bl));
698139c1837SPaolo Bonzini        }
699139c1837SPaolo Bonzini        tcg_out_opc_reg(s, opc_add, rh, th, TCG_REG_TMP0);
700139c1837SPaolo Bonzini    }
701139c1837SPaolo Bonzini}
702139c1837SPaolo Bonzini
703139c1837SPaolo Bonzinistatic const struct {
704139c1837SPaolo Bonzini    RISCVInsn op;
705139c1837SPaolo Bonzini    bool swap;
706139c1837SPaolo Bonzini} tcg_brcond_to_riscv[] = {
707139c1837SPaolo Bonzini    [TCG_COND_EQ] =  { OPC_BEQ,  false },
708139c1837SPaolo Bonzini    [TCG_COND_NE] =  { OPC_BNE,  false },
709139c1837SPaolo Bonzini    [TCG_COND_LT] =  { OPC_BLT,  false },
710139c1837SPaolo Bonzini    [TCG_COND_GE] =  { OPC_BGE,  false },
711139c1837SPaolo Bonzini    [TCG_COND_LE] =  { OPC_BGE,  true  },
712139c1837SPaolo Bonzini    [TCG_COND_GT] =  { OPC_BLT,  true  },
713139c1837SPaolo Bonzini    [TCG_COND_LTU] = { OPC_BLTU, false },
714139c1837SPaolo Bonzini    [TCG_COND_GEU] = { OPC_BGEU, false },
715139c1837SPaolo Bonzini    [TCG_COND_LEU] = { OPC_BGEU, true  },
716139c1837SPaolo Bonzini    [TCG_COND_GTU] = { OPC_BLTU, true  }
717139c1837SPaolo Bonzini};
718139c1837SPaolo Bonzini
719139c1837SPaolo Bonzinistatic void tcg_out_brcond(TCGContext *s, TCGCond cond, TCGReg arg1,
720139c1837SPaolo Bonzini                           TCGReg arg2, TCGLabel *l)
721139c1837SPaolo Bonzini{
722139c1837SPaolo Bonzini    RISCVInsn op = tcg_brcond_to_riscv[cond].op;
723139c1837SPaolo Bonzini
724139c1837SPaolo Bonzini    tcg_debug_assert(op != 0);
725139c1837SPaolo Bonzini
726139c1837SPaolo Bonzini    if (tcg_brcond_to_riscv[cond].swap) {
727139c1837SPaolo Bonzini        TCGReg t = arg1;
728139c1837SPaolo Bonzini        arg1 = arg2;
729139c1837SPaolo Bonzini        arg2 = t;
730139c1837SPaolo Bonzini    }
731139c1837SPaolo Bonzini
732139c1837SPaolo Bonzini    tcg_out_reloc(s, s->code_ptr, R_RISCV_BRANCH, l, 0);
733139c1837SPaolo Bonzini    tcg_out_opc_branch(s, op, arg1, arg2, 0);
734139c1837SPaolo Bonzini}
735139c1837SPaolo Bonzini
736139c1837SPaolo Bonzinistatic void tcg_out_setcond(TCGContext *s, TCGCond cond, TCGReg ret,
737139c1837SPaolo Bonzini                            TCGReg arg1, TCGReg arg2)
738139c1837SPaolo Bonzini{
739139c1837SPaolo Bonzini    switch (cond) {
740139c1837SPaolo Bonzini    case TCG_COND_EQ:
741139c1837SPaolo Bonzini        tcg_out_opc_reg(s, OPC_SUB, ret, arg1, arg2);
742139c1837SPaolo Bonzini        tcg_out_opc_imm(s, OPC_SLTIU, ret, ret, 1);
743139c1837SPaolo Bonzini        break;
744139c1837SPaolo Bonzini    case TCG_COND_NE:
745139c1837SPaolo Bonzini        tcg_out_opc_reg(s, OPC_SUB, ret, arg1, arg2);
746139c1837SPaolo Bonzini        tcg_out_opc_reg(s, OPC_SLTU, ret, TCG_REG_ZERO, ret);
747139c1837SPaolo Bonzini        break;
748139c1837SPaolo Bonzini    case TCG_COND_LT:
749139c1837SPaolo Bonzini        tcg_out_opc_reg(s, OPC_SLT, ret, arg1, arg2);
750139c1837SPaolo Bonzini        break;
751139c1837SPaolo Bonzini    case TCG_COND_GE:
752139c1837SPaolo Bonzini        tcg_out_opc_reg(s, OPC_SLT, ret, arg1, arg2);
753139c1837SPaolo Bonzini        tcg_out_opc_imm(s, OPC_XORI, ret, ret, 1);
754139c1837SPaolo Bonzini        break;
755139c1837SPaolo Bonzini    case TCG_COND_LE:
756139c1837SPaolo Bonzini        tcg_out_opc_reg(s, OPC_SLT, ret, arg2, arg1);
757139c1837SPaolo Bonzini        tcg_out_opc_imm(s, OPC_XORI, ret, ret, 1);
758139c1837SPaolo Bonzini        break;
759139c1837SPaolo Bonzini    case TCG_COND_GT:
760139c1837SPaolo Bonzini        tcg_out_opc_reg(s, OPC_SLT, ret, arg2, arg1);
761139c1837SPaolo Bonzini        break;
762139c1837SPaolo Bonzini    case TCG_COND_LTU:
763139c1837SPaolo Bonzini        tcg_out_opc_reg(s, OPC_SLTU, ret, arg1, arg2);
764139c1837SPaolo Bonzini        break;
765139c1837SPaolo Bonzini    case TCG_COND_GEU:
766139c1837SPaolo Bonzini        tcg_out_opc_reg(s, OPC_SLTU, ret, arg1, arg2);
767139c1837SPaolo Bonzini        tcg_out_opc_imm(s, OPC_XORI, ret, ret, 1);
768139c1837SPaolo Bonzini        break;
769139c1837SPaolo Bonzini    case TCG_COND_LEU:
770139c1837SPaolo Bonzini        tcg_out_opc_reg(s, OPC_SLTU, ret, arg2, arg1);
771139c1837SPaolo Bonzini        tcg_out_opc_imm(s, OPC_XORI, ret, ret, 1);
772139c1837SPaolo Bonzini        break;
773139c1837SPaolo Bonzini    case TCG_COND_GTU:
774139c1837SPaolo Bonzini        tcg_out_opc_reg(s, OPC_SLTU, ret, arg2, arg1);
775139c1837SPaolo Bonzini        break;
776139c1837SPaolo Bonzini    default:
777139c1837SPaolo Bonzini         g_assert_not_reached();
778139c1837SPaolo Bonzini         break;
779139c1837SPaolo Bonzini     }
780139c1837SPaolo Bonzini}
781139c1837SPaolo Bonzini
782139c1837SPaolo Bonzinistatic void tcg_out_brcond2(TCGContext *s, TCGCond cond, TCGReg al, TCGReg ah,
783139c1837SPaolo Bonzini                            TCGReg bl, TCGReg bh, TCGLabel *l)
784139c1837SPaolo Bonzini{
785139c1837SPaolo Bonzini    /* todo */
786139c1837SPaolo Bonzini    g_assert_not_reached();
787139c1837SPaolo Bonzini}
788139c1837SPaolo Bonzini
789139c1837SPaolo Bonzinistatic void tcg_out_setcond2(TCGContext *s, TCGCond cond, TCGReg ret,
790139c1837SPaolo Bonzini                             TCGReg al, TCGReg ah, TCGReg bl, TCGReg bh)
791139c1837SPaolo Bonzini{
792139c1837SPaolo Bonzini    /* todo */
793139c1837SPaolo Bonzini    g_assert_not_reached();
794139c1837SPaolo Bonzini}
795139c1837SPaolo Bonzini
7962be7d76bSRichard Hendersonstatic void tcg_out_call_int(TCGContext *s, const tcg_insn_unit *arg, bool tail)
797139c1837SPaolo Bonzini{
798139c1837SPaolo Bonzini    TCGReg link = tail ? TCG_REG_ZERO : TCG_REG_RA;
799139c1837SPaolo Bonzini    ptrdiff_t offset = tcg_pcrel_diff(s, arg);
800139c1837SPaolo Bonzini    int ret;
801139c1837SPaolo Bonzini
802844d0442SRichard Henderson    tcg_debug_assert((offset & 1) == 0);
803844d0442SRichard Henderson    if (offset == sextreg(offset, 0, 20)) {
804139c1837SPaolo Bonzini        /* short jump: -2097150 to 2097152 */
805139c1837SPaolo Bonzini        tcg_out_opc_jump(s, OPC_JAL, link, offset);
806844d0442SRichard Henderson    } else if (TCG_TARGET_REG_BITS == 32 || offset == (int32_t)offset) {
807139c1837SPaolo Bonzini        /* long jump: -2147483646 to 2147483648 */
808139c1837SPaolo Bonzini        tcg_out_opc_upper(s, OPC_AUIPC, TCG_REG_TMP0, 0);
809139c1837SPaolo Bonzini        tcg_out_opc_imm(s, OPC_JALR, link, TCG_REG_TMP0, 0);
810844d0442SRichard Henderson        ret = reloc_call(s->code_ptr - 2, arg);
811139c1837SPaolo Bonzini        tcg_debug_assert(ret == true);
812139c1837SPaolo Bonzini    } else if (TCG_TARGET_REG_BITS == 64) {
813139c1837SPaolo Bonzini        /* far jump: 64-bit */
814139c1837SPaolo Bonzini        tcg_target_long imm = sextreg((tcg_target_long)arg, 0, 12);
815139c1837SPaolo Bonzini        tcg_target_long base = (tcg_target_long)arg - imm;
816139c1837SPaolo Bonzini        tcg_out_movi(s, TCG_TYPE_PTR, TCG_REG_TMP0, base);
817139c1837SPaolo Bonzini        tcg_out_opc_imm(s, OPC_JALR, link, TCG_REG_TMP0, imm);
818139c1837SPaolo Bonzini    } else {
819139c1837SPaolo Bonzini        g_assert_not_reached();
820139c1837SPaolo Bonzini    }
821139c1837SPaolo Bonzini}
822139c1837SPaolo Bonzini
8232be7d76bSRichard Hendersonstatic void tcg_out_call(TCGContext *s, const tcg_insn_unit *arg)
824139c1837SPaolo Bonzini{
825139c1837SPaolo Bonzini    tcg_out_call_int(s, arg, false);
826139c1837SPaolo Bonzini}
827139c1837SPaolo Bonzini
828139c1837SPaolo Bonzinistatic void tcg_out_mb(TCGContext *s, TCGArg a0)
829139c1837SPaolo Bonzini{
830139c1837SPaolo Bonzini    tcg_insn_unit insn = OPC_FENCE;
831139c1837SPaolo Bonzini
832139c1837SPaolo Bonzini    if (a0 & TCG_MO_LD_LD) {
833139c1837SPaolo Bonzini        insn |= 0x02200000;
834139c1837SPaolo Bonzini    }
835139c1837SPaolo Bonzini    if (a0 & TCG_MO_ST_LD) {
836139c1837SPaolo Bonzini        insn |= 0x01200000;
837139c1837SPaolo Bonzini    }
838139c1837SPaolo Bonzini    if (a0 & TCG_MO_LD_ST) {
839139c1837SPaolo Bonzini        insn |= 0x02100000;
840139c1837SPaolo Bonzini    }
841139c1837SPaolo Bonzini    if (a0 & TCG_MO_ST_ST) {
842139c1837SPaolo Bonzini        insn |= 0x02200000;
843139c1837SPaolo Bonzini    }
844139c1837SPaolo Bonzini    tcg_out32(s, insn);
845139c1837SPaolo Bonzini}
846139c1837SPaolo Bonzini
847139c1837SPaolo Bonzini/*
848139c1837SPaolo Bonzini * Load/store and TLB
849139c1837SPaolo Bonzini */
850139c1837SPaolo Bonzini
851139c1837SPaolo Bonzini#if defined(CONFIG_SOFTMMU)
852139c1837SPaolo Bonzini#include "../tcg-ldst.c.inc"
853139c1837SPaolo Bonzini
854139c1837SPaolo Bonzini/* helper signature: helper_ret_ld_mmu(CPUState *env, target_ulong addr,
855139c1837SPaolo Bonzini *                                     TCGMemOpIdx oi, uintptr_t ra)
856139c1837SPaolo Bonzini */
857139c1837SPaolo Bonzinistatic void * const qemu_ld_helpers[16] = {
858139c1837SPaolo Bonzini    [MO_UB]   = helper_ret_ldub_mmu,
859139c1837SPaolo Bonzini    [MO_SB]   = helper_ret_ldsb_mmu,
860139c1837SPaolo Bonzini    [MO_LEUW] = helper_le_lduw_mmu,
861139c1837SPaolo Bonzini    [MO_LESW] = helper_le_ldsw_mmu,
862139c1837SPaolo Bonzini    [MO_LEUL] = helper_le_ldul_mmu,
863139c1837SPaolo Bonzini#if TCG_TARGET_REG_BITS == 64
864139c1837SPaolo Bonzini    [MO_LESL] = helper_le_ldsl_mmu,
865139c1837SPaolo Bonzini#endif
866139c1837SPaolo Bonzini    [MO_LEQ]  = helper_le_ldq_mmu,
867139c1837SPaolo Bonzini    [MO_BEUW] = helper_be_lduw_mmu,
868139c1837SPaolo Bonzini    [MO_BESW] = helper_be_ldsw_mmu,
869139c1837SPaolo Bonzini    [MO_BEUL] = helper_be_ldul_mmu,
870139c1837SPaolo Bonzini#if TCG_TARGET_REG_BITS == 64
871139c1837SPaolo Bonzini    [MO_BESL] = helper_be_ldsl_mmu,
872139c1837SPaolo Bonzini#endif
873139c1837SPaolo Bonzini    [MO_BEQ]  = helper_be_ldq_mmu,
874139c1837SPaolo Bonzini};
875139c1837SPaolo Bonzini
876139c1837SPaolo Bonzini/* helper signature: helper_ret_st_mmu(CPUState *env, target_ulong addr,
877139c1837SPaolo Bonzini *                                     uintxx_t val, TCGMemOpIdx oi,
878139c1837SPaolo Bonzini *                                     uintptr_t ra)
879139c1837SPaolo Bonzini */
880139c1837SPaolo Bonzinistatic void * const qemu_st_helpers[16] = {
881139c1837SPaolo Bonzini    [MO_UB]   = helper_ret_stb_mmu,
882139c1837SPaolo Bonzini    [MO_LEUW] = helper_le_stw_mmu,
883139c1837SPaolo Bonzini    [MO_LEUL] = helper_le_stl_mmu,
884139c1837SPaolo Bonzini    [MO_LEQ]  = helper_le_stq_mmu,
885139c1837SPaolo Bonzini    [MO_BEUW] = helper_be_stw_mmu,
886139c1837SPaolo Bonzini    [MO_BEUL] = helper_be_stl_mmu,
887139c1837SPaolo Bonzini    [MO_BEQ]  = helper_be_stq_mmu,
888139c1837SPaolo Bonzini};
889139c1837SPaolo Bonzini
890139c1837SPaolo Bonzini/* We don't support oversize guests */
891139c1837SPaolo BonziniQEMU_BUILD_BUG_ON(TCG_TARGET_REG_BITS < TARGET_LONG_BITS);
892139c1837SPaolo Bonzini
893139c1837SPaolo Bonzini/* We expect to use a 12-bit negative offset from ENV.  */
894139c1837SPaolo BonziniQEMU_BUILD_BUG_ON(TLB_MASK_TABLE_OFS(0) > 0);
895139c1837SPaolo BonziniQEMU_BUILD_BUG_ON(TLB_MASK_TABLE_OFS(0) < -(1 << 11));
896139c1837SPaolo Bonzini
897793f7381SRichard Hendersonstatic void tcg_out_goto(TCGContext *s, const tcg_insn_unit *target)
898844d0442SRichard Henderson{
899844d0442SRichard Henderson    tcg_out_opc_jump(s, OPC_JAL, TCG_REG_ZERO, 0);
900844d0442SRichard Henderson    bool ok = reloc_jimm20(s->code_ptr - 1, target);
901844d0442SRichard Henderson    tcg_debug_assert(ok);
902844d0442SRichard Henderson}
903844d0442SRichard Henderson
904139c1837SPaolo Bonzinistatic void tcg_out_tlb_load(TCGContext *s, TCGReg addrl,
905139c1837SPaolo Bonzini                             TCGReg addrh, TCGMemOpIdx oi,
906139c1837SPaolo Bonzini                             tcg_insn_unit **label_ptr, bool is_load)
907139c1837SPaolo Bonzini{
908139c1837SPaolo Bonzini    MemOp opc = get_memop(oi);
909139c1837SPaolo Bonzini    unsigned s_bits = opc & MO_SIZE;
910139c1837SPaolo Bonzini    unsigned a_bits = get_alignment_bits(opc);
911139c1837SPaolo Bonzini    tcg_target_long compare_mask;
912139c1837SPaolo Bonzini    int mem_index = get_mmuidx(oi);
913139c1837SPaolo Bonzini    int fast_ofs = TLB_MASK_TABLE_OFS(mem_index);
914139c1837SPaolo Bonzini    int mask_ofs = fast_ofs + offsetof(CPUTLBDescFast, mask);
915139c1837SPaolo Bonzini    int table_ofs = fast_ofs + offsetof(CPUTLBDescFast, table);
916139c1837SPaolo Bonzini    TCGReg mask_base = TCG_AREG0, table_base = TCG_AREG0;
917139c1837SPaolo Bonzini
918139c1837SPaolo Bonzini    tcg_out_ld(s, TCG_TYPE_PTR, TCG_REG_TMP0, mask_base, mask_ofs);
919139c1837SPaolo Bonzini    tcg_out_ld(s, TCG_TYPE_PTR, TCG_REG_TMP1, table_base, table_ofs);
920139c1837SPaolo Bonzini
921139c1837SPaolo Bonzini    tcg_out_opc_imm(s, OPC_SRLI, TCG_REG_TMP2, addrl,
922139c1837SPaolo Bonzini                    TARGET_PAGE_BITS - CPU_TLB_ENTRY_BITS);
923139c1837SPaolo Bonzini    tcg_out_opc_reg(s, OPC_AND, TCG_REG_TMP2, TCG_REG_TMP2, TCG_REG_TMP0);
924139c1837SPaolo Bonzini    tcg_out_opc_reg(s, OPC_ADD, TCG_REG_TMP2, TCG_REG_TMP2, TCG_REG_TMP1);
925139c1837SPaolo Bonzini
926139c1837SPaolo Bonzini    /* Load the tlb comparator and the addend.  */
927139c1837SPaolo Bonzini    tcg_out_ld(s, TCG_TYPE_TL, TCG_REG_TMP0, TCG_REG_TMP2,
928139c1837SPaolo Bonzini               is_load ? offsetof(CPUTLBEntry, addr_read)
929139c1837SPaolo Bonzini               : offsetof(CPUTLBEntry, addr_write));
930139c1837SPaolo Bonzini    tcg_out_ld(s, TCG_TYPE_PTR, TCG_REG_TMP2, TCG_REG_TMP2,
931139c1837SPaolo Bonzini               offsetof(CPUTLBEntry, addend));
932139c1837SPaolo Bonzini
933139c1837SPaolo Bonzini    /* We don't support unaligned accesses. */
934139c1837SPaolo Bonzini    if (a_bits < s_bits) {
935139c1837SPaolo Bonzini        a_bits = s_bits;
936139c1837SPaolo Bonzini    }
937139c1837SPaolo Bonzini    /* Clear the non-page, non-alignment bits from the address.  */
938139c1837SPaolo Bonzini    compare_mask = (tcg_target_long)TARGET_PAGE_MASK | ((1 << a_bits) - 1);
939139c1837SPaolo Bonzini    if (compare_mask == sextreg(compare_mask, 0, 12)) {
940139c1837SPaolo Bonzini        tcg_out_opc_imm(s, OPC_ANDI, TCG_REG_TMP1, addrl, compare_mask);
941139c1837SPaolo Bonzini    } else {
942139c1837SPaolo Bonzini        tcg_out_movi(s, TCG_TYPE_TL, TCG_REG_TMP1, compare_mask);
943139c1837SPaolo Bonzini        tcg_out_opc_reg(s, OPC_AND, TCG_REG_TMP1, TCG_REG_TMP1, addrl);
944139c1837SPaolo Bonzini    }
945139c1837SPaolo Bonzini
946139c1837SPaolo Bonzini    /* Compare masked address with the TLB entry. */
947139c1837SPaolo Bonzini    label_ptr[0] = s->code_ptr;
948139c1837SPaolo Bonzini    tcg_out_opc_branch(s, OPC_BNE, TCG_REG_TMP0, TCG_REG_TMP1, 0);
949139c1837SPaolo Bonzini
950139c1837SPaolo Bonzini    /* TLB Hit - translate address using addend.  */
951139c1837SPaolo Bonzini    if (TCG_TARGET_REG_BITS > TARGET_LONG_BITS) {
952139c1837SPaolo Bonzini        tcg_out_ext32u(s, TCG_REG_TMP0, addrl);
953139c1837SPaolo Bonzini        addrl = TCG_REG_TMP0;
954139c1837SPaolo Bonzini    }
955139c1837SPaolo Bonzini    tcg_out_opc_reg(s, OPC_ADD, TCG_REG_TMP0, TCG_REG_TMP2, addrl);
956139c1837SPaolo Bonzini}
957139c1837SPaolo Bonzini
958139c1837SPaolo Bonzinistatic void add_qemu_ldst_label(TCGContext *s, int is_ld, TCGMemOpIdx oi,
959139c1837SPaolo Bonzini                                TCGType ext,
960139c1837SPaolo Bonzini                                TCGReg datalo, TCGReg datahi,
961139c1837SPaolo Bonzini                                TCGReg addrlo, TCGReg addrhi,
962139c1837SPaolo Bonzini                                void *raddr, tcg_insn_unit **label_ptr)
963139c1837SPaolo Bonzini{
964139c1837SPaolo Bonzini    TCGLabelQemuLdst *label = new_ldst_label(s);
965139c1837SPaolo Bonzini
966139c1837SPaolo Bonzini    label->is_ld = is_ld;
967139c1837SPaolo Bonzini    label->oi = oi;
968139c1837SPaolo Bonzini    label->type = ext;
969139c1837SPaolo Bonzini    label->datalo_reg = datalo;
970139c1837SPaolo Bonzini    label->datahi_reg = datahi;
971139c1837SPaolo Bonzini    label->addrlo_reg = addrlo;
972139c1837SPaolo Bonzini    label->addrhi_reg = addrhi;
973e5e2e4c7SRichard Henderson    label->raddr = tcg_splitwx_to_rx(raddr);
974139c1837SPaolo Bonzini    label->label_ptr[0] = label_ptr[0];
975139c1837SPaolo Bonzini}
976139c1837SPaolo Bonzini
977139c1837SPaolo Bonzinistatic bool tcg_out_qemu_ld_slow_path(TCGContext *s, TCGLabelQemuLdst *l)
978139c1837SPaolo Bonzini{
979139c1837SPaolo Bonzini    TCGMemOpIdx oi = l->oi;
980139c1837SPaolo Bonzini    MemOp opc = get_memop(oi);
981139c1837SPaolo Bonzini    TCGReg a0 = tcg_target_call_iarg_regs[0];
982139c1837SPaolo Bonzini    TCGReg a1 = tcg_target_call_iarg_regs[1];
983139c1837SPaolo Bonzini    TCGReg a2 = tcg_target_call_iarg_regs[2];
984139c1837SPaolo Bonzini    TCGReg a3 = tcg_target_call_iarg_regs[3];
985139c1837SPaolo Bonzini
986139c1837SPaolo Bonzini    /* We don't support oversize guests */
987139c1837SPaolo Bonzini    if (TCG_TARGET_REG_BITS < TARGET_LONG_BITS) {
988139c1837SPaolo Bonzini        g_assert_not_reached();
989139c1837SPaolo Bonzini    }
990139c1837SPaolo Bonzini
991139c1837SPaolo Bonzini    /* resolve label address */
992793f7381SRichard Henderson    if (!reloc_sbimm12(l->label_ptr[0], tcg_splitwx_to_rx(s->code_ptr))) {
993139c1837SPaolo Bonzini        return false;
994139c1837SPaolo Bonzini    }
995139c1837SPaolo Bonzini
996139c1837SPaolo Bonzini    /* call load helper */
997139c1837SPaolo Bonzini    tcg_out_mov(s, TCG_TYPE_PTR, a0, TCG_AREG0);
998139c1837SPaolo Bonzini    tcg_out_mov(s, TCG_TYPE_PTR, a1, l->addrlo_reg);
999139c1837SPaolo Bonzini    tcg_out_movi(s, TCG_TYPE_PTR, a2, oi);
1000139c1837SPaolo Bonzini    tcg_out_movi(s, TCG_TYPE_PTR, a3, (tcg_target_long)l->raddr);
1001139c1837SPaolo Bonzini
1002139c1837SPaolo Bonzini    tcg_out_call(s, qemu_ld_helpers[opc & (MO_BSWAP | MO_SSIZE)]);
1003139c1837SPaolo Bonzini    tcg_out_mov(s, (opc & MO_SIZE) == MO_64, l->datalo_reg, a0);
1004139c1837SPaolo Bonzini
1005139c1837SPaolo Bonzini    tcg_out_goto(s, l->raddr);
1006139c1837SPaolo Bonzini    return true;
1007139c1837SPaolo Bonzini}
1008139c1837SPaolo Bonzini
1009139c1837SPaolo Bonzinistatic bool tcg_out_qemu_st_slow_path(TCGContext *s, TCGLabelQemuLdst *l)
1010139c1837SPaolo Bonzini{
1011139c1837SPaolo Bonzini    TCGMemOpIdx oi = l->oi;
1012139c1837SPaolo Bonzini    MemOp opc = get_memop(oi);
1013139c1837SPaolo Bonzini    MemOp s_bits = opc & MO_SIZE;
1014139c1837SPaolo Bonzini    TCGReg a0 = tcg_target_call_iarg_regs[0];
1015139c1837SPaolo Bonzini    TCGReg a1 = tcg_target_call_iarg_regs[1];
1016139c1837SPaolo Bonzini    TCGReg a2 = tcg_target_call_iarg_regs[2];
1017139c1837SPaolo Bonzini    TCGReg a3 = tcg_target_call_iarg_regs[3];
1018139c1837SPaolo Bonzini    TCGReg a4 = tcg_target_call_iarg_regs[4];
1019139c1837SPaolo Bonzini
1020139c1837SPaolo Bonzini    /* We don't support oversize guests */
1021139c1837SPaolo Bonzini    if (TCG_TARGET_REG_BITS < TARGET_LONG_BITS) {
1022139c1837SPaolo Bonzini        g_assert_not_reached();
1023139c1837SPaolo Bonzini    }
1024139c1837SPaolo Bonzini
1025139c1837SPaolo Bonzini    /* resolve label address */
1026793f7381SRichard Henderson    if (!reloc_sbimm12(l->label_ptr[0], tcg_splitwx_to_rx(s->code_ptr))) {
1027139c1837SPaolo Bonzini        return false;
1028139c1837SPaolo Bonzini    }
1029139c1837SPaolo Bonzini
1030139c1837SPaolo Bonzini    /* call store helper */
1031139c1837SPaolo Bonzini    tcg_out_mov(s, TCG_TYPE_PTR, a0, TCG_AREG0);
1032139c1837SPaolo Bonzini    tcg_out_mov(s, TCG_TYPE_PTR, a1, l->addrlo_reg);
1033139c1837SPaolo Bonzini    tcg_out_mov(s, TCG_TYPE_PTR, a2, l->datalo_reg);
1034139c1837SPaolo Bonzini    switch (s_bits) {
1035139c1837SPaolo Bonzini    case MO_8:
1036139c1837SPaolo Bonzini        tcg_out_ext8u(s, a2, a2);
1037139c1837SPaolo Bonzini        break;
1038139c1837SPaolo Bonzini    case MO_16:
1039139c1837SPaolo Bonzini        tcg_out_ext16u(s, a2, a2);
1040139c1837SPaolo Bonzini        break;
1041139c1837SPaolo Bonzini    default:
1042139c1837SPaolo Bonzini        break;
1043139c1837SPaolo Bonzini    }
1044139c1837SPaolo Bonzini    tcg_out_movi(s, TCG_TYPE_PTR, a3, oi);
1045139c1837SPaolo Bonzini    tcg_out_movi(s, TCG_TYPE_PTR, a4, (tcg_target_long)l->raddr);
1046139c1837SPaolo Bonzini
1047139c1837SPaolo Bonzini    tcg_out_call(s, qemu_st_helpers[opc & (MO_BSWAP | MO_SSIZE)]);
1048139c1837SPaolo Bonzini
1049139c1837SPaolo Bonzini    tcg_out_goto(s, l->raddr);
1050139c1837SPaolo Bonzini    return true;
1051139c1837SPaolo Bonzini}
1052139c1837SPaolo Bonzini#endif /* CONFIG_SOFTMMU */
1053139c1837SPaolo Bonzini
1054139c1837SPaolo Bonzinistatic void tcg_out_qemu_ld_direct(TCGContext *s, TCGReg lo, TCGReg hi,
1055139c1837SPaolo Bonzini                                   TCGReg base, MemOp opc, bool is_64)
1056139c1837SPaolo Bonzini{
1057139c1837SPaolo Bonzini    const MemOp bswap = opc & MO_BSWAP;
1058139c1837SPaolo Bonzini
1059139c1837SPaolo Bonzini    /* We don't yet handle byteswapping, assert */
1060139c1837SPaolo Bonzini    g_assert(!bswap);
1061139c1837SPaolo Bonzini
1062139c1837SPaolo Bonzini    switch (opc & (MO_SSIZE)) {
1063139c1837SPaolo Bonzini    case MO_UB:
1064139c1837SPaolo Bonzini        tcg_out_opc_imm(s, OPC_LBU, lo, base, 0);
1065139c1837SPaolo Bonzini        break;
1066139c1837SPaolo Bonzini    case MO_SB:
1067139c1837SPaolo Bonzini        tcg_out_opc_imm(s, OPC_LB, lo, base, 0);
1068139c1837SPaolo Bonzini        break;
1069139c1837SPaolo Bonzini    case MO_UW:
1070139c1837SPaolo Bonzini        tcg_out_opc_imm(s, OPC_LHU, lo, base, 0);
1071139c1837SPaolo Bonzini        break;
1072139c1837SPaolo Bonzini    case MO_SW:
1073139c1837SPaolo Bonzini        tcg_out_opc_imm(s, OPC_LH, lo, base, 0);
1074139c1837SPaolo Bonzini        break;
1075139c1837SPaolo Bonzini    case MO_UL:
1076139c1837SPaolo Bonzini        if (TCG_TARGET_REG_BITS == 64 && is_64) {
1077139c1837SPaolo Bonzini            tcg_out_opc_imm(s, OPC_LWU, lo, base, 0);
1078139c1837SPaolo Bonzini            break;
1079139c1837SPaolo Bonzini        }
1080139c1837SPaolo Bonzini        /* FALLTHRU */
1081139c1837SPaolo Bonzini    case MO_SL:
1082139c1837SPaolo Bonzini        tcg_out_opc_imm(s, OPC_LW, lo, base, 0);
1083139c1837SPaolo Bonzini        break;
1084139c1837SPaolo Bonzini    case MO_Q:
1085139c1837SPaolo Bonzini        /* Prefer to load from offset 0 first, but allow for overlap.  */
1086139c1837SPaolo Bonzini        if (TCG_TARGET_REG_BITS == 64) {
1087139c1837SPaolo Bonzini            tcg_out_opc_imm(s, OPC_LD, lo, base, 0);
1088139c1837SPaolo Bonzini        } else if (lo != base) {
1089139c1837SPaolo Bonzini            tcg_out_opc_imm(s, OPC_LW, lo, base, 0);
1090139c1837SPaolo Bonzini            tcg_out_opc_imm(s, OPC_LW, hi, base, 4);
1091139c1837SPaolo Bonzini        } else {
1092139c1837SPaolo Bonzini            tcg_out_opc_imm(s, OPC_LW, hi, base, 4);
1093139c1837SPaolo Bonzini            tcg_out_opc_imm(s, OPC_LW, lo, base, 0);
1094139c1837SPaolo Bonzini        }
1095139c1837SPaolo Bonzini        break;
1096139c1837SPaolo Bonzini    default:
1097139c1837SPaolo Bonzini        g_assert_not_reached();
1098139c1837SPaolo Bonzini    }
1099139c1837SPaolo Bonzini}
1100139c1837SPaolo Bonzini
1101139c1837SPaolo Bonzinistatic void tcg_out_qemu_ld(TCGContext *s, const TCGArg *args, bool is_64)
1102139c1837SPaolo Bonzini{
1103139c1837SPaolo Bonzini    TCGReg addr_regl, addr_regh __attribute__((unused));
1104139c1837SPaolo Bonzini    TCGReg data_regl, data_regh;
1105139c1837SPaolo Bonzini    TCGMemOpIdx oi;
1106139c1837SPaolo Bonzini    MemOp opc;
1107139c1837SPaolo Bonzini#if defined(CONFIG_SOFTMMU)
1108139c1837SPaolo Bonzini    tcg_insn_unit *label_ptr[1];
1109139c1837SPaolo Bonzini#endif
1110139c1837SPaolo Bonzini    TCGReg base = TCG_REG_TMP0;
1111139c1837SPaolo Bonzini
1112139c1837SPaolo Bonzini    data_regl = *args++;
1113139c1837SPaolo Bonzini    data_regh = (TCG_TARGET_REG_BITS == 32 && is_64 ? *args++ : 0);
1114139c1837SPaolo Bonzini    addr_regl = *args++;
1115139c1837SPaolo Bonzini    addr_regh = (TCG_TARGET_REG_BITS < TARGET_LONG_BITS ? *args++ : 0);
1116139c1837SPaolo Bonzini    oi = *args++;
1117139c1837SPaolo Bonzini    opc = get_memop(oi);
1118139c1837SPaolo Bonzini
1119139c1837SPaolo Bonzini#if defined(CONFIG_SOFTMMU)
1120139c1837SPaolo Bonzini    tcg_out_tlb_load(s, addr_regl, addr_regh, oi, label_ptr, 1);
1121139c1837SPaolo Bonzini    tcg_out_qemu_ld_direct(s, data_regl, data_regh, base, opc, is_64);
1122139c1837SPaolo Bonzini    add_qemu_ldst_label(s, 1, oi,
1123139c1837SPaolo Bonzini                        (is_64 ? TCG_TYPE_I64 : TCG_TYPE_I32),
1124139c1837SPaolo Bonzini                        data_regl, data_regh, addr_regl, addr_regh,
1125139c1837SPaolo Bonzini                        s->code_ptr, label_ptr);
1126139c1837SPaolo Bonzini#else
1127139c1837SPaolo Bonzini    if (TCG_TARGET_REG_BITS > TARGET_LONG_BITS) {
1128139c1837SPaolo Bonzini        tcg_out_ext32u(s, base, addr_regl);
1129139c1837SPaolo Bonzini        addr_regl = base;
1130139c1837SPaolo Bonzini    }
1131139c1837SPaolo Bonzini
1132139c1837SPaolo Bonzini    if (guest_base == 0) {
1133139c1837SPaolo Bonzini        tcg_out_opc_reg(s, OPC_ADD, base, addr_regl, TCG_REG_ZERO);
1134139c1837SPaolo Bonzini    } else {
1135139c1837SPaolo Bonzini        tcg_out_opc_reg(s, OPC_ADD, base, TCG_GUEST_BASE_REG, addr_regl);
1136139c1837SPaolo Bonzini    }
1137139c1837SPaolo Bonzini    tcg_out_qemu_ld_direct(s, data_regl, data_regh, base, opc, is_64);
1138139c1837SPaolo Bonzini#endif
1139139c1837SPaolo Bonzini}
1140139c1837SPaolo Bonzini
1141139c1837SPaolo Bonzinistatic void tcg_out_qemu_st_direct(TCGContext *s, TCGReg lo, TCGReg hi,
1142139c1837SPaolo Bonzini                                   TCGReg base, MemOp opc)
1143139c1837SPaolo Bonzini{
1144139c1837SPaolo Bonzini    const MemOp bswap = opc & MO_BSWAP;
1145139c1837SPaolo Bonzini
1146139c1837SPaolo Bonzini    /* We don't yet handle byteswapping, assert */
1147139c1837SPaolo Bonzini    g_assert(!bswap);
1148139c1837SPaolo Bonzini
1149139c1837SPaolo Bonzini    switch (opc & (MO_SSIZE)) {
1150139c1837SPaolo Bonzini    case MO_8:
1151139c1837SPaolo Bonzini        tcg_out_opc_store(s, OPC_SB, base, lo, 0);
1152139c1837SPaolo Bonzini        break;
1153139c1837SPaolo Bonzini    case MO_16:
1154139c1837SPaolo Bonzini        tcg_out_opc_store(s, OPC_SH, base, lo, 0);
1155139c1837SPaolo Bonzini        break;
1156139c1837SPaolo Bonzini    case MO_32:
1157139c1837SPaolo Bonzini        tcg_out_opc_store(s, OPC_SW, base, lo, 0);
1158139c1837SPaolo Bonzini        break;
1159139c1837SPaolo Bonzini    case MO_64:
1160139c1837SPaolo Bonzini        if (TCG_TARGET_REG_BITS == 64) {
1161139c1837SPaolo Bonzini            tcg_out_opc_store(s, OPC_SD, base, lo, 0);
1162139c1837SPaolo Bonzini        } else {
1163139c1837SPaolo Bonzini            tcg_out_opc_store(s, OPC_SW, base, lo, 0);
1164139c1837SPaolo Bonzini            tcg_out_opc_store(s, OPC_SW, base, hi, 4);
1165139c1837SPaolo Bonzini        }
1166139c1837SPaolo Bonzini        break;
1167139c1837SPaolo Bonzini    default:
1168139c1837SPaolo Bonzini        g_assert_not_reached();
1169139c1837SPaolo Bonzini    }
1170139c1837SPaolo Bonzini}
1171139c1837SPaolo Bonzini
1172139c1837SPaolo Bonzinistatic void tcg_out_qemu_st(TCGContext *s, const TCGArg *args, bool is_64)
1173139c1837SPaolo Bonzini{
1174139c1837SPaolo Bonzini    TCGReg addr_regl, addr_regh __attribute__((unused));
1175139c1837SPaolo Bonzini    TCGReg data_regl, data_regh;
1176139c1837SPaolo Bonzini    TCGMemOpIdx oi;
1177139c1837SPaolo Bonzini    MemOp opc;
1178139c1837SPaolo Bonzini#if defined(CONFIG_SOFTMMU)
1179139c1837SPaolo Bonzini    tcg_insn_unit *label_ptr[1];
1180139c1837SPaolo Bonzini#endif
1181139c1837SPaolo Bonzini    TCGReg base = TCG_REG_TMP0;
1182139c1837SPaolo Bonzini
1183139c1837SPaolo Bonzini    data_regl = *args++;
1184139c1837SPaolo Bonzini    data_regh = (TCG_TARGET_REG_BITS == 32 && is_64 ? *args++ : 0);
1185139c1837SPaolo Bonzini    addr_regl = *args++;
1186139c1837SPaolo Bonzini    addr_regh = (TCG_TARGET_REG_BITS < TARGET_LONG_BITS ? *args++ : 0);
1187139c1837SPaolo Bonzini    oi = *args++;
1188139c1837SPaolo Bonzini    opc = get_memop(oi);
1189139c1837SPaolo Bonzini
1190139c1837SPaolo Bonzini#if defined(CONFIG_SOFTMMU)
1191139c1837SPaolo Bonzini    tcg_out_tlb_load(s, addr_regl, addr_regh, oi, label_ptr, 0);
1192139c1837SPaolo Bonzini    tcg_out_qemu_st_direct(s, data_regl, data_regh, base, opc);
1193139c1837SPaolo Bonzini    add_qemu_ldst_label(s, 0, oi,
1194139c1837SPaolo Bonzini                        (is_64 ? TCG_TYPE_I64 : TCG_TYPE_I32),
1195139c1837SPaolo Bonzini                        data_regl, data_regh, addr_regl, addr_regh,
1196139c1837SPaolo Bonzini                        s->code_ptr, label_ptr);
1197139c1837SPaolo Bonzini#else
1198139c1837SPaolo Bonzini    if (TCG_TARGET_REG_BITS > TARGET_LONG_BITS) {
1199139c1837SPaolo Bonzini        tcg_out_ext32u(s, base, addr_regl);
1200139c1837SPaolo Bonzini        addr_regl = base;
1201139c1837SPaolo Bonzini    }
1202139c1837SPaolo Bonzini
1203139c1837SPaolo Bonzini    if (guest_base == 0) {
1204139c1837SPaolo Bonzini        tcg_out_opc_reg(s, OPC_ADD, base, addr_regl, TCG_REG_ZERO);
1205139c1837SPaolo Bonzini    } else {
1206139c1837SPaolo Bonzini        tcg_out_opc_reg(s, OPC_ADD, base, TCG_GUEST_BASE_REG, addr_regl);
1207139c1837SPaolo Bonzini    }
1208139c1837SPaolo Bonzini    tcg_out_qemu_st_direct(s, data_regl, data_regh, base, opc);
1209139c1837SPaolo Bonzini#endif
1210139c1837SPaolo Bonzini}
1211139c1837SPaolo Bonzini
1212793f7381SRichard Hendersonstatic const tcg_insn_unit *tb_ret_addr;
1213139c1837SPaolo Bonzini
1214139c1837SPaolo Bonzinistatic void tcg_out_op(TCGContext *s, TCGOpcode opc,
1215139c1837SPaolo Bonzini                       const TCGArg *args, const int *const_args)
1216139c1837SPaolo Bonzini{
1217139c1837SPaolo Bonzini    TCGArg a0 = args[0];
1218139c1837SPaolo Bonzini    TCGArg a1 = args[1];
1219139c1837SPaolo Bonzini    TCGArg a2 = args[2];
1220139c1837SPaolo Bonzini    int c2 = const_args[2];
1221139c1837SPaolo Bonzini
1222139c1837SPaolo Bonzini    switch (opc) {
1223139c1837SPaolo Bonzini    case INDEX_op_exit_tb:
1224139c1837SPaolo Bonzini        /* Reuse the zeroing that exists for goto_ptr.  */
1225139c1837SPaolo Bonzini        if (a0 == 0) {
12268b5c2b62SRichard Henderson            tcg_out_call_int(s, tcg_code_gen_epilogue, true);
1227139c1837SPaolo Bonzini        } else {
1228139c1837SPaolo Bonzini            tcg_out_movi(s, TCG_TYPE_PTR, TCG_REG_A0, a0);
1229139c1837SPaolo Bonzini            tcg_out_call_int(s, tb_ret_addr, true);
1230139c1837SPaolo Bonzini        }
1231139c1837SPaolo Bonzini        break;
1232139c1837SPaolo Bonzini
1233139c1837SPaolo Bonzini    case INDEX_op_goto_tb:
1234139c1837SPaolo Bonzini        assert(s->tb_jmp_insn_offset == 0);
1235139c1837SPaolo Bonzini        /* indirect jump method */
1236139c1837SPaolo Bonzini        tcg_out_ld(s, TCG_TYPE_PTR, TCG_REG_TMP0, TCG_REG_ZERO,
1237139c1837SPaolo Bonzini                   (uintptr_t)(s->tb_jmp_target_addr + a0));
1238139c1837SPaolo Bonzini        tcg_out_opc_imm(s, OPC_JALR, TCG_REG_ZERO, TCG_REG_TMP0, 0);
1239139c1837SPaolo Bonzini        set_jmp_reset_offset(s, a0);
1240139c1837SPaolo Bonzini        break;
1241139c1837SPaolo Bonzini
1242139c1837SPaolo Bonzini    case INDEX_op_goto_ptr:
1243139c1837SPaolo Bonzini        tcg_out_opc_imm(s, OPC_JALR, TCG_REG_ZERO, a0, 0);
1244139c1837SPaolo Bonzini        break;
1245139c1837SPaolo Bonzini
1246139c1837SPaolo Bonzini    case INDEX_op_br:
1247139c1837SPaolo Bonzini        tcg_out_reloc(s, s->code_ptr, R_RISCV_JAL, arg_label(a0), 0);
1248139c1837SPaolo Bonzini        tcg_out_opc_jump(s, OPC_JAL, TCG_REG_ZERO, 0);
1249139c1837SPaolo Bonzini        break;
1250139c1837SPaolo Bonzini
1251139c1837SPaolo Bonzini    case INDEX_op_ld8u_i32:
1252139c1837SPaolo Bonzini    case INDEX_op_ld8u_i64:
1253139c1837SPaolo Bonzini        tcg_out_ldst(s, OPC_LBU, a0, a1, a2);
1254139c1837SPaolo Bonzini        break;
1255139c1837SPaolo Bonzini    case INDEX_op_ld8s_i32:
1256139c1837SPaolo Bonzini    case INDEX_op_ld8s_i64:
1257139c1837SPaolo Bonzini        tcg_out_ldst(s, OPC_LB, a0, a1, a2);
1258139c1837SPaolo Bonzini        break;
1259139c1837SPaolo Bonzini    case INDEX_op_ld16u_i32:
1260139c1837SPaolo Bonzini    case INDEX_op_ld16u_i64:
1261139c1837SPaolo Bonzini        tcg_out_ldst(s, OPC_LHU, a0, a1, a2);
1262139c1837SPaolo Bonzini        break;
1263139c1837SPaolo Bonzini    case INDEX_op_ld16s_i32:
1264139c1837SPaolo Bonzini    case INDEX_op_ld16s_i64:
1265139c1837SPaolo Bonzini        tcg_out_ldst(s, OPC_LH, a0, a1, a2);
1266139c1837SPaolo Bonzini        break;
1267139c1837SPaolo Bonzini    case INDEX_op_ld32u_i64:
1268139c1837SPaolo Bonzini        tcg_out_ldst(s, OPC_LWU, a0, a1, a2);
1269139c1837SPaolo Bonzini        break;
1270139c1837SPaolo Bonzini    case INDEX_op_ld_i32:
1271139c1837SPaolo Bonzini    case INDEX_op_ld32s_i64:
1272139c1837SPaolo Bonzini        tcg_out_ldst(s, OPC_LW, a0, a1, a2);
1273139c1837SPaolo Bonzini        break;
1274139c1837SPaolo Bonzini    case INDEX_op_ld_i64:
1275139c1837SPaolo Bonzini        tcg_out_ldst(s, OPC_LD, a0, a1, a2);
1276139c1837SPaolo Bonzini        break;
1277139c1837SPaolo Bonzini
1278139c1837SPaolo Bonzini    case INDEX_op_st8_i32:
1279139c1837SPaolo Bonzini    case INDEX_op_st8_i64:
1280139c1837SPaolo Bonzini        tcg_out_ldst(s, OPC_SB, a0, a1, a2);
1281139c1837SPaolo Bonzini        break;
1282139c1837SPaolo Bonzini    case INDEX_op_st16_i32:
1283139c1837SPaolo Bonzini    case INDEX_op_st16_i64:
1284139c1837SPaolo Bonzini        tcg_out_ldst(s, OPC_SH, a0, a1, a2);
1285139c1837SPaolo Bonzini        break;
1286139c1837SPaolo Bonzini    case INDEX_op_st_i32:
1287139c1837SPaolo Bonzini    case INDEX_op_st32_i64:
1288139c1837SPaolo Bonzini        tcg_out_ldst(s, OPC_SW, a0, a1, a2);
1289139c1837SPaolo Bonzini        break;
1290139c1837SPaolo Bonzini    case INDEX_op_st_i64:
1291139c1837SPaolo Bonzini        tcg_out_ldst(s, OPC_SD, a0, a1, a2);
1292139c1837SPaolo Bonzini        break;
1293139c1837SPaolo Bonzini
1294139c1837SPaolo Bonzini    case INDEX_op_add_i32:
1295139c1837SPaolo Bonzini        if (c2) {
1296139c1837SPaolo Bonzini            tcg_out_opc_imm(s, OPC_ADDIW, a0, a1, a2);
1297139c1837SPaolo Bonzini        } else {
1298139c1837SPaolo Bonzini            tcg_out_opc_reg(s, OPC_ADDW, a0, a1, a2);
1299139c1837SPaolo Bonzini        }
1300139c1837SPaolo Bonzini        break;
1301139c1837SPaolo Bonzini    case INDEX_op_add_i64:
1302139c1837SPaolo Bonzini        if (c2) {
1303139c1837SPaolo Bonzini            tcg_out_opc_imm(s, OPC_ADDI, a0, a1, a2);
1304139c1837SPaolo Bonzini        } else {
1305139c1837SPaolo Bonzini            tcg_out_opc_reg(s, OPC_ADD, a0, a1, a2);
1306139c1837SPaolo Bonzini        }
1307139c1837SPaolo Bonzini        break;
1308139c1837SPaolo Bonzini
1309139c1837SPaolo Bonzini    case INDEX_op_sub_i32:
1310139c1837SPaolo Bonzini        if (c2) {
1311139c1837SPaolo Bonzini            tcg_out_opc_imm(s, OPC_ADDIW, a0, a1, -a2);
1312139c1837SPaolo Bonzini        } else {
1313139c1837SPaolo Bonzini            tcg_out_opc_reg(s, OPC_SUBW, a0, a1, a2);
1314139c1837SPaolo Bonzini        }
1315139c1837SPaolo Bonzini        break;
1316139c1837SPaolo Bonzini    case INDEX_op_sub_i64:
1317139c1837SPaolo Bonzini        if (c2) {
1318139c1837SPaolo Bonzini            tcg_out_opc_imm(s, OPC_ADDI, a0, a1, -a2);
1319139c1837SPaolo Bonzini        } else {
1320139c1837SPaolo Bonzini            tcg_out_opc_reg(s, OPC_SUB, a0, a1, a2);
1321139c1837SPaolo Bonzini        }
1322139c1837SPaolo Bonzini        break;
1323139c1837SPaolo Bonzini
1324139c1837SPaolo Bonzini    case INDEX_op_and_i32:
1325139c1837SPaolo Bonzini    case INDEX_op_and_i64:
1326139c1837SPaolo Bonzini        if (c2) {
1327139c1837SPaolo Bonzini            tcg_out_opc_imm(s, OPC_ANDI, a0, a1, a2);
1328139c1837SPaolo Bonzini        } else {
1329139c1837SPaolo Bonzini            tcg_out_opc_reg(s, OPC_AND, a0, a1, a2);
1330139c1837SPaolo Bonzini        }
1331139c1837SPaolo Bonzini        break;
1332139c1837SPaolo Bonzini
1333139c1837SPaolo Bonzini    case INDEX_op_or_i32:
1334139c1837SPaolo Bonzini    case INDEX_op_or_i64:
1335139c1837SPaolo Bonzini        if (c2) {
1336139c1837SPaolo Bonzini            tcg_out_opc_imm(s, OPC_ORI, a0, a1, a2);
1337139c1837SPaolo Bonzini        } else {
1338139c1837SPaolo Bonzini            tcg_out_opc_reg(s, OPC_OR, a0, a1, a2);
1339139c1837SPaolo Bonzini        }
1340139c1837SPaolo Bonzini        break;
1341139c1837SPaolo Bonzini
1342139c1837SPaolo Bonzini    case INDEX_op_xor_i32:
1343139c1837SPaolo Bonzini    case INDEX_op_xor_i64:
1344139c1837SPaolo Bonzini        if (c2) {
1345139c1837SPaolo Bonzini            tcg_out_opc_imm(s, OPC_XORI, a0, a1, a2);
1346139c1837SPaolo Bonzini        } else {
1347139c1837SPaolo Bonzini            tcg_out_opc_reg(s, OPC_XOR, a0, a1, a2);
1348139c1837SPaolo Bonzini        }
1349139c1837SPaolo Bonzini        break;
1350139c1837SPaolo Bonzini
1351139c1837SPaolo Bonzini    case INDEX_op_not_i32:
1352139c1837SPaolo Bonzini    case INDEX_op_not_i64:
1353139c1837SPaolo Bonzini        tcg_out_opc_imm(s, OPC_XORI, a0, a1, -1);
1354139c1837SPaolo Bonzini        break;
1355139c1837SPaolo Bonzini
1356139c1837SPaolo Bonzini    case INDEX_op_neg_i32:
1357139c1837SPaolo Bonzini        tcg_out_opc_reg(s, OPC_SUBW, a0, TCG_REG_ZERO, a1);
1358139c1837SPaolo Bonzini        break;
1359139c1837SPaolo Bonzini    case INDEX_op_neg_i64:
1360139c1837SPaolo Bonzini        tcg_out_opc_reg(s, OPC_SUB, a0, TCG_REG_ZERO, a1);
1361139c1837SPaolo Bonzini        break;
1362139c1837SPaolo Bonzini
1363139c1837SPaolo Bonzini    case INDEX_op_mul_i32:
1364139c1837SPaolo Bonzini        tcg_out_opc_reg(s, OPC_MULW, a0, a1, a2);
1365139c1837SPaolo Bonzini        break;
1366139c1837SPaolo Bonzini    case INDEX_op_mul_i64:
1367139c1837SPaolo Bonzini        tcg_out_opc_reg(s, OPC_MUL, a0, a1, a2);
1368139c1837SPaolo Bonzini        break;
1369139c1837SPaolo Bonzini
1370139c1837SPaolo Bonzini    case INDEX_op_div_i32:
1371139c1837SPaolo Bonzini        tcg_out_opc_reg(s, OPC_DIVW, a0, a1, a2);
1372139c1837SPaolo Bonzini        break;
1373139c1837SPaolo Bonzini    case INDEX_op_div_i64:
1374139c1837SPaolo Bonzini        tcg_out_opc_reg(s, OPC_DIV, a0, a1, a2);
1375139c1837SPaolo Bonzini        break;
1376139c1837SPaolo Bonzini
1377139c1837SPaolo Bonzini    case INDEX_op_divu_i32:
1378139c1837SPaolo Bonzini        tcg_out_opc_reg(s, OPC_DIVUW, a0, a1, a2);
1379139c1837SPaolo Bonzini        break;
1380139c1837SPaolo Bonzini    case INDEX_op_divu_i64:
1381139c1837SPaolo Bonzini        tcg_out_opc_reg(s, OPC_DIVU, a0, a1, a2);
1382139c1837SPaolo Bonzini        break;
1383139c1837SPaolo Bonzini
1384139c1837SPaolo Bonzini    case INDEX_op_rem_i32:
1385139c1837SPaolo Bonzini        tcg_out_opc_reg(s, OPC_REMW, a0, a1, a2);
1386139c1837SPaolo Bonzini        break;
1387139c1837SPaolo Bonzini    case INDEX_op_rem_i64:
1388139c1837SPaolo Bonzini        tcg_out_opc_reg(s, OPC_REM, a0, a1, a2);
1389139c1837SPaolo Bonzini        break;
1390139c1837SPaolo Bonzini
1391139c1837SPaolo Bonzini    case INDEX_op_remu_i32:
1392139c1837SPaolo Bonzini        tcg_out_opc_reg(s, OPC_REMUW, a0, a1, a2);
1393139c1837SPaolo Bonzini        break;
1394139c1837SPaolo Bonzini    case INDEX_op_remu_i64:
1395139c1837SPaolo Bonzini        tcg_out_opc_reg(s, OPC_REMU, a0, a1, a2);
1396139c1837SPaolo Bonzini        break;
1397139c1837SPaolo Bonzini
1398139c1837SPaolo Bonzini    case INDEX_op_shl_i32:
1399139c1837SPaolo Bonzini        if (c2) {
1400d2f3066eSZihao Yu            tcg_out_opc_imm(s, OPC_SLLIW, a0, a1, a2 & 0x1f);
1401139c1837SPaolo Bonzini        } else {
1402139c1837SPaolo Bonzini            tcg_out_opc_reg(s, OPC_SLLW, a0, a1, a2);
1403139c1837SPaolo Bonzini        }
1404139c1837SPaolo Bonzini        break;
1405139c1837SPaolo Bonzini    case INDEX_op_shl_i64:
1406139c1837SPaolo Bonzini        if (c2) {
1407d2f3066eSZihao Yu            tcg_out_opc_imm(s, OPC_SLLI, a0, a1, a2 & 0x3f);
1408139c1837SPaolo Bonzini        } else {
1409139c1837SPaolo Bonzini            tcg_out_opc_reg(s, OPC_SLL, a0, a1, a2);
1410139c1837SPaolo Bonzini        }
1411139c1837SPaolo Bonzini        break;
1412139c1837SPaolo Bonzini
1413139c1837SPaolo Bonzini    case INDEX_op_shr_i32:
1414139c1837SPaolo Bonzini        if (c2) {
1415d2f3066eSZihao Yu            tcg_out_opc_imm(s, OPC_SRLIW, a0, a1, a2 & 0x1f);
1416139c1837SPaolo Bonzini        } else {
1417139c1837SPaolo Bonzini            tcg_out_opc_reg(s, OPC_SRLW, a0, a1, a2);
1418139c1837SPaolo Bonzini        }
1419139c1837SPaolo Bonzini        break;
1420139c1837SPaolo Bonzini    case INDEX_op_shr_i64:
1421139c1837SPaolo Bonzini        if (c2) {
1422d2f3066eSZihao Yu            tcg_out_opc_imm(s, OPC_SRLI, a0, a1, a2 & 0x3f);
1423139c1837SPaolo Bonzini        } else {
1424139c1837SPaolo Bonzini            tcg_out_opc_reg(s, OPC_SRL, a0, a1, a2);
1425139c1837SPaolo Bonzini        }
1426139c1837SPaolo Bonzini        break;
1427139c1837SPaolo Bonzini
1428139c1837SPaolo Bonzini    case INDEX_op_sar_i32:
1429139c1837SPaolo Bonzini        if (c2) {
1430d2f3066eSZihao Yu            tcg_out_opc_imm(s, OPC_SRAIW, a0, a1, a2 & 0x1f);
1431139c1837SPaolo Bonzini        } else {
1432139c1837SPaolo Bonzini            tcg_out_opc_reg(s, OPC_SRAW, a0, a1, a2);
1433139c1837SPaolo Bonzini        }
1434139c1837SPaolo Bonzini        break;
1435139c1837SPaolo Bonzini    case INDEX_op_sar_i64:
1436139c1837SPaolo Bonzini        if (c2) {
1437d2f3066eSZihao Yu            tcg_out_opc_imm(s, OPC_SRAI, a0, a1, a2 & 0x3f);
1438139c1837SPaolo Bonzini        } else {
1439139c1837SPaolo Bonzini            tcg_out_opc_reg(s, OPC_SRA, a0, a1, a2);
1440139c1837SPaolo Bonzini        }
1441139c1837SPaolo Bonzini        break;
1442139c1837SPaolo Bonzini
1443139c1837SPaolo Bonzini    case INDEX_op_add2_i32:
1444139c1837SPaolo Bonzini        tcg_out_addsub2(s, a0, a1, a2, args[3], args[4], args[5],
1445139c1837SPaolo Bonzini                        const_args[4], const_args[5], false, true);
1446139c1837SPaolo Bonzini        break;
1447139c1837SPaolo Bonzini    case INDEX_op_add2_i64:
1448139c1837SPaolo Bonzini        tcg_out_addsub2(s, a0, a1, a2, args[3], args[4], args[5],
1449139c1837SPaolo Bonzini                        const_args[4], const_args[5], false, false);
1450139c1837SPaolo Bonzini        break;
1451139c1837SPaolo Bonzini    case INDEX_op_sub2_i32:
1452139c1837SPaolo Bonzini        tcg_out_addsub2(s, a0, a1, a2, args[3], args[4], args[5],
1453139c1837SPaolo Bonzini                        const_args[4], const_args[5], true, true);
1454139c1837SPaolo Bonzini        break;
1455139c1837SPaolo Bonzini    case INDEX_op_sub2_i64:
1456139c1837SPaolo Bonzini        tcg_out_addsub2(s, a0, a1, a2, args[3], args[4], args[5],
1457139c1837SPaolo Bonzini                        const_args[4], const_args[5], true, false);
1458139c1837SPaolo Bonzini        break;
1459139c1837SPaolo Bonzini
1460139c1837SPaolo Bonzini    case INDEX_op_brcond_i32:
1461139c1837SPaolo Bonzini    case INDEX_op_brcond_i64:
1462139c1837SPaolo Bonzini        tcg_out_brcond(s, a2, a0, a1, arg_label(args[3]));
1463139c1837SPaolo Bonzini        break;
1464139c1837SPaolo Bonzini    case INDEX_op_brcond2_i32:
1465139c1837SPaolo Bonzini        tcg_out_brcond2(s, args[4], a0, a1, a2, args[3], arg_label(args[5]));
1466139c1837SPaolo Bonzini        break;
1467139c1837SPaolo Bonzini
1468139c1837SPaolo Bonzini    case INDEX_op_setcond_i32:
1469139c1837SPaolo Bonzini    case INDEX_op_setcond_i64:
1470139c1837SPaolo Bonzini        tcg_out_setcond(s, args[3], a0, a1, a2);
1471139c1837SPaolo Bonzini        break;
1472139c1837SPaolo Bonzini    case INDEX_op_setcond2_i32:
1473139c1837SPaolo Bonzini        tcg_out_setcond2(s, args[5], a0, a1, a2, args[3], args[4]);
1474139c1837SPaolo Bonzini        break;
1475139c1837SPaolo Bonzini
1476139c1837SPaolo Bonzini    case INDEX_op_qemu_ld_i32:
1477139c1837SPaolo Bonzini        tcg_out_qemu_ld(s, args, false);
1478139c1837SPaolo Bonzini        break;
1479139c1837SPaolo Bonzini    case INDEX_op_qemu_ld_i64:
1480139c1837SPaolo Bonzini        tcg_out_qemu_ld(s, args, true);
1481139c1837SPaolo Bonzini        break;
1482139c1837SPaolo Bonzini    case INDEX_op_qemu_st_i32:
1483139c1837SPaolo Bonzini        tcg_out_qemu_st(s, args, false);
1484139c1837SPaolo Bonzini        break;
1485139c1837SPaolo Bonzini    case INDEX_op_qemu_st_i64:
1486139c1837SPaolo Bonzini        tcg_out_qemu_st(s, args, true);
1487139c1837SPaolo Bonzini        break;
1488139c1837SPaolo Bonzini
1489139c1837SPaolo Bonzini    case INDEX_op_ext8u_i32:
1490139c1837SPaolo Bonzini    case INDEX_op_ext8u_i64:
1491139c1837SPaolo Bonzini        tcg_out_ext8u(s, a0, a1);
1492139c1837SPaolo Bonzini        break;
1493139c1837SPaolo Bonzini
1494139c1837SPaolo Bonzini    case INDEX_op_ext16u_i32:
1495139c1837SPaolo Bonzini    case INDEX_op_ext16u_i64:
1496139c1837SPaolo Bonzini        tcg_out_ext16u(s, a0, a1);
1497139c1837SPaolo Bonzini        break;
1498139c1837SPaolo Bonzini
1499139c1837SPaolo Bonzini    case INDEX_op_ext32u_i64:
1500139c1837SPaolo Bonzini    case INDEX_op_extu_i32_i64:
1501139c1837SPaolo Bonzini        tcg_out_ext32u(s, a0, a1);
1502139c1837SPaolo Bonzini        break;
1503139c1837SPaolo Bonzini
1504139c1837SPaolo Bonzini    case INDEX_op_ext8s_i32:
1505139c1837SPaolo Bonzini    case INDEX_op_ext8s_i64:
1506139c1837SPaolo Bonzini        tcg_out_ext8s(s, a0, a1);
1507139c1837SPaolo Bonzini        break;
1508139c1837SPaolo Bonzini
1509139c1837SPaolo Bonzini    case INDEX_op_ext16s_i32:
1510139c1837SPaolo Bonzini    case INDEX_op_ext16s_i64:
1511139c1837SPaolo Bonzini        tcg_out_ext16s(s, a0, a1);
1512139c1837SPaolo Bonzini        break;
1513139c1837SPaolo Bonzini
1514139c1837SPaolo Bonzini    case INDEX_op_ext32s_i64:
1515139c1837SPaolo Bonzini    case INDEX_op_extrl_i64_i32:
1516139c1837SPaolo Bonzini    case INDEX_op_ext_i32_i64:
1517139c1837SPaolo Bonzini        tcg_out_ext32s(s, a0, a1);
1518139c1837SPaolo Bonzini        break;
1519139c1837SPaolo Bonzini
1520139c1837SPaolo Bonzini    case INDEX_op_extrh_i64_i32:
1521139c1837SPaolo Bonzini        tcg_out_opc_imm(s, OPC_SRAI, a0, a1, 32);
1522139c1837SPaolo Bonzini        break;
1523139c1837SPaolo Bonzini
1524139c1837SPaolo Bonzini    case INDEX_op_mulsh_i32:
1525139c1837SPaolo Bonzini    case INDEX_op_mulsh_i64:
1526139c1837SPaolo Bonzini        tcg_out_opc_reg(s, OPC_MULH, a0, a1, a2);
1527139c1837SPaolo Bonzini        break;
1528139c1837SPaolo Bonzini
1529139c1837SPaolo Bonzini    case INDEX_op_muluh_i32:
1530139c1837SPaolo Bonzini    case INDEX_op_muluh_i64:
1531139c1837SPaolo Bonzini        tcg_out_opc_reg(s, OPC_MULHU, a0, a1, a2);
1532139c1837SPaolo Bonzini        break;
1533139c1837SPaolo Bonzini
1534139c1837SPaolo Bonzini    case INDEX_op_mb:
1535139c1837SPaolo Bonzini        tcg_out_mb(s, a0);
1536139c1837SPaolo Bonzini        break;
1537139c1837SPaolo Bonzini
1538139c1837SPaolo Bonzini    case INDEX_op_mov_i32:  /* Always emitted via tcg_out_mov.  */
1539139c1837SPaolo Bonzini    case INDEX_op_mov_i64:
1540139c1837SPaolo Bonzini    case INDEX_op_call:     /* Always emitted via tcg_out_call.  */
1541139c1837SPaolo Bonzini    default:
1542139c1837SPaolo Bonzini        g_assert_not_reached();
1543139c1837SPaolo Bonzini    }
1544139c1837SPaolo Bonzini}
1545139c1837SPaolo Bonzini
1546*665be288SRichard Hendersonstatic TCGConstraintSetIndex tcg_target_op_def(TCGOpcode op)
1547139c1837SPaolo Bonzini{
1548139c1837SPaolo Bonzini    switch (op) {
1549139c1837SPaolo Bonzini    case INDEX_op_goto_ptr:
1550*665be288SRichard Henderson        return C_O0_I1(r);
1551139c1837SPaolo Bonzini
1552139c1837SPaolo Bonzini    case INDEX_op_ld8u_i32:
1553139c1837SPaolo Bonzini    case INDEX_op_ld8s_i32:
1554139c1837SPaolo Bonzini    case INDEX_op_ld16u_i32:
1555139c1837SPaolo Bonzini    case INDEX_op_ld16s_i32:
1556139c1837SPaolo Bonzini    case INDEX_op_ld_i32:
1557139c1837SPaolo Bonzini    case INDEX_op_not_i32:
1558139c1837SPaolo Bonzini    case INDEX_op_neg_i32:
1559139c1837SPaolo Bonzini    case INDEX_op_ld8u_i64:
1560139c1837SPaolo Bonzini    case INDEX_op_ld8s_i64:
1561139c1837SPaolo Bonzini    case INDEX_op_ld16u_i64:
1562139c1837SPaolo Bonzini    case INDEX_op_ld16s_i64:
1563139c1837SPaolo Bonzini    case INDEX_op_ld32s_i64:
1564139c1837SPaolo Bonzini    case INDEX_op_ld32u_i64:
1565139c1837SPaolo Bonzini    case INDEX_op_ld_i64:
1566139c1837SPaolo Bonzini    case INDEX_op_not_i64:
1567139c1837SPaolo Bonzini    case INDEX_op_neg_i64:
1568139c1837SPaolo Bonzini    case INDEX_op_ext8u_i32:
1569139c1837SPaolo Bonzini    case INDEX_op_ext8u_i64:
1570139c1837SPaolo Bonzini    case INDEX_op_ext16u_i32:
1571139c1837SPaolo Bonzini    case INDEX_op_ext16u_i64:
1572139c1837SPaolo Bonzini    case INDEX_op_ext32u_i64:
1573139c1837SPaolo Bonzini    case INDEX_op_extu_i32_i64:
1574139c1837SPaolo Bonzini    case INDEX_op_ext8s_i32:
1575139c1837SPaolo Bonzini    case INDEX_op_ext8s_i64:
1576139c1837SPaolo Bonzini    case INDEX_op_ext16s_i32:
1577139c1837SPaolo Bonzini    case INDEX_op_ext16s_i64:
1578139c1837SPaolo Bonzini    case INDEX_op_ext32s_i64:
1579139c1837SPaolo Bonzini    case INDEX_op_extrl_i64_i32:
1580139c1837SPaolo Bonzini    case INDEX_op_extrh_i64_i32:
1581139c1837SPaolo Bonzini    case INDEX_op_ext_i32_i64:
1582*665be288SRichard Henderson        return C_O1_I1(r, r);
1583139c1837SPaolo Bonzini
1584139c1837SPaolo Bonzini    case INDEX_op_st8_i32:
1585139c1837SPaolo Bonzini    case INDEX_op_st16_i32:
1586139c1837SPaolo Bonzini    case INDEX_op_st_i32:
1587139c1837SPaolo Bonzini    case INDEX_op_st8_i64:
1588139c1837SPaolo Bonzini    case INDEX_op_st16_i64:
1589139c1837SPaolo Bonzini    case INDEX_op_st32_i64:
1590139c1837SPaolo Bonzini    case INDEX_op_st_i64:
1591*665be288SRichard Henderson        return C_O0_I2(rZ, r);
1592139c1837SPaolo Bonzini
1593139c1837SPaolo Bonzini    case INDEX_op_add_i32:
1594139c1837SPaolo Bonzini    case INDEX_op_and_i32:
1595139c1837SPaolo Bonzini    case INDEX_op_or_i32:
1596139c1837SPaolo Bonzini    case INDEX_op_xor_i32:
1597139c1837SPaolo Bonzini    case INDEX_op_add_i64:
1598139c1837SPaolo Bonzini    case INDEX_op_and_i64:
1599139c1837SPaolo Bonzini    case INDEX_op_or_i64:
1600139c1837SPaolo Bonzini    case INDEX_op_xor_i64:
1601*665be288SRichard Henderson        return C_O1_I2(r, r, rI);
1602139c1837SPaolo Bonzini
1603139c1837SPaolo Bonzini    case INDEX_op_sub_i32:
1604139c1837SPaolo Bonzini    case INDEX_op_sub_i64:
1605*665be288SRichard Henderson        return C_O1_I2(r, rZ, rN);
1606139c1837SPaolo Bonzini
1607139c1837SPaolo Bonzini    case INDEX_op_mul_i32:
1608139c1837SPaolo Bonzini    case INDEX_op_mulsh_i32:
1609139c1837SPaolo Bonzini    case INDEX_op_muluh_i32:
1610139c1837SPaolo Bonzini    case INDEX_op_div_i32:
1611139c1837SPaolo Bonzini    case INDEX_op_divu_i32:
1612139c1837SPaolo Bonzini    case INDEX_op_rem_i32:
1613139c1837SPaolo Bonzini    case INDEX_op_remu_i32:
1614139c1837SPaolo Bonzini    case INDEX_op_setcond_i32:
1615139c1837SPaolo Bonzini    case INDEX_op_mul_i64:
1616139c1837SPaolo Bonzini    case INDEX_op_mulsh_i64:
1617139c1837SPaolo Bonzini    case INDEX_op_muluh_i64:
1618139c1837SPaolo Bonzini    case INDEX_op_div_i64:
1619139c1837SPaolo Bonzini    case INDEX_op_divu_i64:
1620139c1837SPaolo Bonzini    case INDEX_op_rem_i64:
1621139c1837SPaolo Bonzini    case INDEX_op_remu_i64:
1622139c1837SPaolo Bonzini    case INDEX_op_setcond_i64:
1623*665be288SRichard Henderson        return C_O1_I2(r, rZ, rZ);
1624139c1837SPaolo Bonzini
1625139c1837SPaolo Bonzini    case INDEX_op_shl_i32:
1626139c1837SPaolo Bonzini    case INDEX_op_shr_i32:
1627139c1837SPaolo Bonzini    case INDEX_op_sar_i32:
1628139c1837SPaolo Bonzini    case INDEX_op_shl_i64:
1629139c1837SPaolo Bonzini    case INDEX_op_shr_i64:
1630139c1837SPaolo Bonzini    case INDEX_op_sar_i64:
1631*665be288SRichard Henderson        return C_O1_I2(r, r, ri);
1632139c1837SPaolo Bonzini
1633139c1837SPaolo Bonzini    case INDEX_op_brcond_i32:
1634139c1837SPaolo Bonzini    case INDEX_op_brcond_i64:
1635*665be288SRichard Henderson        return C_O0_I2(rZ, rZ);
1636139c1837SPaolo Bonzini
1637139c1837SPaolo Bonzini    case INDEX_op_add2_i32:
1638139c1837SPaolo Bonzini    case INDEX_op_add2_i64:
1639139c1837SPaolo Bonzini    case INDEX_op_sub2_i32:
1640139c1837SPaolo Bonzini    case INDEX_op_sub2_i64:
1641*665be288SRichard Henderson        return C_O2_I4(r, r, rZ, rZ, rM, rM);
1642139c1837SPaolo Bonzini
1643139c1837SPaolo Bonzini    case INDEX_op_brcond2_i32:
1644*665be288SRichard Henderson        return C_O0_I4(rZ, rZ, rZ, rZ);
1645139c1837SPaolo Bonzini
1646139c1837SPaolo Bonzini    case INDEX_op_setcond2_i32:
1647*665be288SRichard Henderson        return C_O1_I4(r, rZ, rZ, rZ, rZ);
1648139c1837SPaolo Bonzini
1649139c1837SPaolo Bonzini    case INDEX_op_qemu_ld_i32:
1650*665be288SRichard Henderson        return (TARGET_LONG_BITS <= TCG_TARGET_REG_BITS
1651*665be288SRichard Henderson                ? C_O1_I1(r, L) : C_O1_I2(r, L, L));
1652139c1837SPaolo Bonzini    case INDEX_op_qemu_st_i32:
1653*665be288SRichard Henderson        return (TARGET_LONG_BITS <= TCG_TARGET_REG_BITS
1654*665be288SRichard Henderson                ? C_O0_I2(LZ, L) : C_O0_I3(LZ, L, L));
1655139c1837SPaolo Bonzini    case INDEX_op_qemu_ld_i64:
1656*665be288SRichard Henderson        return (TCG_TARGET_REG_BITS == 64 ? C_O1_I1(r, L)
1657*665be288SRichard Henderson               : TARGET_LONG_BITS <= TCG_TARGET_REG_BITS ? C_O2_I1(r, r, L)
1658*665be288SRichard Henderson               : C_O2_I2(r, r, L, L));
1659139c1837SPaolo Bonzini    case INDEX_op_qemu_st_i64:
1660*665be288SRichard Henderson        return (TCG_TARGET_REG_BITS == 64 ? C_O0_I2(LZ, L)
1661*665be288SRichard Henderson               : TARGET_LONG_BITS <= TCG_TARGET_REG_BITS ? C_O0_I3(LZ, LZ, L)
1662*665be288SRichard Henderson               : C_O0_I4(LZ, LZ, L, L));
1663139c1837SPaolo Bonzini
1664139c1837SPaolo Bonzini    default:
1665*665be288SRichard Henderson        g_assert_not_reached();
1666139c1837SPaolo Bonzini    }
1667139c1837SPaolo Bonzini}
1668139c1837SPaolo Bonzini
1669139c1837SPaolo Bonzinistatic const int tcg_target_callee_save_regs[] = {
1670139c1837SPaolo Bonzini    TCG_REG_S0,       /* used for the global env (TCG_AREG0) */
1671139c1837SPaolo Bonzini    TCG_REG_S1,
1672139c1837SPaolo Bonzini    TCG_REG_S2,
1673139c1837SPaolo Bonzini    TCG_REG_S3,
1674139c1837SPaolo Bonzini    TCG_REG_S4,
1675139c1837SPaolo Bonzini    TCG_REG_S5,
1676139c1837SPaolo Bonzini    TCG_REG_S6,
1677139c1837SPaolo Bonzini    TCG_REG_S7,
1678139c1837SPaolo Bonzini    TCG_REG_S8,
1679139c1837SPaolo Bonzini    TCG_REG_S9,
1680139c1837SPaolo Bonzini    TCG_REG_S10,
1681139c1837SPaolo Bonzini    TCG_REG_S11,
1682139c1837SPaolo Bonzini    TCG_REG_RA,       /* should be last for ABI compliance */
1683139c1837SPaolo Bonzini};
1684139c1837SPaolo Bonzini
1685139c1837SPaolo Bonzini/* Stack frame parameters.  */
1686139c1837SPaolo Bonzini#define REG_SIZE   (TCG_TARGET_REG_BITS / 8)
1687139c1837SPaolo Bonzini#define SAVE_SIZE  ((int)ARRAY_SIZE(tcg_target_callee_save_regs) * REG_SIZE)
1688139c1837SPaolo Bonzini#define TEMP_SIZE  (CPU_TEMP_BUF_NLONGS * (int)sizeof(long))
1689139c1837SPaolo Bonzini#define FRAME_SIZE ((TCG_STATIC_CALL_ARGS_SIZE + TEMP_SIZE + SAVE_SIZE \
1690139c1837SPaolo Bonzini                     + TCG_TARGET_STACK_ALIGN - 1) \
1691139c1837SPaolo Bonzini                    & -TCG_TARGET_STACK_ALIGN)
1692139c1837SPaolo Bonzini#define SAVE_OFS   (TCG_STATIC_CALL_ARGS_SIZE + TEMP_SIZE)
1693139c1837SPaolo Bonzini
1694139c1837SPaolo Bonzini/* We're expecting to be able to use an immediate for frame allocation.  */
1695139c1837SPaolo BonziniQEMU_BUILD_BUG_ON(FRAME_SIZE > 0x7ff);
1696139c1837SPaolo Bonzini
1697139c1837SPaolo Bonzini/* Generate global QEMU prologue and epilogue code */
1698139c1837SPaolo Bonzinistatic void tcg_target_qemu_prologue(TCGContext *s)
1699139c1837SPaolo Bonzini{
1700139c1837SPaolo Bonzini    int i;
1701139c1837SPaolo Bonzini
1702139c1837SPaolo Bonzini    tcg_set_frame(s, TCG_REG_SP, TCG_STATIC_CALL_ARGS_SIZE, TEMP_SIZE);
1703139c1837SPaolo Bonzini
1704139c1837SPaolo Bonzini    /* TB prologue */
1705139c1837SPaolo Bonzini    tcg_out_opc_imm(s, OPC_ADDI, TCG_REG_SP, TCG_REG_SP, -FRAME_SIZE);
1706139c1837SPaolo Bonzini    for (i = 0; i < ARRAY_SIZE(tcg_target_callee_save_regs); i++) {
1707139c1837SPaolo Bonzini        tcg_out_st(s, TCG_TYPE_REG, tcg_target_callee_save_regs[i],
1708139c1837SPaolo Bonzini                   TCG_REG_SP, SAVE_OFS + i * REG_SIZE);
1709139c1837SPaolo Bonzini    }
1710139c1837SPaolo Bonzini
1711139c1837SPaolo Bonzini#if !defined(CONFIG_SOFTMMU)
1712139c1837SPaolo Bonzini    tcg_out_movi(s, TCG_TYPE_PTR, TCG_GUEST_BASE_REG, guest_base);
1713139c1837SPaolo Bonzini    tcg_regset_set_reg(s->reserved_regs, TCG_GUEST_BASE_REG);
1714139c1837SPaolo Bonzini#endif
1715139c1837SPaolo Bonzini
1716139c1837SPaolo Bonzini    /* Call generated code */
1717139c1837SPaolo Bonzini    tcg_out_mov(s, TCG_TYPE_PTR, TCG_AREG0, tcg_target_call_iarg_regs[0]);
1718139c1837SPaolo Bonzini    tcg_out_opc_imm(s, OPC_JALR, TCG_REG_ZERO, tcg_target_call_iarg_regs[1], 0);
1719139c1837SPaolo Bonzini
1720139c1837SPaolo Bonzini    /* Return path for goto_ptr. Set return value to 0 */
1721c8bc1168SRichard Henderson    tcg_code_gen_epilogue = tcg_splitwx_to_rx(s->code_ptr);
1722139c1837SPaolo Bonzini    tcg_out_mov(s, TCG_TYPE_REG, TCG_REG_A0, TCG_REG_ZERO);
1723139c1837SPaolo Bonzini
1724139c1837SPaolo Bonzini    /* TB epilogue */
1725793f7381SRichard Henderson    tb_ret_addr = tcg_splitwx_to_rx(s->code_ptr);
1726139c1837SPaolo Bonzini    for (i = 0; i < ARRAY_SIZE(tcg_target_callee_save_regs); i++) {
1727139c1837SPaolo Bonzini        tcg_out_ld(s, TCG_TYPE_REG, tcg_target_callee_save_regs[i],
1728139c1837SPaolo Bonzini                   TCG_REG_SP, SAVE_OFS + i * REG_SIZE);
1729139c1837SPaolo Bonzini    }
1730139c1837SPaolo Bonzini
1731139c1837SPaolo Bonzini    tcg_out_opc_imm(s, OPC_ADDI, TCG_REG_SP, TCG_REG_SP, FRAME_SIZE);
1732139c1837SPaolo Bonzini    tcg_out_opc_imm(s, OPC_JALR, TCG_REG_ZERO, TCG_REG_RA, 0);
1733139c1837SPaolo Bonzini}
1734139c1837SPaolo Bonzini
1735139c1837SPaolo Bonzinistatic void tcg_target_init(TCGContext *s)
1736139c1837SPaolo Bonzini{
1737139c1837SPaolo Bonzini    tcg_target_available_regs[TCG_TYPE_I32] = 0xffffffff;
1738139c1837SPaolo Bonzini    if (TCG_TARGET_REG_BITS == 64) {
1739139c1837SPaolo Bonzini        tcg_target_available_regs[TCG_TYPE_I64] = 0xffffffff;
1740139c1837SPaolo Bonzini    }
1741139c1837SPaolo Bonzini
1742139c1837SPaolo Bonzini    tcg_target_call_clobber_regs = -1u;
1743139c1837SPaolo Bonzini    tcg_regset_reset_reg(tcg_target_call_clobber_regs, TCG_REG_S0);
1744139c1837SPaolo Bonzini    tcg_regset_reset_reg(tcg_target_call_clobber_regs, TCG_REG_S1);
1745139c1837SPaolo Bonzini    tcg_regset_reset_reg(tcg_target_call_clobber_regs, TCG_REG_S2);
1746139c1837SPaolo Bonzini    tcg_regset_reset_reg(tcg_target_call_clobber_regs, TCG_REG_S3);
1747139c1837SPaolo Bonzini    tcg_regset_reset_reg(tcg_target_call_clobber_regs, TCG_REG_S4);
1748139c1837SPaolo Bonzini    tcg_regset_reset_reg(tcg_target_call_clobber_regs, TCG_REG_S5);
1749139c1837SPaolo Bonzini    tcg_regset_reset_reg(tcg_target_call_clobber_regs, TCG_REG_S6);
1750139c1837SPaolo Bonzini    tcg_regset_reset_reg(tcg_target_call_clobber_regs, TCG_REG_S7);
1751139c1837SPaolo Bonzini    tcg_regset_reset_reg(tcg_target_call_clobber_regs, TCG_REG_S8);
1752139c1837SPaolo Bonzini    tcg_regset_reset_reg(tcg_target_call_clobber_regs, TCG_REG_S9);
1753139c1837SPaolo Bonzini    tcg_regset_reset_reg(tcg_target_call_clobber_regs, TCG_REG_S10);
1754139c1837SPaolo Bonzini    tcg_regset_reset_reg(tcg_target_call_clobber_regs, TCG_REG_S11);
1755139c1837SPaolo Bonzini
1756139c1837SPaolo Bonzini    s->reserved_regs = 0;
1757139c1837SPaolo Bonzini    tcg_regset_set_reg(s->reserved_regs, TCG_REG_ZERO);
1758139c1837SPaolo Bonzini    tcg_regset_set_reg(s->reserved_regs, TCG_REG_TMP0);
1759139c1837SPaolo Bonzini    tcg_regset_set_reg(s->reserved_regs, TCG_REG_TMP1);
1760139c1837SPaolo Bonzini    tcg_regset_set_reg(s->reserved_regs, TCG_REG_TMP2);
1761139c1837SPaolo Bonzini    tcg_regset_set_reg(s->reserved_regs, TCG_REG_SP);
1762139c1837SPaolo Bonzini    tcg_regset_set_reg(s->reserved_regs, TCG_REG_GP);
1763139c1837SPaolo Bonzini    tcg_regset_set_reg(s->reserved_regs, TCG_REG_TP);
1764139c1837SPaolo Bonzini}
1765139c1837SPaolo Bonzini
1766139c1837SPaolo Bonzinitypedef struct {
1767139c1837SPaolo Bonzini    DebugFrameHeader h;
1768139c1837SPaolo Bonzini    uint8_t fde_def_cfa[4];
1769139c1837SPaolo Bonzini    uint8_t fde_reg_ofs[ARRAY_SIZE(tcg_target_callee_save_regs) * 2];
1770139c1837SPaolo Bonzini} DebugFrame;
1771139c1837SPaolo Bonzini
1772139c1837SPaolo Bonzini#define ELF_HOST_MACHINE EM_RISCV
1773139c1837SPaolo Bonzini
1774139c1837SPaolo Bonzinistatic const DebugFrame debug_frame = {
1775139c1837SPaolo Bonzini    .h.cie.len = sizeof(DebugFrameCIE) - 4, /* length after .len member */
1776139c1837SPaolo Bonzini    .h.cie.id = -1,
1777139c1837SPaolo Bonzini    .h.cie.version = 1,
1778139c1837SPaolo Bonzini    .h.cie.code_align = 1,
1779139c1837SPaolo Bonzini    .h.cie.data_align = -(TCG_TARGET_REG_BITS / 8) & 0x7f, /* sleb128 */
1780139c1837SPaolo Bonzini    .h.cie.return_column = TCG_REG_RA,
1781139c1837SPaolo Bonzini
1782139c1837SPaolo Bonzini    /* Total FDE size does not include the "len" member.  */
1783139c1837SPaolo Bonzini    .h.fde.len = sizeof(DebugFrame) - offsetof(DebugFrame, h.fde.cie_offset),
1784139c1837SPaolo Bonzini
1785139c1837SPaolo Bonzini    .fde_def_cfa = {
1786139c1837SPaolo Bonzini        12, TCG_REG_SP,                 /* DW_CFA_def_cfa sp, ... */
1787139c1837SPaolo Bonzini        (FRAME_SIZE & 0x7f) | 0x80,     /* ... uleb128 FRAME_SIZE */
1788139c1837SPaolo Bonzini        (FRAME_SIZE >> 7)
1789139c1837SPaolo Bonzini    },
1790139c1837SPaolo Bonzini    .fde_reg_ofs = {
1791139c1837SPaolo Bonzini        0x80 + 9,  12,                  /* DW_CFA_offset, s1,  -96 */
1792139c1837SPaolo Bonzini        0x80 + 18, 11,                  /* DW_CFA_offset, s2,  -88 */
1793139c1837SPaolo Bonzini        0x80 + 19, 10,                  /* DW_CFA_offset, s3,  -80 */
1794139c1837SPaolo Bonzini        0x80 + 20, 9,                   /* DW_CFA_offset, s4,  -72 */
1795139c1837SPaolo Bonzini        0x80 + 21, 8,                   /* DW_CFA_offset, s5,  -64 */
1796139c1837SPaolo Bonzini        0x80 + 22, 7,                   /* DW_CFA_offset, s6,  -56 */
1797139c1837SPaolo Bonzini        0x80 + 23, 6,                   /* DW_CFA_offset, s7,  -48 */
1798139c1837SPaolo Bonzini        0x80 + 24, 5,                   /* DW_CFA_offset, s8,  -40 */
1799139c1837SPaolo Bonzini        0x80 + 25, 4,                   /* DW_CFA_offset, s9,  -32 */
1800139c1837SPaolo Bonzini        0x80 + 26, 3,                   /* DW_CFA_offset, s10, -24 */
1801139c1837SPaolo Bonzini        0x80 + 27, 2,                   /* DW_CFA_offset, s11, -16 */
1802139c1837SPaolo Bonzini        0x80 + 1 , 1,                   /* DW_CFA_offset, ra,  -8 */
1803139c1837SPaolo Bonzini    }
1804139c1837SPaolo Bonzini};
1805139c1837SPaolo Bonzini
1806755bf9e5SRichard Hendersonvoid tcg_register_jit(const void *buf, size_t buf_size)
1807139c1837SPaolo Bonzini{
1808139c1837SPaolo Bonzini    tcg_register_jit_int(buf, buf_size, &debug_frame, sizeof(debug_frame));
1809139c1837SPaolo Bonzini}
1810