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