]> git.proxmox.com Git - mirror_qemu.git/blame - tcg/riscv/tcg-target.inc.c
tcg/riscv: Add the relocation functions
[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;
54a9ce0f
AF
287
288/*
289 * RISC-V immediate and instruction encoders (excludes 16-bit RVC)
290 */
291
292/* Type-R */
293
294static int32_t encode_r(RISCVInsn opc, TCGReg rd, TCGReg rs1, TCGReg rs2)
295{
296 return opc | (rd & 0x1f) << 7 | (rs1 & 0x1f) << 15 | (rs2 & 0x1f) << 20;
297}
298
299/* Type-I */
300
301static int32_t encode_imm12(uint32_t imm)
302{
303 return (imm & 0xfff) << 20;
304}
305
306static int32_t encode_i(RISCVInsn opc, TCGReg rd, TCGReg rs1, uint32_t imm)
307{
308 return opc | (rd & 0x1f) << 7 | (rs1 & 0x1f) << 15 | encode_imm12(imm);
309}
310
311/* Type-S */
312
313static int32_t encode_simm12(uint32_t imm)
314{
315 int32_t ret = 0;
316
317 ret |= (imm & 0xFE0) << 20;
318 ret |= (imm & 0x1F) << 7;
319
320 return ret;
321}
322
323static int32_t encode_s(RISCVInsn opc, TCGReg rs1, TCGReg rs2, uint32_t imm)
324{
325 return opc | (rs1 & 0x1f) << 15 | (rs2 & 0x1f) << 20 | encode_simm12(imm);
326}
327
328/* Type-SB */
329
330static int32_t encode_sbimm12(uint32_t imm)
331{
332 int32_t ret = 0;
333
334 ret |= (imm & 0x1000) << 19;
335 ret |= (imm & 0x7e0) << 20;
336 ret |= (imm & 0x1e) << 7;
337 ret |= (imm & 0x800) >> 4;
338
339 return ret;
340}
341
342static int32_t encode_sb(RISCVInsn opc, TCGReg rs1, TCGReg rs2, uint32_t imm)
343{
344 return opc | (rs1 & 0x1f) << 15 | (rs2 & 0x1f) << 20 | encode_sbimm12(imm);
345}
346
347/* Type-U */
348
349static int32_t encode_uimm20(uint32_t imm)
350{
351 return imm & 0xfffff000;
352}
353
354static int32_t encode_u(RISCVInsn opc, TCGReg rd, uint32_t imm)
355{
356 return opc | (rd & 0x1f) << 7 | encode_uimm20(imm);
357}
358
359/* Type-UJ */
360
361static int32_t encode_ujimm20(uint32_t imm)
362{
363 int32_t ret = 0;
364
365 ret |= (imm & 0x0007fe) << (21 - 1);
366 ret |= (imm & 0x000800) << (20 - 11);
367 ret |= (imm & 0x0ff000) << (12 - 12);
368 ret |= (imm & 0x100000) << (31 - 20);
369
370 return ret;
371}
372
373static int32_t encode_uj(RISCVInsn opc, TCGReg rd, uint32_t imm)
374{
375 return opc | (rd & 0x1f) << 7 | encode_ujimm20(imm);
376}
bedf14e3
AF
377
378/*
379 * RISC-V instruction emitters
380 */
381
382static void tcg_out_opc_reg(TCGContext *s, RISCVInsn opc,
383 TCGReg rd, TCGReg rs1, TCGReg rs2)
384{
385 tcg_out32(s, encode_r(opc, rd, rs1, rs2));
386}
387
388static void tcg_out_opc_imm(TCGContext *s, RISCVInsn opc,
389 TCGReg rd, TCGReg rs1, TCGArg imm)
390{
391 tcg_out32(s, encode_i(opc, rd, rs1, imm));
392}
393
394static void tcg_out_opc_store(TCGContext *s, RISCVInsn opc,
395 TCGReg rs1, TCGReg rs2, uint32_t imm)
396{
397 tcg_out32(s, encode_s(opc, rs1, rs2, imm));
398}
399
400static void tcg_out_opc_branch(TCGContext *s, RISCVInsn opc,
401 TCGReg rs1, TCGReg rs2, uint32_t imm)
402{
403 tcg_out32(s, encode_sb(opc, rs1, rs2, imm));
404}
405
406static void tcg_out_opc_upper(TCGContext *s, RISCVInsn opc,
407 TCGReg rd, uint32_t imm)
408{
409 tcg_out32(s, encode_u(opc, rd, imm));
410}
411
412static void tcg_out_opc_jump(TCGContext *s, RISCVInsn opc,
413 TCGReg rd, uint32_t imm)
414{
415 tcg_out32(s, encode_uj(opc, rd, imm));
416}
417
418static void tcg_out_nop_fill(tcg_insn_unit *p, int count)
419{
420 int i;
421 for (i = 0; i < count; ++i) {
422 p[i] = encode_i(OPC_ADDI, TCG_REG_ZERO, TCG_REG_ZERO, 0);
423 }
424}
dfa8e74f
AF
425
426/*
427 * Relocations
428 */
429
430static bool reloc_sbimm12(tcg_insn_unit *code_ptr, tcg_insn_unit *target)
431{
432 intptr_t offset = (intptr_t)target - (intptr_t)code_ptr;
433
434 if (offset == sextreg(offset, 1, 12) << 1) {
435 code_ptr[0] |= encode_sbimm12(offset);
436 return true;
437 }
438
439 return false;
440}
441
442static bool reloc_jimm20(tcg_insn_unit *code_ptr, tcg_insn_unit *target)
443{
444 intptr_t offset = (intptr_t)target - (intptr_t)code_ptr;
445
446 if (offset == sextreg(offset, 1, 20) << 1) {
447 code_ptr[0] |= encode_ujimm20(offset);
448 return true;
449 }
450
451 return false;
452}
453
454static bool reloc_call(tcg_insn_unit *code_ptr, tcg_insn_unit *target)
455{
456 intptr_t offset = (intptr_t)target - (intptr_t)code_ptr;
457 int32_t lo = sextreg(offset, 0, 12);
458 int32_t hi = offset - lo;
459
460 if (offset == hi + lo) {
461 code_ptr[0] |= encode_uimm20(hi);
462 code_ptr[1] |= encode_imm12(lo);
463 return true;
464 }
465
466 return false;
467}
468
469static bool patch_reloc(tcg_insn_unit *code_ptr, int type,
470 intptr_t value, intptr_t addend)
471{
472 uint32_t insn = *code_ptr;
473 intptr_t diff;
474 bool short_jmp;
475
476 tcg_debug_assert(addend == 0);
477
478 switch (type) {
479 case R_RISCV_BRANCH:
480 diff = value - (uintptr_t)code_ptr;
481 short_jmp = diff == sextreg(diff, 0, 12);
482 if (short_jmp) {
483 return reloc_sbimm12(code_ptr, (tcg_insn_unit *)value);
484 } else {
485 /* Invert the condition */
486 insn = insn ^ (1 << 12);
487 /* Clear the offset */
488 insn &= 0x01fff07f;
489 /* Set the offset to the PC + 8 */
490 insn |= encode_sbimm12(8);
491
492 /* Move forward */
493 code_ptr[0] = insn;
494
495 /* Overwrite the NOP with jal x0,value */
496 diff = value - (uintptr_t)(code_ptr + 1);
497 insn = encode_uj(OPC_JAL, TCG_REG_ZERO, diff);
498 code_ptr[1] = insn;
499
500 return true;
501 }
502 break;
503 case R_RISCV_JAL:
504 return reloc_jimm20(code_ptr, (tcg_insn_unit *)value);
505 break;
506 case R_RISCV_CALL:
507 return reloc_call(code_ptr, (tcg_insn_unit *)value);
508 break;
509 default:
510 tcg_abort();
511 }
512}