]> git.proxmox.com Git - mirror_qemu.git/blame - tcg/riscv/tcg-target.inc.c
tcg/riscv: Add support for the constraints
[mirror_qemu.git] / tcg / riscv / tcg-target.inc.c
CommitLineData
505e75c5
AF
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.inc.c"
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};
8ce23a13
AF
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->ct |= TCG_CT_REG;
141 ct->u.regs = 0xffffffff;
142 break;
143 case 'L':
144 /* qemu_ld/qemu_st constraint */
145 ct->ct |= TCG_CT_REG;
146 ct->u.regs = 0xffffffff;
147 /* qemu_ld/qemu_st uses TCG_REG_TMP0 */
148#if defined(CONFIG_SOFTMMU)
149 tcg_regset_reset_reg(ct->u.regs, tcg_target_call_iarg_regs[0]);
150 tcg_regset_reset_reg(ct->u.regs, tcg_target_call_iarg_regs[1]);
151 tcg_regset_reset_reg(ct->u.regs, tcg_target_call_iarg_regs[2]);
152 tcg_regset_reset_reg(ct->u.regs, tcg_target_call_iarg_regs[3]);
153 tcg_regset_reset_reg(ct->u.regs, tcg_target_call_iarg_regs[4]);
154#endif
155 break;
156 case 'I':
157 ct->ct |= TCG_CT_CONST_S12;
158 break;
159 case 'N':
160 ct->ct |= TCG_CT_CONST_N12;
161 break;
162 case 'M':
163 ct->ct |= TCG_CT_CONST_M12;
164 break;
165 case 'Z':
166 /* we can use a zero immediate as a zero register argument. */
167 ct->ct |= TCG_CT_CONST_ZERO;
168 break;
169 default:
170 return NULL;
171 }
172 return ct_str;
173}
174
175/* test if a constant matches the constraint */
176static int tcg_target_const_match(tcg_target_long val, TCGType type,
177 const TCGArgConstraint *arg_ct)
178{
179 int ct = arg_ct->ct;
180 if (ct & TCG_CT_CONST) {
181 return 1;
182 }
183 if ((ct & TCG_CT_CONST_ZERO) && val == 0) {
184 return 1;
185 }
186 if ((ct & TCG_CT_CONST_S12) && val == sextreg(val, 0, 12)) {
187 return 1;
188 }
189 if ((ct & TCG_CT_CONST_N12) && -val == sextreg(-val, 0, 12)) {
190 return 1;
191 }
192 if ((ct & TCG_CT_CONST_M12) && val >= -0xfff && val <= 0xfff) {
193 return 1;
194 }
195 return 0;
196}
197
198/*
199 * RISC-V Base ISA opcodes (IM)
200 */
201
202typedef enum {
203 OPC_ADD = 0x33,
204 OPC_ADDI = 0x13,
205 OPC_AND = 0x7033,
206 OPC_ANDI = 0x7013,
207 OPC_AUIPC = 0x17,
208 OPC_BEQ = 0x63,
209 OPC_BGE = 0x5063,
210 OPC_BGEU = 0x7063,
211 OPC_BLT = 0x4063,
212 OPC_BLTU = 0x6063,
213 OPC_BNE = 0x1063,
214 OPC_DIV = 0x2004033,
215 OPC_DIVU = 0x2005033,
216 OPC_JAL = 0x6f,
217 OPC_JALR = 0x67,
218 OPC_LB = 0x3,
219 OPC_LBU = 0x4003,
220 OPC_LD = 0x3003,
221 OPC_LH = 0x1003,
222 OPC_LHU = 0x5003,
223 OPC_LUI = 0x37,
224 OPC_LW = 0x2003,
225 OPC_LWU = 0x6003,
226 OPC_MUL = 0x2000033,
227 OPC_MULH = 0x2001033,
228 OPC_MULHSU = 0x2002033,
229 OPC_MULHU = 0x2003033,
230 OPC_OR = 0x6033,
231 OPC_ORI = 0x6013,
232 OPC_REM = 0x2006033,
233 OPC_REMU = 0x2007033,
234 OPC_SB = 0x23,
235 OPC_SD = 0x3023,
236 OPC_SH = 0x1023,
237 OPC_SLL = 0x1033,
238 OPC_SLLI = 0x1013,
239 OPC_SLT = 0x2033,
240 OPC_SLTI = 0x2013,
241 OPC_SLTIU = 0x3013,
242 OPC_SLTU = 0x3033,
243 OPC_SRA = 0x40005033,
244 OPC_SRAI = 0x40005013,
245 OPC_SRL = 0x5033,
246 OPC_SRLI = 0x5013,
247 OPC_SUB = 0x40000033,
248 OPC_SW = 0x2023,
249 OPC_XOR = 0x4033,
250 OPC_XORI = 0x4013,
251
252#if TCG_TARGET_REG_BITS == 64
253 OPC_ADDIW = 0x1b,
254 OPC_ADDW = 0x3b,
255 OPC_DIVUW = 0x200503b,
256 OPC_DIVW = 0x200403b,
257 OPC_MULW = 0x200003b,
258 OPC_REMUW = 0x200703b,
259 OPC_REMW = 0x200603b,
260 OPC_SLLIW = 0x101b,
261 OPC_SLLW = 0x103b,
262 OPC_SRAIW = 0x4000501b,
263 OPC_SRAW = 0x4000503b,
264 OPC_SRLIW = 0x501b,
265 OPC_SRLW = 0x503b,
266 OPC_SUBW = 0x4000003b,
267#else
268 /* Simplify code throughout by defining aliases for RV32. */
269 OPC_ADDIW = OPC_ADDI,
270 OPC_ADDW = OPC_ADD,
271 OPC_DIVUW = OPC_DIVU,
272 OPC_DIVW = OPC_DIV,
273 OPC_MULW = OPC_MUL,
274 OPC_REMUW = OPC_REMU,
275 OPC_REMW = OPC_REM,
276 OPC_SLLIW = OPC_SLLI,
277 OPC_SLLW = OPC_SLL,
278 OPC_SRAIW = OPC_SRAI,
279 OPC_SRAW = OPC_SRA,
280 OPC_SRLIW = OPC_SRLI,
281 OPC_SRLW = OPC_SRL,
282 OPC_SUBW = OPC_SUB,
283#endif
284
285 OPC_FENCE = 0x0000000f,
286} RISCVInsn;