xref: /openbmc/qemu/tcg/riscv/tcg-target.c.inc (revision 139c1837db7eaee53e1c441629b5bcc159e1deb0)
1*139c1837SPaolo Bonzini/*
2*139c1837SPaolo Bonzini * Tiny Code Generator for QEMU
3*139c1837SPaolo Bonzini *
4*139c1837SPaolo Bonzini * Copyright (c) 2018 SiFive, Inc
5*139c1837SPaolo Bonzini * Copyright (c) 2008-2009 Arnaud Patard <arnaud.patard@rtp-net.org>
6*139c1837SPaolo Bonzini * Copyright (c) 2009 Aurelien Jarno <aurelien@aurel32.net>
7*139c1837SPaolo Bonzini * Copyright (c) 2008 Fabrice Bellard
8*139c1837SPaolo Bonzini *
9*139c1837SPaolo Bonzini * Based on i386/tcg-target.c and mips/tcg-target.c
10*139c1837SPaolo Bonzini *
11*139c1837SPaolo Bonzini * Permission is hereby granted, free of charge, to any person obtaining a copy
12*139c1837SPaolo Bonzini * of this software and associated documentation files (the "Software"), to deal
13*139c1837SPaolo Bonzini * in the Software without restriction, including without limitation the rights
14*139c1837SPaolo Bonzini * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
15*139c1837SPaolo Bonzini * copies of the Software, and to permit persons to whom the Software is
16*139c1837SPaolo Bonzini * furnished to do so, subject to the following conditions:
17*139c1837SPaolo Bonzini *
18*139c1837SPaolo Bonzini * The above copyright notice and this permission notice shall be included in
19*139c1837SPaolo Bonzini * all copies or substantial portions of the Software.
20*139c1837SPaolo Bonzini *
21*139c1837SPaolo Bonzini * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
22*139c1837SPaolo Bonzini * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
23*139c1837SPaolo Bonzini * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
24*139c1837SPaolo Bonzini * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
25*139c1837SPaolo Bonzini * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
26*139c1837SPaolo Bonzini * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
27*139c1837SPaolo Bonzini * THE SOFTWARE.
28*139c1837SPaolo Bonzini */
29*139c1837SPaolo Bonzini
30*139c1837SPaolo Bonzini#include "../tcg-pool.c.inc"
31*139c1837SPaolo Bonzini
32*139c1837SPaolo Bonzini#ifdef CONFIG_DEBUG_TCG
33*139c1837SPaolo Bonzinistatic const char * const tcg_target_reg_names[TCG_TARGET_NB_REGS] = {
34*139c1837SPaolo Bonzini    "zero",
35*139c1837SPaolo Bonzini    "ra",
36*139c1837SPaolo Bonzini    "sp",
37*139c1837SPaolo Bonzini    "gp",
38*139c1837SPaolo Bonzini    "tp",
39*139c1837SPaolo Bonzini    "t0",
40*139c1837SPaolo Bonzini    "t1",
41*139c1837SPaolo Bonzini    "t2",
42*139c1837SPaolo Bonzini    "s0",
43*139c1837SPaolo Bonzini    "s1",
44*139c1837SPaolo Bonzini    "a0",
45*139c1837SPaolo Bonzini    "a1",
46*139c1837SPaolo Bonzini    "a2",
47*139c1837SPaolo Bonzini    "a3",
48*139c1837SPaolo Bonzini    "a4",
49*139c1837SPaolo Bonzini    "a5",
50*139c1837SPaolo Bonzini    "a6",
51*139c1837SPaolo Bonzini    "a7",
52*139c1837SPaolo Bonzini    "s2",
53*139c1837SPaolo Bonzini    "s3",
54*139c1837SPaolo Bonzini    "s4",
55*139c1837SPaolo Bonzini    "s5",
56*139c1837SPaolo Bonzini    "s6",
57*139c1837SPaolo Bonzini    "s7",
58*139c1837SPaolo Bonzini    "s8",
59*139c1837SPaolo Bonzini    "s9",
60*139c1837SPaolo Bonzini    "s10",
61*139c1837SPaolo Bonzini    "s11",
62*139c1837SPaolo Bonzini    "t3",
63*139c1837SPaolo Bonzini    "t4",
64*139c1837SPaolo Bonzini    "t5",
65*139c1837SPaolo Bonzini    "t6"
66*139c1837SPaolo Bonzini};
67*139c1837SPaolo Bonzini#endif
68*139c1837SPaolo Bonzini
69*139c1837SPaolo Bonzinistatic const int tcg_target_reg_alloc_order[] = {
70*139c1837SPaolo Bonzini    /* Call saved registers */
71*139c1837SPaolo Bonzini    /* TCG_REG_S0 reservered for TCG_AREG0 */
72*139c1837SPaolo Bonzini    TCG_REG_S1,
73*139c1837SPaolo Bonzini    TCG_REG_S2,
74*139c1837SPaolo Bonzini    TCG_REG_S3,
75*139c1837SPaolo Bonzini    TCG_REG_S4,
76*139c1837SPaolo Bonzini    TCG_REG_S5,
77*139c1837SPaolo Bonzini    TCG_REG_S6,
78*139c1837SPaolo Bonzini    TCG_REG_S7,
79*139c1837SPaolo Bonzini    TCG_REG_S8,
80*139c1837SPaolo Bonzini    TCG_REG_S9,
81*139c1837SPaolo Bonzini    TCG_REG_S10,
82*139c1837SPaolo Bonzini    TCG_REG_S11,
83*139c1837SPaolo Bonzini
84*139c1837SPaolo Bonzini    /* Call clobbered registers */
85*139c1837SPaolo Bonzini    TCG_REG_T0,
86*139c1837SPaolo Bonzini    TCG_REG_T1,
87*139c1837SPaolo Bonzini    TCG_REG_T2,
88*139c1837SPaolo Bonzini    TCG_REG_T3,
89*139c1837SPaolo Bonzini    TCG_REG_T4,
90*139c1837SPaolo Bonzini    TCG_REG_T5,
91*139c1837SPaolo Bonzini    TCG_REG_T6,
92*139c1837SPaolo Bonzini
93*139c1837SPaolo Bonzini    /* Argument registers */
94*139c1837SPaolo Bonzini    TCG_REG_A0,
95*139c1837SPaolo Bonzini    TCG_REG_A1,
96*139c1837SPaolo Bonzini    TCG_REG_A2,
97*139c1837SPaolo Bonzini    TCG_REG_A3,
98*139c1837SPaolo Bonzini    TCG_REG_A4,
99*139c1837SPaolo Bonzini    TCG_REG_A5,
100*139c1837SPaolo Bonzini    TCG_REG_A6,
101*139c1837SPaolo Bonzini    TCG_REG_A7,
102*139c1837SPaolo Bonzini};
103*139c1837SPaolo Bonzini
104*139c1837SPaolo Bonzinistatic const int tcg_target_call_iarg_regs[] = {
105*139c1837SPaolo Bonzini    TCG_REG_A0,
106*139c1837SPaolo Bonzini    TCG_REG_A1,
107*139c1837SPaolo Bonzini    TCG_REG_A2,
108*139c1837SPaolo Bonzini    TCG_REG_A3,
109*139c1837SPaolo Bonzini    TCG_REG_A4,
110*139c1837SPaolo Bonzini    TCG_REG_A5,
111*139c1837SPaolo Bonzini    TCG_REG_A6,
112*139c1837SPaolo Bonzini    TCG_REG_A7,
113*139c1837SPaolo Bonzini};
114*139c1837SPaolo Bonzini
115*139c1837SPaolo Bonzinistatic const int tcg_target_call_oarg_regs[] = {
116*139c1837SPaolo Bonzini    TCG_REG_A0,
117*139c1837SPaolo Bonzini    TCG_REG_A1,
118*139c1837SPaolo Bonzini};
119*139c1837SPaolo Bonzini
120*139c1837SPaolo Bonzini#define TCG_CT_CONST_ZERO  0x100
121*139c1837SPaolo Bonzini#define TCG_CT_CONST_S12   0x200
122*139c1837SPaolo Bonzini#define TCG_CT_CONST_N12   0x400
123*139c1837SPaolo Bonzini#define TCG_CT_CONST_M12   0x800
124*139c1837SPaolo Bonzini
125*139c1837SPaolo Bonzinistatic inline tcg_target_long sextreg(tcg_target_long val, int pos, int len)
126*139c1837SPaolo Bonzini{
127*139c1837SPaolo Bonzini    if (TCG_TARGET_REG_BITS == 32) {
128*139c1837SPaolo Bonzini        return sextract32(val, pos, len);
129*139c1837SPaolo Bonzini    } else {
130*139c1837SPaolo Bonzini        return sextract64(val, pos, len);
131*139c1837SPaolo Bonzini    }
132*139c1837SPaolo Bonzini}
133*139c1837SPaolo Bonzini
134*139c1837SPaolo Bonzini/* parse target specific constraints */
135*139c1837SPaolo Bonzinistatic const char *target_parse_constraint(TCGArgConstraint *ct,
136*139c1837SPaolo Bonzini                                           const char *ct_str, TCGType type)
137*139c1837SPaolo Bonzini{
138*139c1837SPaolo Bonzini    switch (*ct_str++) {
139*139c1837SPaolo Bonzini    case 'r':
140*139c1837SPaolo Bonzini        ct->ct |= TCG_CT_REG;
141*139c1837SPaolo Bonzini        ct->u.regs = 0xffffffff;
142*139c1837SPaolo Bonzini        break;
143*139c1837SPaolo Bonzini    case 'L':
144*139c1837SPaolo Bonzini        /* qemu_ld/qemu_st constraint */
145*139c1837SPaolo Bonzini        ct->ct |= TCG_CT_REG;
146*139c1837SPaolo Bonzini        ct->u.regs = 0xffffffff;
147*139c1837SPaolo Bonzini        /* qemu_ld/qemu_st uses TCG_REG_TMP0 */
148*139c1837SPaolo Bonzini#if defined(CONFIG_SOFTMMU)
149*139c1837SPaolo Bonzini        tcg_regset_reset_reg(ct->u.regs, tcg_target_call_iarg_regs[0]);
150*139c1837SPaolo Bonzini        tcg_regset_reset_reg(ct->u.regs, tcg_target_call_iarg_regs[1]);
151*139c1837SPaolo Bonzini        tcg_regset_reset_reg(ct->u.regs, tcg_target_call_iarg_regs[2]);
152*139c1837SPaolo Bonzini        tcg_regset_reset_reg(ct->u.regs, tcg_target_call_iarg_regs[3]);
153*139c1837SPaolo Bonzini        tcg_regset_reset_reg(ct->u.regs, tcg_target_call_iarg_regs[4]);
154*139c1837SPaolo Bonzini#endif
155*139c1837SPaolo Bonzini        break;
156*139c1837SPaolo Bonzini    case 'I':
157*139c1837SPaolo Bonzini        ct->ct |= TCG_CT_CONST_S12;
158*139c1837SPaolo Bonzini        break;
159*139c1837SPaolo Bonzini    case 'N':
160*139c1837SPaolo Bonzini        ct->ct |= TCG_CT_CONST_N12;
161*139c1837SPaolo Bonzini        break;
162*139c1837SPaolo Bonzini    case 'M':
163*139c1837SPaolo Bonzini        ct->ct |= TCG_CT_CONST_M12;
164*139c1837SPaolo Bonzini        break;
165*139c1837SPaolo Bonzini    case 'Z':
166*139c1837SPaolo Bonzini        /* we can use a zero immediate as a zero register argument. */
167*139c1837SPaolo Bonzini        ct->ct |= TCG_CT_CONST_ZERO;
168*139c1837SPaolo Bonzini        break;
169*139c1837SPaolo Bonzini    default:
170*139c1837SPaolo Bonzini        return NULL;
171*139c1837SPaolo Bonzini    }
172*139c1837SPaolo Bonzini    return ct_str;
173*139c1837SPaolo Bonzini}
174*139c1837SPaolo Bonzini
175*139c1837SPaolo Bonzini/* test if a constant matches the constraint */
176*139c1837SPaolo Bonzinistatic int tcg_target_const_match(tcg_target_long val, TCGType type,
177*139c1837SPaolo Bonzini                                  const TCGArgConstraint *arg_ct)
178*139c1837SPaolo Bonzini{
179*139c1837SPaolo Bonzini    int ct = arg_ct->ct;
180*139c1837SPaolo Bonzini    if (ct & TCG_CT_CONST) {
181*139c1837SPaolo Bonzini        return 1;
182*139c1837SPaolo Bonzini    }
183*139c1837SPaolo Bonzini    if ((ct & TCG_CT_CONST_ZERO) && val == 0) {
184*139c1837SPaolo Bonzini        return 1;
185*139c1837SPaolo Bonzini    }
186*139c1837SPaolo Bonzini    if ((ct & TCG_CT_CONST_S12) && val == sextreg(val, 0, 12)) {
187*139c1837SPaolo Bonzini        return 1;
188*139c1837SPaolo Bonzini    }
189*139c1837SPaolo Bonzini    if ((ct & TCG_CT_CONST_N12) && -val == sextreg(-val, 0, 12)) {
190*139c1837SPaolo Bonzini        return 1;
191*139c1837SPaolo Bonzini    }
192*139c1837SPaolo Bonzini    if ((ct & TCG_CT_CONST_M12) && val >= -0xfff && val <= 0xfff) {
193*139c1837SPaolo Bonzini        return 1;
194*139c1837SPaolo Bonzini    }
195*139c1837SPaolo Bonzini    return 0;
196*139c1837SPaolo Bonzini}
197*139c1837SPaolo Bonzini
198*139c1837SPaolo Bonzini/*
199*139c1837SPaolo Bonzini * RISC-V Base ISA opcodes (IM)
200*139c1837SPaolo Bonzini */
201*139c1837SPaolo Bonzini
202*139c1837SPaolo Bonzinitypedef enum {
203*139c1837SPaolo Bonzini    OPC_ADD = 0x33,
204*139c1837SPaolo Bonzini    OPC_ADDI = 0x13,
205*139c1837SPaolo Bonzini    OPC_AND = 0x7033,
206*139c1837SPaolo Bonzini    OPC_ANDI = 0x7013,
207*139c1837SPaolo Bonzini    OPC_AUIPC = 0x17,
208*139c1837SPaolo Bonzini    OPC_BEQ = 0x63,
209*139c1837SPaolo Bonzini    OPC_BGE = 0x5063,
210*139c1837SPaolo Bonzini    OPC_BGEU = 0x7063,
211*139c1837SPaolo Bonzini    OPC_BLT = 0x4063,
212*139c1837SPaolo Bonzini    OPC_BLTU = 0x6063,
213*139c1837SPaolo Bonzini    OPC_BNE = 0x1063,
214*139c1837SPaolo Bonzini    OPC_DIV = 0x2004033,
215*139c1837SPaolo Bonzini    OPC_DIVU = 0x2005033,
216*139c1837SPaolo Bonzini    OPC_JAL = 0x6f,
217*139c1837SPaolo Bonzini    OPC_JALR = 0x67,
218*139c1837SPaolo Bonzini    OPC_LB = 0x3,
219*139c1837SPaolo Bonzini    OPC_LBU = 0x4003,
220*139c1837SPaolo Bonzini    OPC_LD = 0x3003,
221*139c1837SPaolo Bonzini    OPC_LH = 0x1003,
222*139c1837SPaolo Bonzini    OPC_LHU = 0x5003,
223*139c1837SPaolo Bonzini    OPC_LUI = 0x37,
224*139c1837SPaolo Bonzini    OPC_LW = 0x2003,
225*139c1837SPaolo Bonzini    OPC_LWU = 0x6003,
226*139c1837SPaolo Bonzini    OPC_MUL = 0x2000033,
227*139c1837SPaolo Bonzini    OPC_MULH = 0x2001033,
228*139c1837SPaolo Bonzini    OPC_MULHSU = 0x2002033,
229*139c1837SPaolo Bonzini    OPC_MULHU = 0x2003033,
230*139c1837SPaolo Bonzini    OPC_OR = 0x6033,
231*139c1837SPaolo Bonzini    OPC_ORI = 0x6013,
232*139c1837SPaolo Bonzini    OPC_REM = 0x2006033,
233*139c1837SPaolo Bonzini    OPC_REMU = 0x2007033,
234*139c1837SPaolo Bonzini    OPC_SB = 0x23,
235*139c1837SPaolo Bonzini    OPC_SD = 0x3023,
236*139c1837SPaolo Bonzini    OPC_SH = 0x1023,
237*139c1837SPaolo Bonzini    OPC_SLL = 0x1033,
238*139c1837SPaolo Bonzini    OPC_SLLI = 0x1013,
239*139c1837SPaolo Bonzini    OPC_SLT = 0x2033,
240*139c1837SPaolo Bonzini    OPC_SLTI = 0x2013,
241*139c1837SPaolo Bonzini    OPC_SLTIU = 0x3013,
242*139c1837SPaolo Bonzini    OPC_SLTU = 0x3033,
243*139c1837SPaolo Bonzini    OPC_SRA = 0x40005033,
244*139c1837SPaolo Bonzini    OPC_SRAI = 0x40005013,
245*139c1837SPaolo Bonzini    OPC_SRL = 0x5033,
246*139c1837SPaolo Bonzini    OPC_SRLI = 0x5013,
247*139c1837SPaolo Bonzini    OPC_SUB = 0x40000033,
248*139c1837SPaolo Bonzini    OPC_SW = 0x2023,
249*139c1837SPaolo Bonzini    OPC_XOR = 0x4033,
250*139c1837SPaolo Bonzini    OPC_XORI = 0x4013,
251*139c1837SPaolo Bonzini
252*139c1837SPaolo Bonzini#if TCG_TARGET_REG_BITS == 64
253*139c1837SPaolo Bonzini    OPC_ADDIW = 0x1b,
254*139c1837SPaolo Bonzini    OPC_ADDW = 0x3b,
255*139c1837SPaolo Bonzini    OPC_DIVUW = 0x200503b,
256*139c1837SPaolo Bonzini    OPC_DIVW = 0x200403b,
257*139c1837SPaolo Bonzini    OPC_MULW = 0x200003b,
258*139c1837SPaolo Bonzini    OPC_REMUW = 0x200703b,
259*139c1837SPaolo Bonzini    OPC_REMW = 0x200603b,
260*139c1837SPaolo Bonzini    OPC_SLLIW = 0x101b,
261*139c1837SPaolo Bonzini    OPC_SLLW = 0x103b,
262*139c1837SPaolo Bonzini    OPC_SRAIW = 0x4000501b,
263*139c1837SPaolo Bonzini    OPC_SRAW = 0x4000503b,
264*139c1837SPaolo Bonzini    OPC_SRLIW = 0x501b,
265*139c1837SPaolo Bonzini    OPC_SRLW = 0x503b,
266*139c1837SPaolo Bonzini    OPC_SUBW = 0x4000003b,
267*139c1837SPaolo Bonzini#else
268*139c1837SPaolo Bonzini    /* Simplify code throughout by defining aliases for RV32.  */
269*139c1837SPaolo Bonzini    OPC_ADDIW = OPC_ADDI,
270*139c1837SPaolo Bonzini    OPC_ADDW = OPC_ADD,
271*139c1837SPaolo Bonzini    OPC_DIVUW = OPC_DIVU,
272*139c1837SPaolo Bonzini    OPC_DIVW = OPC_DIV,
273*139c1837SPaolo Bonzini    OPC_MULW = OPC_MUL,
274*139c1837SPaolo Bonzini    OPC_REMUW = OPC_REMU,
275*139c1837SPaolo Bonzini    OPC_REMW = OPC_REM,
276*139c1837SPaolo Bonzini    OPC_SLLIW = OPC_SLLI,
277*139c1837SPaolo Bonzini    OPC_SLLW = OPC_SLL,
278*139c1837SPaolo Bonzini    OPC_SRAIW = OPC_SRAI,
279*139c1837SPaolo Bonzini    OPC_SRAW = OPC_SRA,
280*139c1837SPaolo Bonzini    OPC_SRLIW = OPC_SRLI,
281*139c1837SPaolo Bonzini    OPC_SRLW = OPC_SRL,
282*139c1837SPaolo Bonzini    OPC_SUBW = OPC_SUB,
283*139c1837SPaolo Bonzini#endif
284*139c1837SPaolo Bonzini
285*139c1837SPaolo Bonzini    OPC_FENCE = 0x0000000f,
286*139c1837SPaolo Bonzini} RISCVInsn;
287*139c1837SPaolo Bonzini
288*139c1837SPaolo Bonzini/*
289*139c1837SPaolo Bonzini * RISC-V immediate and instruction encoders (excludes 16-bit RVC)
290*139c1837SPaolo Bonzini */
291*139c1837SPaolo Bonzini
292*139c1837SPaolo Bonzini/* Type-R */
293*139c1837SPaolo Bonzini
294*139c1837SPaolo Bonzinistatic int32_t encode_r(RISCVInsn opc, TCGReg rd, TCGReg rs1, TCGReg rs2)
295*139c1837SPaolo Bonzini{
296*139c1837SPaolo Bonzini    return opc | (rd & 0x1f) << 7 | (rs1 & 0x1f) << 15 | (rs2 & 0x1f) << 20;
297*139c1837SPaolo Bonzini}
298*139c1837SPaolo Bonzini
299*139c1837SPaolo Bonzini/* Type-I */
300*139c1837SPaolo Bonzini
301*139c1837SPaolo Bonzinistatic int32_t encode_imm12(uint32_t imm)
302*139c1837SPaolo Bonzini{
303*139c1837SPaolo Bonzini    return (imm & 0xfff) << 20;
304*139c1837SPaolo Bonzini}
305*139c1837SPaolo Bonzini
306*139c1837SPaolo Bonzinistatic int32_t encode_i(RISCVInsn opc, TCGReg rd, TCGReg rs1, uint32_t imm)
307*139c1837SPaolo Bonzini{
308*139c1837SPaolo Bonzini    return opc | (rd & 0x1f) << 7 | (rs1 & 0x1f) << 15 | encode_imm12(imm);
309*139c1837SPaolo Bonzini}
310*139c1837SPaolo Bonzini
311*139c1837SPaolo Bonzini/* Type-S */
312*139c1837SPaolo Bonzini
313*139c1837SPaolo Bonzinistatic int32_t encode_simm12(uint32_t imm)
314*139c1837SPaolo Bonzini{
315*139c1837SPaolo Bonzini    int32_t ret = 0;
316*139c1837SPaolo Bonzini
317*139c1837SPaolo Bonzini    ret |= (imm & 0xFE0) << 20;
318*139c1837SPaolo Bonzini    ret |= (imm & 0x1F) << 7;
319*139c1837SPaolo Bonzini
320*139c1837SPaolo Bonzini    return ret;
321*139c1837SPaolo Bonzini}
322*139c1837SPaolo Bonzini
323*139c1837SPaolo Bonzinistatic int32_t encode_s(RISCVInsn opc, TCGReg rs1, TCGReg rs2, uint32_t imm)
324*139c1837SPaolo Bonzini{
325*139c1837SPaolo Bonzini    return opc | (rs1 & 0x1f) << 15 | (rs2 & 0x1f) << 20 | encode_simm12(imm);
326*139c1837SPaolo Bonzini}
327*139c1837SPaolo Bonzini
328*139c1837SPaolo Bonzini/* Type-SB */
329*139c1837SPaolo Bonzini
330*139c1837SPaolo Bonzinistatic int32_t encode_sbimm12(uint32_t imm)
331*139c1837SPaolo Bonzini{
332*139c1837SPaolo Bonzini    int32_t ret = 0;
333*139c1837SPaolo Bonzini
334*139c1837SPaolo Bonzini    ret |= (imm & 0x1000) << 19;
335*139c1837SPaolo Bonzini    ret |= (imm & 0x7e0) << 20;
336*139c1837SPaolo Bonzini    ret |= (imm & 0x1e) << 7;
337*139c1837SPaolo Bonzini    ret |= (imm & 0x800) >> 4;
338*139c1837SPaolo Bonzini
339*139c1837SPaolo Bonzini    return ret;
340*139c1837SPaolo Bonzini}
341*139c1837SPaolo Bonzini
342*139c1837SPaolo Bonzinistatic int32_t encode_sb(RISCVInsn opc, TCGReg rs1, TCGReg rs2, uint32_t imm)
343*139c1837SPaolo Bonzini{
344*139c1837SPaolo Bonzini    return opc | (rs1 & 0x1f) << 15 | (rs2 & 0x1f) << 20 | encode_sbimm12(imm);
345*139c1837SPaolo Bonzini}
346*139c1837SPaolo Bonzini
347*139c1837SPaolo Bonzini/* Type-U */
348*139c1837SPaolo Bonzini
349*139c1837SPaolo Bonzinistatic int32_t encode_uimm20(uint32_t imm)
350*139c1837SPaolo Bonzini{
351*139c1837SPaolo Bonzini    return imm & 0xfffff000;
352*139c1837SPaolo Bonzini}
353*139c1837SPaolo Bonzini
354*139c1837SPaolo Bonzinistatic int32_t encode_u(RISCVInsn opc, TCGReg rd, uint32_t imm)
355*139c1837SPaolo Bonzini{
356*139c1837SPaolo Bonzini    return opc | (rd & 0x1f) << 7 | encode_uimm20(imm);
357*139c1837SPaolo Bonzini}
358*139c1837SPaolo Bonzini
359*139c1837SPaolo Bonzini/* Type-UJ */
360*139c1837SPaolo Bonzini
361*139c1837SPaolo Bonzinistatic int32_t encode_ujimm20(uint32_t imm)
362*139c1837SPaolo Bonzini{
363*139c1837SPaolo Bonzini    int32_t ret = 0;
364*139c1837SPaolo Bonzini
365*139c1837SPaolo Bonzini    ret |= (imm & 0x0007fe) << (21 - 1);
366*139c1837SPaolo Bonzini    ret |= (imm & 0x000800) << (20 - 11);
367*139c1837SPaolo Bonzini    ret |= (imm & 0x0ff000) << (12 - 12);
368*139c1837SPaolo Bonzini    ret |= (imm & 0x100000) << (31 - 20);
369*139c1837SPaolo Bonzini
370*139c1837SPaolo Bonzini    return ret;
371*139c1837SPaolo Bonzini}
372*139c1837SPaolo Bonzini
373*139c1837SPaolo Bonzinistatic int32_t encode_uj(RISCVInsn opc, TCGReg rd, uint32_t imm)
374*139c1837SPaolo Bonzini{
375*139c1837SPaolo Bonzini    return opc | (rd & 0x1f) << 7 | encode_ujimm20(imm);
376*139c1837SPaolo Bonzini}
377*139c1837SPaolo Bonzini
378*139c1837SPaolo Bonzini/*
379*139c1837SPaolo Bonzini * RISC-V instruction emitters
380*139c1837SPaolo Bonzini */
381*139c1837SPaolo Bonzini
382*139c1837SPaolo Bonzinistatic void tcg_out_opc_reg(TCGContext *s, RISCVInsn opc,
383*139c1837SPaolo Bonzini                            TCGReg rd, TCGReg rs1, TCGReg rs2)
384*139c1837SPaolo Bonzini{
385*139c1837SPaolo Bonzini    tcg_out32(s, encode_r(opc, rd, rs1, rs2));
386*139c1837SPaolo Bonzini}
387*139c1837SPaolo Bonzini
388*139c1837SPaolo Bonzinistatic void tcg_out_opc_imm(TCGContext *s, RISCVInsn opc,
389*139c1837SPaolo Bonzini                            TCGReg rd, TCGReg rs1, TCGArg imm)
390*139c1837SPaolo Bonzini{
391*139c1837SPaolo Bonzini    tcg_out32(s, encode_i(opc, rd, rs1, imm));
392*139c1837SPaolo Bonzini}
393*139c1837SPaolo Bonzini
394*139c1837SPaolo Bonzinistatic void tcg_out_opc_store(TCGContext *s, RISCVInsn opc,
395*139c1837SPaolo Bonzini                              TCGReg rs1, TCGReg rs2, uint32_t imm)
396*139c1837SPaolo Bonzini{
397*139c1837SPaolo Bonzini    tcg_out32(s, encode_s(opc, rs1, rs2, imm));
398*139c1837SPaolo Bonzini}
399*139c1837SPaolo Bonzini
400*139c1837SPaolo Bonzinistatic void tcg_out_opc_branch(TCGContext *s, RISCVInsn opc,
401*139c1837SPaolo Bonzini                               TCGReg rs1, TCGReg rs2, uint32_t imm)
402*139c1837SPaolo Bonzini{
403*139c1837SPaolo Bonzini    tcg_out32(s, encode_sb(opc, rs1, rs2, imm));
404*139c1837SPaolo Bonzini}
405*139c1837SPaolo Bonzini
406*139c1837SPaolo Bonzinistatic void tcg_out_opc_upper(TCGContext *s, RISCVInsn opc,
407*139c1837SPaolo Bonzini                              TCGReg rd, uint32_t imm)
408*139c1837SPaolo Bonzini{
409*139c1837SPaolo Bonzini    tcg_out32(s, encode_u(opc, rd, imm));
410*139c1837SPaolo Bonzini}
411*139c1837SPaolo Bonzini
412*139c1837SPaolo Bonzinistatic void tcg_out_opc_jump(TCGContext *s, RISCVInsn opc,
413*139c1837SPaolo Bonzini                             TCGReg rd, uint32_t imm)
414*139c1837SPaolo Bonzini{
415*139c1837SPaolo Bonzini    tcg_out32(s, encode_uj(opc, rd, imm));
416*139c1837SPaolo Bonzini}
417*139c1837SPaolo Bonzini
418*139c1837SPaolo Bonzinistatic void tcg_out_nop_fill(tcg_insn_unit *p, int count)
419*139c1837SPaolo Bonzini{
420*139c1837SPaolo Bonzini    int i;
421*139c1837SPaolo Bonzini    for (i = 0; i < count; ++i) {
422*139c1837SPaolo Bonzini        p[i] = encode_i(OPC_ADDI, TCG_REG_ZERO, TCG_REG_ZERO, 0);
423*139c1837SPaolo Bonzini    }
424*139c1837SPaolo Bonzini}
425*139c1837SPaolo Bonzini
426*139c1837SPaolo Bonzini/*
427*139c1837SPaolo Bonzini * Relocations
428*139c1837SPaolo Bonzini */
429*139c1837SPaolo Bonzini
430*139c1837SPaolo Bonzinistatic bool reloc_sbimm12(tcg_insn_unit *code_ptr, tcg_insn_unit *target)
431*139c1837SPaolo Bonzini{
432*139c1837SPaolo Bonzini    intptr_t offset = (intptr_t)target - (intptr_t)code_ptr;
433*139c1837SPaolo Bonzini
434*139c1837SPaolo Bonzini    if (offset == sextreg(offset, 1, 12) << 1) {
435*139c1837SPaolo Bonzini        code_ptr[0] |= encode_sbimm12(offset);
436*139c1837SPaolo Bonzini        return true;
437*139c1837SPaolo Bonzini    }
438*139c1837SPaolo Bonzini
439*139c1837SPaolo Bonzini    return false;
440*139c1837SPaolo Bonzini}
441*139c1837SPaolo Bonzini
442*139c1837SPaolo Bonzinistatic bool reloc_jimm20(tcg_insn_unit *code_ptr, tcg_insn_unit *target)
443*139c1837SPaolo Bonzini{
444*139c1837SPaolo Bonzini    intptr_t offset = (intptr_t)target - (intptr_t)code_ptr;
445*139c1837SPaolo Bonzini
446*139c1837SPaolo Bonzini    if (offset == sextreg(offset, 1, 20) << 1) {
447*139c1837SPaolo Bonzini        code_ptr[0] |= encode_ujimm20(offset);
448*139c1837SPaolo Bonzini        return true;
449*139c1837SPaolo Bonzini    }
450*139c1837SPaolo Bonzini
451*139c1837SPaolo Bonzini    return false;
452*139c1837SPaolo Bonzini}
453*139c1837SPaolo Bonzini
454*139c1837SPaolo Bonzinistatic bool reloc_call(tcg_insn_unit *code_ptr, tcg_insn_unit *target)
455*139c1837SPaolo Bonzini{
456*139c1837SPaolo Bonzini    intptr_t offset = (intptr_t)target - (intptr_t)code_ptr;
457*139c1837SPaolo Bonzini    int32_t lo = sextreg(offset, 0, 12);
458*139c1837SPaolo Bonzini    int32_t hi = offset - lo;
459*139c1837SPaolo Bonzini
460*139c1837SPaolo Bonzini    if (offset == hi + lo) {
461*139c1837SPaolo Bonzini        code_ptr[0] |= encode_uimm20(hi);
462*139c1837SPaolo Bonzini        code_ptr[1] |= encode_imm12(lo);
463*139c1837SPaolo Bonzini        return true;
464*139c1837SPaolo Bonzini    }
465*139c1837SPaolo Bonzini
466*139c1837SPaolo Bonzini    return false;
467*139c1837SPaolo Bonzini}
468*139c1837SPaolo Bonzini
469*139c1837SPaolo Bonzinistatic bool patch_reloc(tcg_insn_unit *code_ptr, int type,
470*139c1837SPaolo Bonzini                        intptr_t value, intptr_t addend)
471*139c1837SPaolo Bonzini{
472*139c1837SPaolo Bonzini    uint32_t insn = *code_ptr;
473*139c1837SPaolo Bonzini    intptr_t diff;
474*139c1837SPaolo Bonzini    bool short_jmp;
475*139c1837SPaolo Bonzini
476*139c1837SPaolo Bonzini    tcg_debug_assert(addend == 0);
477*139c1837SPaolo Bonzini
478*139c1837SPaolo Bonzini    switch (type) {
479*139c1837SPaolo Bonzini    case R_RISCV_BRANCH:
480*139c1837SPaolo Bonzini        diff = value - (uintptr_t)code_ptr;
481*139c1837SPaolo Bonzini        short_jmp = diff == sextreg(diff, 0, 12);
482*139c1837SPaolo Bonzini        if (short_jmp) {
483*139c1837SPaolo Bonzini            return reloc_sbimm12(code_ptr, (tcg_insn_unit *)value);
484*139c1837SPaolo Bonzini        } else {
485*139c1837SPaolo Bonzini            /* Invert the condition */
486*139c1837SPaolo Bonzini            insn = insn ^ (1 << 12);
487*139c1837SPaolo Bonzini            /* Clear the offset */
488*139c1837SPaolo Bonzini            insn &= 0x01fff07f;
489*139c1837SPaolo Bonzini            /* Set the offset to the PC + 8 */
490*139c1837SPaolo Bonzini            insn |= encode_sbimm12(8);
491*139c1837SPaolo Bonzini
492*139c1837SPaolo Bonzini            /* Move forward */
493*139c1837SPaolo Bonzini            code_ptr[0] = insn;
494*139c1837SPaolo Bonzini
495*139c1837SPaolo Bonzini            /* Overwrite the NOP with jal x0,value */
496*139c1837SPaolo Bonzini            diff = value - (uintptr_t)(code_ptr + 1);
497*139c1837SPaolo Bonzini            insn = encode_uj(OPC_JAL, TCG_REG_ZERO, diff);
498*139c1837SPaolo Bonzini            code_ptr[1] = insn;
499*139c1837SPaolo Bonzini
500*139c1837SPaolo Bonzini            return true;
501*139c1837SPaolo Bonzini        }
502*139c1837SPaolo Bonzini        break;
503*139c1837SPaolo Bonzini    case R_RISCV_JAL:
504*139c1837SPaolo Bonzini        return reloc_jimm20(code_ptr, (tcg_insn_unit *)value);
505*139c1837SPaolo Bonzini    case R_RISCV_CALL:
506*139c1837SPaolo Bonzini        return reloc_call(code_ptr, (tcg_insn_unit *)value);
507*139c1837SPaolo Bonzini    default:
508*139c1837SPaolo Bonzini        tcg_abort();
509*139c1837SPaolo Bonzini    }
510*139c1837SPaolo Bonzini}
511*139c1837SPaolo Bonzini
512*139c1837SPaolo Bonzini/*
513*139c1837SPaolo Bonzini * TCG intrinsics
514*139c1837SPaolo Bonzini */
515*139c1837SPaolo Bonzini
516*139c1837SPaolo Bonzinistatic bool tcg_out_mov(TCGContext *s, TCGType type, TCGReg ret, TCGReg arg)
517*139c1837SPaolo Bonzini{
518*139c1837SPaolo Bonzini    if (ret == arg) {
519*139c1837SPaolo Bonzini        return true;
520*139c1837SPaolo Bonzini    }
521*139c1837SPaolo Bonzini    switch (type) {
522*139c1837SPaolo Bonzini    case TCG_TYPE_I32:
523*139c1837SPaolo Bonzini    case TCG_TYPE_I64:
524*139c1837SPaolo Bonzini        tcg_out_opc_imm(s, OPC_ADDI, ret, arg, 0);
525*139c1837SPaolo Bonzini        break;
526*139c1837SPaolo Bonzini    default:
527*139c1837SPaolo Bonzini        g_assert_not_reached();
528*139c1837SPaolo Bonzini    }
529*139c1837SPaolo Bonzini    return true;
530*139c1837SPaolo Bonzini}
531*139c1837SPaolo Bonzini
532*139c1837SPaolo Bonzinistatic void tcg_out_movi(TCGContext *s, TCGType type, TCGReg rd,
533*139c1837SPaolo Bonzini                         tcg_target_long val)
534*139c1837SPaolo Bonzini{
535*139c1837SPaolo Bonzini    tcg_target_long lo, hi, tmp;
536*139c1837SPaolo Bonzini    int shift, ret;
537*139c1837SPaolo Bonzini
538*139c1837SPaolo Bonzini    if (TCG_TARGET_REG_BITS == 64 && type == TCG_TYPE_I32) {
539*139c1837SPaolo Bonzini        val = (int32_t)val;
540*139c1837SPaolo Bonzini    }
541*139c1837SPaolo Bonzini
542*139c1837SPaolo Bonzini    lo = sextreg(val, 0, 12);
543*139c1837SPaolo Bonzini    if (val == lo) {
544*139c1837SPaolo Bonzini        tcg_out_opc_imm(s, OPC_ADDI, rd, TCG_REG_ZERO, lo);
545*139c1837SPaolo Bonzini        return;
546*139c1837SPaolo Bonzini    }
547*139c1837SPaolo Bonzini
548*139c1837SPaolo Bonzini    hi = val - lo;
549*139c1837SPaolo Bonzini    if (TCG_TARGET_REG_BITS == 32 || val == (int32_t)val) {
550*139c1837SPaolo Bonzini        tcg_out_opc_upper(s, OPC_LUI, rd, hi);
551*139c1837SPaolo Bonzini        if (lo != 0) {
552*139c1837SPaolo Bonzini            tcg_out_opc_imm(s, OPC_ADDIW, rd, rd, lo);
553*139c1837SPaolo Bonzini        }
554*139c1837SPaolo Bonzini        return;
555*139c1837SPaolo Bonzini    }
556*139c1837SPaolo Bonzini
557*139c1837SPaolo Bonzini    /* We can only be here if TCG_TARGET_REG_BITS != 32 */
558*139c1837SPaolo Bonzini    tmp = tcg_pcrel_diff(s, (void *)val);
559*139c1837SPaolo Bonzini    if (tmp == (int32_t)tmp) {
560*139c1837SPaolo Bonzini        tcg_out_opc_upper(s, OPC_AUIPC, rd, 0);
561*139c1837SPaolo Bonzini        tcg_out_opc_imm(s, OPC_ADDI, rd, rd, 0);
562*139c1837SPaolo Bonzini        ret = reloc_call(s->code_ptr - 2, (tcg_insn_unit *)val);
563*139c1837SPaolo Bonzini        tcg_debug_assert(ret == true);
564*139c1837SPaolo Bonzini        return;
565*139c1837SPaolo Bonzini    }
566*139c1837SPaolo Bonzini
567*139c1837SPaolo Bonzini    /* Look for a single 20-bit section.  */
568*139c1837SPaolo Bonzini    shift = ctz64(val);
569*139c1837SPaolo Bonzini    tmp = val >> shift;
570*139c1837SPaolo Bonzini    if (tmp == sextreg(tmp, 0, 20)) {
571*139c1837SPaolo Bonzini        tcg_out_opc_upper(s, OPC_LUI, rd, tmp << 12);
572*139c1837SPaolo Bonzini        if (shift > 12) {
573*139c1837SPaolo Bonzini            tcg_out_opc_imm(s, OPC_SLLI, rd, rd, shift - 12);
574*139c1837SPaolo Bonzini        } else {
575*139c1837SPaolo Bonzini            tcg_out_opc_imm(s, OPC_SRAI, rd, rd, 12 - shift);
576*139c1837SPaolo Bonzini        }
577*139c1837SPaolo Bonzini        return;
578*139c1837SPaolo Bonzini    }
579*139c1837SPaolo Bonzini
580*139c1837SPaolo Bonzini    /* Look for a few high zero bits, with lots of bits set in the middle.  */
581*139c1837SPaolo Bonzini    shift = clz64(val);
582*139c1837SPaolo Bonzini    tmp = val << shift;
583*139c1837SPaolo Bonzini    if (tmp == sextreg(tmp, 12, 20) << 12) {
584*139c1837SPaolo Bonzini        tcg_out_opc_upper(s, OPC_LUI, rd, tmp);
585*139c1837SPaolo Bonzini        tcg_out_opc_imm(s, OPC_SRLI, rd, rd, shift);
586*139c1837SPaolo Bonzini        return;
587*139c1837SPaolo Bonzini    } else if (tmp == sextreg(tmp, 0, 12)) {
588*139c1837SPaolo Bonzini        tcg_out_opc_imm(s, OPC_ADDI, rd, TCG_REG_ZERO, tmp);
589*139c1837SPaolo Bonzini        tcg_out_opc_imm(s, OPC_SRLI, rd, rd, shift);
590*139c1837SPaolo Bonzini        return;
591*139c1837SPaolo Bonzini    }
592*139c1837SPaolo Bonzini
593*139c1837SPaolo Bonzini    /* Drop into the constant pool.  */
594*139c1837SPaolo Bonzini    new_pool_label(s, val, R_RISCV_CALL, s->code_ptr, 0);
595*139c1837SPaolo Bonzini    tcg_out_opc_upper(s, OPC_AUIPC, rd, 0);
596*139c1837SPaolo Bonzini    tcg_out_opc_imm(s, OPC_LD, rd, rd, 0);
597*139c1837SPaolo Bonzini}
598*139c1837SPaolo Bonzini
599*139c1837SPaolo Bonzinistatic void tcg_out_ext8u(TCGContext *s, TCGReg ret, TCGReg arg)
600*139c1837SPaolo Bonzini{
601*139c1837SPaolo Bonzini    tcg_out_opc_imm(s, OPC_ANDI, ret, arg, 0xff);
602*139c1837SPaolo Bonzini}
603*139c1837SPaolo Bonzini
604*139c1837SPaolo Bonzinistatic void tcg_out_ext16u(TCGContext *s, TCGReg ret, TCGReg arg)
605*139c1837SPaolo Bonzini{
606*139c1837SPaolo Bonzini    tcg_out_opc_imm(s, OPC_SLLIW, ret, arg, 16);
607*139c1837SPaolo Bonzini    tcg_out_opc_imm(s, OPC_SRLIW, ret, ret, 16);
608*139c1837SPaolo Bonzini}
609*139c1837SPaolo Bonzini
610*139c1837SPaolo Bonzinistatic void tcg_out_ext32u(TCGContext *s, TCGReg ret, TCGReg arg)
611*139c1837SPaolo Bonzini{
612*139c1837SPaolo Bonzini    tcg_out_opc_imm(s, OPC_SLLI, ret, arg, 32);
613*139c1837SPaolo Bonzini    tcg_out_opc_imm(s, OPC_SRLI, ret, ret, 32);
614*139c1837SPaolo Bonzini}
615*139c1837SPaolo Bonzini
616*139c1837SPaolo Bonzinistatic void tcg_out_ext8s(TCGContext *s, TCGReg ret, TCGReg arg)
617*139c1837SPaolo Bonzini{
618*139c1837SPaolo Bonzini    tcg_out_opc_imm(s, OPC_SLLIW, ret, arg, 24);
619*139c1837SPaolo Bonzini    tcg_out_opc_imm(s, OPC_SRAIW, ret, ret, 24);
620*139c1837SPaolo Bonzini}
621*139c1837SPaolo Bonzini
622*139c1837SPaolo Bonzinistatic void tcg_out_ext16s(TCGContext *s, TCGReg ret, TCGReg arg)
623*139c1837SPaolo Bonzini{
624*139c1837SPaolo Bonzini    tcg_out_opc_imm(s, OPC_SLLIW, ret, arg, 16);
625*139c1837SPaolo Bonzini    tcg_out_opc_imm(s, OPC_SRAIW, ret, ret, 16);
626*139c1837SPaolo Bonzini}
627*139c1837SPaolo Bonzini
628*139c1837SPaolo Bonzinistatic void tcg_out_ext32s(TCGContext *s, TCGReg ret, TCGReg arg)
629*139c1837SPaolo Bonzini{
630*139c1837SPaolo Bonzini    tcg_out_opc_imm(s, OPC_ADDIW, ret, arg, 0);
631*139c1837SPaolo Bonzini}
632*139c1837SPaolo Bonzini
633*139c1837SPaolo Bonzinistatic void tcg_out_ldst(TCGContext *s, RISCVInsn opc, TCGReg data,
634*139c1837SPaolo Bonzini                         TCGReg addr, intptr_t offset)
635*139c1837SPaolo Bonzini{
636*139c1837SPaolo Bonzini    intptr_t imm12 = sextreg(offset, 0, 12);
637*139c1837SPaolo Bonzini
638*139c1837SPaolo Bonzini    if (offset != imm12) {
639*139c1837SPaolo Bonzini        intptr_t diff = offset - (uintptr_t)s->code_ptr;
640*139c1837SPaolo Bonzini
641*139c1837SPaolo Bonzini        if (addr == TCG_REG_ZERO && diff == (int32_t)diff) {
642*139c1837SPaolo Bonzini            imm12 = sextreg(diff, 0, 12);
643*139c1837SPaolo Bonzini            tcg_out_opc_upper(s, OPC_AUIPC, TCG_REG_TMP2, diff - imm12);
644*139c1837SPaolo Bonzini        } else {
645*139c1837SPaolo Bonzini            tcg_out_movi(s, TCG_TYPE_PTR, TCG_REG_TMP2, offset - imm12);
646*139c1837SPaolo Bonzini            if (addr != TCG_REG_ZERO) {
647*139c1837SPaolo Bonzini                tcg_out_opc_reg(s, OPC_ADD, TCG_REG_TMP2, TCG_REG_TMP2, addr);
648*139c1837SPaolo Bonzini            }
649*139c1837SPaolo Bonzini        }
650*139c1837SPaolo Bonzini        addr = TCG_REG_TMP2;
651*139c1837SPaolo Bonzini    }
652*139c1837SPaolo Bonzini
653*139c1837SPaolo Bonzini    switch (opc) {
654*139c1837SPaolo Bonzini    case OPC_SB:
655*139c1837SPaolo Bonzini    case OPC_SH:
656*139c1837SPaolo Bonzini    case OPC_SW:
657*139c1837SPaolo Bonzini    case OPC_SD:
658*139c1837SPaolo Bonzini        tcg_out_opc_store(s, opc, addr, data, imm12);
659*139c1837SPaolo Bonzini        break;
660*139c1837SPaolo Bonzini    case OPC_LB:
661*139c1837SPaolo Bonzini    case OPC_LBU:
662*139c1837SPaolo Bonzini    case OPC_LH:
663*139c1837SPaolo Bonzini    case OPC_LHU:
664*139c1837SPaolo Bonzini    case OPC_LW:
665*139c1837SPaolo Bonzini    case OPC_LWU:
666*139c1837SPaolo Bonzini    case OPC_LD:
667*139c1837SPaolo Bonzini        tcg_out_opc_imm(s, opc, data, addr, imm12);
668*139c1837SPaolo Bonzini        break;
669*139c1837SPaolo Bonzini    default:
670*139c1837SPaolo Bonzini        g_assert_not_reached();
671*139c1837SPaolo Bonzini    }
672*139c1837SPaolo Bonzini}
673*139c1837SPaolo Bonzini
674*139c1837SPaolo Bonzinistatic void tcg_out_ld(TCGContext *s, TCGType type, TCGReg arg,
675*139c1837SPaolo Bonzini                       TCGReg arg1, intptr_t arg2)
676*139c1837SPaolo Bonzini{
677*139c1837SPaolo Bonzini    bool is32bit = (TCG_TARGET_REG_BITS == 32 || type == TCG_TYPE_I32);
678*139c1837SPaolo Bonzini    tcg_out_ldst(s, is32bit ? OPC_LW : OPC_LD, arg, arg1, arg2);
679*139c1837SPaolo Bonzini}
680*139c1837SPaolo Bonzini
681*139c1837SPaolo Bonzinistatic void tcg_out_st(TCGContext *s, TCGType type, TCGReg arg,
682*139c1837SPaolo Bonzini                       TCGReg arg1, intptr_t arg2)
683*139c1837SPaolo Bonzini{
684*139c1837SPaolo Bonzini    bool is32bit = (TCG_TARGET_REG_BITS == 32 || type == TCG_TYPE_I32);
685*139c1837SPaolo Bonzini    tcg_out_ldst(s, is32bit ? OPC_SW : OPC_SD, arg, arg1, arg2);
686*139c1837SPaolo Bonzini}
687*139c1837SPaolo Bonzini
688*139c1837SPaolo Bonzinistatic bool tcg_out_sti(TCGContext *s, TCGType type, TCGArg val,
689*139c1837SPaolo Bonzini                        TCGReg base, intptr_t ofs)
690*139c1837SPaolo Bonzini{
691*139c1837SPaolo Bonzini    if (val == 0) {
692*139c1837SPaolo Bonzini        tcg_out_st(s, type, TCG_REG_ZERO, base, ofs);
693*139c1837SPaolo Bonzini        return true;
694*139c1837SPaolo Bonzini    }
695*139c1837SPaolo Bonzini    return false;
696*139c1837SPaolo Bonzini}
697*139c1837SPaolo Bonzini
698*139c1837SPaolo Bonzinistatic void tcg_out_addsub2(TCGContext *s,
699*139c1837SPaolo Bonzini                            TCGReg rl, TCGReg rh,
700*139c1837SPaolo Bonzini                            TCGReg al, TCGReg ah,
701*139c1837SPaolo Bonzini                            TCGArg bl, TCGArg bh,
702*139c1837SPaolo Bonzini                            bool cbl, bool cbh, bool is_sub, bool is32bit)
703*139c1837SPaolo Bonzini{
704*139c1837SPaolo Bonzini    const RISCVInsn opc_add = is32bit ? OPC_ADDW : OPC_ADD;
705*139c1837SPaolo Bonzini    const RISCVInsn opc_addi = is32bit ? OPC_ADDIW : OPC_ADDI;
706*139c1837SPaolo Bonzini    const RISCVInsn opc_sub = is32bit ? OPC_SUBW : OPC_SUB;
707*139c1837SPaolo Bonzini    TCGReg th = TCG_REG_TMP1;
708*139c1837SPaolo Bonzini
709*139c1837SPaolo Bonzini    /* If we have a negative constant such that negating it would
710*139c1837SPaolo Bonzini       make the high part zero, we can (usually) eliminate one insn.  */
711*139c1837SPaolo Bonzini    if (cbl && cbh && bh == -1 && bl != 0) {
712*139c1837SPaolo Bonzini        bl = -bl;
713*139c1837SPaolo Bonzini        bh = 0;
714*139c1837SPaolo Bonzini        is_sub = !is_sub;
715*139c1837SPaolo Bonzini    }
716*139c1837SPaolo Bonzini
717*139c1837SPaolo Bonzini    /* By operating on the high part first, we get to use the final
718*139c1837SPaolo Bonzini       carry operation to move back from the temporary.  */
719*139c1837SPaolo Bonzini    if (!cbh) {
720*139c1837SPaolo Bonzini        tcg_out_opc_reg(s, (is_sub ? opc_sub : opc_add), th, ah, bh);
721*139c1837SPaolo Bonzini    } else if (bh != 0 || ah == rl) {
722*139c1837SPaolo Bonzini        tcg_out_opc_imm(s, opc_addi, th, ah, (is_sub ? -bh : bh));
723*139c1837SPaolo Bonzini    } else {
724*139c1837SPaolo Bonzini        th = ah;
725*139c1837SPaolo Bonzini    }
726*139c1837SPaolo Bonzini
727*139c1837SPaolo Bonzini    /* Note that tcg optimization should eliminate the bl == 0 case.  */
728*139c1837SPaolo Bonzini    if (is_sub) {
729*139c1837SPaolo Bonzini        if (cbl) {
730*139c1837SPaolo Bonzini            tcg_out_opc_imm(s, OPC_SLTIU, TCG_REG_TMP0, al, bl);
731*139c1837SPaolo Bonzini            tcg_out_opc_imm(s, opc_addi, rl, al, -bl);
732*139c1837SPaolo Bonzini        } else {
733*139c1837SPaolo Bonzini            tcg_out_opc_reg(s, OPC_SLTU, TCG_REG_TMP0, al, bl);
734*139c1837SPaolo Bonzini            tcg_out_opc_reg(s, opc_sub, rl, al, bl);
735*139c1837SPaolo Bonzini        }
736*139c1837SPaolo Bonzini        tcg_out_opc_reg(s, opc_sub, rh, th, TCG_REG_TMP0);
737*139c1837SPaolo Bonzini    } else {
738*139c1837SPaolo Bonzini        if (cbl) {
739*139c1837SPaolo Bonzini            tcg_out_opc_imm(s, opc_addi, rl, al, bl);
740*139c1837SPaolo Bonzini            tcg_out_opc_imm(s, OPC_SLTIU, TCG_REG_TMP0, rl, bl);
741*139c1837SPaolo Bonzini        } else if (rl == al && rl == bl) {
742*139c1837SPaolo Bonzini            tcg_out_opc_imm(s, OPC_SLTI, TCG_REG_TMP0, al, 0);
743*139c1837SPaolo Bonzini            tcg_out_opc_reg(s, opc_addi, rl, al, bl);
744*139c1837SPaolo Bonzini        } else {
745*139c1837SPaolo Bonzini            tcg_out_opc_reg(s, opc_add, rl, al, bl);
746*139c1837SPaolo Bonzini            tcg_out_opc_reg(s, OPC_SLTU, TCG_REG_TMP0,
747*139c1837SPaolo Bonzini                            rl, (rl == bl ? al : bl));
748*139c1837SPaolo Bonzini        }
749*139c1837SPaolo Bonzini        tcg_out_opc_reg(s, opc_add, rh, th, TCG_REG_TMP0);
750*139c1837SPaolo Bonzini    }
751*139c1837SPaolo Bonzini}
752*139c1837SPaolo Bonzini
753*139c1837SPaolo Bonzinistatic const struct {
754*139c1837SPaolo Bonzini    RISCVInsn op;
755*139c1837SPaolo Bonzini    bool swap;
756*139c1837SPaolo Bonzini} tcg_brcond_to_riscv[] = {
757*139c1837SPaolo Bonzini    [TCG_COND_EQ] =  { OPC_BEQ,  false },
758*139c1837SPaolo Bonzini    [TCG_COND_NE] =  { OPC_BNE,  false },
759*139c1837SPaolo Bonzini    [TCG_COND_LT] =  { OPC_BLT,  false },
760*139c1837SPaolo Bonzini    [TCG_COND_GE] =  { OPC_BGE,  false },
761*139c1837SPaolo Bonzini    [TCG_COND_LE] =  { OPC_BGE,  true  },
762*139c1837SPaolo Bonzini    [TCG_COND_GT] =  { OPC_BLT,  true  },
763*139c1837SPaolo Bonzini    [TCG_COND_LTU] = { OPC_BLTU, false },
764*139c1837SPaolo Bonzini    [TCG_COND_GEU] = { OPC_BGEU, false },
765*139c1837SPaolo Bonzini    [TCG_COND_LEU] = { OPC_BGEU, true  },
766*139c1837SPaolo Bonzini    [TCG_COND_GTU] = { OPC_BLTU, true  }
767*139c1837SPaolo Bonzini};
768*139c1837SPaolo Bonzini
769*139c1837SPaolo Bonzinistatic void tcg_out_brcond(TCGContext *s, TCGCond cond, TCGReg arg1,
770*139c1837SPaolo Bonzini                           TCGReg arg2, TCGLabel *l)
771*139c1837SPaolo Bonzini{
772*139c1837SPaolo Bonzini    RISCVInsn op = tcg_brcond_to_riscv[cond].op;
773*139c1837SPaolo Bonzini
774*139c1837SPaolo Bonzini    tcg_debug_assert(op != 0);
775*139c1837SPaolo Bonzini
776*139c1837SPaolo Bonzini    if (tcg_brcond_to_riscv[cond].swap) {
777*139c1837SPaolo Bonzini        TCGReg t = arg1;
778*139c1837SPaolo Bonzini        arg1 = arg2;
779*139c1837SPaolo Bonzini        arg2 = t;
780*139c1837SPaolo Bonzini    }
781*139c1837SPaolo Bonzini
782*139c1837SPaolo Bonzini    if (l->has_value) {
783*139c1837SPaolo Bonzini        intptr_t diff = tcg_pcrel_diff(s, l->u.value_ptr);
784*139c1837SPaolo Bonzini        if (diff == sextreg(diff, 0, 12)) {
785*139c1837SPaolo Bonzini            tcg_out_opc_branch(s, op, arg1, arg2, diff);
786*139c1837SPaolo Bonzini        } else {
787*139c1837SPaolo Bonzini            /* Invert the conditional branch.  */
788*139c1837SPaolo Bonzini            tcg_out_opc_branch(s, op ^ (1 << 12), arg1, arg2, 8);
789*139c1837SPaolo Bonzini            tcg_out_opc_jump(s, OPC_JAL, TCG_REG_ZERO, diff - 4);
790*139c1837SPaolo Bonzini        }
791*139c1837SPaolo Bonzini    } else {
792*139c1837SPaolo Bonzini        tcg_out_reloc(s, s->code_ptr, R_RISCV_BRANCH, l, 0);
793*139c1837SPaolo Bonzini        tcg_out_opc_branch(s, op, arg1, arg2, 0);
794*139c1837SPaolo Bonzini        /* NOP to allow patching later */
795*139c1837SPaolo Bonzini        tcg_out_opc_imm(s, OPC_ADDI, TCG_REG_ZERO, TCG_REG_ZERO, 0);
796*139c1837SPaolo Bonzini    }
797*139c1837SPaolo Bonzini}
798*139c1837SPaolo Bonzini
799*139c1837SPaolo Bonzinistatic void tcg_out_setcond(TCGContext *s, TCGCond cond, TCGReg ret,
800*139c1837SPaolo Bonzini                            TCGReg arg1, TCGReg arg2)
801*139c1837SPaolo Bonzini{
802*139c1837SPaolo Bonzini    switch (cond) {
803*139c1837SPaolo Bonzini    case TCG_COND_EQ:
804*139c1837SPaolo Bonzini        tcg_out_opc_reg(s, OPC_SUB, ret, arg1, arg2);
805*139c1837SPaolo Bonzini        tcg_out_opc_imm(s, OPC_SLTIU, ret, ret, 1);
806*139c1837SPaolo Bonzini        break;
807*139c1837SPaolo Bonzini    case TCG_COND_NE:
808*139c1837SPaolo Bonzini        tcg_out_opc_reg(s, OPC_SUB, ret, arg1, arg2);
809*139c1837SPaolo Bonzini        tcg_out_opc_reg(s, OPC_SLTU, ret, TCG_REG_ZERO, ret);
810*139c1837SPaolo Bonzini        break;
811*139c1837SPaolo Bonzini    case TCG_COND_LT:
812*139c1837SPaolo Bonzini        tcg_out_opc_reg(s, OPC_SLT, ret, arg1, arg2);
813*139c1837SPaolo Bonzini        break;
814*139c1837SPaolo Bonzini    case TCG_COND_GE:
815*139c1837SPaolo Bonzini        tcg_out_opc_reg(s, OPC_SLT, ret, arg1, arg2);
816*139c1837SPaolo Bonzini        tcg_out_opc_imm(s, OPC_XORI, ret, ret, 1);
817*139c1837SPaolo Bonzini        break;
818*139c1837SPaolo Bonzini    case TCG_COND_LE:
819*139c1837SPaolo Bonzini        tcg_out_opc_reg(s, OPC_SLT, ret, arg2, arg1);
820*139c1837SPaolo Bonzini        tcg_out_opc_imm(s, OPC_XORI, ret, ret, 1);
821*139c1837SPaolo Bonzini        break;
822*139c1837SPaolo Bonzini    case TCG_COND_GT:
823*139c1837SPaolo Bonzini        tcg_out_opc_reg(s, OPC_SLT, ret, arg2, arg1);
824*139c1837SPaolo Bonzini        break;
825*139c1837SPaolo Bonzini    case TCG_COND_LTU:
826*139c1837SPaolo Bonzini        tcg_out_opc_reg(s, OPC_SLTU, ret, arg1, arg2);
827*139c1837SPaolo Bonzini        break;
828*139c1837SPaolo Bonzini    case TCG_COND_GEU:
829*139c1837SPaolo Bonzini        tcg_out_opc_reg(s, OPC_SLTU, ret, arg1, arg2);
830*139c1837SPaolo Bonzini        tcg_out_opc_imm(s, OPC_XORI, ret, ret, 1);
831*139c1837SPaolo Bonzini        break;
832*139c1837SPaolo Bonzini    case TCG_COND_LEU:
833*139c1837SPaolo Bonzini        tcg_out_opc_reg(s, OPC_SLTU, ret, arg2, arg1);
834*139c1837SPaolo Bonzini        tcg_out_opc_imm(s, OPC_XORI, ret, ret, 1);
835*139c1837SPaolo Bonzini        break;
836*139c1837SPaolo Bonzini    case TCG_COND_GTU:
837*139c1837SPaolo Bonzini        tcg_out_opc_reg(s, OPC_SLTU, ret, arg2, arg1);
838*139c1837SPaolo Bonzini        break;
839*139c1837SPaolo Bonzini    default:
840*139c1837SPaolo Bonzini         g_assert_not_reached();
841*139c1837SPaolo Bonzini         break;
842*139c1837SPaolo Bonzini     }
843*139c1837SPaolo Bonzini}
844*139c1837SPaolo Bonzini
845*139c1837SPaolo Bonzinistatic void tcg_out_brcond2(TCGContext *s, TCGCond cond, TCGReg al, TCGReg ah,
846*139c1837SPaolo Bonzini                            TCGReg bl, TCGReg bh, TCGLabel *l)
847*139c1837SPaolo Bonzini{
848*139c1837SPaolo Bonzini    /* todo */
849*139c1837SPaolo Bonzini    g_assert_not_reached();
850*139c1837SPaolo Bonzini}
851*139c1837SPaolo Bonzini
852*139c1837SPaolo Bonzinistatic void tcg_out_setcond2(TCGContext *s, TCGCond cond, TCGReg ret,
853*139c1837SPaolo Bonzini                             TCGReg al, TCGReg ah, TCGReg bl, TCGReg bh)
854*139c1837SPaolo Bonzini{
855*139c1837SPaolo Bonzini    /* todo */
856*139c1837SPaolo Bonzini    g_assert_not_reached();
857*139c1837SPaolo Bonzini}
858*139c1837SPaolo Bonzini
859*139c1837SPaolo Bonzinistatic inline void tcg_out_goto(TCGContext *s, tcg_insn_unit *target)
860*139c1837SPaolo Bonzini{
861*139c1837SPaolo Bonzini    ptrdiff_t offset = tcg_pcrel_diff(s, target);
862*139c1837SPaolo Bonzini    tcg_debug_assert(offset == sextreg(offset, 1, 20) << 1);
863*139c1837SPaolo Bonzini    tcg_out_opc_jump(s, OPC_JAL, TCG_REG_ZERO, offset);
864*139c1837SPaolo Bonzini}
865*139c1837SPaolo Bonzini
866*139c1837SPaolo Bonzinistatic void tcg_out_call_int(TCGContext *s, tcg_insn_unit *arg, bool tail)
867*139c1837SPaolo Bonzini{
868*139c1837SPaolo Bonzini    TCGReg link = tail ? TCG_REG_ZERO : TCG_REG_RA;
869*139c1837SPaolo Bonzini    ptrdiff_t offset = tcg_pcrel_diff(s, arg);
870*139c1837SPaolo Bonzini    int ret;
871*139c1837SPaolo Bonzini
872*139c1837SPaolo Bonzini    if (offset == sextreg(offset, 1, 20) << 1) {
873*139c1837SPaolo Bonzini        /* short jump: -2097150 to 2097152 */
874*139c1837SPaolo Bonzini        tcg_out_opc_jump(s, OPC_JAL, link, offset);
875*139c1837SPaolo Bonzini    } else if (TCG_TARGET_REG_BITS == 32 ||
876*139c1837SPaolo Bonzini        offset == sextreg(offset, 1, 31) << 1) {
877*139c1837SPaolo Bonzini        /* long jump: -2147483646 to 2147483648 */
878*139c1837SPaolo Bonzini        tcg_out_opc_upper(s, OPC_AUIPC, TCG_REG_TMP0, 0);
879*139c1837SPaolo Bonzini        tcg_out_opc_imm(s, OPC_JALR, link, TCG_REG_TMP0, 0);
880*139c1837SPaolo Bonzini        ret = reloc_call(s->code_ptr - 2, arg);\
881*139c1837SPaolo Bonzini        tcg_debug_assert(ret == true);
882*139c1837SPaolo Bonzini    } else if (TCG_TARGET_REG_BITS == 64) {
883*139c1837SPaolo Bonzini        /* far jump: 64-bit */
884*139c1837SPaolo Bonzini        tcg_target_long imm = sextreg((tcg_target_long)arg, 0, 12);
885*139c1837SPaolo Bonzini        tcg_target_long base = (tcg_target_long)arg - imm;
886*139c1837SPaolo Bonzini        tcg_out_movi(s, TCG_TYPE_PTR, TCG_REG_TMP0, base);
887*139c1837SPaolo Bonzini        tcg_out_opc_imm(s, OPC_JALR, link, TCG_REG_TMP0, imm);
888*139c1837SPaolo Bonzini    } else {
889*139c1837SPaolo Bonzini        g_assert_not_reached();
890*139c1837SPaolo Bonzini    }
891*139c1837SPaolo Bonzini}
892*139c1837SPaolo Bonzini
893*139c1837SPaolo Bonzinistatic void tcg_out_call(TCGContext *s, tcg_insn_unit *arg)
894*139c1837SPaolo Bonzini{
895*139c1837SPaolo Bonzini    tcg_out_call_int(s, arg, false);
896*139c1837SPaolo Bonzini}
897*139c1837SPaolo Bonzini
898*139c1837SPaolo Bonzinistatic void tcg_out_mb(TCGContext *s, TCGArg a0)
899*139c1837SPaolo Bonzini{
900*139c1837SPaolo Bonzini    tcg_insn_unit insn = OPC_FENCE;
901*139c1837SPaolo Bonzini
902*139c1837SPaolo Bonzini    if (a0 & TCG_MO_LD_LD) {
903*139c1837SPaolo Bonzini        insn |= 0x02200000;
904*139c1837SPaolo Bonzini    }
905*139c1837SPaolo Bonzini    if (a0 & TCG_MO_ST_LD) {
906*139c1837SPaolo Bonzini        insn |= 0x01200000;
907*139c1837SPaolo Bonzini    }
908*139c1837SPaolo Bonzini    if (a0 & TCG_MO_LD_ST) {
909*139c1837SPaolo Bonzini        insn |= 0x02100000;
910*139c1837SPaolo Bonzini    }
911*139c1837SPaolo Bonzini    if (a0 & TCG_MO_ST_ST) {
912*139c1837SPaolo Bonzini        insn |= 0x02200000;
913*139c1837SPaolo Bonzini    }
914*139c1837SPaolo Bonzini    tcg_out32(s, insn);
915*139c1837SPaolo Bonzini}
916*139c1837SPaolo Bonzini
917*139c1837SPaolo Bonzini/*
918*139c1837SPaolo Bonzini * Load/store and TLB
919*139c1837SPaolo Bonzini */
920*139c1837SPaolo Bonzini
921*139c1837SPaolo Bonzini#if defined(CONFIG_SOFTMMU)
922*139c1837SPaolo Bonzini#include "../tcg-ldst.c.inc"
923*139c1837SPaolo Bonzini
924*139c1837SPaolo Bonzini/* helper signature: helper_ret_ld_mmu(CPUState *env, target_ulong addr,
925*139c1837SPaolo Bonzini *                                     TCGMemOpIdx oi, uintptr_t ra)
926*139c1837SPaolo Bonzini */
927*139c1837SPaolo Bonzinistatic void * const qemu_ld_helpers[16] = {
928*139c1837SPaolo Bonzini    [MO_UB]   = helper_ret_ldub_mmu,
929*139c1837SPaolo Bonzini    [MO_SB]   = helper_ret_ldsb_mmu,
930*139c1837SPaolo Bonzini    [MO_LEUW] = helper_le_lduw_mmu,
931*139c1837SPaolo Bonzini    [MO_LESW] = helper_le_ldsw_mmu,
932*139c1837SPaolo Bonzini    [MO_LEUL] = helper_le_ldul_mmu,
933*139c1837SPaolo Bonzini#if TCG_TARGET_REG_BITS == 64
934*139c1837SPaolo Bonzini    [MO_LESL] = helper_le_ldsl_mmu,
935*139c1837SPaolo Bonzini#endif
936*139c1837SPaolo Bonzini    [MO_LEQ]  = helper_le_ldq_mmu,
937*139c1837SPaolo Bonzini    [MO_BEUW] = helper_be_lduw_mmu,
938*139c1837SPaolo Bonzini    [MO_BESW] = helper_be_ldsw_mmu,
939*139c1837SPaolo Bonzini    [MO_BEUL] = helper_be_ldul_mmu,
940*139c1837SPaolo Bonzini#if TCG_TARGET_REG_BITS == 64
941*139c1837SPaolo Bonzini    [MO_BESL] = helper_be_ldsl_mmu,
942*139c1837SPaolo Bonzini#endif
943*139c1837SPaolo Bonzini    [MO_BEQ]  = helper_be_ldq_mmu,
944*139c1837SPaolo Bonzini};
945*139c1837SPaolo Bonzini
946*139c1837SPaolo Bonzini/* helper signature: helper_ret_st_mmu(CPUState *env, target_ulong addr,
947*139c1837SPaolo Bonzini *                                     uintxx_t val, TCGMemOpIdx oi,
948*139c1837SPaolo Bonzini *                                     uintptr_t ra)
949*139c1837SPaolo Bonzini */
950*139c1837SPaolo Bonzinistatic void * const qemu_st_helpers[16] = {
951*139c1837SPaolo Bonzini    [MO_UB]   = helper_ret_stb_mmu,
952*139c1837SPaolo Bonzini    [MO_LEUW] = helper_le_stw_mmu,
953*139c1837SPaolo Bonzini    [MO_LEUL] = helper_le_stl_mmu,
954*139c1837SPaolo Bonzini    [MO_LEQ]  = helper_le_stq_mmu,
955*139c1837SPaolo Bonzini    [MO_BEUW] = helper_be_stw_mmu,
956*139c1837SPaolo Bonzini    [MO_BEUL] = helper_be_stl_mmu,
957*139c1837SPaolo Bonzini    [MO_BEQ]  = helper_be_stq_mmu,
958*139c1837SPaolo Bonzini};
959*139c1837SPaolo Bonzini
960*139c1837SPaolo Bonzini/* We don't support oversize guests */
961*139c1837SPaolo BonziniQEMU_BUILD_BUG_ON(TCG_TARGET_REG_BITS < TARGET_LONG_BITS);
962*139c1837SPaolo Bonzini
963*139c1837SPaolo Bonzini/* We expect to use a 12-bit negative offset from ENV.  */
964*139c1837SPaolo BonziniQEMU_BUILD_BUG_ON(TLB_MASK_TABLE_OFS(0) > 0);
965*139c1837SPaolo BonziniQEMU_BUILD_BUG_ON(TLB_MASK_TABLE_OFS(0) < -(1 << 11));
966*139c1837SPaolo Bonzini
967*139c1837SPaolo Bonzinistatic void tcg_out_tlb_load(TCGContext *s, TCGReg addrl,
968*139c1837SPaolo Bonzini                             TCGReg addrh, TCGMemOpIdx oi,
969*139c1837SPaolo Bonzini                             tcg_insn_unit **label_ptr, bool is_load)
970*139c1837SPaolo Bonzini{
971*139c1837SPaolo Bonzini    MemOp opc = get_memop(oi);
972*139c1837SPaolo Bonzini    unsigned s_bits = opc & MO_SIZE;
973*139c1837SPaolo Bonzini    unsigned a_bits = get_alignment_bits(opc);
974*139c1837SPaolo Bonzini    tcg_target_long compare_mask;
975*139c1837SPaolo Bonzini    int mem_index = get_mmuidx(oi);
976*139c1837SPaolo Bonzini    int fast_ofs = TLB_MASK_TABLE_OFS(mem_index);
977*139c1837SPaolo Bonzini    int mask_ofs = fast_ofs + offsetof(CPUTLBDescFast, mask);
978*139c1837SPaolo Bonzini    int table_ofs = fast_ofs + offsetof(CPUTLBDescFast, table);
979*139c1837SPaolo Bonzini    TCGReg mask_base = TCG_AREG0, table_base = TCG_AREG0;
980*139c1837SPaolo Bonzini
981*139c1837SPaolo Bonzini    tcg_out_ld(s, TCG_TYPE_PTR, TCG_REG_TMP0, mask_base, mask_ofs);
982*139c1837SPaolo Bonzini    tcg_out_ld(s, TCG_TYPE_PTR, TCG_REG_TMP1, table_base, table_ofs);
983*139c1837SPaolo Bonzini
984*139c1837SPaolo Bonzini    tcg_out_opc_imm(s, OPC_SRLI, TCG_REG_TMP2, addrl,
985*139c1837SPaolo Bonzini                    TARGET_PAGE_BITS - CPU_TLB_ENTRY_BITS);
986*139c1837SPaolo Bonzini    tcg_out_opc_reg(s, OPC_AND, TCG_REG_TMP2, TCG_REG_TMP2, TCG_REG_TMP0);
987*139c1837SPaolo Bonzini    tcg_out_opc_reg(s, OPC_ADD, TCG_REG_TMP2, TCG_REG_TMP2, TCG_REG_TMP1);
988*139c1837SPaolo Bonzini
989*139c1837SPaolo Bonzini    /* Load the tlb comparator and the addend.  */
990*139c1837SPaolo Bonzini    tcg_out_ld(s, TCG_TYPE_TL, TCG_REG_TMP0, TCG_REG_TMP2,
991*139c1837SPaolo Bonzini               is_load ? offsetof(CPUTLBEntry, addr_read)
992*139c1837SPaolo Bonzini               : offsetof(CPUTLBEntry, addr_write));
993*139c1837SPaolo Bonzini    tcg_out_ld(s, TCG_TYPE_PTR, TCG_REG_TMP2, TCG_REG_TMP2,
994*139c1837SPaolo Bonzini               offsetof(CPUTLBEntry, addend));
995*139c1837SPaolo Bonzini
996*139c1837SPaolo Bonzini    /* We don't support unaligned accesses. */
997*139c1837SPaolo Bonzini    if (a_bits < s_bits) {
998*139c1837SPaolo Bonzini        a_bits = s_bits;
999*139c1837SPaolo Bonzini    }
1000*139c1837SPaolo Bonzini    /* Clear the non-page, non-alignment bits from the address.  */
1001*139c1837SPaolo Bonzini    compare_mask = (tcg_target_long)TARGET_PAGE_MASK | ((1 << a_bits) - 1);
1002*139c1837SPaolo Bonzini    if (compare_mask == sextreg(compare_mask, 0, 12)) {
1003*139c1837SPaolo Bonzini        tcg_out_opc_imm(s, OPC_ANDI, TCG_REG_TMP1, addrl, compare_mask);
1004*139c1837SPaolo Bonzini    } else {
1005*139c1837SPaolo Bonzini        tcg_out_movi(s, TCG_TYPE_TL, TCG_REG_TMP1, compare_mask);
1006*139c1837SPaolo Bonzini        tcg_out_opc_reg(s, OPC_AND, TCG_REG_TMP1, TCG_REG_TMP1, addrl);
1007*139c1837SPaolo Bonzini    }
1008*139c1837SPaolo Bonzini
1009*139c1837SPaolo Bonzini    /* Compare masked address with the TLB entry. */
1010*139c1837SPaolo Bonzini    label_ptr[0] = s->code_ptr;
1011*139c1837SPaolo Bonzini    tcg_out_opc_branch(s, OPC_BNE, TCG_REG_TMP0, TCG_REG_TMP1, 0);
1012*139c1837SPaolo Bonzini    /* NOP to allow patching later */
1013*139c1837SPaolo Bonzini    tcg_out_opc_imm(s, OPC_ADDI, TCG_REG_ZERO, TCG_REG_ZERO, 0);
1014*139c1837SPaolo Bonzini
1015*139c1837SPaolo Bonzini    /* TLB Hit - translate address using addend.  */
1016*139c1837SPaolo Bonzini    if (TCG_TARGET_REG_BITS > TARGET_LONG_BITS) {
1017*139c1837SPaolo Bonzini        tcg_out_ext32u(s, TCG_REG_TMP0, addrl);
1018*139c1837SPaolo Bonzini        addrl = TCG_REG_TMP0;
1019*139c1837SPaolo Bonzini    }
1020*139c1837SPaolo Bonzini    tcg_out_opc_reg(s, OPC_ADD, TCG_REG_TMP0, TCG_REG_TMP2, addrl);
1021*139c1837SPaolo Bonzini}
1022*139c1837SPaolo Bonzini
1023*139c1837SPaolo Bonzinistatic void add_qemu_ldst_label(TCGContext *s, int is_ld, TCGMemOpIdx oi,
1024*139c1837SPaolo Bonzini                                TCGType ext,
1025*139c1837SPaolo Bonzini                                TCGReg datalo, TCGReg datahi,
1026*139c1837SPaolo Bonzini                                TCGReg addrlo, TCGReg addrhi,
1027*139c1837SPaolo Bonzini                                void *raddr, tcg_insn_unit **label_ptr)
1028*139c1837SPaolo Bonzini{
1029*139c1837SPaolo Bonzini    TCGLabelQemuLdst *label = new_ldst_label(s);
1030*139c1837SPaolo Bonzini
1031*139c1837SPaolo Bonzini    label->is_ld = is_ld;
1032*139c1837SPaolo Bonzini    label->oi = oi;
1033*139c1837SPaolo Bonzini    label->type = ext;
1034*139c1837SPaolo Bonzini    label->datalo_reg = datalo;
1035*139c1837SPaolo Bonzini    label->datahi_reg = datahi;
1036*139c1837SPaolo Bonzini    label->addrlo_reg = addrlo;
1037*139c1837SPaolo Bonzini    label->addrhi_reg = addrhi;
1038*139c1837SPaolo Bonzini    label->raddr = raddr;
1039*139c1837SPaolo Bonzini    label->label_ptr[0] = label_ptr[0];
1040*139c1837SPaolo Bonzini}
1041*139c1837SPaolo Bonzini
1042*139c1837SPaolo Bonzinistatic bool tcg_out_qemu_ld_slow_path(TCGContext *s, TCGLabelQemuLdst *l)
1043*139c1837SPaolo Bonzini{
1044*139c1837SPaolo Bonzini    TCGMemOpIdx oi = l->oi;
1045*139c1837SPaolo Bonzini    MemOp opc = get_memop(oi);
1046*139c1837SPaolo Bonzini    TCGReg a0 = tcg_target_call_iarg_regs[0];
1047*139c1837SPaolo Bonzini    TCGReg a1 = tcg_target_call_iarg_regs[1];
1048*139c1837SPaolo Bonzini    TCGReg a2 = tcg_target_call_iarg_regs[2];
1049*139c1837SPaolo Bonzini    TCGReg a3 = tcg_target_call_iarg_regs[3];
1050*139c1837SPaolo Bonzini
1051*139c1837SPaolo Bonzini    /* We don't support oversize guests */
1052*139c1837SPaolo Bonzini    if (TCG_TARGET_REG_BITS < TARGET_LONG_BITS) {
1053*139c1837SPaolo Bonzini        g_assert_not_reached();
1054*139c1837SPaolo Bonzini    }
1055*139c1837SPaolo Bonzini
1056*139c1837SPaolo Bonzini    /* resolve label address */
1057*139c1837SPaolo Bonzini    if (!patch_reloc(l->label_ptr[0], R_RISCV_BRANCH,
1058*139c1837SPaolo Bonzini                     (intptr_t) s->code_ptr, 0)) {
1059*139c1837SPaolo Bonzini        return false;
1060*139c1837SPaolo Bonzini    }
1061*139c1837SPaolo Bonzini
1062*139c1837SPaolo Bonzini    /* call load helper */
1063*139c1837SPaolo Bonzini    tcg_out_mov(s, TCG_TYPE_PTR, a0, TCG_AREG0);
1064*139c1837SPaolo Bonzini    tcg_out_mov(s, TCG_TYPE_PTR, a1, l->addrlo_reg);
1065*139c1837SPaolo Bonzini    tcg_out_movi(s, TCG_TYPE_PTR, a2, oi);
1066*139c1837SPaolo Bonzini    tcg_out_movi(s, TCG_TYPE_PTR, a3, (tcg_target_long)l->raddr);
1067*139c1837SPaolo Bonzini
1068*139c1837SPaolo Bonzini    tcg_out_call(s, qemu_ld_helpers[opc & (MO_BSWAP | MO_SSIZE)]);
1069*139c1837SPaolo Bonzini    tcg_out_mov(s, (opc & MO_SIZE) == MO_64, l->datalo_reg, a0);
1070*139c1837SPaolo Bonzini
1071*139c1837SPaolo Bonzini    tcg_out_goto(s, l->raddr);
1072*139c1837SPaolo Bonzini    return true;
1073*139c1837SPaolo Bonzini}
1074*139c1837SPaolo Bonzini
1075*139c1837SPaolo Bonzinistatic bool tcg_out_qemu_st_slow_path(TCGContext *s, TCGLabelQemuLdst *l)
1076*139c1837SPaolo Bonzini{
1077*139c1837SPaolo Bonzini    TCGMemOpIdx oi = l->oi;
1078*139c1837SPaolo Bonzini    MemOp opc = get_memop(oi);
1079*139c1837SPaolo Bonzini    MemOp s_bits = opc & MO_SIZE;
1080*139c1837SPaolo Bonzini    TCGReg a0 = tcg_target_call_iarg_regs[0];
1081*139c1837SPaolo Bonzini    TCGReg a1 = tcg_target_call_iarg_regs[1];
1082*139c1837SPaolo Bonzini    TCGReg a2 = tcg_target_call_iarg_regs[2];
1083*139c1837SPaolo Bonzini    TCGReg a3 = tcg_target_call_iarg_regs[3];
1084*139c1837SPaolo Bonzini    TCGReg a4 = tcg_target_call_iarg_regs[4];
1085*139c1837SPaolo Bonzini
1086*139c1837SPaolo Bonzini    /* We don't support oversize guests */
1087*139c1837SPaolo Bonzini    if (TCG_TARGET_REG_BITS < TARGET_LONG_BITS) {
1088*139c1837SPaolo Bonzini        g_assert_not_reached();
1089*139c1837SPaolo Bonzini    }
1090*139c1837SPaolo Bonzini
1091*139c1837SPaolo Bonzini    /* resolve label address */
1092*139c1837SPaolo Bonzini    if (!patch_reloc(l->label_ptr[0], R_RISCV_BRANCH,
1093*139c1837SPaolo Bonzini                     (intptr_t) s->code_ptr, 0)) {
1094*139c1837SPaolo Bonzini        return false;
1095*139c1837SPaolo Bonzini    }
1096*139c1837SPaolo Bonzini
1097*139c1837SPaolo Bonzini    /* call store helper */
1098*139c1837SPaolo Bonzini    tcg_out_mov(s, TCG_TYPE_PTR, a0, TCG_AREG0);
1099*139c1837SPaolo Bonzini    tcg_out_mov(s, TCG_TYPE_PTR, a1, l->addrlo_reg);
1100*139c1837SPaolo Bonzini    tcg_out_mov(s, TCG_TYPE_PTR, a2, l->datalo_reg);
1101*139c1837SPaolo Bonzini    switch (s_bits) {
1102*139c1837SPaolo Bonzini    case MO_8:
1103*139c1837SPaolo Bonzini        tcg_out_ext8u(s, a2, a2);
1104*139c1837SPaolo Bonzini        break;
1105*139c1837SPaolo Bonzini    case MO_16:
1106*139c1837SPaolo Bonzini        tcg_out_ext16u(s, a2, a2);
1107*139c1837SPaolo Bonzini        break;
1108*139c1837SPaolo Bonzini    default:
1109*139c1837SPaolo Bonzini        break;
1110*139c1837SPaolo Bonzini    }
1111*139c1837SPaolo Bonzini    tcg_out_movi(s, TCG_TYPE_PTR, a3, oi);
1112*139c1837SPaolo Bonzini    tcg_out_movi(s, TCG_TYPE_PTR, a4, (tcg_target_long)l->raddr);
1113*139c1837SPaolo Bonzini
1114*139c1837SPaolo Bonzini    tcg_out_call(s, qemu_st_helpers[opc & (MO_BSWAP | MO_SSIZE)]);
1115*139c1837SPaolo Bonzini
1116*139c1837SPaolo Bonzini    tcg_out_goto(s, l->raddr);
1117*139c1837SPaolo Bonzini    return true;
1118*139c1837SPaolo Bonzini}
1119*139c1837SPaolo Bonzini#endif /* CONFIG_SOFTMMU */
1120*139c1837SPaolo Bonzini
1121*139c1837SPaolo Bonzinistatic void tcg_out_qemu_ld_direct(TCGContext *s, TCGReg lo, TCGReg hi,
1122*139c1837SPaolo Bonzini                                   TCGReg base, MemOp opc, bool is_64)
1123*139c1837SPaolo Bonzini{
1124*139c1837SPaolo Bonzini    const MemOp bswap = opc & MO_BSWAP;
1125*139c1837SPaolo Bonzini
1126*139c1837SPaolo Bonzini    /* We don't yet handle byteswapping, assert */
1127*139c1837SPaolo Bonzini    g_assert(!bswap);
1128*139c1837SPaolo Bonzini
1129*139c1837SPaolo Bonzini    switch (opc & (MO_SSIZE)) {
1130*139c1837SPaolo Bonzini    case MO_UB:
1131*139c1837SPaolo Bonzini        tcg_out_opc_imm(s, OPC_LBU, lo, base, 0);
1132*139c1837SPaolo Bonzini        break;
1133*139c1837SPaolo Bonzini    case MO_SB:
1134*139c1837SPaolo Bonzini        tcg_out_opc_imm(s, OPC_LB, lo, base, 0);
1135*139c1837SPaolo Bonzini        break;
1136*139c1837SPaolo Bonzini    case MO_UW:
1137*139c1837SPaolo Bonzini        tcg_out_opc_imm(s, OPC_LHU, lo, base, 0);
1138*139c1837SPaolo Bonzini        break;
1139*139c1837SPaolo Bonzini    case MO_SW:
1140*139c1837SPaolo Bonzini        tcg_out_opc_imm(s, OPC_LH, lo, base, 0);
1141*139c1837SPaolo Bonzini        break;
1142*139c1837SPaolo Bonzini    case MO_UL:
1143*139c1837SPaolo Bonzini        if (TCG_TARGET_REG_BITS == 64 && is_64) {
1144*139c1837SPaolo Bonzini            tcg_out_opc_imm(s, OPC_LWU, lo, base, 0);
1145*139c1837SPaolo Bonzini            break;
1146*139c1837SPaolo Bonzini        }
1147*139c1837SPaolo Bonzini        /* FALLTHRU */
1148*139c1837SPaolo Bonzini    case MO_SL:
1149*139c1837SPaolo Bonzini        tcg_out_opc_imm(s, OPC_LW, lo, base, 0);
1150*139c1837SPaolo Bonzini        break;
1151*139c1837SPaolo Bonzini    case MO_Q:
1152*139c1837SPaolo Bonzini        /* Prefer to load from offset 0 first, but allow for overlap.  */
1153*139c1837SPaolo Bonzini        if (TCG_TARGET_REG_BITS == 64) {
1154*139c1837SPaolo Bonzini            tcg_out_opc_imm(s, OPC_LD, lo, base, 0);
1155*139c1837SPaolo Bonzini        } else if (lo != base) {
1156*139c1837SPaolo Bonzini            tcg_out_opc_imm(s, OPC_LW, lo, base, 0);
1157*139c1837SPaolo Bonzini            tcg_out_opc_imm(s, OPC_LW, hi, base, 4);
1158*139c1837SPaolo Bonzini        } else {
1159*139c1837SPaolo Bonzini            tcg_out_opc_imm(s, OPC_LW, hi, base, 4);
1160*139c1837SPaolo Bonzini            tcg_out_opc_imm(s, OPC_LW, lo, base, 0);
1161*139c1837SPaolo Bonzini        }
1162*139c1837SPaolo Bonzini        break;
1163*139c1837SPaolo Bonzini    default:
1164*139c1837SPaolo Bonzini        g_assert_not_reached();
1165*139c1837SPaolo Bonzini    }
1166*139c1837SPaolo Bonzini}
1167*139c1837SPaolo Bonzini
1168*139c1837SPaolo Bonzinistatic void tcg_out_qemu_ld(TCGContext *s, const TCGArg *args, bool is_64)
1169*139c1837SPaolo Bonzini{
1170*139c1837SPaolo Bonzini    TCGReg addr_regl, addr_regh __attribute__((unused));
1171*139c1837SPaolo Bonzini    TCGReg data_regl, data_regh;
1172*139c1837SPaolo Bonzini    TCGMemOpIdx oi;
1173*139c1837SPaolo Bonzini    MemOp opc;
1174*139c1837SPaolo Bonzini#if defined(CONFIG_SOFTMMU)
1175*139c1837SPaolo Bonzini    tcg_insn_unit *label_ptr[1];
1176*139c1837SPaolo Bonzini#endif
1177*139c1837SPaolo Bonzini    TCGReg base = TCG_REG_TMP0;
1178*139c1837SPaolo Bonzini
1179*139c1837SPaolo Bonzini    data_regl = *args++;
1180*139c1837SPaolo Bonzini    data_regh = (TCG_TARGET_REG_BITS == 32 && is_64 ? *args++ : 0);
1181*139c1837SPaolo Bonzini    addr_regl = *args++;
1182*139c1837SPaolo Bonzini    addr_regh = (TCG_TARGET_REG_BITS < TARGET_LONG_BITS ? *args++ : 0);
1183*139c1837SPaolo Bonzini    oi = *args++;
1184*139c1837SPaolo Bonzini    opc = get_memop(oi);
1185*139c1837SPaolo Bonzini
1186*139c1837SPaolo Bonzini#if defined(CONFIG_SOFTMMU)
1187*139c1837SPaolo Bonzini    tcg_out_tlb_load(s, addr_regl, addr_regh, oi, label_ptr, 1);
1188*139c1837SPaolo Bonzini    tcg_out_qemu_ld_direct(s, data_regl, data_regh, base, opc, is_64);
1189*139c1837SPaolo Bonzini    add_qemu_ldst_label(s, 1, oi,
1190*139c1837SPaolo Bonzini                        (is_64 ? TCG_TYPE_I64 : TCG_TYPE_I32),
1191*139c1837SPaolo Bonzini                        data_regl, data_regh, addr_regl, addr_regh,
1192*139c1837SPaolo Bonzini                        s->code_ptr, label_ptr);
1193*139c1837SPaolo Bonzini#else
1194*139c1837SPaolo Bonzini    if (TCG_TARGET_REG_BITS > TARGET_LONG_BITS) {
1195*139c1837SPaolo Bonzini        tcg_out_ext32u(s, base, addr_regl);
1196*139c1837SPaolo Bonzini        addr_regl = base;
1197*139c1837SPaolo Bonzini    }
1198*139c1837SPaolo Bonzini
1199*139c1837SPaolo Bonzini    if (guest_base == 0) {
1200*139c1837SPaolo Bonzini        tcg_out_opc_reg(s, OPC_ADD, base, addr_regl, TCG_REG_ZERO);
1201*139c1837SPaolo Bonzini    } else {
1202*139c1837SPaolo Bonzini        tcg_out_opc_reg(s, OPC_ADD, base, TCG_GUEST_BASE_REG, addr_regl);
1203*139c1837SPaolo Bonzini    }
1204*139c1837SPaolo Bonzini    tcg_out_qemu_ld_direct(s, data_regl, data_regh, base, opc, is_64);
1205*139c1837SPaolo Bonzini#endif
1206*139c1837SPaolo Bonzini}
1207*139c1837SPaolo Bonzini
1208*139c1837SPaolo Bonzinistatic void tcg_out_qemu_st_direct(TCGContext *s, TCGReg lo, TCGReg hi,
1209*139c1837SPaolo Bonzini                                   TCGReg base, MemOp opc)
1210*139c1837SPaolo Bonzini{
1211*139c1837SPaolo Bonzini    const MemOp bswap = opc & MO_BSWAP;
1212*139c1837SPaolo Bonzini
1213*139c1837SPaolo Bonzini    /* We don't yet handle byteswapping, assert */
1214*139c1837SPaolo Bonzini    g_assert(!bswap);
1215*139c1837SPaolo Bonzini
1216*139c1837SPaolo Bonzini    switch (opc & (MO_SSIZE)) {
1217*139c1837SPaolo Bonzini    case MO_8:
1218*139c1837SPaolo Bonzini        tcg_out_opc_store(s, OPC_SB, base, lo, 0);
1219*139c1837SPaolo Bonzini        break;
1220*139c1837SPaolo Bonzini    case MO_16:
1221*139c1837SPaolo Bonzini        tcg_out_opc_store(s, OPC_SH, base, lo, 0);
1222*139c1837SPaolo Bonzini        break;
1223*139c1837SPaolo Bonzini    case MO_32:
1224*139c1837SPaolo Bonzini        tcg_out_opc_store(s, OPC_SW, base, lo, 0);
1225*139c1837SPaolo Bonzini        break;
1226*139c1837SPaolo Bonzini    case MO_64:
1227*139c1837SPaolo Bonzini        if (TCG_TARGET_REG_BITS == 64) {
1228*139c1837SPaolo Bonzini            tcg_out_opc_store(s, OPC_SD, base, lo, 0);
1229*139c1837SPaolo Bonzini        } else {
1230*139c1837SPaolo Bonzini            tcg_out_opc_store(s, OPC_SW, base, lo, 0);
1231*139c1837SPaolo Bonzini            tcg_out_opc_store(s, OPC_SW, base, hi, 4);
1232*139c1837SPaolo Bonzini        }
1233*139c1837SPaolo Bonzini        break;
1234*139c1837SPaolo Bonzini    default:
1235*139c1837SPaolo Bonzini        g_assert_not_reached();
1236*139c1837SPaolo Bonzini    }
1237*139c1837SPaolo Bonzini}
1238*139c1837SPaolo Bonzini
1239*139c1837SPaolo Bonzinistatic void tcg_out_qemu_st(TCGContext *s, const TCGArg *args, bool is_64)
1240*139c1837SPaolo Bonzini{
1241*139c1837SPaolo Bonzini    TCGReg addr_regl, addr_regh __attribute__((unused));
1242*139c1837SPaolo Bonzini    TCGReg data_regl, data_regh;
1243*139c1837SPaolo Bonzini    TCGMemOpIdx oi;
1244*139c1837SPaolo Bonzini    MemOp opc;
1245*139c1837SPaolo Bonzini#if defined(CONFIG_SOFTMMU)
1246*139c1837SPaolo Bonzini    tcg_insn_unit *label_ptr[1];
1247*139c1837SPaolo Bonzini#endif
1248*139c1837SPaolo Bonzini    TCGReg base = TCG_REG_TMP0;
1249*139c1837SPaolo Bonzini
1250*139c1837SPaolo Bonzini    data_regl = *args++;
1251*139c1837SPaolo Bonzini    data_regh = (TCG_TARGET_REG_BITS == 32 && is_64 ? *args++ : 0);
1252*139c1837SPaolo Bonzini    addr_regl = *args++;
1253*139c1837SPaolo Bonzini    addr_regh = (TCG_TARGET_REG_BITS < TARGET_LONG_BITS ? *args++ : 0);
1254*139c1837SPaolo Bonzini    oi = *args++;
1255*139c1837SPaolo Bonzini    opc = get_memop(oi);
1256*139c1837SPaolo Bonzini
1257*139c1837SPaolo Bonzini#if defined(CONFIG_SOFTMMU)
1258*139c1837SPaolo Bonzini    tcg_out_tlb_load(s, addr_regl, addr_regh, oi, label_ptr, 0);
1259*139c1837SPaolo Bonzini    tcg_out_qemu_st_direct(s, data_regl, data_regh, base, opc);
1260*139c1837SPaolo Bonzini    add_qemu_ldst_label(s, 0, oi,
1261*139c1837SPaolo Bonzini                        (is_64 ? TCG_TYPE_I64 : TCG_TYPE_I32),
1262*139c1837SPaolo Bonzini                        data_regl, data_regh, addr_regl, addr_regh,
1263*139c1837SPaolo Bonzini                        s->code_ptr, label_ptr);
1264*139c1837SPaolo Bonzini#else
1265*139c1837SPaolo Bonzini    if (TCG_TARGET_REG_BITS > TARGET_LONG_BITS) {
1266*139c1837SPaolo Bonzini        tcg_out_ext32u(s, base, addr_regl);
1267*139c1837SPaolo Bonzini        addr_regl = base;
1268*139c1837SPaolo Bonzini    }
1269*139c1837SPaolo Bonzini
1270*139c1837SPaolo Bonzini    if (guest_base == 0) {
1271*139c1837SPaolo Bonzini        tcg_out_opc_reg(s, OPC_ADD, base, addr_regl, TCG_REG_ZERO);
1272*139c1837SPaolo Bonzini    } else {
1273*139c1837SPaolo Bonzini        tcg_out_opc_reg(s, OPC_ADD, base, TCG_GUEST_BASE_REG, addr_regl);
1274*139c1837SPaolo Bonzini    }
1275*139c1837SPaolo Bonzini    tcg_out_qemu_st_direct(s, data_regl, data_regh, base, opc);
1276*139c1837SPaolo Bonzini#endif
1277*139c1837SPaolo Bonzini}
1278*139c1837SPaolo Bonzini
1279*139c1837SPaolo Bonzinistatic tcg_insn_unit *tb_ret_addr;
1280*139c1837SPaolo Bonzini
1281*139c1837SPaolo Bonzinistatic void tcg_out_op(TCGContext *s, TCGOpcode opc,
1282*139c1837SPaolo Bonzini                       const TCGArg *args, const int *const_args)
1283*139c1837SPaolo Bonzini{
1284*139c1837SPaolo Bonzini    TCGArg a0 = args[0];
1285*139c1837SPaolo Bonzini    TCGArg a1 = args[1];
1286*139c1837SPaolo Bonzini    TCGArg a2 = args[2];
1287*139c1837SPaolo Bonzini    int c2 = const_args[2];
1288*139c1837SPaolo Bonzini
1289*139c1837SPaolo Bonzini    switch (opc) {
1290*139c1837SPaolo Bonzini    case INDEX_op_exit_tb:
1291*139c1837SPaolo Bonzini        /* Reuse the zeroing that exists for goto_ptr.  */
1292*139c1837SPaolo Bonzini        if (a0 == 0) {
1293*139c1837SPaolo Bonzini            tcg_out_call_int(s, s->code_gen_epilogue, true);
1294*139c1837SPaolo Bonzini        } else {
1295*139c1837SPaolo Bonzini            tcg_out_movi(s, TCG_TYPE_PTR, TCG_REG_A0, a0);
1296*139c1837SPaolo Bonzini            tcg_out_call_int(s, tb_ret_addr, true);
1297*139c1837SPaolo Bonzini        }
1298*139c1837SPaolo Bonzini        break;
1299*139c1837SPaolo Bonzini
1300*139c1837SPaolo Bonzini    case INDEX_op_goto_tb:
1301*139c1837SPaolo Bonzini        assert(s->tb_jmp_insn_offset == 0);
1302*139c1837SPaolo Bonzini        /* indirect jump method */
1303*139c1837SPaolo Bonzini        tcg_out_ld(s, TCG_TYPE_PTR, TCG_REG_TMP0, TCG_REG_ZERO,
1304*139c1837SPaolo Bonzini                   (uintptr_t)(s->tb_jmp_target_addr + a0));
1305*139c1837SPaolo Bonzini        tcg_out_opc_imm(s, OPC_JALR, TCG_REG_ZERO, TCG_REG_TMP0, 0);
1306*139c1837SPaolo Bonzini        set_jmp_reset_offset(s, a0);
1307*139c1837SPaolo Bonzini        break;
1308*139c1837SPaolo Bonzini
1309*139c1837SPaolo Bonzini    case INDEX_op_goto_ptr:
1310*139c1837SPaolo Bonzini        tcg_out_opc_imm(s, OPC_JALR, TCG_REG_ZERO, a0, 0);
1311*139c1837SPaolo Bonzini        break;
1312*139c1837SPaolo Bonzini
1313*139c1837SPaolo Bonzini    case INDEX_op_br:
1314*139c1837SPaolo Bonzini        tcg_out_reloc(s, s->code_ptr, R_RISCV_JAL, arg_label(a0), 0);
1315*139c1837SPaolo Bonzini        tcg_out_opc_jump(s, OPC_JAL, TCG_REG_ZERO, 0);
1316*139c1837SPaolo Bonzini        break;
1317*139c1837SPaolo Bonzini
1318*139c1837SPaolo Bonzini    case INDEX_op_ld8u_i32:
1319*139c1837SPaolo Bonzini    case INDEX_op_ld8u_i64:
1320*139c1837SPaolo Bonzini        tcg_out_ldst(s, OPC_LBU, a0, a1, a2);
1321*139c1837SPaolo Bonzini        break;
1322*139c1837SPaolo Bonzini    case INDEX_op_ld8s_i32:
1323*139c1837SPaolo Bonzini    case INDEX_op_ld8s_i64:
1324*139c1837SPaolo Bonzini        tcg_out_ldst(s, OPC_LB, a0, a1, a2);
1325*139c1837SPaolo Bonzini        break;
1326*139c1837SPaolo Bonzini    case INDEX_op_ld16u_i32:
1327*139c1837SPaolo Bonzini    case INDEX_op_ld16u_i64:
1328*139c1837SPaolo Bonzini        tcg_out_ldst(s, OPC_LHU, a0, a1, a2);
1329*139c1837SPaolo Bonzini        break;
1330*139c1837SPaolo Bonzini    case INDEX_op_ld16s_i32:
1331*139c1837SPaolo Bonzini    case INDEX_op_ld16s_i64:
1332*139c1837SPaolo Bonzini        tcg_out_ldst(s, OPC_LH, a0, a1, a2);
1333*139c1837SPaolo Bonzini        break;
1334*139c1837SPaolo Bonzini    case INDEX_op_ld32u_i64:
1335*139c1837SPaolo Bonzini        tcg_out_ldst(s, OPC_LWU, a0, a1, a2);
1336*139c1837SPaolo Bonzini        break;
1337*139c1837SPaolo Bonzini    case INDEX_op_ld_i32:
1338*139c1837SPaolo Bonzini    case INDEX_op_ld32s_i64:
1339*139c1837SPaolo Bonzini        tcg_out_ldst(s, OPC_LW, a0, a1, a2);
1340*139c1837SPaolo Bonzini        break;
1341*139c1837SPaolo Bonzini    case INDEX_op_ld_i64:
1342*139c1837SPaolo Bonzini        tcg_out_ldst(s, OPC_LD, a0, a1, a2);
1343*139c1837SPaolo Bonzini        break;
1344*139c1837SPaolo Bonzini
1345*139c1837SPaolo Bonzini    case INDEX_op_st8_i32:
1346*139c1837SPaolo Bonzini    case INDEX_op_st8_i64:
1347*139c1837SPaolo Bonzini        tcg_out_ldst(s, OPC_SB, a0, a1, a2);
1348*139c1837SPaolo Bonzini        break;
1349*139c1837SPaolo Bonzini    case INDEX_op_st16_i32:
1350*139c1837SPaolo Bonzini    case INDEX_op_st16_i64:
1351*139c1837SPaolo Bonzini        tcg_out_ldst(s, OPC_SH, a0, a1, a2);
1352*139c1837SPaolo Bonzini        break;
1353*139c1837SPaolo Bonzini    case INDEX_op_st_i32:
1354*139c1837SPaolo Bonzini    case INDEX_op_st32_i64:
1355*139c1837SPaolo Bonzini        tcg_out_ldst(s, OPC_SW, a0, a1, a2);
1356*139c1837SPaolo Bonzini        break;
1357*139c1837SPaolo Bonzini    case INDEX_op_st_i64:
1358*139c1837SPaolo Bonzini        tcg_out_ldst(s, OPC_SD, a0, a1, a2);
1359*139c1837SPaolo Bonzini        break;
1360*139c1837SPaolo Bonzini
1361*139c1837SPaolo Bonzini    case INDEX_op_add_i32:
1362*139c1837SPaolo Bonzini        if (c2) {
1363*139c1837SPaolo Bonzini            tcg_out_opc_imm(s, OPC_ADDIW, a0, a1, a2);
1364*139c1837SPaolo Bonzini        } else {
1365*139c1837SPaolo Bonzini            tcg_out_opc_reg(s, OPC_ADDW, a0, a1, a2);
1366*139c1837SPaolo Bonzini        }
1367*139c1837SPaolo Bonzini        break;
1368*139c1837SPaolo Bonzini    case INDEX_op_add_i64:
1369*139c1837SPaolo Bonzini        if (c2) {
1370*139c1837SPaolo Bonzini            tcg_out_opc_imm(s, OPC_ADDI, a0, a1, a2);
1371*139c1837SPaolo Bonzini        } else {
1372*139c1837SPaolo Bonzini            tcg_out_opc_reg(s, OPC_ADD, a0, a1, a2);
1373*139c1837SPaolo Bonzini        }
1374*139c1837SPaolo Bonzini        break;
1375*139c1837SPaolo Bonzini
1376*139c1837SPaolo Bonzini    case INDEX_op_sub_i32:
1377*139c1837SPaolo Bonzini        if (c2) {
1378*139c1837SPaolo Bonzini            tcg_out_opc_imm(s, OPC_ADDIW, a0, a1, -a2);
1379*139c1837SPaolo Bonzini        } else {
1380*139c1837SPaolo Bonzini            tcg_out_opc_reg(s, OPC_SUBW, a0, a1, a2);
1381*139c1837SPaolo Bonzini        }
1382*139c1837SPaolo Bonzini        break;
1383*139c1837SPaolo Bonzini    case INDEX_op_sub_i64:
1384*139c1837SPaolo Bonzini        if (c2) {
1385*139c1837SPaolo Bonzini            tcg_out_opc_imm(s, OPC_ADDI, a0, a1, -a2);
1386*139c1837SPaolo Bonzini        } else {
1387*139c1837SPaolo Bonzini            tcg_out_opc_reg(s, OPC_SUB, a0, a1, a2);
1388*139c1837SPaolo Bonzini        }
1389*139c1837SPaolo Bonzini        break;
1390*139c1837SPaolo Bonzini
1391*139c1837SPaolo Bonzini    case INDEX_op_and_i32:
1392*139c1837SPaolo Bonzini    case INDEX_op_and_i64:
1393*139c1837SPaolo Bonzini        if (c2) {
1394*139c1837SPaolo Bonzini            tcg_out_opc_imm(s, OPC_ANDI, a0, a1, a2);
1395*139c1837SPaolo Bonzini        } else {
1396*139c1837SPaolo Bonzini            tcg_out_opc_reg(s, OPC_AND, a0, a1, a2);
1397*139c1837SPaolo Bonzini        }
1398*139c1837SPaolo Bonzini        break;
1399*139c1837SPaolo Bonzini
1400*139c1837SPaolo Bonzini    case INDEX_op_or_i32:
1401*139c1837SPaolo Bonzini    case INDEX_op_or_i64:
1402*139c1837SPaolo Bonzini        if (c2) {
1403*139c1837SPaolo Bonzini            tcg_out_opc_imm(s, OPC_ORI, a0, a1, a2);
1404*139c1837SPaolo Bonzini        } else {
1405*139c1837SPaolo Bonzini            tcg_out_opc_reg(s, OPC_OR, a0, a1, a2);
1406*139c1837SPaolo Bonzini        }
1407*139c1837SPaolo Bonzini        break;
1408*139c1837SPaolo Bonzini
1409*139c1837SPaolo Bonzini    case INDEX_op_xor_i32:
1410*139c1837SPaolo Bonzini    case INDEX_op_xor_i64:
1411*139c1837SPaolo Bonzini        if (c2) {
1412*139c1837SPaolo Bonzini            tcg_out_opc_imm(s, OPC_XORI, a0, a1, a2);
1413*139c1837SPaolo Bonzini        } else {
1414*139c1837SPaolo Bonzini            tcg_out_opc_reg(s, OPC_XOR, a0, a1, a2);
1415*139c1837SPaolo Bonzini        }
1416*139c1837SPaolo Bonzini        break;
1417*139c1837SPaolo Bonzini
1418*139c1837SPaolo Bonzini    case INDEX_op_not_i32:
1419*139c1837SPaolo Bonzini    case INDEX_op_not_i64:
1420*139c1837SPaolo Bonzini        tcg_out_opc_imm(s, OPC_XORI, a0, a1, -1);
1421*139c1837SPaolo Bonzini        break;
1422*139c1837SPaolo Bonzini
1423*139c1837SPaolo Bonzini    case INDEX_op_neg_i32:
1424*139c1837SPaolo Bonzini        tcg_out_opc_reg(s, OPC_SUBW, a0, TCG_REG_ZERO, a1);
1425*139c1837SPaolo Bonzini        break;
1426*139c1837SPaolo Bonzini    case INDEX_op_neg_i64:
1427*139c1837SPaolo Bonzini        tcg_out_opc_reg(s, OPC_SUB, a0, TCG_REG_ZERO, a1);
1428*139c1837SPaolo Bonzini        break;
1429*139c1837SPaolo Bonzini
1430*139c1837SPaolo Bonzini    case INDEX_op_mul_i32:
1431*139c1837SPaolo Bonzini        tcg_out_opc_reg(s, OPC_MULW, a0, a1, a2);
1432*139c1837SPaolo Bonzini        break;
1433*139c1837SPaolo Bonzini    case INDEX_op_mul_i64:
1434*139c1837SPaolo Bonzini        tcg_out_opc_reg(s, OPC_MUL, a0, a1, a2);
1435*139c1837SPaolo Bonzini        break;
1436*139c1837SPaolo Bonzini
1437*139c1837SPaolo Bonzini    case INDEX_op_div_i32:
1438*139c1837SPaolo Bonzini        tcg_out_opc_reg(s, OPC_DIVW, a0, a1, a2);
1439*139c1837SPaolo Bonzini        break;
1440*139c1837SPaolo Bonzini    case INDEX_op_div_i64:
1441*139c1837SPaolo Bonzini        tcg_out_opc_reg(s, OPC_DIV, a0, a1, a2);
1442*139c1837SPaolo Bonzini        break;
1443*139c1837SPaolo Bonzini
1444*139c1837SPaolo Bonzini    case INDEX_op_divu_i32:
1445*139c1837SPaolo Bonzini        tcg_out_opc_reg(s, OPC_DIVUW, a0, a1, a2);
1446*139c1837SPaolo Bonzini        break;
1447*139c1837SPaolo Bonzini    case INDEX_op_divu_i64:
1448*139c1837SPaolo Bonzini        tcg_out_opc_reg(s, OPC_DIVU, a0, a1, a2);
1449*139c1837SPaolo Bonzini        break;
1450*139c1837SPaolo Bonzini
1451*139c1837SPaolo Bonzini    case INDEX_op_rem_i32:
1452*139c1837SPaolo Bonzini        tcg_out_opc_reg(s, OPC_REMW, a0, a1, a2);
1453*139c1837SPaolo Bonzini        break;
1454*139c1837SPaolo Bonzini    case INDEX_op_rem_i64:
1455*139c1837SPaolo Bonzini        tcg_out_opc_reg(s, OPC_REM, a0, a1, a2);
1456*139c1837SPaolo Bonzini        break;
1457*139c1837SPaolo Bonzini
1458*139c1837SPaolo Bonzini    case INDEX_op_remu_i32:
1459*139c1837SPaolo Bonzini        tcg_out_opc_reg(s, OPC_REMUW, a0, a1, a2);
1460*139c1837SPaolo Bonzini        break;
1461*139c1837SPaolo Bonzini    case INDEX_op_remu_i64:
1462*139c1837SPaolo Bonzini        tcg_out_opc_reg(s, OPC_REMU, a0, a1, a2);
1463*139c1837SPaolo Bonzini        break;
1464*139c1837SPaolo Bonzini
1465*139c1837SPaolo Bonzini    case INDEX_op_shl_i32:
1466*139c1837SPaolo Bonzini        if (c2) {
1467*139c1837SPaolo Bonzini            tcg_out_opc_imm(s, OPC_SLLIW, a0, a1, a2);
1468*139c1837SPaolo Bonzini        } else {
1469*139c1837SPaolo Bonzini            tcg_out_opc_reg(s, OPC_SLLW, a0, a1, a2);
1470*139c1837SPaolo Bonzini        }
1471*139c1837SPaolo Bonzini        break;
1472*139c1837SPaolo Bonzini    case INDEX_op_shl_i64:
1473*139c1837SPaolo Bonzini        if (c2) {
1474*139c1837SPaolo Bonzini            tcg_out_opc_imm(s, OPC_SLLI, a0, a1, a2);
1475*139c1837SPaolo Bonzini        } else {
1476*139c1837SPaolo Bonzini            tcg_out_opc_reg(s, OPC_SLL, a0, a1, a2);
1477*139c1837SPaolo Bonzini        }
1478*139c1837SPaolo Bonzini        break;
1479*139c1837SPaolo Bonzini
1480*139c1837SPaolo Bonzini    case INDEX_op_shr_i32:
1481*139c1837SPaolo Bonzini        if (c2) {
1482*139c1837SPaolo Bonzini            tcg_out_opc_imm(s, OPC_SRLIW, a0, a1, a2);
1483*139c1837SPaolo Bonzini        } else {
1484*139c1837SPaolo Bonzini            tcg_out_opc_reg(s, OPC_SRLW, a0, a1, a2);
1485*139c1837SPaolo Bonzini        }
1486*139c1837SPaolo Bonzini        break;
1487*139c1837SPaolo Bonzini    case INDEX_op_shr_i64:
1488*139c1837SPaolo Bonzini        if (c2) {
1489*139c1837SPaolo Bonzini            tcg_out_opc_imm(s, OPC_SRLI, a0, a1, a2);
1490*139c1837SPaolo Bonzini        } else {
1491*139c1837SPaolo Bonzini            tcg_out_opc_reg(s, OPC_SRL, a0, a1, a2);
1492*139c1837SPaolo Bonzini        }
1493*139c1837SPaolo Bonzini        break;
1494*139c1837SPaolo Bonzini
1495*139c1837SPaolo Bonzini    case INDEX_op_sar_i32:
1496*139c1837SPaolo Bonzini        if (c2) {
1497*139c1837SPaolo Bonzini            tcg_out_opc_imm(s, OPC_SRAIW, a0, a1, a2);
1498*139c1837SPaolo Bonzini        } else {
1499*139c1837SPaolo Bonzini            tcg_out_opc_reg(s, OPC_SRAW, a0, a1, a2);
1500*139c1837SPaolo Bonzini        }
1501*139c1837SPaolo Bonzini        break;
1502*139c1837SPaolo Bonzini    case INDEX_op_sar_i64:
1503*139c1837SPaolo Bonzini        if (c2) {
1504*139c1837SPaolo Bonzini            tcg_out_opc_imm(s, OPC_SRAI, a0, a1, a2);
1505*139c1837SPaolo Bonzini        } else {
1506*139c1837SPaolo Bonzini            tcg_out_opc_reg(s, OPC_SRA, a0, a1, a2);
1507*139c1837SPaolo Bonzini        }
1508*139c1837SPaolo Bonzini        break;
1509*139c1837SPaolo Bonzini
1510*139c1837SPaolo Bonzini    case INDEX_op_add2_i32:
1511*139c1837SPaolo Bonzini        tcg_out_addsub2(s, a0, a1, a2, args[3], args[4], args[5],
1512*139c1837SPaolo Bonzini                        const_args[4], const_args[5], false, true);
1513*139c1837SPaolo Bonzini        break;
1514*139c1837SPaolo Bonzini    case INDEX_op_add2_i64:
1515*139c1837SPaolo Bonzini        tcg_out_addsub2(s, a0, a1, a2, args[3], args[4], args[5],
1516*139c1837SPaolo Bonzini                        const_args[4], const_args[5], false, false);
1517*139c1837SPaolo Bonzini        break;
1518*139c1837SPaolo Bonzini    case INDEX_op_sub2_i32:
1519*139c1837SPaolo Bonzini        tcg_out_addsub2(s, a0, a1, a2, args[3], args[4], args[5],
1520*139c1837SPaolo Bonzini                        const_args[4], const_args[5], true, true);
1521*139c1837SPaolo Bonzini        break;
1522*139c1837SPaolo Bonzini    case INDEX_op_sub2_i64:
1523*139c1837SPaolo Bonzini        tcg_out_addsub2(s, a0, a1, a2, args[3], args[4], args[5],
1524*139c1837SPaolo Bonzini                        const_args[4], const_args[5], true, false);
1525*139c1837SPaolo Bonzini        break;
1526*139c1837SPaolo Bonzini
1527*139c1837SPaolo Bonzini    case INDEX_op_brcond_i32:
1528*139c1837SPaolo Bonzini    case INDEX_op_brcond_i64:
1529*139c1837SPaolo Bonzini        tcg_out_brcond(s, a2, a0, a1, arg_label(args[3]));
1530*139c1837SPaolo Bonzini        break;
1531*139c1837SPaolo Bonzini    case INDEX_op_brcond2_i32:
1532*139c1837SPaolo Bonzini        tcg_out_brcond2(s, args[4], a0, a1, a2, args[3], arg_label(args[5]));
1533*139c1837SPaolo Bonzini        break;
1534*139c1837SPaolo Bonzini
1535*139c1837SPaolo Bonzini    case INDEX_op_setcond_i32:
1536*139c1837SPaolo Bonzini    case INDEX_op_setcond_i64:
1537*139c1837SPaolo Bonzini        tcg_out_setcond(s, args[3], a0, a1, a2);
1538*139c1837SPaolo Bonzini        break;
1539*139c1837SPaolo Bonzini    case INDEX_op_setcond2_i32:
1540*139c1837SPaolo Bonzini        tcg_out_setcond2(s, args[5], a0, a1, a2, args[3], args[4]);
1541*139c1837SPaolo Bonzini        break;
1542*139c1837SPaolo Bonzini
1543*139c1837SPaolo Bonzini    case INDEX_op_qemu_ld_i32:
1544*139c1837SPaolo Bonzini        tcg_out_qemu_ld(s, args, false);
1545*139c1837SPaolo Bonzini        break;
1546*139c1837SPaolo Bonzini    case INDEX_op_qemu_ld_i64:
1547*139c1837SPaolo Bonzini        tcg_out_qemu_ld(s, args, true);
1548*139c1837SPaolo Bonzini        break;
1549*139c1837SPaolo Bonzini    case INDEX_op_qemu_st_i32:
1550*139c1837SPaolo Bonzini        tcg_out_qemu_st(s, args, false);
1551*139c1837SPaolo Bonzini        break;
1552*139c1837SPaolo Bonzini    case INDEX_op_qemu_st_i64:
1553*139c1837SPaolo Bonzini        tcg_out_qemu_st(s, args, true);
1554*139c1837SPaolo Bonzini        break;
1555*139c1837SPaolo Bonzini
1556*139c1837SPaolo Bonzini    case INDEX_op_ext8u_i32:
1557*139c1837SPaolo Bonzini    case INDEX_op_ext8u_i64:
1558*139c1837SPaolo Bonzini        tcg_out_ext8u(s, a0, a1);
1559*139c1837SPaolo Bonzini        break;
1560*139c1837SPaolo Bonzini
1561*139c1837SPaolo Bonzini    case INDEX_op_ext16u_i32:
1562*139c1837SPaolo Bonzini    case INDEX_op_ext16u_i64:
1563*139c1837SPaolo Bonzini        tcg_out_ext16u(s, a0, a1);
1564*139c1837SPaolo Bonzini        break;
1565*139c1837SPaolo Bonzini
1566*139c1837SPaolo Bonzini    case INDEX_op_ext32u_i64:
1567*139c1837SPaolo Bonzini    case INDEX_op_extu_i32_i64:
1568*139c1837SPaolo Bonzini        tcg_out_ext32u(s, a0, a1);
1569*139c1837SPaolo Bonzini        break;
1570*139c1837SPaolo Bonzini
1571*139c1837SPaolo Bonzini    case INDEX_op_ext8s_i32:
1572*139c1837SPaolo Bonzini    case INDEX_op_ext8s_i64:
1573*139c1837SPaolo Bonzini        tcg_out_ext8s(s, a0, a1);
1574*139c1837SPaolo Bonzini        break;
1575*139c1837SPaolo Bonzini
1576*139c1837SPaolo Bonzini    case INDEX_op_ext16s_i32:
1577*139c1837SPaolo Bonzini    case INDEX_op_ext16s_i64:
1578*139c1837SPaolo Bonzini        tcg_out_ext16s(s, a0, a1);
1579*139c1837SPaolo Bonzini        break;
1580*139c1837SPaolo Bonzini
1581*139c1837SPaolo Bonzini    case INDEX_op_ext32s_i64:
1582*139c1837SPaolo Bonzini    case INDEX_op_extrl_i64_i32:
1583*139c1837SPaolo Bonzini    case INDEX_op_ext_i32_i64:
1584*139c1837SPaolo Bonzini        tcg_out_ext32s(s, a0, a1);
1585*139c1837SPaolo Bonzini        break;
1586*139c1837SPaolo Bonzini
1587*139c1837SPaolo Bonzini    case INDEX_op_extrh_i64_i32:
1588*139c1837SPaolo Bonzini        tcg_out_opc_imm(s, OPC_SRAI, a0, a1, 32);
1589*139c1837SPaolo Bonzini        break;
1590*139c1837SPaolo Bonzini
1591*139c1837SPaolo Bonzini    case INDEX_op_mulsh_i32:
1592*139c1837SPaolo Bonzini    case INDEX_op_mulsh_i64:
1593*139c1837SPaolo Bonzini        tcg_out_opc_reg(s, OPC_MULH, a0, a1, a2);
1594*139c1837SPaolo Bonzini        break;
1595*139c1837SPaolo Bonzini
1596*139c1837SPaolo Bonzini    case INDEX_op_muluh_i32:
1597*139c1837SPaolo Bonzini    case INDEX_op_muluh_i64:
1598*139c1837SPaolo Bonzini        tcg_out_opc_reg(s, OPC_MULHU, a0, a1, a2);
1599*139c1837SPaolo Bonzini        break;
1600*139c1837SPaolo Bonzini
1601*139c1837SPaolo Bonzini    case INDEX_op_mb:
1602*139c1837SPaolo Bonzini        tcg_out_mb(s, a0);
1603*139c1837SPaolo Bonzini        break;
1604*139c1837SPaolo Bonzini
1605*139c1837SPaolo Bonzini    case INDEX_op_mov_i32:  /* Always emitted via tcg_out_mov.  */
1606*139c1837SPaolo Bonzini    case INDEX_op_mov_i64:
1607*139c1837SPaolo Bonzini    case INDEX_op_movi_i32: /* Always emitted via tcg_out_movi.  */
1608*139c1837SPaolo Bonzini    case INDEX_op_movi_i64:
1609*139c1837SPaolo Bonzini    case INDEX_op_call:     /* Always emitted via tcg_out_call.  */
1610*139c1837SPaolo Bonzini    default:
1611*139c1837SPaolo Bonzini        g_assert_not_reached();
1612*139c1837SPaolo Bonzini    }
1613*139c1837SPaolo Bonzini}
1614*139c1837SPaolo Bonzini
1615*139c1837SPaolo Bonzinistatic const TCGTargetOpDef *tcg_target_op_def(TCGOpcode op)
1616*139c1837SPaolo Bonzini{
1617*139c1837SPaolo Bonzini    static const TCGTargetOpDef r
1618*139c1837SPaolo Bonzini        = { .args_ct_str = { "r" } };
1619*139c1837SPaolo Bonzini    static const TCGTargetOpDef r_r
1620*139c1837SPaolo Bonzini        = { .args_ct_str = { "r", "r" } };
1621*139c1837SPaolo Bonzini    static const TCGTargetOpDef rZ_r
1622*139c1837SPaolo Bonzini        = { .args_ct_str = { "rZ", "r" } };
1623*139c1837SPaolo Bonzini    static const TCGTargetOpDef rZ_rZ
1624*139c1837SPaolo Bonzini        = { .args_ct_str = { "rZ", "rZ" } };
1625*139c1837SPaolo Bonzini    static const TCGTargetOpDef rZ_rZ_rZ_rZ
1626*139c1837SPaolo Bonzini        = { .args_ct_str = { "rZ", "rZ", "rZ", "rZ" } };
1627*139c1837SPaolo Bonzini    static const TCGTargetOpDef r_r_ri
1628*139c1837SPaolo Bonzini        = { .args_ct_str = { "r", "r", "ri" } };
1629*139c1837SPaolo Bonzini    static const TCGTargetOpDef r_r_rI
1630*139c1837SPaolo Bonzini        = { .args_ct_str = { "r", "r", "rI" } };
1631*139c1837SPaolo Bonzini    static const TCGTargetOpDef r_rZ_rN
1632*139c1837SPaolo Bonzini        = { .args_ct_str = { "r", "rZ", "rN" } };
1633*139c1837SPaolo Bonzini    static const TCGTargetOpDef r_rZ_rZ
1634*139c1837SPaolo Bonzini        = { .args_ct_str = { "r", "rZ", "rZ" } };
1635*139c1837SPaolo Bonzini    static const TCGTargetOpDef r_rZ_rZ_rZ_rZ
1636*139c1837SPaolo Bonzini        = { .args_ct_str = { "r", "rZ", "rZ", "rZ", "rZ" } };
1637*139c1837SPaolo Bonzini    static const TCGTargetOpDef r_L
1638*139c1837SPaolo Bonzini        = { .args_ct_str = { "r", "L" } };
1639*139c1837SPaolo Bonzini    static const TCGTargetOpDef r_r_L
1640*139c1837SPaolo Bonzini        = { .args_ct_str = { "r", "r", "L" } };
1641*139c1837SPaolo Bonzini    static const TCGTargetOpDef r_L_L
1642*139c1837SPaolo Bonzini        = { .args_ct_str = { "r", "L", "L" } };
1643*139c1837SPaolo Bonzini    static const TCGTargetOpDef r_r_L_L
1644*139c1837SPaolo Bonzini        = { .args_ct_str = { "r", "r", "L", "L" } };
1645*139c1837SPaolo Bonzini    static const TCGTargetOpDef LZ_L
1646*139c1837SPaolo Bonzini        = { .args_ct_str = { "LZ", "L" } };
1647*139c1837SPaolo Bonzini    static const TCGTargetOpDef LZ_L_L
1648*139c1837SPaolo Bonzini        = { .args_ct_str = { "LZ", "L", "L" } };
1649*139c1837SPaolo Bonzini    static const TCGTargetOpDef LZ_LZ_L
1650*139c1837SPaolo Bonzini        = { .args_ct_str = { "LZ", "LZ", "L" } };
1651*139c1837SPaolo Bonzini    static const TCGTargetOpDef LZ_LZ_L_L
1652*139c1837SPaolo Bonzini        = { .args_ct_str = { "LZ", "LZ", "L", "L" } };
1653*139c1837SPaolo Bonzini    static const TCGTargetOpDef r_r_rZ_rZ_rM_rM
1654*139c1837SPaolo Bonzini        = { .args_ct_str = { "r", "r", "rZ", "rZ", "rM", "rM" } };
1655*139c1837SPaolo Bonzini
1656*139c1837SPaolo Bonzini    switch (op) {
1657*139c1837SPaolo Bonzini    case INDEX_op_goto_ptr:
1658*139c1837SPaolo Bonzini        return &r;
1659*139c1837SPaolo Bonzini
1660*139c1837SPaolo Bonzini    case INDEX_op_ld8u_i32:
1661*139c1837SPaolo Bonzini    case INDEX_op_ld8s_i32:
1662*139c1837SPaolo Bonzini    case INDEX_op_ld16u_i32:
1663*139c1837SPaolo Bonzini    case INDEX_op_ld16s_i32:
1664*139c1837SPaolo Bonzini    case INDEX_op_ld_i32:
1665*139c1837SPaolo Bonzini    case INDEX_op_not_i32:
1666*139c1837SPaolo Bonzini    case INDEX_op_neg_i32:
1667*139c1837SPaolo Bonzini    case INDEX_op_ld8u_i64:
1668*139c1837SPaolo Bonzini    case INDEX_op_ld8s_i64:
1669*139c1837SPaolo Bonzini    case INDEX_op_ld16u_i64:
1670*139c1837SPaolo Bonzini    case INDEX_op_ld16s_i64:
1671*139c1837SPaolo Bonzini    case INDEX_op_ld32s_i64:
1672*139c1837SPaolo Bonzini    case INDEX_op_ld32u_i64:
1673*139c1837SPaolo Bonzini    case INDEX_op_ld_i64:
1674*139c1837SPaolo Bonzini    case INDEX_op_not_i64:
1675*139c1837SPaolo Bonzini    case INDEX_op_neg_i64:
1676*139c1837SPaolo Bonzini    case INDEX_op_ext8u_i32:
1677*139c1837SPaolo Bonzini    case INDEX_op_ext8u_i64:
1678*139c1837SPaolo Bonzini    case INDEX_op_ext16u_i32:
1679*139c1837SPaolo Bonzini    case INDEX_op_ext16u_i64:
1680*139c1837SPaolo Bonzini    case INDEX_op_ext32u_i64:
1681*139c1837SPaolo Bonzini    case INDEX_op_extu_i32_i64:
1682*139c1837SPaolo Bonzini    case INDEX_op_ext8s_i32:
1683*139c1837SPaolo Bonzini    case INDEX_op_ext8s_i64:
1684*139c1837SPaolo Bonzini    case INDEX_op_ext16s_i32:
1685*139c1837SPaolo Bonzini    case INDEX_op_ext16s_i64:
1686*139c1837SPaolo Bonzini    case INDEX_op_ext32s_i64:
1687*139c1837SPaolo Bonzini    case INDEX_op_extrl_i64_i32:
1688*139c1837SPaolo Bonzini    case INDEX_op_extrh_i64_i32:
1689*139c1837SPaolo Bonzini    case INDEX_op_ext_i32_i64:
1690*139c1837SPaolo Bonzini        return &r_r;
1691*139c1837SPaolo Bonzini
1692*139c1837SPaolo Bonzini    case INDEX_op_st8_i32:
1693*139c1837SPaolo Bonzini    case INDEX_op_st16_i32:
1694*139c1837SPaolo Bonzini    case INDEX_op_st_i32:
1695*139c1837SPaolo Bonzini    case INDEX_op_st8_i64:
1696*139c1837SPaolo Bonzini    case INDEX_op_st16_i64:
1697*139c1837SPaolo Bonzini    case INDEX_op_st32_i64:
1698*139c1837SPaolo Bonzini    case INDEX_op_st_i64:
1699*139c1837SPaolo Bonzini        return &rZ_r;
1700*139c1837SPaolo Bonzini
1701*139c1837SPaolo Bonzini    case INDEX_op_add_i32:
1702*139c1837SPaolo Bonzini    case INDEX_op_and_i32:
1703*139c1837SPaolo Bonzini    case INDEX_op_or_i32:
1704*139c1837SPaolo Bonzini    case INDEX_op_xor_i32:
1705*139c1837SPaolo Bonzini    case INDEX_op_add_i64:
1706*139c1837SPaolo Bonzini    case INDEX_op_and_i64:
1707*139c1837SPaolo Bonzini    case INDEX_op_or_i64:
1708*139c1837SPaolo Bonzini    case INDEX_op_xor_i64:
1709*139c1837SPaolo Bonzini        return &r_r_rI;
1710*139c1837SPaolo Bonzini
1711*139c1837SPaolo Bonzini    case INDEX_op_sub_i32:
1712*139c1837SPaolo Bonzini    case INDEX_op_sub_i64:
1713*139c1837SPaolo Bonzini        return &r_rZ_rN;
1714*139c1837SPaolo Bonzini
1715*139c1837SPaolo Bonzini    case INDEX_op_mul_i32:
1716*139c1837SPaolo Bonzini    case INDEX_op_mulsh_i32:
1717*139c1837SPaolo Bonzini    case INDEX_op_muluh_i32:
1718*139c1837SPaolo Bonzini    case INDEX_op_div_i32:
1719*139c1837SPaolo Bonzini    case INDEX_op_divu_i32:
1720*139c1837SPaolo Bonzini    case INDEX_op_rem_i32:
1721*139c1837SPaolo Bonzini    case INDEX_op_remu_i32:
1722*139c1837SPaolo Bonzini    case INDEX_op_setcond_i32:
1723*139c1837SPaolo Bonzini    case INDEX_op_mul_i64:
1724*139c1837SPaolo Bonzini    case INDEX_op_mulsh_i64:
1725*139c1837SPaolo Bonzini    case INDEX_op_muluh_i64:
1726*139c1837SPaolo Bonzini    case INDEX_op_div_i64:
1727*139c1837SPaolo Bonzini    case INDEX_op_divu_i64:
1728*139c1837SPaolo Bonzini    case INDEX_op_rem_i64:
1729*139c1837SPaolo Bonzini    case INDEX_op_remu_i64:
1730*139c1837SPaolo Bonzini    case INDEX_op_setcond_i64:
1731*139c1837SPaolo Bonzini        return &r_rZ_rZ;
1732*139c1837SPaolo Bonzini
1733*139c1837SPaolo Bonzini    case INDEX_op_shl_i32:
1734*139c1837SPaolo Bonzini    case INDEX_op_shr_i32:
1735*139c1837SPaolo Bonzini    case INDEX_op_sar_i32:
1736*139c1837SPaolo Bonzini    case INDEX_op_shl_i64:
1737*139c1837SPaolo Bonzini    case INDEX_op_shr_i64:
1738*139c1837SPaolo Bonzini    case INDEX_op_sar_i64:
1739*139c1837SPaolo Bonzini        return &r_r_ri;
1740*139c1837SPaolo Bonzini
1741*139c1837SPaolo Bonzini    case INDEX_op_brcond_i32:
1742*139c1837SPaolo Bonzini    case INDEX_op_brcond_i64:
1743*139c1837SPaolo Bonzini        return &rZ_rZ;
1744*139c1837SPaolo Bonzini
1745*139c1837SPaolo Bonzini    case INDEX_op_add2_i32:
1746*139c1837SPaolo Bonzini    case INDEX_op_add2_i64:
1747*139c1837SPaolo Bonzini    case INDEX_op_sub2_i32:
1748*139c1837SPaolo Bonzini    case INDEX_op_sub2_i64:
1749*139c1837SPaolo Bonzini        return &r_r_rZ_rZ_rM_rM;
1750*139c1837SPaolo Bonzini
1751*139c1837SPaolo Bonzini    case INDEX_op_brcond2_i32:
1752*139c1837SPaolo Bonzini        return &rZ_rZ_rZ_rZ;
1753*139c1837SPaolo Bonzini
1754*139c1837SPaolo Bonzini    case INDEX_op_setcond2_i32:
1755*139c1837SPaolo Bonzini        return &r_rZ_rZ_rZ_rZ;
1756*139c1837SPaolo Bonzini
1757*139c1837SPaolo Bonzini    case INDEX_op_qemu_ld_i32:
1758*139c1837SPaolo Bonzini        return TARGET_LONG_BITS <= TCG_TARGET_REG_BITS ? &r_L : &r_L_L;
1759*139c1837SPaolo Bonzini    case INDEX_op_qemu_st_i32:
1760*139c1837SPaolo Bonzini        return TARGET_LONG_BITS <= TCG_TARGET_REG_BITS ? &LZ_L : &LZ_L_L;
1761*139c1837SPaolo Bonzini    case INDEX_op_qemu_ld_i64:
1762*139c1837SPaolo Bonzini        return TCG_TARGET_REG_BITS == 64 ? &r_L
1763*139c1837SPaolo Bonzini               : TARGET_LONG_BITS <= TCG_TARGET_REG_BITS ? &r_r_L
1764*139c1837SPaolo Bonzini               : &r_r_L_L;
1765*139c1837SPaolo Bonzini    case INDEX_op_qemu_st_i64:
1766*139c1837SPaolo Bonzini        return TCG_TARGET_REG_BITS == 64 ? &LZ_L
1767*139c1837SPaolo Bonzini               : TARGET_LONG_BITS <= TCG_TARGET_REG_BITS ? &LZ_LZ_L
1768*139c1837SPaolo Bonzini               : &LZ_LZ_L_L;
1769*139c1837SPaolo Bonzini
1770*139c1837SPaolo Bonzini    default:
1771*139c1837SPaolo Bonzini        return NULL;
1772*139c1837SPaolo Bonzini    }
1773*139c1837SPaolo Bonzini}
1774*139c1837SPaolo Bonzini
1775*139c1837SPaolo Bonzinistatic const int tcg_target_callee_save_regs[] = {
1776*139c1837SPaolo Bonzini    TCG_REG_S0,       /* used for the global env (TCG_AREG0) */
1777*139c1837SPaolo Bonzini    TCG_REG_S1,
1778*139c1837SPaolo Bonzini    TCG_REG_S2,
1779*139c1837SPaolo Bonzini    TCG_REG_S3,
1780*139c1837SPaolo Bonzini    TCG_REG_S4,
1781*139c1837SPaolo Bonzini    TCG_REG_S5,
1782*139c1837SPaolo Bonzini    TCG_REG_S6,
1783*139c1837SPaolo Bonzini    TCG_REG_S7,
1784*139c1837SPaolo Bonzini    TCG_REG_S8,
1785*139c1837SPaolo Bonzini    TCG_REG_S9,
1786*139c1837SPaolo Bonzini    TCG_REG_S10,
1787*139c1837SPaolo Bonzini    TCG_REG_S11,
1788*139c1837SPaolo Bonzini    TCG_REG_RA,       /* should be last for ABI compliance */
1789*139c1837SPaolo Bonzini};
1790*139c1837SPaolo Bonzini
1791*139c1837SPaolo Bonzini/* Stack frame parameters.  */
1792*139c1837SPaolo Bonzini#define REG_SIZE   (TCG_TARGET_REG_BITS / 8)
1793*139c1837SPaolo Bonzini#define SAVE_SIZE  ((int)ARRAY_SIZE(tcg_target_callee_save_regs) * REG_SIZE)
1794*139c1837SPaolo Bonzini#define TEMP_SIZE  (CPU_TEMP_BUF_NLONGS * (int)sizeof(long))
1795*139c1837SPaolo Bonzini#define FRAME_SIZE ((TCG_STATIC_CALL_ARGS_SIZE + TEMP_SIZE + SAVE_SIZE \
1796*139c1837SPaolo Bonzini                     + TCG_TARGET_STACK_ALIGN - 1) \
1797*139c1837SPaolo Bonzini                    & -TCG_TARGET_STACK_ALIGN)
1798*139c1837SPaolo Bonzini#define SAVE_OFS   (TCG_STATIC_CALL_ARGS_SIZE + TEMP_SIZE)
1799*139c1837SPaolo Bonzini
1800*139c1837SPaolo Bonzini/* We're expecting to be able to use an immediate for frame allocation.  */
1801*139c1837SPaolo BonziniQEMU_BUILD_BUG_ON(FRAME_SIZE > 0x7ff);
1802*139c1837SPaolo Bonzini
1803*139c1837SPaolo Bonzini/* Generate global QEMU prologue and epilogue code */
1804*139c1837SPaolo Bonzinistatic void tcg_target_qemu_prologue(TCGContext *s)
1805*139c1837SPaolo Bonzini{
1806*139c1837SPaolo Bonzini    int i;
1807*139c1837SPaolo Bonzini
1808*139c1837SPaolo Bonzini    tcg_set_frame(s, TCG_REG_SP, TCG_STATIC_CALL_ARGS_SIZE, TEMP_SIZE);
1809*139c1837SPaolo Bonzini
1810*139c1837SPaolo Bonzini    /* TB prologue */
1811*139c1837SPaolo Bonzini    tcg_out_opc_imm(s, OPC_ADDI, TCG_REG_SP, TCG_REG_SP, -FRAME_SIZE);
1812*139c1837SPaolo Bonzini    for (i = 0; i < ARRAY_SIZE(tcg_target_callee_save_regs); i++) {
1813*139c1837SPaolo Bonzini        tcg_out_st(s, TCG_TYPE_REG, tcg_target_callee_save_regs[i],
1814*139c1837SPaolo Bonzini                   TCG_REG_SP, SAVE_OFS + i * REG_SIZE);
1815*139c1837SPaolo Bonzini    }
1816*139c1837SPaolo Bonzini
1817*139c1837SPaolo Bonzini#if !defined(CONFIG_SOFTMMU)
1818*139c1837SPaolo Bonzini    tcg_out_movi(s, TCG_TYPE_PTR, TCG_GUEST_BASE_REG, guest_base);
1819*139c1837SPaolo Bonzini    tcg_regset_set_reg(s->reserved_regs, TCG_GUEST_BASE_REG);
1820*139c1837SPaolo Bonzini#endif
1821*139c1837SPaolo Bonzini
1822*139c1837SPaolo Bonzini    /* Call generated code */
1823*139c1837SPaolo Bonzini    tcg_out_mov(s, TCG_TYPE_PTR, TCG_AREG0, tcg_target_call_iarg_regs[0]);
1824*139c1837SPaolo Bonzini    tcg_out_opc_imm(s, OPC_JALR, TCG_REG_ZERO, tcg_target_call_iarg_regs[1], 0);
1825*139c1837SPaolo Bonzini
1826*139c1837SPaolo Bonzini    /* Return path for goto_ptr. Set return value to 0 */
1827*139c1837SPaolo Bonzini    s->code_gen_epilogue = s->code_ptr;
1828*139c1837SPaolo Bonzini    tcg_out_mov(s, TCG_TYPE_REG, TCG_REG_A0, TCG_REG_ZERO);
1829*139c1837SPaolo Bonzini
1830*139c1837SPaolo Bonzini    /* TB epilogue */
1831*139c1837SPaolo Bonzini    tb_ret_addr = s->code_ptr;
1832*139c1837SPaolo Bonzini    for (i = 0; i < ARRAY_SIZE(tcg_target_callee_save_regs); i++) {
1833*139c1837SPaolo Bonzini        tcg_out_ld(s, TCG_TYPE_REG, tcg_target_callee_save_regs[i],
1834*139c1837SPaolo Bonzini                   TCG_REG_SP, SAVE_OFS + i * REG_SIZE);
1835*139c1837SPaolo Bonzini    }
1836*139c1837SPaolo Bonzini
1837*139c1837SPaolo Bonzini    tcg_out_opc_imm(s, OPC_ADDI, TCG_REG_SP, TCG_REG_SP, FRAME_SIZE);
1838*139c1837SPaolo Bonzini    tcg_out_opc_imm(s, OPC_JALR, TCG_REG_ZERO, TCG_REG_RA, 0);
1839*139c1837SPaolo Bonzini}
1840*139c1837SPaolo Bonzini
1841*139c1837SPaolo Bonzinistatic void tcg_target_init(TCGContext *s)
1842*139c1837SPaolo Bonzini{
1843*139c1837SPaolo Bonzini    tcg_target_available_regs[TCG_TYPE_I32] = 0xffffffff;
1844*139c1837SPaolo Bonzini    if (TCG_TARGET_REG_BITS == 64) {
1845*139c1837SPaolo Bonzini        tcg_target_available_regs[TCG_TYPE_I64] = 0xffffffff;
1846*139c1837SPaolo Bonzini    }
1847*139c1837SPaolo Bonzini
1848*139c1837SPaolo Bonzini    tcg_target_call_clobber_regs = -1u;
1849*139c1837SPaolo Bonzini    tcg_regset_reset_reg(tcg_target_call_clobber_regs, TCG_REG_S0);
1850*139c1837SPaolo Bonzini    tcg_regset_reset_reg(tcg_target_call_clobber_regs, TCG_REG_S1);
1851*139c1837SPaolo Bonzini    tcg_regset_reset_reg(tcg_target_call_clobber_regs, TCG_REG_S2);
1852*139c1837SPaolo Bonzini    tcg_regset_reset_reg(tcg_target_call_clobber_regs, TCG_REG_S3);
1853*139c1837SPaolo Bonzini    tcg_regset_reset_reg(tcg_target_call_clobber_regs, TCG_REG_S4);
1854*139c1837SPaolo Bonzini    tcg_regset_reset_reg(tcg_target_call_clobber_regs, TCG_REG_S5);
1855*139c1837SPaolo Bonzini    tcg_regset_reset_reg(tcg_target_call_clobber_regs, TCG_REG_S6);
1856*139c1837SPaolo Bonzini    tcg_regset_reset_reg(tcg_target_call_clobber_regs, TCG_REG_S7);
1857*139c1837SPaolo Bonzini    tcg_regset_reset_reg(tcg_target_call_clobber_regs, TCG_REG_S8);
1858*139c1837SPaolo Bonzini    tcg_regset_reset_reg(tcg_target_call_clobber_regs, TCG_REG_S9);
1859*139c1837SPaolo Bonzini    tcg_regset_reset_reg(tcg_target_call_clobber_regs, TCG_REG_S10);
1860*139c1837SPaolo Bonzini    tcg_regset_reset_reg(tcg_target_call_clobber_regs, TCG_REG_S11);
1861*139c1837SPaolo Bonzini
1862*139c1837SPaolo Bonzini    s->reserved_regs = 0;
1863*139c1837SPaolo Bonzini    tcg_regset_set_reg(s->reserved_regs, TCG_REG_ZERO);
1864*139c1837SPaolo Bonzini    tcg_regset_set_reg(s->reserved_regs, TCG_REG_TMP0);
1865*139c1837SPaolo Bonzini    tcg_regset_set_reg(s->reserved_regs, TCG_REG_TMP1);
1866*139c1837SPaolo Bonzini    tcg_regset_set_reg(s->reserved_regs, TCG_REG_TMP2);
1867*139c1837SPaolo Bonzini    tcg_regset_set_reg(s->reserved_regs, TCG_REG_SP);
1868*139c1837SPaolo Bonzini    tcg_regset_set_reg(s->reserved_regs, TCG_REG_GP);
1869*139c1837SPaolo Bonzini    tcg_regset_set_reg(s->reserved_regs, TCG_REG_TP);
1870*139c1837SPaolo Bonzini}
1871*139c1837SPaolo Bonzini
1872*139c1837SPaolo Bonzinitypedef struct {
1873*139c1837SPaolo Bonzini    DebugFrameHeader h;
1874*139c1837SPaolo Bonzini    uint8_t fde_def_cfa[4];
1875*139c1837SPaolo Bonzini    uint8_t fde_reg_ofs[ARRAY_SIZE(tcg_target_callee_save_regs) * 2];
1876*139c1837SPaolo Bonzini} DebugFrame;
1877*139c1837SPaolo Bonzini
1878*139c1837SPaolo Bonzini#define ELF_HOST_MACHINE EM_RISCV
1879*139c1837SPaolo Bonzini
1880*139c1837SPaolo Bonzinistatic const DebugFrame debug_frame = {
1881*139c1837SPaolo Bonzini    .h.cie.len = sizeof(DebugFrameCIE) - 4, /* length after .len member */
1882*139c1837SPaolo Bonzini    .h.cie.id = -1,
1883*139c1837SPaolo Bonzini    .h.cie.version = 1,
1884*139c1837SPaolo Bonzini    .h.cie.code_align = 1,
1885*139c1837SPaolo Bonzini    .h.cie.data_align = -(TCG_TARGET_REG_BITS / 8) & 0x7f, /* sleb128 */
1886*139c1837SPaolo Bonzini    .h.cie.return_column = TCG_REG_RA,
1887*139c1837SPaolo Bonzini
1888*139c1837SPaolo Bonzini    /* Total FDE size does not include the "len" member.  */
1889*139c1837SPaolo Bonzini    .h.fde.len = sizeof(DebugFrame) - offsetof(DebugFrame, h.fde.cie_offset),
1890*139c1837SPaolo Bonzini
1891*139c1837SPaolo Bonzini    .fde_def_cfa = {
1892*139c1837SPaolo Bonzini        12, TCG_REG_SP,                 /* DW_CFA_def_cfa sp, ... */
1893*139c1837SPaolo Bonzini        (FRAME_SIZE & 0x7f) | 0x80,     /* ... uleb128 FRAME_SIZE */
1894*139c1837SPaolo Bonzini        (FRAME_SIZE >> 7)
1895*139c1837SPaolo Bonzini    },
1896*139c1837SPaolo Bonzini    .fde_reg_ofs = {
1897*139c1837SPaolo Bonzini        0x80 + 9,  12,                  /* DW_CFA_offset, s1,  -96 */
1898*139c1837SPaolo Bonzini        0x80 + 18, 11,                  /* DW_CFA_offset, s2,  -88 */
1899*139c1837SPaolo Bonzini        0x80 + 19, 10,                  /* DW_CFA_offset, s3,  -80 */
1900*139c1837SPaolo Bonzini        0x80 + 20, 9,                   /* DW_CFA_offset, s4,  -72 */
1901*139c1837SPaolo Bonzini        0x80 + 21, 8,                   /* DW_CFA_offset, s5,  -64 */
1902*139c1837SPaolo Bonzini        0x80 + 22, 7,                   /* DW_CFA_offset, s6,  -56 */
1903*139c1837SPaolo Bonzini        0x80 + 23, 6,                   /* DW_CFA_offset, s7,  -48 */
1904*139c1837SPaolo Bonzini        0x80 + 24, 5,                   /* DW_CFA_offset, s8,  -40 */
1905*139c1837SPaolo Bonzini        0x80 + 25, 4,                   /* DW_CFA_offset, s9,  -32 */
1906*139c1837SPaolo Bonzini        0x80 + 26, 3,                   /* DW_CFA_offset, s10, -24 */
1907*139c1837SPaolo Bonzini        0x80 + 27, 2,                   /* DW_CFA_offset, s11, -16 */
1908*139c1837SPaolo Bonzini        0x80 + 1 , 1,                   /* DW_CFA_offset, ra,  -8 */
1909*139c1837SPaolo Bonzini    }
1910*139c1837SPaolo Bonzini};
1911*139c1837SPaolo Bonzini
1912*139c1837SPaolo Bonzinivoid tcg_register_jit(void *buf, size_t buf_size)
1913*139c1837SPaolo Bonzini{
1914*139c1837SPaolo Bonzini    tcg_register_jit_int(buf, buf_size, &debug_frame, sizeof(debug_frame));
1915*139c1837SPaolo Bonzini}
1916