]> git.proxmox.com Git - mirror_qemu.git/blame - tcg/aarch64/tcg-target.c
tcg-aarch64: Use tcg_out_call for qemu_ld/st
[mirror_qemu.git] / tcg / aarch64 / tcg-target.c
CommitLineData
4a136e0a
CF
1/*
2 * Initial TCG Implementation for aarch64
3 *
4 * Copyright (c) 2013 Huawei Technologies Duesseldorf GmbH
5 * Written by Claudio Fontana
6 *
7 * This work is licensed under the terms of the GNU GPL, version 2 or
8 * (at your option) any later version.
9 *
10 * See the COPYING file in the top-level directory for details.
11 */
12
9ecefc84 13#include "tcg-be-ldst.h"
4a136e0a
CF
14#include "qemu/bitops.h"
15
7763ffa0
RH
16/* We're going to re-use TCGType in setting of the SF bit, which controls
17 the size of the operation performed. If we know the values match, it
18 makes things much cleaner. */
19QEMU_BUILD_BUG_ON(TCG_TYPE_I32 != 0 || TCG_TYPE_I64 != 1);
20
4a136e0a
CF
21#ifndef NDEBUG
22static const char * const tcg_target_reg_names[TCG_TARGET_NB_REGS] = {
23 "%x0", "%x1", "%x2", "%x3", "%x4", "%x5", "%x6", "%x7",
24 "%x8", "%x9", "%x10", "%x11", "%x12", "%x13", "%x14", "%x15",
25 "%x16", "%x17", "%x18", "%x19", "%x20", "%x21", "%x22", "%x23",
d82b78e4 26 "%x24", "%x25", "%x26", "%x27", "%x28", "%fp", "%x30", "%sp",
4a136e0a
CF
27};
28#endif /* NDEBUG */
29
6a91c7c9
JK
30#ifdef TARGET_WORDS_BIGENDIAN
31 #define TCG_LDST_BSWAP 1
32#else
33 #define TCG_LDST_BSWAP 0
34#endif
35
4a136e0a
CF
36static const int tcg_target_reg_alloc_order[] = {
37 TCG_REG_X20, TCG_REG_X21, TCG_REG_X22, TCG_REG_X23,
38 TCG_REG_X24, TCG_REG_X25, TCG_REG_X26, TCG_REG_X27,
6a91c7c9 39 TCG_REG_X28, /* we will reserve this for GUEST_BASE if configured */
4a136e0a 40
d82b78e4
RH
41 TCG_REG_X8, TCG_REG_X9, TCG_REG_X10, TCG_REG_X11,
42 TCG_REG_X12, TCG_REG_X13, TCG_REG_X14, TCG_REG_X15,
4a136e0a
CF
43 TCG_REG_X16, TCG_REG_X17,
44
4a136e0a
CF
45 TCG_REG_X0, TCG_REG_X1, TCG_REG_X2, TCG_REG_X3,
46 TCG_REG_X4, TCG_REG_X5, TCG_REG_X6, TCG_REG_X7,
47
d82b78e4
RH
48 /* X18 reserved by system */
49 /* X19 reserved for AREG0 */
50 /* X29 reserved as fp */
51 /* X30 reserved as temporary */
4a136e0a
CF
52};
53
54static const int tcg_target_call_iarg_regs[8] = {
55 TCG_REG_X0, TCG_REG_X1, TCG_REG_X2, TCG_REG_X3,
56 TCG_REG_X4, TCG_REG_X5, TCG_REG_X6, TCG_REG_X7
57};
58static const int tcg_target_call_oarg_regs[1] = {
59 TCG_REG_X0
60};
61
d82b78e4 62#define TCG_REG_TMP TCG_REG_X30
4a136e0a 63
6a91c7c9 64#ifndef CONFIG_SOFTMMU
d82b78e4
RH
65# ifdef CONFIG_USE_GUEST_BASE
66# define TCG_REG_GUEST_BASE TCG_REG_X28
6a91c7c9 67# else
d82b78e4 68# define TCG_REG_GUEST_BASE TCG_REG_XZR
6a91c7c9
JK
69# endif
70#endif
71
017a86f7 72static inline void reloc_pc26(void *code_ptr, intptr_t target)
4a136e0a 73{
017a86f7 74 intptr_t offset = (target - (intptr_t)code_ptr) / 4;
4a136e0a
CF
75 /* read instruction, mask away previous PC_REL26 parameter contents,
76 set the proper offset, then write back the instruction. */
017a86f7 77 uint32_t insn = *(uint32_t *)code_ptr;
4a136e0a
CF
78 insn = deposit32(insn, 0, 26, offset);
79 *(uint32_t *)code_ptr = insn;
80}
81
017a86f7 82static inline void reloc_pc19(void *code_ptr, intptr_t target)
4a136e0a 83{
017a86f7 84 intptr_t offset = (target - (intptr_t)code_ptr) / 4;
4a136e0a
CF
85 /* read instruction, mask away previous PC_REL19 parameter contents,
86 set the proper offset, then write back the instruction. */
017a86f7 87 uint32_t insn = *(uint32_t *)code_ptr;
4a136e0a
CF
88 insn = deposit32(insn, 5, 19, offset);
89 *(uint32_t *)code_ptr = insn;
90}
91
92static inline void patch_reloc(uint8_t *code_ptr, int type,
2ba7fae2 93 intptr_t value, intptr_t addend)
4a136e0a
CF
94{
95 value += addend;
96
97 switch (type) {
98 case R_AARCH64_JUMP26:
99 case R_AARCH64_CALL26:
100 reloc_pc26(code_ptr, value);
101 break;
102 case R_AARCH64_CONDBR19:
103 reloc_pc19(code_ptr, value);
104 break;
105
106 default:
107 tcg_abort();
108 }
109}
110
90f1cd91
RH
111#define TCG_CT_CONST_IS32 0x100
112#define TCG_CT_CONST_AIMM 0x200
e029f293 113#define TCG_CT_CONST_LIMM 0x400
04ce397b 114#define TCG_CT_CONST_ZERO 0x800
c6e929e7 115#define TCG_CT_CONST_MONE 0x1000
90f1cd91 116
4a136e0a
CF
117/* parse target specific constraints */
118static int target_parse_constraint(TCGArgConstraint *ct,
119 const char **pct_str)
120{
121 const char *ct_str = *pct_str;
122
123 switch (ct_str[0]) {
124 case 'r':
125 ct->ct |= TCG_CT_REG;
126 tcg_regset_set32(ct->u.regs, 0, (1ULL << TCG_TARGET_NB_REGS) - 1);
127 break;
128 case 'l': /* qemu_ld / qemu_st address, data_reg */
129 ct->ct |= TCG_CT_REG;
130 tcg_regset_set32(ct->u.regs, 0, (1ULL << TCG_TARGET_NB_REGS) - 1);
131#ifdef CONFIG_SOFTMMU
132 /* x0 and x1 will be overwritten when reading the tlb entry,
133 and x2, and x3 for helper args, better to avoid using them. */
134 tcg_regset_reset_reg(ct->u.regs, TCG_REG_X0);
135 tcg_regset_reset_reg(ct->u.regs, TCG_REG_X1);
136 tcg_regset_reset_reg(ct->u.regs, TCG_REG_X2);
137 tcg_regset_reset_reg(ct->u.regs, TCG_REG_X3);
138#endif
139 break;
90f1cd91
RH
140 case 'w': /* The operand should be considered 32-bit. */
141 ct->ct |= TCG_CT_CONST_IS32;
142 break;
143 case 'A': /* Valid for arithmetic immediate (positive or negative). */
144 ct->ct |= TCG_CT_CONST_AIMM;
145 break;
e029f293
RH
146 case 'L': /* Valid for logical immediate. */
147 ct->ct |= TCG_CT_CONST_LIMM;
148 break;
c6e929e7
RH
149 case 'M': /* minus one */
150 ct->ct |= TCG_CT_CONST_MONE;
151 break;
04ce397b
RH
152 case 'Z': /* zero */
153 ct->ct |= TCG_CT_CONST_ZERO;
154 break;
4a136e0a
CF
155 default:
156 return -1;
157 }
158
159 ct_str++;
160 *pct_str = ct_str;
161 return 0;
162}
163
90f1cd91
RH
164static inline bool is_aimm(uint64_t val)
165{
166 return (val & ~0xfff) == 0 || (val & ~0xfff000) == 0;
167}
168
e029f293
RH
169static inline bool is_limm(uint64_t val)
170{
171 /* Taking a simplified view of the logical immediates for now, ignoring
172 the replication that can happen across the field. Match bit patterns
173 of the forms
174 0....01....1
175 0..01..10..0
176 and their inverses. */
177
178 /* Make things easier below, by testing the form with msb clear. */
179 if ((int64_t)val < 0) {
180 val = ~val;
181 }
182 if (val == 0) {
183 return false;
184 }
185 val += val & -val;
186 return (val & (val - 1)) == 0;
187}
188
90f1cd91
RH
189static int tcg_target_const_match(tcg_target_long val,
190 const TCGArgConstraint *arg_ct)
4a136e0a
CF
191{
192 int ct = arg_ct->ct;
193
194 if (ct & TCG_CT_CONST) {
195 return 1;
196 }
90f1cd91
RH
197 if (ct & TCG_CT_CONST_IS32) {
198 val = (int32_t)val;
199 }
200 if ((ct & TCG_CT_CONST_AIMM) && (is_aimm(val) || is_aimm(-val))) {
201 return 1;
202 }
e029f293
RH
203 if ((ct & TCG_CT_CONST_LIMM) && is_limm(val)) {
204 return 1;
205 }
04ce397b
RH
206 if ((ct & TCG_CT_CONST_ZERO) && val == 0) {
207 return 1;
208 }
c6e929e7
RH
209 if ((ct & TCG_CT_CONST_MONE) && val == -1) {
210 return 1;
211 }
4a136e0a
CF
212
213 return 0;
214}
215
216enum aarch64_cond_code {
217 COND_EQ = 0x0,
218 COND_NE = 0x1,
219 COND_CS = 0x2, /* Unsigned greater or equal */
220 COND_HS = COND_CS, /* ALIAS greater or equal */
221 COND_CC = 0x3, /* Unsigned less than */
222 COND_LO = COND_CC, /* ALIAS Lower */
223 COND_MI = 0x4, /* Negative */
224 COND_PL = 0x5, /* Zero or greater */
225 COND_VS = 0x6, /* Overflow */
226 COND_VC = 0x7, /* No overflow */
227 COND_HI = 0x8, /* Unsigned greater than */
228 COND_LS = 0x9, /* Unsigned less or equal */
229 COND_GE = 0xa,
230 COND_LT = 0xb,
231 COND_GT = 0xc,
232 COND_LE = 0xd,
233 COND_AL = 0xe,
234 COND_NV = 0xf, /* behaves like COND_AL here */
235};
236
237static const enum aarch64_cond_code tcg_cond_to_aarch64[] = {
238 [TCG_COND_EQ] = COND_EQ,
239 [TCG_COND_NE] = COND_NE,
240 [TCG_COND_LT] = COND_LT,
241 [TCG_COND_GE] = COND_GE,
242 [TCG_COND_LE] = COND_LE,
243 [TCG_COND_GT] = COND_GT,
244 /* unsigned */
245 [TCG_COND_LTU] = COND_LO,
246 [TCG_COND_GTU] = COND_HI,
247 [TCG_COND_GEU] = COND_HS,
248 [TCG_COND_LEU] = COND_LS,
249};
250
251/* opcodes for LDR / STR instructions with base + simm9 addressing */
252enum aarch64_ldst_op_data { /* size of the data moved */
253 LDST_8 = 0x38,
254 LDST_16 = 0x78,
255 LDST_32 = 0xb8,
256 LDST_64 = 0xf8,
257};
258enum aarch64_ldst_op_type { /* type of operation */
259 LDST_ST = 0x0, /* store */
260 LDST_LD = 0x4, /* load */
261 LDST_LD_S_X = 0x8, /* load and sign-extend into Xt */
262 LDST_LD_S_W = 0xc, /* load and sign-extend into Wt */
263};
264
50573c66
RH
265/* We encode the format of the insn into the beginning of the name, so that
266 we can have the preprocessor help "typecheck" the insn vs the output
267 function. Arm didn't provide us with nice names for the formats, so we
268 use the section number of the architecture reference manual in which the
269 instruction group is described. */
270typedef enum {
3d9e69a2
RH
271 /* Compare and branch (immediate). */
272 I3201_CBZ = 0x34000000,
273 I3201_CBNZ = 0x35000000,
274
81d8a5ee
RH
275 /* Conditional branch (immediate). */
276 I3202_B_C = 0x54000000,
277
278 /* Unconditional branch (immediate). */
279 I3206_B = 0x14000000,
280 I3206_BL = 0x94000000,
281
282 /* Unconditional branch (register). */
283 I3207_BR = 0xd61f0000,
284 I3207_BLR = 0xd63f0000,
285 I3207_RET = 0xd65f0000,
286
95f72aa9
RH
287 /* Load/store register pair instructions. */
288 I3314_LDP = 0x28400000,
289 I3314_STP = 0x28000000,
290
096c46c0
RH
291 /* Add/subtract immediate instructions. */
292 I3401_ADDI = 0x11000000,
293 I3401_ADDSI = 0x31000000,
294 I3401_SUBI = 0x51000000,
295 I3401_SUBSI = 0x71000000,
296
b3c56df7
RH
297 /* Bitfield instructions. */
298 I3402_BFM = 0x33000000,
299 I3402_SBFM = 0x13000000,
300 I3402_UBFM = 0x53000000,
301
302 /* Extract instruction. */
303 I3403_EXTR = 0x13800000,
304
e029f293
RH
305 /* Logical immediate instructions. */
306 I3404_ANDI = 0x12000000,
307 I3404_ORRI = 0x32000000,
308 I3404_EORI = 0x52000000,
309
582ab779
RH
310 /* Move wide immediate instructions. */
311 I3405_MOVN = 0x12800000,
312 I3405_MOVZ = 0x52800000,
313 I3405_MOVK = 0x72800000,
314
c6e310d9
RH
315 /* PC relative addressing instructions. */
316 I3406_ADR = 0x10000000,
317 I3406_ADRP = 0x90000000,
318
50573c66
RH
319 /* Add/subtract shifted register instructions (without a shift). */
320 I3502_ADD = 0x0b000000,
321 I3502_ADDS = 0x2b000000,
322 I3502_SUB = 0x4b000000,
323 I3502_SUBS = 0x6b000000,
324
325 /* Add/subtract shifted register instructions (with a shift). */
326 I3502S_ADD_LSL = I3502_ADD,
327
c6e929e7
RH
328 /* Add/subtract with carry instructions. */
329 I3503_ADC = 0x1a000000,
330 I3503_SBC = 0x5a000000,
331
04ce397b
RH
332 /* Conditional select instructions. */
333 I3506_CSEL = 0x1a800000,
334 I3506_CSINC = 0x1a800400,
335
df9351e3
RH
336 /* Data-processing (2 source) instructions. */
337 I3508_LSLV = 0x1ac02000,
338 I3508_LSRV = 0x1ac02400,
339 I3508_ASRV = 0x1ac02800,
340 I3508_RORV = 0x1ac02c00,
1fcc9ddf
RH
341 I3508_SMULH = 0x9b407c00,
342 I3508_UMULH = 0x9bc07c00,
8678b71c
RH
343 I3508_UDIV = 0x1ac00800,
344 I3508_SDIV = 0x1ac00c00,
345
346 /* Data-processing (3 source) instructions. */
347 I3509_MADD = 0x1b000000,
348 I3509_MSUB = 0x1b008000,
df9351e3 349
50573c66
RH
350 /* Logical shifted register instructions (without a shift). */
351 I3510_AND = 0x0a000000,
14b155dd 352 I3510_BIC = 0x0a200000,
50573c66 353 I3510_ORR = 0x2a000000,
14b155dd 354 I3510_ORN = 0x2a200000,
50573c66 355 I3510_EOR = 0x4a000000,
14b155dd 356 I3510_EON = 0x4a200000,
50573c66
RH
357 I3510_ANDS = 0x6a000000,
358} AArch64Insn;
4a136e0a 359
4a136e0a
CF
360static inline enum aarch64_ldst_op_data
361aarch64_ldst_get_data(TCGOpcode tcg_op)
362{
363 switch (tcg_op) {
364 case INDEX_op_ld8u_i32:
365 case INDEX_op_ld8s_i32:
366 case INDEX_op_ld8u_i64:
367 case INDEX_op_ld8s_i64:
368 case INDEX_op_st8_i32:
369 case INDEX_op_st8_i64:
370 return LDST_8;
371
372 case INDEX_op_ld16u_i32:
373 case INDEX_op_ld16s_i32:
374 case INDEX_op_ld16u_i64:
375 case INDEX_op_ld16s_i64:
376 case INDEX_op_st16_i32:
377 case INDEX_op_st16_i64:
378 return LDST_16;
379
380 case INDEX_op_ld_i32:
381 case INDEX_op_st_i32:
382 case INDEX_op_ld32u_i64:
383 case INDEX_op_ld32s_i64:
384 case INDEX_op_st32_i64:
385 return LDST_32;
386
387 case INDEX_op_ld_i64:
388 case INDEX_op_st_i64:
389 return LDST_64;
390
391 default:
392 tcg_abort();
393 }
394}
395
396static inline enum aarch64_ldst_op_type
397aarch64_ldst_get_type(TCGOpcode tcg_op)
398{
399 switch (tcg_op) {
400 case INDEX_op_st8_i32:
401 case INDEX_op_st16_i32:
402 case INDEX_op_st8_i64:
403 case INDEX_op_st16_i64:
404 case INDEX_op_st_i32:
405 case INDEX_op_st32_i64:
406 case INDEX_op_st_i64:
407 return LDST_ST;
408
409 case INDEX_op_ld8u_i32:
410 case INDEX_op_ld16u_i32:
411 case INDEX_op_ld8u_i64:
412 case INDEX_op_ld16u_i64:
413 case INDEX_op_ld_i32:
414 case INDEX_op_ld32u_i64:
415 case INDEX_op_ld_i64:
416 return LDST_LD;
417
418 case INDEX_op_ld8s_i32:
419 case INDEX_op_ld16s_i32:
420 return LDST_LD_S_W;
421
422 case INDEX_op_ld8s_i64:
423 case INDEX_op_ld16s_i64:
424 case INDEX_op_ld32s_i64:
425 return LDST_LD_S_X;
426
427 default:
428 tcg_abort();
429 }
430}
431
432static inline uint32_t tcg_in32(TCGContext *s)
433{
434 uint32_t v = *(uint32_t *)s->code_ptr;
435 return v;
436}
437
50573c66
RH
438/* Emit an opcode with "type-checking" of the format. */
439#define tcg_out_insn(S, FMT, OP, ...) \
440 glue(tcg_out_insn_,FMT)(S, glue(glue(glue(I,FMT),_),OP), ## __VA_ARGS__)
441
3d9e69a2
RH
442static void tcg_out_insn_3201(TCGContext *s, AArch64Insn insn, TCGType ext,
443 TCGReg rt, int imm19)
444{
445 tcg_out32(s, insn | ext << 31 | (imm19 & 0x7ffff) << 5 | rt);
446}
447
81d8a5ee
RH
448static void tcg_out_insn_3202(TCGContext *s, AArch64Insn insn,
449 TCGCond c, int imm19)
450{
451 tcg_out32(s, insn | tcg_cond_to_aarch64[c] | (imm19 & 0x7ffff) << 5);
452}
453
454static void tcg_out_insn_3206(TCGContext *s, AArch64Insn insn, int imm26)
455{
456 tcg_out32(s, insn | (imm26 & 0x03ffffff));
457}
458
459static void tcg_out_insn_3207(TCGContext *s, AArch64Insn insn, TCGReg rn)
460{
461 tcg_out32(s, insn | rn << 5);
462}
463
95f72aa9
RH
464static void tcg_out_insn_3314(TCGContext *s, AArch64Insn insn,
465 TCGReg r1, TCGReg r2, TCGReg rn,
466 tcg_target_long ofs, bool pre, bool w)
467{
468 insn |= 1u << 31; /* ext */
469 insn |= pre << 24;
470 insn |= w << 23;
471
472 assert(ofs >= -0x200 && ofs < 0x200 && (ofs & 7) == 0);
473 insn |= (ofs & (0x7f << 3)) << (15 - 3);
474
475 tcg_out32(s, insn | r2 << 10 | rn << 5 | r1);
476}
477
096c46c0
RH
478static void tcg_out_insn_3401(TCGContext *s, AArch64Insn insn, TCGType ext,
479 TCGReg rd, TCGReg rn, uint64_t aimm)
480{
481 if (aimm > 0xfff) {
482 assert((aimm & 0xfff) == 0);
483 aimm >>= 12;
484 assert(aimm <= 0xfff);
485 aimm |= 1 << 12; /* apply LSL 12 */
486 }
487 tcg_out32(s, insn | ext << 31 | aimm << 10 | rn << 5 | rd);
488}
489
e029f293
RH
490/* This function can be used for both 3.4.2 (Bitfield) and 3.4.4
491 (Logical immediate). Both insn groups have N, IMMR and IMMS fields
492 that feed the DecodeBitMasks pseudo function. */
493static void tcg_out_insn_3402(TCGContext *s, AArch64Insn insn, TCGType ext,
494 TCGReg rd, TCGReg rn, int n, int immr, int imms)
495{
496 tcg_out32(s, insn | ext << 31 | n << 22 | immr << 16 | imms << 10
497 | rn << 5 | rd);
498}
499
500#define tcg_out_insn_3404 tcg_out_insn_3402
501
b3c56df7
RH
502static void tcg_out_insn_3403(TCGContext *s, AArch64Insn insn, TCGType ext,
503 TCGReg rd, TCGReg rn, TCGReg rm, int imms)
504{
505 tcg_out32(s, insn | ext << 31 | ext << 22 | rm << 16 | imms << 10
506 | rn << 5 | rd);
507}
508
582ab779
RH
509/* This function is used for the Move (wide immediate) instruction group.
510 Note that SHIFT is a full shift count, not the 2 bit HW field. */
511static void tcg_out_insn_3405(TCGContext *s, AArch64Insn insn, TCGType ext,
512 TCGReg rd, uint16_t half, unsigned shift)
513{
514 assert((shift & ~0x30) == 0);
515 tcg_out32(s, insn | ext << 31 | shift << (21 - 4) | half << 5 | rd);
516}
517
c6e310d9
RH
518static void tcg_out_insn_3406(TCGContext *s, AArch64Insn insn,
519 TCGReg rd, int64_t disp)
520{
521 tcg_out32(s, insn | (disp & 3) << 29 | (disp & 0x1ffffc) << (5 - 2) | rd);
522}
523
50573c66
RH
524/* This function is for both 3.5.2 (Add/Subtract shifted register), for
525 the rare occasion when we actually want to supply a shift amount. */
526static inline void tcg_out_insn_3502S(TCGContext *s, AArch64Insn insn,
527 TCGType ext, TCGReg rd, TCGReg rn,
528 TCGReg rm, int imm6)
529{
530 tcg_out32(s, insn | ext << 31 | rm << 16 | imm6 << 10 | rn << 5 | rd);
531}
532
533/* This function is for 3.5.2 (Add/subtract shifted register),
534 and 3.5.10 (Logical shifted register), for the vast majorty of cases
535 when we don't want to apply a shift. Thus it can also be used for
536 3.5.3 (Add/subtract with carry) and 3.5.8 (Data processing 2 source). */
537static void tcg_out_insn_3502(TCGContext *s, AArch64Insn insn, TCGType ext,
538 TCGReg rd, TCGReg rn, TCGReg rm)
539{
540 tcg_out32(s, insn | ext << 31 | rm << 16 | rn << 5 | rd);
541}
542
543#define tcg_out_insn_3503 tcg_out_insn_3502
544#define tcg_out_insn_3508 tcg_out_insn_3502
545#define tcg_out_insn_3510 tcg_out_insn_3502
546
04ce397b
RH
547static void tcg_out_insn_3506(TCGContext *s, AArch64Insn insn, TCGType ext,
548 TCGReg rd, TCGReg rn, TCGReg rm, TCGCond c)
549{
550 tcg_out32(s, insn | ext << 31 | rm << 16 | rn << 5 | rd
551 | tcg_cond_to_aarch64[c] << 12);
552}
553
8678b71c
RH
554static void tcg_out_insn_3509(TCGContext *s, AArch64Insn insn, TCGType ext,
555 TCGReg rd, TCGReg rn, TCGReg rm, TCGReg ra)
556{
557 tcg_out32(s, insn | ext << 31 | rm << 16 | ra << 10 | rn << 5 | rd);
558}
559
50573c66 560
4a136e0a
CF
561static inline void tcg_out_ldst_9(TCGContext *s,
562 enum aarch64_ldst_op_data op_data,
563 enum aarch64_ldst_op_type op_type,
8bf56493 564 TCGReg rd, TCGReg rn, intptr_t offset)
4a136e0a
CF
565{
566 /* use LDUR with BASE register with 9bit signed unscaled offset */
523fdc08
RH
567 tcg_out32(s, op_data << 24 | op_type << 20
568 | (offset & 0x1ff) << 12 | rn << 5 | rd);
4a136e0a
CF
569}
570
b1f6dc0d
CF
571/* tcg_out_ldst_12 expects a scaled unsigned immediate offset */
572static inline void tcg_out_ldst_12(TCGContext *s,
573 enum aarch64_ldst_op_data op_data,
574 enum aarch64_ldst_op_type op_type,
575 TCGReg rd, TCGReg rn,
576 tcg_target_ulong scaled_uimm)
577{
578 tcg_out32(s, (op_data | 1) << 24
579 | op_type << 20 | scaled_uimm << 10 | rn << 5 | rd);
580}
581
7d11fc7c
RH
582/* Register to register move using ORR (shifted register with no shift). */
583static void tcg_out_movr(TCGContext *s, TCGType ext, TCGReg rd, TCGReg rm)
4a136e0a 584{
7d11fc7c
RH
585 tcg_out_insn(s, 3510, ORR, ext, rd, TCG_REG_XZR, rm);
586}
587
588/* Register to register move using ADDI (move to/from SP). */
589static void tcg_out_movr_sp(TCGContext *s, TCGType ext, TCGReg rd, TCGReg rn)
590{
591 tcg_out_insn(s, 3401, ADDI, ext, rd, rn, 0);
4a136e0a
CF
592}
593
4ec4f0bd
RH
594/* This function is used for the Logical (immediate) instruction group.
595 The value of LIMM must satisfy IS_LIMM. See the comment above about
596 only supporting simplified logical immediates. */
597static void tcg_out_logicali(TCGContext *s, AArch64Insn insn, TCGType ext,
598 TCGReg rd, TCGReg rn, uint64_t limm)
599{
600 unsigned h, l, r, c;
601
602 assert(is_limm(limm));
603
604 h = clz64(limm);
605 l = ctz64(limm);
606 if (l == 0) {
607 r = 0; /* form 0....01....1 */
608 c = ctz64(~limm) - 1;
609 if (h == 0) {
610 r = clz64(~limm); /* form 1..10..01..1 */
611 c += r;
612 }
613 } else {
614 r = 64 - l; /* form 1....10....0 or 0..01..10..0 */
615 c = r - h - 1;
616 }
617 if (ext == TCG_TYPE_I32) {
618 r &= 31;
619 c &= 31;
620 }
621
622 tcg_out_insn_3404(s, insn, ext, rd, rn, ext, r, c);
623}
624
582ab779
RH
625static void tcg_out_movi(TCGContext *s, TCGType type, TCGReg rd,
626 tcg_target_long value)
4a136e0a 627{
582ab779 628 AArch64Insn insn;
dfeb5fe7
RH
629 int i, wantinv, shift;
630 tcg_target_long svalue = value;
631 tcg_target_long ivalue = ~value;
632 tcg_target_long imask;
633
634 /* For 32-bit values, discard potential garbage in value. For 64-bit
635 values within [2**31, 2**32-1], we can create smaller sequences by
636 interpreting this as a negative 32-bit number, while ensuring that
637 the high 32 bits are cleared by setting SF=0. */
638 if (type == TCG_TYPE_I32 || (value & ~0xffffffffull) == 0) {
639 svalue = (int32_t)value;
582ab779 640 value = (uint32_t)value;
dfeb5fe7
RH
641 ivalue = (uint32_t)ivalue;
642 type = TCG_TYPE_I32;
643 }
644
d8918df5
RH
645 /* Speed things up by handling the common case of small positive
646 and negative values specially. */
647 if ((value & ~0xffffull) == 0) {
648 tcg_out_insn(s, 3405, MOVZ, type, rd, value, 0);
649 return;
650 } else if ((ivalue & ~0xffffull) == 0) {
651 tcg_out_insn(s, 3405, MOVN, type, rd, ivalue, 0);
652 return;
653 }
654
4ec4f0bd
RH
655 /* Check for bitfield immediates. For the benefit of 32-bit quantities,
656 use the sign-extended value. That lets us match rotated values such
657 as 0xff0000ff with the same 64-bit logic matching 0xffffffffff0000ff. */
658 if (is_limm(svalue)) {
659 tcg_out_logicali(s, I3404_ORRI, type, rd, TCG_REG_XZR, svalue);
660 return;
661 }
662
c6e310d9
RH
663 /* Look for host pointer values within 4G of the PC. This happens
664 often when loading pointers to QEMU's own data structures. */
665 if (type == TCG_TYPE_I64) {
666 tcg_target_long disp = (value >> 12) - ((intptr_t)s->code_ptr >> 12);
667 if (disp == sextract64(disp, 0, 21)) {
668 tcg_out_insn(s, 3406, ADRP, rd, disp);
669 if (value & 0xfff) {
670 tcg_out_insn(s, 3401, ADDI, type, rd, rd, value & 0xfff);
671 }
672 return;
673 }
674 }
675
dfeb5fe7
RH
676 /* Would it take fewer insns to begin with MOVN? For the value and its
677 inverse, count the number of 16-bit lanes that are 0. */
678 for (i = wantinv = imask = 0; i < 64; i += 16) {
679 tcg_target_long mask = 0xffffull << i;
680 if ((value & mask) == 0) {
681 wantinv -= 1;
682 }
683 if ((ivalue & mask) == 0) {
684 wantinv += 1;
685 imask |= mask;
686 }
582ab779
RH
687 }
688
dfeb5fe7 689 /* If we had more 0xffff than 0x0000, invert VALUE and use MOVN. */
582ab779 690 insn = I3405_MOVZ;
dfeb5fe7
RH
691 if (wantinv > 0) {
692 value = ivalue;
693 insn = I3405_MOVN;
694 }
695
696 /* Find the lowest lane that is not 0x0000. */
697 shift = ctz64(value) & (63 & -16);
698 tcg_out_insn_3405(s, insn, type, rd, value >> shift, shift);
699
700 if (wantinv > 0) {
701 /* Re-invert the value, so MOVK sees non-inverted bits. */
702 value = ~value;
703 /* Clear out all the 0xffff lanes. */
704 value ^= imask;
705 }
706 /* Clear out the lane that we just set. */
707 value &= ~(0xffffUL << shift);
708
709 /* Iterate until all lanes have been set, and thus cleared from VALUE. */
710 while (value) {
711 shift = ctz64(value) & (63 & -16);
712 tcg_out_insn(s, 3405, MOVK, type, rd, value >> shift, shift);
4a136e0a 713 value &= ~(0xffffUL << shift);
dfeb5fe7 714 }
4a136e0a
CF
715}
716
4a136e0a
CF
717static inline void tcg_out_ldst_r(TCGContext *s,
718 enum aarch64_ldst_op_data op_data,
719 enum aarch64_ldst_op_type op_type,
720 TCGReg rd, TCGReg base, TCGReg regoff)
721{
722 /* load from memory to register using base + 64bit register offset */
723 /* using f.e. STR Wt, [Xn, Xm] 0xb8600800|(regoff << 16)|(base << 5)|rd */
724 /* the 0x6000 is for the "no extend field" */
725 tcg_out32(s, 0x00206800
726 | op_data << 24 | op_type << 20 | regoff << 16 | base << 5 | rd);
727}
728
729/* solve the whole ldst problem */
730static inline void tcg_out_ldst(TCGContext *s, enum aarch64_ldst_op_data data,
731 enum aarch64_ldst_op_type type,
8bf56493 732 TCGReg rd, TCGReg rn, intptr_t offset)
4a136e0a
CF
733{
734 if (offset >= -256 && offset < 256) {
735 tcg_out_ldst_9(s, data, type, rd, rn, offset);
b1f6dc0d 736 return;
4a136e0a 737 }
b1f6dc0d
CF
738
739 if (offset >= 256) {
740 /* if the offset is naturally aligned and in range,
741 then we can use the scaled uimm12 encoding */
742 unsigned int s_bits = data >> 6;
743 if (!(offset & ((1 << s_bits) - 1))) {
744 tcg_target_ulong scaled_uimm = offset >> s_bits;
745 if (scaled_uimm <= 0xfff) {
746 tcg_out_ldst_12(s, data, type, rd, rn, scaled_uimm);
747 return;
748 }
749 }
750 }
751
752 /* worst-case scenario, move offset to temp register, use reg offset */
753 tcg_out_movi(s, TCG_TYPE_I64, TCG_REG_TMP, offset);
754 tcg_out_ldst_r(s, data, type, rd, rn, TCG_REG_TMP);
4a136e0a
CF
755}
756
4a136e0a
CF
757static inline void tcg_out_mov(TCGContext *s,
758 TCGType type, TCGReg ret, TCGReg arg)
759{
760 if (ret != arg) {
929f8b55 761 tcg_out_movr(s, type, ret, arg);
4a136e0a
CF
762 }
763}
764
765static inline void tcg_out_ld(TCGContext *s, TCGType type, TCGReg arg,
a05b5b9b 766 TCGReg arg1, intptr_t arg2)
4a136e0a
CF
767{
768 tcg_out_ldst(s, (type == TCG_TYPE_I64) ? LDST_64 : LDST_32, LDST_LD,
769 arg, arg1, arg2);
770}
771
772static inline void tcg_out_st(TCGContext *s, TCGType type, TCGReg arg,
a05b5b9b 773 TCGReg arg1, intptr_t arg2)
4a136e0a
CF
774{
775 tcg_out_ldst(s, (type == TCG_TYPE_I64) ? LDST_64 : LDST_32, LDST_ST,
776 arg, arg1, arg2);
777}
778
b3c56df7
RH
779static inline void tcg_out_bfm(TCGContext *s, TCGType ext, TCGReg rd,
780 TCGReg rn, unsigned int a, unsigned int b)
781{
782 tcg_out_insn(s, 3402, BFM, ext, rd, rn, ext, a, b);
783}
784
7763ffa0
RH
785static inline void tcg_out_ubfm(TCGContext *s, TCGType ext, TCGReg rd,
786 TCGReg rn, unsigned int a, unsigned int b)
4a136e0a 787{
b3c56df7 788 tcg_out_insn(s, 3402, UBFM, ext, rd, rn, ext, a, b);
4a136e0a
CF
789}
790
7763ffa0
RH
791static inline void tcg_out_sbfm(TCGContext *s, TCGType ext, TCGReg rd,
792 TCGReg rn, unsigned int a, unsigned int b)
4a136e0a 793{
b3c56df7 794 tcg_out_insn(s, 3402, SBFM, ext, rd, rn, ext, a, b);
4a136e0a
CF
795}
796
7763ffa0 797static inline void tcg_out_extr(TCGContext *s, TCGType ext, TCGReg rd,
4a136e0a
CF
798 TCGReg rn, TCGReg rm, unsigned int a)
799{
b3c56df7 800 tcg_out_insn(s, 3403, EXTR, ext, rd, rn, rm, a);
4a136e0a
CF
801}
802
7763ffa0 803static inline void tcg_out_shl(TCGContext *s, TCGType ext,
4a136e0a
CF
804 TCGReg rd, TCGReg rn, unsigned int m)
805{
b3c56df7
RH
806 int bits = ext ? 64 : 32;
807 int max = bits - 1;
4a136e0a
CF
808 tcg_out_ubfm(s, ext, rd, rn, bits - (m & max), max - (m & max));
809}
810
7763ffa0 811static inline void tcg_out_shr(TCGContext *s, TCGType ext,
4a136e0a
CF
812 TCGReg rd, TCGReg rn, unsigned int m)
813{
814 int max = ext ? 63 : 31;
815 tcg_out_ubfm(s, ext, rd, rn, m & max, max);
816}
817
7763ffa0 818static inline void tcg_out_sar(TCGContext *s, TCGType ext,
4a136e0a
CF
819 TCGReg rd, TCGReg rn, unsigned int m)
820{
821 int max = ext ? 63 : 31;
822 tcg_out_sbfm(s, ext, rd, rn, m & max, max);
823}
824
7763ffa0 825static inline void tcg_out_rotr(TCGContext *s, TCGType ext,
4a136e0a
CF
826 TCGReg rd, TCGReg rn, unsigned int m)
827{
828 int max = ext ? 63 : 31;
829 tcg_out_extr(s, ext, rd, rn, rn, m & max);
830}
831
7763ffa0 832static inline void tcg_out_rotl(TCGContext *s, TCGType ext,
4a136e0a
CF
833 TCGReg rd, TCGReg rn, unsigned int m)
834{
b3c56df7
RH
835 int bits = ext ? 64 : 32;
836 int max = bits - 1;
4a136e0a
CF
837 tcg_out_extr(s, ext, rd, rn, rn, bits - (m & max));
838}
839
b3c56df7
RH
840static inline void tcg_out_dep(TCGContext *s, TCGType ext, TCGReg rd,
841 TCGReg rn, unsigned lsb, unsigned width)
842{
843 unsigned size = ext ? 64 : 32;
844 unsigned a = (size - lsb) & (size - 1);
845 unsigned b = width - 1;
846 tcg_out_bfm(s, ext, rd, rn, a, b);
847}
848
90f1cd91
RH
849static void tcg_out_cmp(TCGContext *s, TCGType ext, TCGReg a,
850 tcg_target_long b, bool const_b)
4a136e0a 851{
90f1cd91
RH
852 if (const_b) {
853 /* Using CMP or CMN aliases. */
854 if (b >= 0) {
855 tcg_out_insn(s, 3401, SUBSI, ext, TCG_REG_XZR, a, b);
856 } else {
857 tcg_out_insn(s, 3401, ADDSI, ext, TCG_REG_XZR, a, -b);
858 }
859 } else {
860 /* Using CMP alias SUBS wzr, Wn, Wm */
861 tcg_out_insn(s, 3502, SUBS, ext, TCG_REG_XZR, a, b);
862 }
4a136e0a
CF
863}
864
017a86f7 865static inline void tcg_out_goto(TCGContext *s, intptr_t target)
4a136e0a 866{
017a86f7 867 intptr_t offset = (target - (intptr_t)s->code_ptr) / 4;
4a136e0a
CF
868
869 if (offset < -0x02000000 || offset >= 0x02000000) {
870 /* out of 26bit range */
871 tcg_abort();
872 }
873
81d8a5ee 874 tcg_out_insn(s, 3206, B, offset);
4a136e0a
CF
875}
876
877static inline void tcg_out_goto_noaddr(TCGContext *s)
878{
81d8a5ee
RH
879 /* We pay attention here to not modify the branch target by reading from
880 the buffer. This ensure that caches and memory are kept coherent during
881 retranslation. Mask away possible garbage in the high bits for the
882 first translation, while keeping the offset bits for retranslation. */
883 uint32_t old = tcg_in32(s);
884 tcg_out_insn(s, 3206, B, old);
4a136e0a
CF
885}
886
887static inline void tcg_out_goto_cond_noaddr(TCGContext *s, TCGCond c)
888{
81d8a5ee
RH
889 /* See comments in tcg_out_goto_noaddr. */
890 uint32_t old = tcg_in32(s) >> 5;
891 tcg_out_insn(s, 3202, B_C, c, old);
4a136e0a
CF
892}
893
4a136e0a
CF
894static inline void tcg_out_callr(TCGContext *s, TCGReg reg)
895{
81d8a5ee 896 tcg_out_insn(s, 3207, BLR, reg);
4a136e0a
CF
897}
898
017a86f7 899static inline void tcg_out_call(TCGContext *s, intptr_t target)
4a136e0a 900{
017a86f7 901 intptr_t offset = (target - (intptr_t)s->code_ptr) / 4;
4a136e0a
CF
902
903 if (offset < -0x02000000 || offset >= 0x02000000) { /* out of 26bit rng */
904 tcg_out_movi(s, TCG_TYPE_I64, TCG_REG_TMP, target);
905 tcg_out_callr(s, TCG_REG_TMP);
906 } else {
81d8a5ee 907 tcg_out_insn(s, 3206, BL, offset);
4a136e0a
CF
908 }
909}
910
4a136e0a
CF
911void aarch64_tb_set_jmp_target(uintptr_t jmp_addr, uintptr_t addr)
912{
017a86f7
RH
913 intptr_t target = addr;
914 intptr_t offset = (target - (intptr_t)jmp_addr) / 4;
4a136e0a
CF
915
916 if (offset < -0x02000000 || offset >= 0x02000000) {
917 /* out of 26bit range */
918 tcg_abort();
919 }
920
921 patch_reloc((uint8_t *)jmp_addr, R_AARCH64_JUMP26, target, 0);
922 flush_icache_range(jmp_addr, jmp_addr + 4);
923}
924
925static inline void tcg_out_goto_label(TCGContext *s, int label_index)
926{
927 TCGLabel *l = &s->labels[label_index];
928
929 if (!l->has_value) {
930 tcg_out_reloc(s, s->code_ptr, R_AARCH64_JUMP26, label_index, 0);
931 tcg_out_goto_noaddr(s);
932 } else {
933 tcg_out_goto(s, l->u.value);
934 }
935}
936
cae1f6f3
RH
937static void tcg_out_brcond(TCGContext *s, TCGMemOp ext, TCGCond c, TCGArg a,
938 TCGArg b, bool b_const, int label)
4a136e0a 939{
cae1f6f3
RH
940 TCGLabel *l = &s->labels[label];
941 intptr_t offset;
3d9e69a2 942 bool need_cmp;
cae1f6f3 943
3d9e69a2
RH
944 if (b_const && b == 0 && (c == TCG_COND_EQ || c == TCG_COND_NE)) {
945 need_cmp = false;
946 } else {
947 need_cmp = true;
948 tcg_out_cmp(s, ext, a, b, b_const);
949 }
4a136e0a
CF
950
951 if (!l->has_value) {
cae1f6f3
RH
952 tcg_out_reloc(s, s->code_ptr, R_AARCH64_CONDBR19, label, 0);
953 offset = tcg_in32(s) >> 5;
4a136e0a 954 } else {
cae1f6f3
RH
955 offset = l->u.value - (uintptr_t)s->code_ptr;
956 offset >>= 2;
957 assert(offset >= -0x40000 && offset < 0x40000);
4a136e0a 958 }
cae1f6f3 959
3d9e69a2
RH
960 if (need_cmp) {
961 tcg_out_insn(s, 3202, B_C, c, offset);
962 } else if (c == TCG_COND_EQ) {
963 tcg_out_insn(s, 3201, CBZ, ext, a, offset);
964 } else {
965 tcg_out_insn(s, 3201, CBNZ, ext, a, offset);
966 }
4a136e0a
CF
967}
968
7763ffa0
RH
969static inline void tcg_out_rev(TCGContext *s, TCGType ext,
970 TCGReg rd, TCGReg rm)
9c4a059d
CF
971{
972 /* using REV 0x5ac00800 */
973 unsigned int base = ext ? 0xdac00c00 : 0x5ac00800;
974 tcg_out32(s, base | rm << 5 | rd);
975}
976
7763ffa0
RH
977static inline void tcg_out_rev16(TCGContext *s, TCGType ext,
978 TCGReg rd, TCGReg rm)
9c4a059d
CF
979{
980 /* using REV16 0x5ac00400 */
981 unsigned int base = ext ? 0xdac00400 : 0x5ac00400;
982 tcg_out32(s, base | rm << 5 | rd);
983}
984
929f8b55 985static inline void tcg_out_sxt(TCGContext *s, TCGType ext, TCGMemOp s_bits,
31f1275b
CF
986 TCGReg rd, TCGReg rn)
987{
b3c56df7 988 /* Using ALIASes SXTB, SXTH, SXTW, of SBFM Xd, Xn, #0, #7|15|31 */
929f8b55 989 int bits = (8 << s_bits) - 1;
31f1275b
CF
990 tcg_out_sbfm(s, ext, rd, rn, 0, bits);
991}
992
929f8b55 993static inline void tcg_out_uxt(TCGContext *s, TCGMemOp s_bits,
31f1275b
CF
994 TCGReg rd, TCGReg rn)
995{
b3c56df7 996 /* Using ALIASes UXTB, UXTH of UBFM Wd, Wn, #0, #7|15 */
929f8b55 997 int bits = (8 << s_bits) - 1;
31f1275b
CF
998 tcg_out_ubfm(s, 0, rd, rn, 0, bits);
999}
1000
90f1cd91
RH
1001static void tcg_out_addsubi(TCGContext *s, int ext, TCGReg rd,
1002 TCGReg rn, int64_t aimm)
1003{
1004 if (aimm >= 0) {
1005 tcg_out_insn(s, 3401, ADDI, ext, rd, rn, aimm);
1006 } else {
1007 tcg_out_insn(s, 3401, SUBI, ext, rd, rn, -aimm);
1008 }
1009}
1010
c6e929e7
RH
1011static inline void tcg_out_addsub2(TCGContext *s, int ext, TCGReg rl,
1012 TCGReg rh, TCGReg al, TCGReg ah,
1013 tcg_target_long bl, tcg_target_long bh,
1014 bool const_bl, bool const_bh, bool sub)
1015{
1016 TCGReg orig_rl = rl;
1017 AArch64Insn insn;
1018
1019 if (rl == ah || (!const_bh && rl == bh)) {
1020 rl = TCG_REG_TMP;
1021 }
1022
1023 if (const_bl) {
1024 insn = I3401_ADDSI;
1025 if ((bl < 0) ^ sub) {
1026 insn = I3401_SUBSI;
1027 bl = -bl;
1028 }
1029 tcg_out_insn_3401(s, insn, ext, rl, al, bl);
1030 } else {
1031 tcg_out_insn_3502(s, sub ? I3502_SUBS : I3502_ADDS, ext, rl, al, bl);
1032 }
1033
1034 insn = I3503_ADC;
1035 if (const_bh) {
1036 /* Note that the only two constants we support are 0 and -1, and
1037 that SBC = rn + ~rm + c, so adc -1 is sbc 0, and vice-versa. */
1038 if ((bh != 0) ^ sub) {
1039 insn = I3503_SBC;
1040 }
1041 bh = TCG_REG_XZR;
1042 } else if (sub) {
1043 insn = I3503_SBC;
1044 }
1045 tcg_out_insn_3503(s, insn, ext, rh, ah, bh);
1046
1047 if (rl != orig_rl) {
1048 tcg_out_movr(s, ext, orig_rl, rl);
1049 }
1050}
1051
4a136e0a 1052#ifdef CONFIG_SOFTMMU
023261ef
RH
1053/* helper signature: helper_ret_ld_mmu(CPUState *env, target_ulong addr,
1054 * int mmu_idx, uintptr_t ra)
1055 */
4a136e0a 1056static const void * const qemu_ld_helpers[4] = {
023261ef
RH
1057 helper_ret_ldub_mmu,
1058 helper_ret_lduw_mmu,
1059 helper_ret_ldul_mmu,
1060 helper_ret_ldq_mmu,
4a136e0a
CF
1061};
1062
023261ef
RH
1063/* helper signature: helper_ret_st_mmu(CPUState *env, target_ulong addr,
1064 * uintxx_t val, int mmu_idx, uintptr_t ra)
1065 */
4a136e0a 1066static const void * const qemu_st_helpers[4] = {
023261ef
RH
1067 helper_ret_stb_mmu,
1068 helper_ret_stw_mmu,
1069 helper_ret_stl_mmu,
1070 helper_ret_stq_mmu,
4a136e0a
CF
1071};
1072
c6d8ed24
JK
1073static void tcg_out_qemu_ld_slow_path(TCGContext *s, TCGLabelQemuLdst *lb)
1074{
929f8b55
RH
1075 TCGMemOp opc = lb->opc;
1076 TCGMemOp size = opc & MO_SIZE;
1077
017a86f7
RH
1078 reloc_pc19(lb->label_ptr[0], (intptr_t)s->code_ptr);
1079
929f8b55
RH
1080 tcg_out_movr(s, TCG_TYPE_I64, TCG_REG_X0, TCG_AREG0);
1081 tcg_out_movr(s, TARGET_LONG_BITS == 64, TCG_REG_X1, lb->addrlo_reg);
c6d8ed24 1082 tcg_out_movi(s, TCG_TYPE_I32, TCG_REG_X2, lb->mem_index);
8bf56493 1083 tcg_out_movi(s, TCG_TYPE_PTR, TCG_REG_X3, (intptr_t)lb->raddr);
ae7ab46a 1084 tcg_out_call(s, (intptr_t)qemu_ld_helpers[size]);
929f8b55
RH
1085 if (opc & MO_SIGN) {
1086 tcg_out_sxt(s, TCG_TYPE_I64, size, lb->datalo_reg, TCG_REG_X0);
c6d8ed24 1087 } else {
929f8b55 1088 tcg_out_movr(s, TCG_TYPE_I64, lb->datalo_reg, TCG_REG_X0);
c6d8ed24
JK
1089 }
1090
017a86f7 1091 tcg_out_goto(s, (intptr_t)lb->raddr);
c6d8ed24
JK
1092}
1093
1094static void tcg_out_qemu_st_slow_path(TCGContext *s, TCGLabelQemuLdst *lb)
1095{
929f8b55
RH
1096 TCGMemOp size = lb->opc;
1097
017a86f7 1098 reloc_pc19(lb->label_ptr[0], (intptr_t)s->code_ptr);
c6d8ed24 1099
929f8b55
RH
1100 tcg_out_movr(s, TCG_TYPE_I64, TCG_REG_X0, TCG_AREG0);
1101 tcg_out_movr(s, TARGET_LONG_BITS == 64, TCG_REG_X1, lb->addrlo_reg);
1102 tcg_out_movr(s, size == MO_64, TCG_REG_X2, lb->datalo_reg);
c6d8ed24 1103 tcg_out_movi(s, TCG_TYPE_I32, TCG_REG_X3, lb->mem_index);
017a86f7 1104 tcg_out_movi(s, TCG_TYPE_PTR, TCG_REG_X4, (intptr_t)lb->raddr);
ae7ab46a 1105 tcg_out_call(s, (intptr_t)qemu_st_helpers[size]);
8bf56493 1106 tcg_out_goto(s, (intptr_t)lb->raddr);
c6d8ed24
JK
1107}
1108
c6d8ed24
JK
1109static void add_qemu_ldst_label(TCGContext *s, int is_ld, int opc,
1110 TCGReg data_reg, TCGReg addr_reg,
1111 int mem_index,
1112 uint8_t *raddr, uint8_t *label_ptr)
1113{
9ecefc84 1114 TCGLabelQemuLdst *label = new_ldst_label(s);
c6d8ed24 1115
c6d8ed24
JK
1116 label->is_ld = is_ld;
1117 label->opc = opc;
1118 label->datalo_reg = data_reg;
1119 label->addrlo_reg = addr_reg;
1120 label->mem_index = mem_index;
1121 label->raddr = raddr;
1122 label->label_ptr[0] = label_ptr;
1123}
1124
1125/* Load and compare a TLB entry, emitting the conditional jump to the
1126 slow path for the failure case, which will be patched later when finalizing
1127 the slow path. Generated code returns the host addend in X1,
1128 clobbers X0,X2,X3,TMP. */
6f472467
RH
1129static void tcg_out_tlb_read(TCGContext *s, TCGReg addr_reg, int s_bits,
1130 uint8_t **label_ptr, int mem_index, bool is_read)
c6d8ed24
JK
1131{
1132 TCGReg base = TCG_AREG0;
1133 int tlb_offset = is_read ?
1134 offsetof(CPUArchState, tlb_table[mem_index][0].addr_read)
1135 : offsetof(CPUArchState, tlb_table[mem_index][0].addr_write);
6f472467 1136
c6d8ed24
JK
1137 /* Extract the TLB index from the address into X0.
1138 X0<CPU_TLB_BITS:0> =
1139 addr_reg<TARGET_PAGE_BITS+CPU_TLB_BITS:TARGET_PAGE_BITS> */
6f472467 1140 tcg_out_ubfm(s, TARGET_LONG_BITS == 64, TCG_REG_X0, addr_reg,
c6d8ed24 1141 TARGET_PAGE_BITS, TARGET_PAGE_BITS + CPU_TLB_BITS);
6f472467 1142
c6d8ed24
JK
1143 /* Store the page mask part of the address and the low s_bits into X3.
1144 Later this allows checking for equality and alignment at the same time.
1145 X3 = addr_reg & (PAGE_MASK | ((1 << s_bits) - 1)) */
e029f293
RH
1146 tcg_out_logicali(s, I3404_ANDI, TARGET_LONG_BITS == 64, TCG_REG_X3,
1147 addr_reg, TARGET_PAGE_MASK | ((1 << s_bits) - 1));
6f472467 1148
c6d8ed24 1149 /* Add any "high bits" from the tlb offset to the env address into X2,
096c46c0 1150 to take advantage of the LSL12 form of the ADDI instruction.
c6d8ed24 1151 X2 = env + (tlb_offset & 0xfff000) */
6f472467
RH
1152 if (tlb_offset & 0xfff000) {
1153 tcg_out_insn(s, 3401, ADDI, TCG_TYPE_I64, TCG_REG_X2, base,
1154 tlb_offset & 0xfff000);
1155 base = TCG_REG_X2;
1156 }
1157
c6d8ed24
JK
1158 /* Merge the tlb index contribution into X2.
1159 X2 = X2 + (X0 << CPU_TLB_ENTRY_BITS) */
6f472467 1160 tcg_out_insn(s, 3502S, ADD_LSL, TCG_TYPE_I64, TCG_REG_X2, base,
50573c66 1161 TCG_REG_X0, CPU_TLB_ENTRY_BITS);
6f472467 1162
c6d8ed24
JK
1163 /* Merge "low bits" from tlb offset, load the tlb comparator into X0.
1164 X0 = load [X2 + (tlb_offset & 0x000fff)] */
1165 tcg_out_ldst(s, TARGET_LONG_BITS == 64 ? LDST_64 : LDST_32,
6f472467
RH
1166 LDST_LD, TCG_REG_X0, TCG_REG_X2, tlb_offset & 0xfff);
1167
c6d8ed24
JK
1168 /* Load the tlb addend. Do that early to avoid stalling.
1169 X1 = load [X2 + (tlb_offset & 0xfff) + offsetof(addend)] */
1170 tcg_out_ldst(s, LDST_64, LDST_LD, TCG_REG_X1, TCG_REG_X2,
1171 (tlb_offset & 0xfff) + (offsetof(CPUTLBEntry, addend)) -
1172 (is_read ? offsetof(CPUTLBEntry, addr_read)
1173 : offsetof(CPUTLBEntry, addr_write)));
6f472467 1174
c6d8ed24 1175 /* Perform the address comparison. */
90f1cd91 1176 tcg_out_cmp(s, (TARGET_LONG_BITS == 64), TCG_REG_X0, TCG_REG_X3, 0);
6f472467 1177
c6d8ed24 1178 /* If not equal, we jump to the slow path. */
6f472467 1179 *label_ptr = s->code_ptr;
c6d8ed24
JK
1180 tcg_out_goto_cond_noaddr(s, TCG_COND_NE);
1181}
1182
1183#endif /* CONFIG_SOFTMMU */
6a91c7c9
JK
1184
1185static void tcg_out_qemu_ld_direct(TCGContext *s, int opc, TCGReg data_r,
1186 TCGReg addr_r, TCGReg off_r)
1187{
1188 switch (opc) {
1189 case 0:
1190 tcg_out_ldst_r(s, LDST_8, LDST_LD, data_r, addr_r, off_r);
1191 break;
1192 case 0 | 4:
1193 tcg_out_ldst_r(s, LDST_8, LDST_LD_S_X, data_r, addr_r, off_r);
1194 break;
1195 case 1:
1196 tcg_out_ldst_r(s, LDST_16, LDST_LD, data_r, addr_r, off_r);
1197 if (TCG_LDST_BSWAP) {
929f8b55 1198 tcg_out_rev16(s, TCG_TYPE_I32, data_r, data_r);
6a91c7c9
JK
1199 }
1200 break;
1201 case 1 | 4:
1202 if (TCG_LDST_BSWAP) {
1203 tcg_out_ldst_r(s, LDST_16, LDST_LD, data_r, addr_r, off_r);
929f8b55
RH
1204 tcg_out_rev16(s, TCG_TYPE_I32, data_r, data_r);
1205 tcg_out_sxt(s, TCG_TYPE_I64, MO_16, data_r, data_r);
6a91c7c9
JK
1206 } else {
1207 tcg_out_ldst_r(s, LDST_16, LDST_LD_S_X, data_r, addr_r, off_r);
1208 }
1209 break;
1210 case 2:
1211 tcg_out_ldst_r(s, LDST_32, LDST_LD, data_r, addr_r, off_r);
1212 if (TCG_LDST_BSWAP) {
929f8b55 1213 tcg_out_rev(s, TCG_TYPE_I32, data_r, data_r);
6a91c7c9
JK
1214 }
1215 break;
1216 case 2 | 4:
1217 if (TCG_LDST_BSWAP) {
1218 tcg_out_ldst_r(s, LDST_32, LDST_LD, data_r, addr_r, off_r);
929f8b55
RH
1219 tcg_out_rev(s, TCG_TYPE_I32, data_r, data_r);
1220 tcg_out_sxt(s, TCG_TYPE_I64, MO_32, data_r, data_r);
6a91c7c9
JK
1221 } else {
1222 tcg_out_ldst_r(s, LDST_32, LDST_LD_S_X, data_r, addr_r, off_r);
1223 }
1224 break;
1225 case 3:
1226 tcg_out_ldst_r(s, LDST_64, LDST_LD, data_r, addr_r, off_r);
1227 if (TCG_LDST_BSWAP) {
929f8b55 1228 tcg_out_rev(s, TCG_TYPE_I64, data_r, data_r);
6a91c7c9
JK
1229 }
1230 break;
1231 default:
1232 tcg_abort();
1233 }
1234}
1235
1236static void tcg_out_qemu_st_direct(TCGContext *s, int opc, TCGReg data_r,
1237 TCGReg addr_r, TCGReg off_r)
1238{
1239 switch (opc) {
1240 case 0:
1241 tcg_out_ldst_r(s, LDST_8, LDST_ST, data_r, addr_r, off_r);
1242 break;
1243 case 1:
1244 if (TCG_LDST_BSWAP) {
929f8b55 1245 tcg_out_rev16(s, TCG_TYPE_I32, TCG_REG_TMP, data_r);
6a91c7c9
JK
1246 tcg_out_ldst_r(s, LDST_16, LDST_ST, TCG_REG_TMP, addr_r, off_r);
1247 } else {
1248 tcg_out_ldst_r(s, LDST_16, LDST_ST, data_r, addr_r, off_r);
1249 }
1250 break;
1251 case 2:
1252 if (TCG_LDST_BSWAP) {
929f8b55 1253 tcg_out_rev(s, TCG_TYPE_I32, TCG_REG_TMP, data_r);
6a91c7c9
JK
1254 tcg_out_ldst_r(s, LDST_32, LDST_ST, TCG_REG_TMP, addr_r, off_r);
1255 } else {
1256 tcg_out_ldst_r(s, LDST_32, LDST_ST, data_r, addr_r, off_r);
1257 }
1258 break;
1259 case 3:
1260 if (TCG_LDST_BSWAP) {
929f8b55 1261 tcg_out_rev(s, TCG_TYPE_I64, TCG_REG_TMP, data_r);
6a91c7c9
JK
1262 tcg_out_ldst_r(s, LDST_64, LDST_ST, TCG_REG_TMP, addr_r, off_r);
1263 } else {
1264 tcg_out_ldst_r(s, LDST_64, LDST_ST, data_r, addr_r, off_r);
1265 }
1266 break;
1267 default:
1268 tcg_abort();
1269 }
1270}
4a136e0a
CF
1271
1272static void tcg_out_qemu_ld(TCGContext *s, const TCGArg *args, int opc)
1273{
1274 TCGReg addr_reg, data_reg;
1275#ifdef CONFIG_SOFTMMU
1276 int mem_index, s_bits;
c6d8ed24 1277 uint8_t *label_ptr;
4a136e0a
CF
1278#endif
1279 data_reg = args[0];
1280 addr_reg = args[1];
1281
1282#ifdef CONFIG_SOFTMMU
1283 mem_index = args[2];
1284 s_bits = opc & 3;
c6d8ed24
JK
1285 tcg_out_tlb_read(s, addr_reg, s_bits, &label_ptr, mem_index, 1);
1286 tcg_out_qemu_ld_direct(s, opc, data_reg, addr_reg, TCG_REG_X1);
1287 add_qemu_ldst_label(s, 1, opc, data_reg, addr_reg,
1288 mem_index, s->code_ptr, label_ptr);
4a136e0a 1289#else /* !CONFIG_SOFTMMU */
6a91c7c9
JK
1290 tcg_out_qemu_ld_direct(s, opc, data_reg, addr_reg,
1291 GUEST_BASE ? TCG_REG_GUEST_BASE : TCG_REG_XZR);
1292#endif /* CONFIG_SOFTMMU */
4a136e0a
CF
1293}
1294
1295static void tcg_out_qemu_st(TCGContext *s, const TCGArg *args, int opc)
1296{
1297 TCGReg addr_reg, data_reg;
1298#ifdef CONFIG_SOFTMMU
1299 int mem_index, s_bits;
c6d8ed24 1300 uint8_t *label_ptr;
4a136e0a
CF
1301#endif
1302 data_reg = args[0];
1303 addr_reg = args[1];
1304
1305#ifdef CONFIG_SOFTMMU
1306 mem_index = args[2];
1307 s_bits = opc & 3;
1308
c6d8ed24
JK
1309 tcg_out_tlb_read(s, addr_reg, s_bits, &label_ptr, mem_index, 0);
1310 tcg_out_qemu_st_direct(s, opc, data_reg, addr_reg, TCG_REG_X1);
1311 add_qemu_ldst_label(s, 0, opc, data_reg, addr_reg,
1312 mem_index, s->code_ptr, label_ptr);
4a136e0a 1313#else /* !CONFIG_SOFTMMU */
6a91c7c9
JK
1314 tcg_out_qemu_st_direct(s, opc, data_reg, addr_reg,
1315 GUEST_BASE ? TCG_REG_GUEST_BASE : TCG_REG_XZR);
1316#endif /* CONFIG_SOFTMMU */
4a136e0a
CF
1317}
1318
1319static uint8_t *tb_ret_addr;
1320
4a136e0a 1321static void tcg_out_op(TCGContext *s, TCGOpcode opc,
8d8db193
RH
1322 const TCGArg args[TCG_MAX_OP_ARGS],
1323 const int const_args[TCG_MAX_OP_ARGS])
4a136e0a 1324{
f0293414
RH
1325 /* 99% of the time, we can signal the use of extension registers
1326 by looking to see if the opcode handles 64-bit data. */
1327 TCGType ext = (tcg_op_defs[opc].flags & TCG_OPF_64BIT) != 0;
4a136e0a 1328
8d8db193
RH
1329 /* Hoist the loads of the most common arguments. */
1330 TCGArg a0 = args[0];
1331 TCGArg a1 = args[1];
1332 TCGArg a2 = args[2];
1333 int c2 = const_args[2];
1334
04ce397b
RH
1335 /* Some operands are defined with "rZ" constraint, a register or
1336 the zero register. These need not actually test args[I] == 0. */
1337#define REG0(I) (const_args[I] ? TCG_REG_XZR : (TCGReg)args[I])
1338
4a136e0a
CF
1339 switch (opc) {
1340 case INDEX_op_exit_tb:
8d8db193 1341 tcg_out_movi(s, TCG_TYPE_I64, TCG_REG_X0, a0);
017a86f7 1342 tcg_out_goto(s, (intptr_t)tb_ret_addr);
4a136e0a
CF
1343 break;
1344
1345 case INDEX_op_goto_tb:
1346#ifndef USE_DIRECT_JUMP
1347#error "USE_DIRECT_JUMP required for aarch64"
1348#endif
1349 assert(s->tb_jmp_offset != NULL); /* consistency for USE_DIRECT_JUMP */
8d8db193 1350 s->tb_jmp_offset[a0] = s->code_ptr - s->code_buf;
4a136e0a
CF
1351 /* actual branch destination will be patched by
1352 aarch64_tb_set_jmp_target later, beware retranslation. */
1353 tcg_out_goto_noaddr(s);
8d8db193 1354 s->tb_next_offset[a0] = s->code_ptr - s->code_buf;
4a136e0a
CF
1355 break;
1356
1357 case INDEX_op_call:
1358 if (const_args[0]) {
8d8db193 1359 tcg_out_call(s, a0);
4a136e0a 1360 } else {
8d8db193 1361 tcg_out_callr(s, a0);
4a136e0a
CF
1362 }
1363 break;
1364
1365 case INDEX_op_br:
8d8db193 1366 tcg_out_goto_label(s, a0);
4a136e0a
CF
1367 break;
1368
1369 case INDEX_op_ld_i32:
1370 case INDEX_op_ld_i64:
1371 case INDEX_op_st_i32:
1372 case INDEX_op_st_i64:
1373 case INDEX_op_ld8u_i32:
1374 case INDEX_op_ld8s_i32:
1375 case INDEX_op_ld16u_i32:
1376 case INDEX_op_ld16s_i32:
1377 case INDEX_op_ld8u_i64:
1378 case INDEX_op_ld8s_i64:
1379 case INDEX_op_ld16u_i64:
1380 case INDEX_op_ld16s_i64:
1381 case INDEX_op_ld32u_i64:
1382 case INDEX_op_ld32s_i64:
1383 case INDEX_op_st8_i32:
1384 case INDEX_op_st8_i64:
1385 case INDEX_op_st16_i32:
1386 case INDEX_op_st16_i64:
1387 case INDEX_op_st32_i64:
1388 tcg_out_ldst(s, aarch64_ldst_get_data(opc), aarch64_ldst_get_type(opc),
8d8db193 1389 a0, a1, a2);
4a136e0a
CF
1390 break;
1391
4a136e0a 1392 case INDEX_op_add_i32:
90f1cd91
RH
1393 a2 = (int32_t)a2;
1394 /* FALLTHRU */
1395 case INDEX_op_add_i64:
1396 if (c2) {
1397 tcg_out_addsubi(s, ext, a0, a1, a2);
1398 } else {
1399 tcg_out_insn(s, 3502, ADD, ext, a0, a1, a2);
1400 }
4a136e0a
CF
1401 break;
1402
4a136e0a 1403 case INDEX_op_sub_i32:
90f1cd91
RH
1404 a2 = (int32_t)a2;
1405 /* FALLTHRU */
1406 case INDEX_op_sub_i64:
1407 if (c2) {
1408 tcg_out_addsubi(s, ext, a0, a1, -a2);
1409 } else {
1410 tcg_out_insn(s, 3502, SUB, ext, a0, a1, a2);
1411 }
4a136e0a
CF
1412 break;
1413
14b155dd
RH
1414 case INDEX_op_neg_i64:
1415 case INDEX_op_neg_i32:
1416 tcg_out_insn(s, 3502, SUB, ext, a0, TCG_REG_XZR, a1);
1417 break;
1418
4a136e0a 1419 case INDEX_op_and_i32:
e029f293
RH
1420 a2 = (int32_t)a2;
1421 /* FALLTHRU */
1422 case INDEX_op_and_i64:
1423 if (c2) {
1424 tcg_out_logicali(s, I3404_ANDI, ext, a0, a1, a2);
1425 } else {
1426 tcg_out_insn(s, 3510, AND, ext, a0, a1, a2);
1427 }
4a136e0a
CF
1428 break;
1429
14b155dd
RH
1430 case INDEX_op_andc_i32:
1431 a2 = (int32_t)a2;
1432 /* FALLTHRU */
1433 case INDEX_op_andc_i64:
1434 if (c2) {
1435 tcg_out_logicali(s, I3404_ANDI, ext, a0, a1, ~a2);
1436 } else {
1437 tcg_out_insn(s, 3510, BIC, ext, a0, a1, a2);
1438 }
1439 break;
1440
4a136e0a 1441 case INDEX_op_or_i32:
e029f293
RH
1442 a2 = (int32_t)a2;
1443 /* FALLTHRU */
1444 case INDEX_op_or_i64:
1445 if (c2) {
1446 tcg_out_logicali(s, I3404_ORRI, ext, a0, a1, a2);
1447 } else {
1448 tcg_out_insn(s, 3510, ORR, ext, a0, a1, a2);
1449 }
4a136e0a
CF
1450 break;
1451
14b155dd
RH
1452 case INDEX_op_orc_i32:
1453 a2 = (int32_t)a2;
1454 /* FALLTHRU */
1455 case INDEX_op_orc_i64:
1456 if (c2) {
1457 tcg_out_logicali(s, I3404_ORRI, ext, a0, a1, ~a2);
1458 } else {
1459 tcg_out_insn(s, 3510, ORN, ext, a0, a1, a2);
1460 }
1461 break;
1462
4a136e0a 1463 case INDEX_op_xor_i32:
e029f293
RH
1464 a2 = (int32_t)a2;
1465 /* FALLTHRU */
1466 case INDEX_op_xor_i64:
1467 if (c2) {
1468 tcg_out_logicali(s, I3404_EORI, ext, a0, a1, a2);
1469 } else {
1470 tcg_out_insn(s, 3510, EOR, ext, a0, a1, a2);
1471 }
4a136e0a
CF
1472 break;
1473
14b155dd
RH
1474 case INDEX_op_eqv_i32:
1475 a2 = (int32_t)a2;
1476 /* FALLTHRU */
1477 case INDEX_op_eqv_i64:
1478 if (c2) {
1479 tcg_out_logicali(s, I3404_EORI, ext, a0, a1, ~a2);
1480 } else {
1481 tcg_out_insn(s, 3510, EON, ext, a0, a1, a2);
1482 }
1483 break;
1484
1485 case INDEX_op_not_i64:
1486 case INDEX_op_not_i32:
1487 tcg_out_insn(s, 3510, ORN, ext, a0, TCG_REG_XZR, a1);
1488 break;
1489
4a136e0a 1490 case INDEX_op_mul_i64:
4a136e0a 1491 case INDEX_op_mul_i32:
8678b71c
RH
1492 tcg_out_insn(s, 3509, MADD, ext, a0, a1, a2, TCG_REG_XZR);
1493 break;
1494
1495 case INDEX_op_div_i64:
1496 case INDEX_op_div_i32:
1497 tcg_out_insn(s, 3508, SDIV, ext, a0, a1, a2);
1498 break;
1499 case INDEX_op_divu_i64:
1500 case INDEX_op_divu_i32:
1501 tcg_out_insn(s, 3508, UDIV, ext, a0, a1, a2);
1502 break;
1503
1504 case INDEX_op_rem_i64:
1505 case INDEX_op_rem_i32:
1506 tcg_out_insn(s, 3508, SDIV, ext, TCG_REG_TMP, a1, a2);
1507 tcg_out_insn(s, 3509, MSUB, ext, a0, TCG_REG_TMP, a2, a1);
1508 break;
1509 case INDEX_op_remu_i64:
1510 case INDEX_op_remu_i32:
1511 tcg_out_insn(s, 3508, UDIV, ext, TCG_REG_TMP, a1, a2);
1512 tcg_out_insn(s, 3509, MSUB, ext, a0, TCG_REG_TMP, a2, a1);
4a136e0a
CF
1513 break;
1514
1515 case INDEX_op_shl_i64:
4a136e0a 1516 case INDEX_op_shl_i32:
df9351e3 1517 if (c2) {
8d8db193 1518 tcg_out_shl(s, ext, a0, a1, a2);
df9351e3
RH
1519 } else {
1520 tcg_out_insn(s, 3508, LSLV, ext, a0, a1, a2);
4a136e0a
CF
1521 }
1522 break;
1523
1524 case INDEX_op_shr_i64:
4a136e0a 1525 case INDEX_op_shr_i32:
df9351e3 1526 if (c2) {
8d8db193 1527 tcg_out_shr(s, ext, a0, a1, a2);
df9351e3
RH
1528 } else {
1529 tcg_out_insn(s, 3508, LSRV, ext, a0, a1, a2);
4a136e0a
CF
1530 }
1531 break;
1532
1533 case INDEX_op_sar_i64:
4a136e0a 1534 case INDEX_op_sar_i32:
df9351e3 1535 if (c2) {
8d8db193 1536 tcg_out_sar(s, ext, a0, a1, a2);
df9351e3
RH
1537 } else {
1538 tcg_out_insn(s, 3508, ASRV, ext, a0, a1, a2);
4a136e0a
CF
1539 }
1540 break;
1541
1542 case INDEX_op_rotr_i64:
4a136e0a 1543 case INDEX_op_rotr_i32:
df9351e3 1544 if (c2) {
8d8db193 1545 tcg_out_rotr(s, ext, a0, a1, a2);
df9351e3
RH
1546 } else {
1547 tcg_out_insn(s, 3508, RORV, ext, a0, a1, a2);
4a136e0a
CF
1548 }
1549 break;
1550
1551 case INDEX_op_rotl_i64:
df9351e3
RH
1552 case INDEX_op_rotl_i32:
1553 if (c2) {
8d8db193 1554 tcg_out_rotl(s, ext, a0, a1, a2);
4a136e0a 1555 } else {
50573c66 1556 tcg_out_insn(s, 3502, SUB, 0, TCG_REG_TMP, TCG_REG_XZR, a2);
df9351e3 1557 tcg_out_insn(s, 3508, RORV, ext, a0, a1, TCG_REG_TMP);
4a136e0a
CF
1558 }
1559 break;
1560
8d8db193 1561 case INDEX_op_brcond_i32:
90f1cd91
RH
1562 a1 = (int32_t)a1;
1563 /* FALLTHRU */
1564 case INDEX_op_brcond_i64:
cae1f6f3 1565 tcg_out_brcond(s, ext, a2, a0, a1, const_args[1], args[3]);
4a136e0a
CF
1566 break;
1567
4a136e0a 1568 case INDEX_op_setcond_i32:
90f1cd91
RH
1569 a2 = (int32_t)a2;
1570 /* FALLTHRU */
1571 case INDEX_op_setcond_i64:
1572 tcg_out_cmp(s, ext, a1, a2, c2);
ed7a0aa8
RH
1573 /* Use CSET alias of CSINC Wd, WZR, WZR, invert(cond). */
1574 tcg_out_insn(s, 3506, CSINC, TCG_TYPE_I32, a0, TCG_REG_XZR,
1575 TCG_REG_XZR, tcg_invert_cond(args[3]));
4a136e0a
CF
1576 break;
1577
04ce397b
RH
1578 case INDEX_op_movcond_i32:
1579 a2 = (int32_t)a2;
1580 /* FALLTHRU */
1581 case INDEX_op_movcond_i64:
1582 tcg_out_cmp(s, ext, a1, a2, c2);
1583 tcg_out_insn(s, 3506, CSEL, ext, a0, REG0(3), REG0(4), args[5]);
1584 break;
1585
4a136e0a
CF
1586 case INDEX_op_qemu_ld8u:
1587 tcg_out_qemu_ld(s, args, 0 | 0);
1588 break;
1589 case INDEX_op_qemu_ld8s:
1590 tcg_out_qemu_ld(s, args, 4 | 0);
1591 break;
1592 case INDEX_op_qemu_ld16u:
1593 tcg_out_qemu_ld(s, args, 0 | 1);
1594 break;
1595 case INDEX_op_qemu_ld16s:
1596 tcg_out_qemu_ld(s, args, 4 | 1);
1597 break;
1598 case INDEX_op_qemu_ld32u:
1599 tcg_out_qemu_ld(s, args, 0 | 2);
1600 break;
1601 case INDEX_op_qemu_ld32s:
1602 tcg_out_qemu_ld(s, args, 4 | 2);
1603 break;
1604 case INDEX_op_qemu_ld32:
1605 tcg_out_qemu_ld(s, args, 0 | 2);
1606 break;
1607 case INDEX_op_qemu_ld64:
1608 tcg_out_qemu_ld(s, args, 0 | 3);
1609 break;
1610 case INDEX_op_qemu_st8:
1611 tcg_out_qemu_st(s, args, 0);
1612 break;
1613 case INDEX_op_qemu_st16:
1614 tcg_out_qemu_st(s, args, 1);
1615 break;
1616 case INDEX_op_qemu_st32:
1617 tcg_out_qemu_st(s, args, 2);
1618 break;
1619 case INDEX_op_qemu_st64:
1620 tcg_out_qemu_st(s, args, 3);
1621 break;
1622
9c4a059d 1623 case INDEX_op_bswap32_i64:
f0293414
RH
1624 /* Despite the _i64, this is a 32-bit bswap. */
1625 ext = 0;
1626 /* FALLTHRU */
1627 case INDEX_op_bswap64_i64:
9c4a059d 1628 case INDEX_op_bswap32_i32:
8d8db193 1629 tcg_out_rev(s, ext, a0, a1);
9c4a059d
CF
1630 break;
1631 case INDEX_op_bswap16_i64:
1632 case INDEX_op_bswap16_i32:
929f8b55 1633 tcg_out_rev16(s, TCG_TYPE_I32, a0, a1);
9c4a059d
CF
1634 break;
1635
31f1275b 1636 case INDEX_op_ext8s_i64:
31f1275b 1637 case INDEX_op_ext8s_i32:
929f8b55 1638 tcg_out_sxt(s, ext, MO_8, a0, a1);
31f1275b
CF
1639 break;
1640 case INDEX_op_ext16s_i64:
31f1275b 1641 case INDEX_op_ext16s_i32:
929f8b55 1642 tcg_out_sxt(s, ext, MO_16, a0, a1);
31f1275b
CF
1643 break;
1644 case INDEX_op_ext32s_i64:
929f8b55 1645 tcg_out_sxt(s, TCG_TYPE_I64, MO_32, a0, a1);
31f1275b
CF
1646 break;
1647 case INDEX_op_ext8u_i64:
1648 case INDEX_op_ext8u_i32:
929f8b55 1649 tcg_out_uxt(s, MO_8, a0, a1);
31f1275b
CF
1650 break;
1651 case INDEX_op_ext16u_i64:
1652 case INDEX_op_ext16u_i32:
929f8b55 1653 tcg_out_uxt(s, MO_16, a0, a1);
31f1275b
CF
1654 break;
1655 case INDEX_op_ext32u_i64:
929f8b55 1656 tcg_out_movr(s, TCG_TYPE_I32, a0, a1);
31f1275b
CF
1657 break;
1658
b3c56df7
RH
1659 case INDEX_op_deposit_i64:
1660 case INDEX_op_deposit_i32:
1661 tcg_out_dep(s, ext, a0, REG0(2), args[3], args[4]);
1662 break;
1663
c6e929e7
RH
1664 case INDEX_op_add2_i32:
1665 tcg_out_addsub2(s, TCG_TYPE_I32, a0, a1, REG0(2), REG0(3),
1666 (int32_t)args[4], args[5], const_args[4],
1667 const_args[5], false);
1668 break;
1669 case INDEX_op_add2_i64:
1670 tcg_out_addsub2(s, TCG_TYPE_I64, a0, a1, REG0(2), REG0(3), args[4],
1671 args[5], const_args[4], const_args[5], false);
1672 break;
1673 case INDEX_op_sub2_i32:
1674 tcg_out_addsub2(s, TCG_TYPE_I32, a0, a1, REG0(2), REG0(3),
1675 (int32_t)args[4], args[5], const_args[4],
1676 const_args[5], true);
1677 break;
1678 case INDEX_op_sub2_i64:
1679 tcg_out_addsub2(s, TCG_TYPE_I64, a0, a1, REG0(2), REG0(3), args[4],
1680 args[5], const_args[4], const_args[5], true);
1681 break;
1682
1fcc9ddf
RH
1683 case INDEX_op_muluh_i64:
1684 tcg_out_insn(s, 3508, UMULH, TCG_TYPE_I64, a0, a1, a2);
1685 break;
1686 case INDEX_op_mulsh_i64:
1687 tcg_out_insn(s, 3508, SMULH, TCG_TYPE_I64, a0, a1, a2);
1688 break;
1689
a51a6b6a
RH
1690 case INDEX_op_mov_i64:
1691 case INDEX_op_mov_i32:
1692 case INDEX_op_movi_i64:
1693 case INDEX_op_movi_i32:
1694 /* Always implemented with tcg_out_mov/i, never with tcg_out_op. */
4a136e0a 1695 default:
a51a6b6a
RH
1696 /* Opcode not implemented. */
1697 tcg_abort();
4a136e0a 1698 }
04ce397b
RH
1699
1700#undef REG0
4a136e0a
CF
1701}
1702
1703static const TCGTargetOpDef aarch64_op_defs[] = {
1704 { INDEX_op_exit_tb, { } },
1705 { INDEX_op_goto_tb, { } },
1706 { INDEX_op_call, { "ri" } },
1707 { INDEX_op_br, { } },
1708
1709 { INDEX_op_mov_i32, { "r", "r" } },
1710 { INDEX_op_mov_i64, { "r", "r" } },
1711
1712 { INDEX_op_movi_i32, { "r" } },
1713 { INDEX_op_movi_i64, { "r" } },
1714
1715 { INDEX_op_ld8u_i32, { "r", "r" } },
1716 { INDEX_op_ld8s_i32, { "r", "r" } },
1717 { INDEX_op_ld16u_i32, { "r", "r" } },
1718 { INDEX_op_ld16s_i32, { "r", "r" } },
1719 { INDEX_op_ld_i32, { "r", "r" } },
1720 { INDEX_op_ld8u_i64, { "r", "r" } },
1721 { INDEX_op_ld8s_i64, { "r", "r" } },
1722 { INDEX_op_ld16u_i64, { "r", "r" } },
1723 { INDEX_op_ld16s_i64, { "r", "r" } },
1724 { INDEX_op_ld32u_i64, { "r", "r" } },
1725 { INDEX_op_ld32s_i64, { "r", "r" } },
1726 { INDEX_op_ld_i64, { "r", "r" } },
1727
1728 { INDEX_op_st8_i32, { "r", "r" } },
1729 { INDEX_op_st16_i32, { "r", "r" } },
1730 { INDEX_op_st_i32, { "r", "r" } },
1731 { INDEX_op_st8_i64, { "r", "r" } },
1732 { INDEX_op_st16_i64, { "r", "r" } },
1733 { INDEX_op_st32_i64, { "r", "r" } },
1734 { INDEX_op_st_i64, { "r", "r" } },
1735
90f1cd91
RH
1736 { INDEX_op_add_i32, { "r", "r", "rwA" } },
1737 { INDEX_op_add_i64, { "r", "r", "rA" } },
1738 { INDEX_op_sub_i32, { "r", "r", "rwA" } },
1739 { INDEX_op_sub_i64, { "r", "r", "rA" } },
4a136e0a
CF
1740 { INDEX_op_mul_i32, { "r", "r", "r" } },
1741 { INDEX_op_mul_i64, { "r", "r", "r" } },
8678b71c
RH
1742 { INDEX_op_div_i32, { "r", "r", "r" } },
1743 { INDEX_op_div_i64, { "r", "r", "r" } },
1744 { INDEX_op_divu_i32, { "r", "r", "r" } },
1745 { INDEX_op_divu_i64, { "r", "r", "r" } },
1746 { INDEX_op_rem_i32, { "r", "r", "r" } },
1747 { INDEX_op_rem_i64, { "r", "r", "r" } },
1748 { INDEX_op_remu_i32, { "r", "r", "r" } },
1749 { INDEX_op_remu_i64, { "r", "r", "r" } },
e029f293
RH
1750 { INDEX_op_and_i32, { "r", "r", "rwL" } },
1751 { INDEX_op_and_i64, { "r", "r", "rL" } },
1752 { INDEX_op_or_i32, { "r", "r", "rwL" } },
1753 { INDEX_op_or_i64, { "r", "r", "rL" } },
1754 { INDEX_op_xor_i32, { "r", "r", "rwL" } },
1755 { INDEX_op_xor_i64, { "r", "r", "rL" } },
14b155dd
RH
1756 { INDEX_op_andc_i32, { "r", "r", "rwL" } },
1757 { INDEX_op_andc_i64, { "r", "r", "rL" } },
1758 { INDEX_op_orc_i32, { "r", "r", "rwL" } },
1759 { INDEX_op_orc_i64, { "r", "r", "rL" } },
1760 { INDEX_op_eqv_i32, { "r", "r", "rwL" } },
1761 { INDEX_op_eqv_i64, { "r", "r", "rL" } },
1762
1763 { INDEX_op_neg_i32, { "r", "r" } },
1764 { INDEX_op_neg_i64, { "r", "r" } },
1765 { INDEX_op_not_i32, { "r", "r" } },
1766 { INDEX_op_not_i64, { "r", "r" } },
4a136e0a
CF
1767
1768 { INDEX_op_shl_i32, { "r", "r", "ri" } },
1769 { INDEX_op_shr_i32, { "r", "r", "ri" } },
1770 { INDEX_op_sar_i32, { "r", "r", "ri" } },
1771 { INDEX_op_rotl_i32, { "r", "r", "ri" } },
1772 { INDEX_op_rotr_i32, { "r", "r", "ri" } },
1773 { INDEX_op_shl_i64, { "r", "r", "ri" } },
1774 { INDEX_op_shr_i64, { "r", "r", "ri" } },
1775 { INDEX_op_sar_i64, { "r", "r", "ri" } },
1776 { INDEX_op_rotl_i64, { "r", "r", "ri" } },
1777 { INDEX_op_rotr_i64, { "r", "r", "ri" } },
1778
90f1cd91
RH
1779 { INDEX_op_brcond_i32, { "r", "rwA" } },
1780 { INDEX_op_brcond_i64, { "r", "rA" } },
1781 { INDEX_op_setcond_i32, { "r", "r", "rwA" } },
1782 { INDEX_op_setcond_i64, { "r", "r", "rA" } },
04ce397b
RH
1783 { INDEX_op_movcond_i32, { "r", "r", "rwA", "rZ", "rZ" } },
1784 { INDEX_op_movcond_i64, { "r", "r", "rA", "rZ", "rZ" } },
4a136e0a
CF
1785
1786 { INDEX_op_qemu_ld8u, { "r", "l" } },
1787 { INDEX_op_qemu_ld8s, { "r", "l" } },
1788 { INDEX_op_qemu_ld16u, { "r", "l" } },
1789 { INDEX_op_qemu_ld16s, { "r", "l" } },
1790 { INDEX_op_qemu_ld32u, { "r", "l" } },
1791 { INDEX_op_qemu_ld32s, { "r", "l" } },
1792
1793 { INDEX_op_qemu_ld32, { "r", "l" } },
1794 { INDEX_op_qemu_ld64, { "r", "l" } },
1795
1796 { INDEX_op_qemu_st8, { "l", "l" } },
1797 { INDEX_op_qemu_st16, { "l", "l" } },
1798 { INDEX_op_qemu_st32, { "l", "l" } },
1799 { INDEX_op_qemu_st64, { "l", "l" } },
9c4a059d
CF
1800
1801 { INDEX_op_bswap16_i32, { "r", "r" } },
1802 { INDEX_op_bswap32_i32, { "r", "r" } },
1803 { INDEX_op_bswap16_i64, { "r", "r" } },
1804 { INDEX_op_bswap32_i64, { "r", "r" } },
1805 { INDEX_op_bswap64_i64, { "r", "r" } },
1806
31f1275b
CF
1807 { INDEX_op_ext8s_i32, { "r", "r" } },
1808 { INDEX_op_ext16s_i32, { "r", "r" } },
1809 { INDEX_op_ext8u_i32, { "r", "r" } },
1810 { INDEX_op_ext16u_i32, { "r", "r" } },
1811
1812 { INDEX_op_ext8s_i64, { "r", "r" } },
1813 { INDEX_op_ext16s_i64, { "r", "r" } },
1814 { INDEX_op_ext32s_i64, { "r", "r" } },
1815 { INDEX_op_ext8u_i64, { "r", "r" } },
1816 { INDEX_op_ext16u_i64, { "r", "r" } },
1817 { INDEX_op_ext32u_i64, { "r", "r" } },
1818
b3c56df7
RH
1819 { INDEX_op_deposit_i32, { "r", "0", "rZ" } },
1820 { INDEX_op_deposit_i64, { "r", "0", "rZ" } },
1821
c6e929e7
RH
1822 { INDEX_op_add2_i32, { "r", "r", "rZ", "rZ", "rwA", "rwMZ" } },
1823 { INDEX_op_add2_i64, { "r", "r", "rZ", "rZ", "rA", "rMZ" } },
1824 { INDEX_op_sub2_i32, { "r", "r", "rZ", "rZ", "rwA", "rwMZ" } },
1825 { INDEX_op_sub2_i64, { "r", "r", "rZ", "rZ", "rA", "rMZ" } },
1826
1fcc9ddf
RH
1827 { INDEX_op_muluh_i64, { "r", "r", "r" } },
1828 { INDEX_op_mulsh_i64, { "r", "r", "r" } },
1829
4a136e0a
CF
1830 { -1 },
1831};
1832
1833static void tcg_target_init(TCGContext *s)
1834{
4a136e0a
CF
1835 tcg_regset_set32(tcg_target_available_regs[TCG_TYPE_I32], 0, 0xffffffff);
1836 tcg_regset_set32(tcg_target_available_regs[TCG_TYPE_I64], 0, 0xffffffff);
1837
1838 tcg_regset_set32(tcg_target_call_clobber_regs, 0,
1839 (1 << TCG_REG_X0) | (1 << TCG_REG_X1) |
1840 (1 << TCG_REG_X2) | (1 << TCG_REG_X3) |
1841 (1 << TCG_REG_X4) | (1 << TCG_REG_X5) |
1842 (1 << TCG_REG_X6) | (1 << TCG_REG_X7) |
1843 (1 << TCG_REG_X8) | (1 << TCG_REG_X9) |
1844 (1 << TCG_REG_X10) | (1 << TCG_REG_X11) |
1845 (1 << TCG_REG_X12) | (1 << TCG_REG_X13) |
1846 (1 << TCG_REG_X14) | (1 << TCG_REG_X15) |
1847 (1 << TCG_REG_X16) | (1 << TCG_REG_X17) |
d82b78e4 1848 (1 << TCG_REG_X18) | (1 << TCG_REG_X30));
4a136e0a
CF
1849
1850 tcg_regset_clear(s->reserved_regs);
1851 tcg_regset_set_reg(s->reserved_regs, TCG_REG_SP);
1852 tcg_regset_set_reg(s->reserved_regs, TCG_REG_FP);
1853 tcg_regset_set_reg(s->reserved_regs, TCG_REG_TMP);
1854 tcg_regset_set_reg(s->reserved_regs, TCG_REG_X18); /* platform register */
1855
1856 tcg_add_target_add_op_defs(aarch64_op_defs);
1857}
1858
38d195aa
RH
1859/* Saving pairs: (X19, X20) .. (X27, X28), (X29(fp), X30(lr)). */
1860#define PUSH_SIZE ((30 - 19 + 1) * 8)
1861
1862#define FRAME_SIZE \
1863 ((PUSH_SIZE \
1864 + TCG_STATIC_CALL_ARGS_SIZE \
1865 + CPU_TEMP_BUF_NLONGS * sizeof(long) \
1866 + TCG_TARGET_STACK_ALIGN - 1) \
1867 & ~(TCG_TARGET_STACK_ALIGN - 1))
1868
1869/* We're expecting a 2 byte uleb128 encoded value. */
1870QEMU_BUILD_BUG_ON(FRAME_SIZE >= (1 << 14));
1871
1872/* We're expecting to use a single ADDI insn. */
1873QEMU_BUILD_BUG_ON(FRAME_SIZE - PUSH_SIZE > 0xfff);
1874
4a136e0a
CF
1875static void tcg_target_qemu_prologue(TCGContext *s)
1876{
4a136e0a
CF
1877 TCGReg r;
1878
95f72aa9
RH
1879 /* Push (FP, LR) and allocate space for all saved registers. */
1880 tcg_out_insn(s, 3314, STP, TCG_REG_FP, TCG_REG_LR,
38d195aa 1881 TCG_REG_SP, -PUSH_SIZE, 1, 1);
4a136e0a 1882
d82b78e4 1883 /* Set up frame pointer for canonical unwinding. */
929f8b55 1884 tcg_out_movr_sp(s, TCG_TYPE_I64, TCG_REG_FP, TCG_REG_SP);
4a136e0a 1885
d82b78e4 1886 /* Store callee-preserved regs x19..x28. */
4a136e0a 1887 for (r = TCG_REG_X19; r <= TCG_REG_X27; r += 2) {
95f72aa9
RH
1888 int ofs = (r - TCG_REG_X19 + 2) * 8;
1889 tcg_out_insn(s, 3314, STP, r, r + 1, TCG_REG_SP, ofs, 1, 0);
4a136e0a
CF
1890 }
1891
096c46c0
RH
1892 /* Make stack space for TCG locals. */
1893 tcg_out_insn(s, 3401, SUBI, TCG_TYPE_I64, TCG_REG_SP, TCG_REG_SP,
38d195aa 1894 FRAME_SIZE - PUSH_SIZE);
096c46c0 1895
95f72aa9 1896 /* Inform TCG about how to find TCG locals with register, offset, size. */
4a136e0a
CF
1897 tcg_set_frame(s, TCG_REG_SP, TCG_STATIC_CALL_ARGS_SIZE,
1898 CPU_TEMP_BUF_NLONGS * sizeof(long));
1899
6a91c7c9
JK
1900#if defined(CONFIG_USE_GUEST_BASE)
1901 if (GUEST_BASE) {
1902 tcg_out_movi(s, TCG_TYPE_PTR, TCG_REG_GUEST_BASE, GUEST_BASE);
1903 tcg_regset_set_reg(s->reserved_regs, TCG_REG_GUEST_BASE);
1904 }
1905#endif
1906
4a136e0a 1907 tcg_out_mov(s, TCG_TYPE_PTR, TCG_AREG0, tcg_target_call_iarg_regs[0]);
81d8a5ee 1908 tcg_out_insn(s, 3207, BR, tcg_target_call_iarg_regs[1]);
4a136e0a
CF
1909
1910 tb_ret_addr = s->code_ptr;
1911
096c46c0
RH
1912 /* Remove TCG locals stack space. */
1913 tcg_out_insn(s, 3401, ADDI, TCG_TYPE_I64, TCG_REG_SP, TCG_REG_SP,
38d195aa 1914 FRAME_SIZE - PUSH_SIZE);
4a136e0a 1915
95f72aa9 1916 /* Restore registers x19..x28. */
4a136e0a 1917 for (r = TCG_REG_X19; r <= TCG_REG_X27; r += 2) {
95f72aa9
RH
1918 int ofs = (r - TCG_REG_X19 + 2) * 8;
1919 tcg_out_insn(s, 3314, LDP, r, r + 1, TCG_REG_SP, ofs, 1, 0);
4a136e0a
CF
1920 }
1921
95f72aa9
RH
1922 /* Pop (FP, LR), restore SP to previous frame. */
1923 tcg_out_insn(s, 3314, LDP, TCG_REG_FP, TCG_REG_LR,
38d195aa 1924 TCG_REG_SP, PUSH_SIZE, 0, 1);
81d8a5ee 1925 tcg_out_insn(s, 3207, RET, TCG_REG_LR);
4a136e0a 1926}
38d195aa
RH
1927
1928typedef struct {
1929 DebugFrameCIE cie;
1930 DebugFrameFDEHeader fde;
1931 uint8_t fde_def_cfa[4];
1932 uint8_t fde_reg_ofs[24];
1933} DebugFrame;
1934
1935#define ELF_HOST_MACHINE EM_AARCH64
1936
1937static DebugFrame debug_frame = {
1938 .cie.len = sizeof(DebugFrameCIE)-4, /* length after .len member */
1939 .cie.id = -1,
1940 .cie.version = 1,
1941 .cie.code_align = 1,
1942 .cie.data_align = 0x78, /* sleb128 -8 */
1943 .cie.return_column = TCG_REG_LR,
1944
1945 /* Total FDE size does not include the "len" member. */
1946 .fde.len = sizeof(DebugFrame) - offsetof(DebugFrame, fde.cie_offset),
1947
1948 .fde_def_cfa = {
1949 12, TCG_REG_SP, /* DW_CFA_def_cfa sp, ... */
1950 (FRAME_SIZE & 0x7f) | 0x80, /* ... uleb128 FRAME_SIZE */
1951 (FRAME_SIZE >> 7)
1952 },
1953 .fde_reg_ofs = {
1954 0x80 + 28, 1, /* DW_CFA_offset, x28, -8 */
1955 0x80 + 27, 2, /* DW_CFA_offset, x27, -16 */
1956 0x80 + 26, 3, /* DW_CFA_offset, x26, -24 */
1957 0x80 + 25, 4, /* DW_CFA_offset, x25, -32 */
1958 0x80 + 24, 5, /* DW_CFA_offset, x24, -40 */
1959 0x80 + 23, 6, /* DW_CFA_offset, x23, -48 */
1960 0x80 + 22, 7, /* DW_CFA_offset, x22, -56 */
1961 0x80 + 21, 8, /* DW_CFA_offset, x21, -64 */
1962 0x80 + 20, 9, /* DW_CFA_offset, x20, -72 */
1963 0x80 + 19, 10, /* DW_CFA_offset, x1p, -80 */
1964 0x80 + 30, 11, /* DW_CFA_offset, lr, -88 */
1965 0x80 + 29, 12, /* DW_CFA_offset, fp, -96 */
1966 }
1967};
1968
1969void tcg_register_jit(void *buf, size_t buf_size)
1970{
1971 debug_frame.fde.func_start = (intptr_t)buf;
1972 debug_frame.fde.func_len = buf_size;
1973
1974 tcg_register_jit_int(buf, buf_size, &debug_frame, sizeof(debug_frame));
1975}