linux-user: remove --enable-guest-base/--disable-guest-base
[qemu/ar7.git] / tcg / aarch64 / tcg-target.c
blobb0ddcf2f0883aba4db529a026e6fb30befa0b819
1 /*
2 * Initial TCG Implementation for aarch64
4 * Copyright (c) 2013 Huawei Technologies Duesseldorf GmbH
5 * Written by Claudio Fontana
7 * This work is licensed under the terms of the GNU GPL, version 2 or
8 * (at your option) any later version.
10 * See the COPYING file in the top-level directory for details.
13 #include "tcg-be-ldst.h"
14 #include "qemu/bitops.h"
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. */
19 QEMU_BUILD_BUG_ON(TCG_TYPE_I32 != 0 || TCG_TYPE_I64 != 1);
21 #ifndef NDEBUG
22 static 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",
26 "%x24", "%x25", "%x26", "%x27", "%x28", "%fp", "%x30", "%sp",
28 #endif /* NDEBUG */
30 static const int tcg_target_reg_alloc_order[] = {
31 TCG_REG_X20, TCG_REG_X21, TCG_REG_X22, TCG_REG_X23,
32 TCG_REG_X24, TCG_REG_X25, TCG_REG_X26, TCG_REG_X27,
33 TCG_REG_X28, /* we will reserve this for GUEST_BASE if configured */
35 TCG_REG_X8, TCG_REG_X9, TCG_REG_X10, TCG_REG_X11,
36 TCG_REG_X12, TCG_REG_X13, TCG_REG_X14, TCG_REG_X15,
37 TCG_REG_X16, TCG_REG_X17,
39 TCG_REG_X0, TCG_REG_X1, TCG_REG_X2, TCG_REG_X3,
40 TCG_REG_X4, TCG_REG_X5, TCG_REG_X6, TCG_REG_X7,
42 /* X18 reserved by system */
43 /* X19 reserved for AREG0 */
44 /* X29 reserved as fp */
45 /* X30 reserved as temporary */
48 static const int tcg_target_call_iarg_regs[8] = {
49 TCG_REG_X0, TCG_REG_X1, TCG_REG_X2, TCG_REG_X3,
50 TCG_REG_X4, TCG_REG_X5, TCG_REG_X6, TCG_REG_X7
52 static const int tcg_target_call_oarg_regs[1] = {
53 TCG_REG_X0
56 #define TCG_REG_TMP TCG_REG_X30
58 #ifndef CONFIG_SOFTMMU
59 #define TCG_REG_GUEST_BASE TCG_REG_X28
60 #endif
62 static inline void reloc_pc26(tcg_insn_unit *code_ptr, tcg_insn_unit *target)
64 ptrdiff_t offset = target - code_ptr;
65 assert(offset == sextract64(offset, 0, 26));
66 /* read instruction, mask away previous PC_REL26 parameter contents,
67 set the proper offset, then write back the instruction. */
68 *code_ptr = deposit32(*code_ptr, 0, 26, offset);
71 static inline void reloc_pc19(tcg_insn_unit *code_ptr, tcg_insn_unit *target)
73 ptrdiff_t offset = target - code_ptr;
74 assert(offset == sextract64(offset, 0, 19));
75 *code_ptr = deposit32(*code_ptr, 5, 19, offset);
78 static inline void patch_reloc(tcg_insn_unit *code_ptr, int type,
79 intptr_t value, intptr_t addend)
81 assert(addend == 0);
82 switch (type) {
83 case R_AARCH64_JUMP26:
84 case R_AARCH64_CALL26:
85 reloc_pc26(code_ptr, (tcg_insn_unit *)value);
86 break;
87 case R_AARCH64_CONDBR19:
88 reloc_pc19(code_ptr, (tcg_insn_unit *)value);
89 break;
90 default:
91 tcg_abort();
95 #define TCG_CT_CONST_AIMM 0x100
96 #define TCG_CT_CONST_LIMM 0x200
97 #define TCG_CT_CONST_ZERO 0x400
98 #define TCG_CT_CONST_MONE 0x800
100 /* parse target specific constraints */
101 static int target_parse_constraint(TCGArgConstraint *ct,
102 const char **pct_str)
104 const char *ct_str = *pct_str;
106 switch (ct_str[0]) {
107 case 'r':
108 ct->ct |= TCG_CT_REG;
109 tcg_regset_set32(ct->u.regs, 0, (1ULL << TCG_TARGET_NB_REGS) - 1);
110 break;
111 case 'l': /* qemu_ld / qemu_st address, data_reg */
112 ct->ct |= TCG_CT_REG;
113 tcg_regset_set32(ct->u.regs, 0, (1ULL << TCG_TARGET_NB_REGS) - 1);
114 #ifdef CONFIG_SOFTMMU
115 /* x0 and x1 will be overwritten when reading the tlb entry,
116 and x2, and x3 for helper args, better to avoid using them. */
117 tcg_regset_reset_reg(ct->u.regs, TCG_REG_X0);
118 tcg_regset_reset_reg(ct->u.regs, TCG_REG_X1);
119 tcg_regset_reset_reg(ct->u.regs, TCG_REG_X2);
120 tcg_regset_reset_reg(ct->u.regs, TCG_REG_X3);
121 #endif
122 break;
123 case 'A': /* Valid for arithmetic immediate (positive or negative). */
124 ct->ct |= TCG_CT_CONST_AIMM;
125 break;
126 case 'L': /* Valid for logical immediate. */
127 ct->ct |= TCG_CT_CONST_LIMM;
128 break;
129 case 'M': /* minus one */
130 ct->ct |= TCG_CT_CONST_MONE;
131 break;
132 case 'Z': /* zero */
133 ct->ct |= TCG_CT_CONST_ZERO;
134 break;
135 default:
136 return -1;
139 ct_str++;
140 *pct_str = ct_str;
141 return 0;
144 static inline bool is_aimm(uint64_t val)
146 return (val & ~0xfff) == 0 || (val & ~0xfff000) == 0;
149 static inline bool is_limm(uint64_t val)
151 /* Taking a simplified view of the logical immediates for now, ignoring
152 the replication that can happen across the field. Match bit patterns
153 of the forms
154 0....01....1
155 0..01..10..0
156 and their inverses. */
158 /* Make things easier below, by testing the form with msb clear. */
159 if ((int64_t)val < 0) {
160 val = ~val;
162 if (val == 0) {
163 return false;
165 val += val & -val;
166 return (val & (val - 1)) == 0;
169 static int tcg_target_const_match(tcg_target_long val, TCGType type,
170 const TCGArgConstraint *arg_ct)
172 int ct = arg_ct->ct;
174 if (ct & TCG_CT_CONST) {
175 return 1;
177 if (type == TCG_TYPE_I32) {
178 val = (int32_t)val;
180 if ((ct & TCG_CT_CONST_AIMM) && (is_aimm(val) || is_aimm(-val))) {
181 return 1;
183 if ((ct & TCG_CT_CONST_LIMM) && is_limm(val)) {
184 return 1;
186 if ((ct & TCG_CT_CONST_ZERO) && val == 0) {
187 return 1;
189 if ((ct & TCG_CT_CONST_MONE) && val == -1) {
190 return 1;
193 return 0;
196 enum aarch64_cond_code {
197 COND_EQ = 0x0,
198 COND_NE = 0x1,
199 COND_CS = 0x2, /* Unsigned greater or equal */
200 COND_HS = COND_CS, /* ALIAS greater or equal */
201 COND_CC = 0x3, /* Unsigned less than */
202 COND_LO = COND_CC, /* ALIAS Lower */
203 COND_MI = 0x4, /* Negative */
204 COND_PL = 0x5, /* Zero or greater */
205 COND_VS = 0x6, /* Overflow */
206 COND_VC = 0x7, /* No overflow */
207 COND_HI = 0x8, /* Unsigned greater than */
208 COND_LS = 0x9, /* Unsigned less or equal */
209 COND_GE = 0xa,
210 COND_LT = 0xb,
211 COND_GT = 0xc,
212 COND_LE = 0xd,
213 COND_AL = 0xe,
214 COND_NV = 0xf, /* behaves like COND_AL here */
217 static const enum aarch64_cond_code tcg_cond_to_aarch64[] = {
218 [TCG_COND_EQ] = COND_EQ,
219 [TCG_COND_NE] = COND_NE,
220 [TCG_COND_LT] = COND_LT,
221 [TCG_COND_GE] = COND_GE,
222 [TCG_COND_LE] = COND_LE,
223 [TCG_COND_GT] = COND_GT,
224 /* unsigned */
225 [TCG_COND_LTU] = COND_LO,
226 [TCG_COND_GTU] = COND_HI,
227 [TCG_COND_GEU] = COND_HS,
228 [TCG_COND_LEU] = COND_LS,
231 typedef enum {
232 LDST_ST = 0, /* store */
233 LDST_LD = 1, /* load */
234 LDST_LD_S_X = 2, /* load and sign-extend into Xt */
235 LDST_LD_S_W = 3, /* load and sign-extend into Wt */
236 } AArch64LdstType;
238 /* We encode the format of the insn into the beginning of the name, so that
239 we can have the preprocessor help "typecheck" the insn vs the output
240 function. Arm didn't provide us with nice names for the formats, so we
241 use the section number of the architecture reference manual in which the
242 instruction group is described. */
243 typedef enum {
244 /* Compare and branch (immediate). */
245 I3201_CBZ = 0x34000000,
246 I3201_CBNZ = 0x35000000,
248 /* Conditional branch (immediate). */
249 I3202_B_C = 0x54000000,
251 /* Unconditional branch (immediate). */
252 I3206_B = 0x14000000,
253 I3206_BL = 0x94000000,
255 /* Unconditional branch (register). */
256 I3207_BR = 0xd61f0000,
257 I3207_BLR = 0xd63f0000,
258 I3207_RET = 0xd65f0000,
260 /* Load/store register. Described here as 3.3.12, but the helper
261 that emits them can transform to 3.3.10 or 3.3.13. */
262 I3312_STRB = 0x38000000 | LDST_ST << 22 | MO_8 << 30,
263 I3312_STRH = 0x38000000 | LDST_ST << 22 | MO_16 << 30,
264 I3312_STRW = 0x38000000 | LDST_ST << 22 | MO_32 << 30,
265 I3312_STRX = 0x38000000 | LDST_ST << 22 | MO_64 << 30,
267 I3312_LDRB = 0x38000000 | LDST_LD << 22 | MO_8 << 30,
268 I3312_LDRH = 0x38000000 | LDST_LD << 22 | MO_16 << 30,
269 I3312_LDRW = 0x38000000 | LDST_LD << 22 | MO_32 << 30,
270 I3312_LDRX = 0x38000000 | LDST_LD << 22 | MO_64 << 30,
272 I3312_LDRSBW = 0x38000000 | LDST_LD_S_W << 22 | MO_8 << 30,
273 I3312_LDRSHW = 0x38000000 | LDST_LD_S_W << 22 | MO_16 << 30,
275 I3312_LDRSBX = 0x38000000 | LDST_LD_S_X << 22 | MO_8 << 30,
276 I3312_LDRSHX = 0x38000000 | LDST_LD_S_X << 22 | MO_16 << 30,
277 I3312_LDRSWX = 0x38000000 | LDST_LD_S_X << 22 | MO_32 << 30,
279 I3312_TO_I3310 = 0x00200800,
280 I3312_TO_I3313 = 0x01000000,
282 /* Load/store register pair instructions. */
283 I3314_LDP = 0x28400000,
284 I3314_STP = 0x28000000,
286 /* Add/subtract immediate instructions. */
287 I3401_ADDI = 0x11000000,
288 I3401_ADDSI = 0x31000000,
289 I3401_SUBI = 0x51000000,
290 I3401_SUBSI = 0x71000000,
292 /* Bitfield instructions. */
293 I3402_BFM = 0x33000000,
294 I3402_SBFM = 0x13000000,
295 I3402_UBFM = 0x53000000,
297 /* Extract instruction. */
298 I3403_EXTR = 0x13800000,
300 /* Logical immediate instructions. */
301 I3404_ANDI = 0x12000000,
302 I3404_ORRI = 0x32000000,
303 I3404_EORI = 0x52000000,
305 /* Move wide immediate instructions. */
306 I3405_MOVN = 0x12800000,
307 I3405_MOVZ = 0x52800000,
308 I3405_MOVK = 0x72800000,
310 /* PC relative addressing instructions. */
311 I3406_ADR = 0x10000000,
312 I3406_ADRP = 0x90000000,
314 /* Add/subtract shifted register instructions (without a shift). */
315 I3502_ADD = 0x0b000000,
316 I3502_ADDS = 0x2b000000,
317 I3502_SUB = 0x4b000000,
318 I3502_SUBS = 0x6b000000,
320 /* Add/subtract shifted register instructions (with a shift). */
321 I3502S_ADD_LSL = I3502_ADD,
323 /* Add/subtract with carry instructions. */
324 I3503_ADC = 0x1a000000,
325 I3503_SBC = 0x5a000000,
327 /* Conditional select instructions. */
328 I3506_CSEL = 0x1a800000,
329 I3506_CSINC = 0x1a800400,
331 /* Data-processing (1 source) instructions. */
332 I3507_REV16 = 0x5ac00400,
333 I3507_REV32 = 0x5ac00800,
334 I3507_REV64 = 0x5ac00c00,
336 /* Data-processing (2 source) instructions. */
337 I3508_LSLV = 0x1ac02000,
338 I3508_LSRV = 0x1ac02400,
339 I3508_ASRV = 0x1ac02800,
340 I3508_RORV = 0x1ac02c00,
341 I3508_SMULH = 0x9b407c00,
342 I3508_UMULH = 0x9bc07c00,
343 I3508_UDIV = 0x1ac00800,
344 I3508_SDIV = 0x1ac00c00,
346 /* Data-processing (3 source) instructions. */
347 I3509_MADD = 0x1b000000,
348 I3509_MSUB = 0x1b008000,
350 /* Logical shifted register instructions (without a shift). */
351 I3510_AND = 0x0a000000,
352 I3510_BIC = 0x0a200000,
353 I3510_ORR = 0x2a000000,
354 I3510_ORN = 0x2a200000,
355 I3510_EOR = 0x4a000000,
356 I3510_EON = 0x4a200000,
357 I3510_ANDS = 0x6a000000,
358 } AArch64Insn;
360 static inline uint32_t tcg_in32(TCGContext *s)
362 uint32_t v = *(uint32_t *)s->code_ptr;
363 return v;
366 /* Emit an opcode with "type-checking" of the format. */
367 #define tcg_out_insn(S, FMT, OP, ...) \
368 glue(tcg_out_insn_,FMT)(S, glue(glue(glue(I,FMT),_),OP), ## __VA_ARGS__)
370 static void tcg_out_insn_3201(TCGContext *s, AArch64Insn insn, TCGType ext,
371 TCGReg rt, int imm19)
373 tcg_out32(s, insn | ext << 31 | (imm19 & 0x7ffff) << 5 | rt);
376 static void tcg_out_insn_3202(TCGContext *s, AArch64Insn insn,
377 TCGCond c, int imm19)
379 tcg_out32(s, insn | tcg_cond_to_aarch64[c] | (imm19 & 0x7ffff) << 5);
382 static void tcg_out_insn_3206(TCGContext *s, AArch64Insn insn, int imm26)
384 tcg_out32(s, insn | (imm26 & 0x03ffffff));
387 static void tcg_out_insn_3207(TCGContext *s, AArch64Insn insn, TCGReg rn)
389 tcg_out32(s, insn | rn << 5);
392 static void tcg_out_insn_3314(TCGContext *s, AArch64Insn insn,
393 TCGReg r1, TCGReg r2, TCGReg rn,
394 tcg_target_long ofs, bool pre, bool w)
396 insn |= 1u << 31; /* ext */
397 insn |= pre << 24;
398 insn |= w << 23;
400 assert(ofs >= -0x200 && ofs < 0x200 && (ofs & 7) == 0);
401 insn |= (ofs & (0x7f << 3)) << (15 - 3);
403 tcg_out32(s, insn | r2 << 10 | rn << 5 | r1);
406 static void tcg_out_insn_3401(TCGContext *s, AArch64Insn insn, TCGType ext,
407 TCGReg rd, TCGReg rn, uint64_t aimm)
409 if (aimm > 0xfff) {
410 assert((aimm & 0xfff) == 0);
411 aimm >>= 12;
412 assert(aimm <= 0xfff);
413 aimm |= 1 << 12; /* apply LSL 12 */
415 tcg_out32(s, insn | ext << 31 | aimm << 10 | rn << 5 | rd);
418 /* This function can be used for both 3.4.2 (Bitfield) and 3.4.4
419 (Logical immediate). Both insn groups have N, IMMR and IMMS fields
420 that feed the DecodeBitMasks pseudo function. */
421 static void tcg_out_insn_3402(TCGContext *s, AArch64Insn insn, TCGType ext,
422 TCGReg rd, TCGReg rn, int n, int immr, int imms)
424 tcg_out32(s, insn | ext << 31 | n << 22 | immr << 16 | imms << 10
425 | rn << 5 | rd);
428 #define tcg_out_insn_3404 tcg_out_insn_3402
430 static void tcg_out_insn_3403(TCGContext *s, AArch64Insn insn, TCGType ext,
431 TCGReg rd, TCGReg rn, TCGReg rm, int imms)
433 tcg_out32(s, insn | ext << 31 | ext << 22 | rm << 16 | imms << 10
434 | rn << 5 | rd);
437 /* This function is used for the Move (wide immediate) instruction group.
438 Note that SHIFT is a full shift count, not the 2 bit HW field. */
439 static void tcg_out_insn_3405(TCGContext *s, AArch64Insn insn, TCGType ext,
440 TCGReg rd, uint16_t half, unsigned shift)
442 assert((shift & ~0x30) == 0);
443 tcg_out32(s, insn | ext << 31 | shift << (21 - 4) | half << 5 | rd);
446 static void tcg_out_insn_3406(TCGContext *s, AArch64Insn insn,
447 TCGReg rd, int64_t disp)
449 tcg_out32(s, insn | (disp & 3) << 29 | (disp & 0x1ffffc) << (5 - 2) | rd);
452 /* This function is for both 3.5.2 (Add/Subtract shifted register), for
453 the rare occasion when we actually want to supply a shift amount. */
454 static inline void tcg_out_insn_3502S(TCGContext *s, AArch64Insn insn,
455 TCGType ext, TCGReg rd, TCGReg rn,
456 TCGReg rm, int imm6)
458 tcg_out32(s, insn | ext << 31 | rm << 16 | imm6 << 10 | rn << 5 | rd);
461 /* This function is for 3.5.2 (Add/subtract shifted register),
462 and 3.5.10 (Logical shifted register), for the vast majorty of cases
463 when we don't want to apply a shift. Thus it can also be used for
464 3.5.3 (Add/subtract with carry) and 3.5.8 (Data processing 2 source). */
465 static void tcg_out_insn_3502(TCGContext *s, AArch64Insn insn, TCGType ext,
466 TCGReg rd, TCGReg rn, TCGReg rm)
468 tcg_out32(s, insn | ext << 31 | rm << 16 | rn << 5 | rd);
471 #define tcg_out_insn_3503 tcg_out_insn_3502
472 #define tcg_out_insn_3508 tcg_out_insn_3502
473 #define tcg_out_insn_3510 tcg_out_insn_3502
475 static void tcg_out_insn_3506(TCGContext *s, AArch64Insn insn, TCGType ext,
476 TCGReg rd, TCGReg rn, TCGReg rm, TCGCond c)
478 tcg_out32(s, insn | ext << 31 | rm << 16 | rn << 5 | rd
479 | tcg_cond_to_aarch64[c] << 12);
482 static void tcg_out_insn_3507(TCGContext *s, AArch64Insn insn, TCGType ext,
483 TCGReg rd, TCGReg rn)
485 tcg_out32(s, insn | ext << 31 | rn << 5 | rd);
488 static void tcg_out_insn_3509(TCGContext *s, AArch64Insn insn, TCGType ext,
489 TCGReg rd, TCGReg rn, TCGReg rm, TCGReg ra)
491 tcg_out32(s, insn | ext << 31 | rm << 16 | ra << 10 | rn << 5 | rd);
494 static void tcg_out_insn_3310(TCGContext *s, AArch64Insn insn,
495 TCGReg rd, TCGReg base, TCGType ext,
496 TCGReg regoff)
498 /* Note the AArch64Insn constants above are for C3.3.12. Adjust. */
499 tcg_out32(s, insn | I3312_TO_I3310 | regoff << 16 |
500 0x4000 | ext << 13 | base << 5 | rd);
503 static void tcg_out_insn_3312(TCGContext *s, AArch64Insn insn,
504 TCGReg rd, TCGReg rn, intptr_t offset)
506 tcg_out32(s, insn | (offset & 0x1ff) << 12 | rn << 5 | rd);
509 static void tcg_out_insn_3313(TCGContext *s, AArch64Insn insn,
510 TCGReg rd, TCGReg rn, uintptr_t scaled_uimm)
512 /* Note the AArch64Insn constants above are for C3.3.12. Adjust. */
513 tcg_out32(s, insn | I3312_TO_I3313 | scaled_uimm << 10 | rn << 5 | rd);
516 /* Register to register move using ORR (shifted register with no shift). */
517 static void tcg_out_movr(TCGContext *s, TCGType ext, TCGReg rd, TCGReg rm)
519 tcg_out_insn(s, 3510, ORR, ext, rd, TCG_REG_XZR, rm);
522 /* Register to register move using ADDI (move to/from SP). */
523 static void tcg_out_movr_sp(TCGContext *s, TCGType ext, TCGReg rd, TCGReg rn)
525 tcg_out_insn(s, 3401, ADDI, ext, rd, rn, 0);
528 /* This function is used for the Logical (immediate) instruction group.
529 The value of LIMM must satisfy IS_LIMM. See the comment above about
530 only supporting simplified logical immediates. */
531 static void tcg_out_logicali(TCGContext *s, AArch64Insn insn, TCGType ext,
532 TCGReg rd, TCGReg rn, uint64_t limm)
534 unsigned h, l, r, c;
536 assert(is_limm(limm));
538 h = clz64(limm);
539 l = ctz64(limm);
540 if (l == 0) {
541 r = 0; /* form 0....01....1 */
542 c = ctz64(~limm) - 1;
543 if (h == 0) {
544 r = clz64(~limm); /* form 1..10..01..1 */
545 c += r;
547 } else {
548 r = 64 - l; /* form 1....10....0 or 0..01..10..0 */
549 c = r - h - 1;
551 if (ext == TCG_TYPE_I32) {
552 r &= 31;
553 c &= 31;
556 tcg_out_insn_3404(s, insn, ext, rd, rn, ext, r, c);
559 static void tcg_out_movi(TCGContext *s, TCGType type, TCGReg rd,
560 tcg_target_long value)
562 AArch64Insn insn;
563 int i, wantinv, shift;
564 tcg_target_long svalue = value;
565 tcg_target_long ivalue = ~value;
566 tcg_target_long imask;
568 /* For 32-bit values, discard potential garbage in value. For 64-bit
569 values within [2**31, 2**32-1], we can create smaller sequences by
570 interpreting this as a negative 32-bit number, while ensuring that
571 the high 32 bits are cleared by setting SF=0. */
572 if (type == TCG_TYPE_I32 || (value & ~0xffffffffull) == 0) {
573 svalue = (int32_t)value;
574 value = (uint32_t)value;
575 ivalue = (uint32_t)ivalue;
576 type = TCG_TYPE_I32;
579 /* Speed things up by handling the common case of small positive
580 and negative values specially. */
581 if ((value & ~0xffffull) == 0) {
582 tcg_out_insn(s, 3405, MOVZ, type, rd, value, 0);
583 return;
584 } else if ((ivalue & ~0xffffull) == 0) {
585 tcg_out_insn(s, 3405, MOVN, type, rd, ivalue, 0);
586 return;
589 /* Check for bitfield immediates. For the benefit of 32-bit quantities,
590 use the sign-extended value. That lets us match rotated values such
591 as 0xff0000ff with the same 64-bit logic matching 0xffffffffff0000ff. */
592 if (is_limm(svalue)) {
593 tcg_out_logicali(s, I3404_ORRI, type, rd, TCG_REG_XZR, svalue);
594 return;
597 /* Look for host pointer values within 4G of the PC. This happens
598 often when loading pointers to QEMU's own data structures. */
599 if (type == TCG_TYPE_I64) {
600 tcg_target_long disp = (value >> 12) - ((intptr_t)s->code_ptr >> 12);
601 if (disp == sextract64(disp, 0, 21)) {
602 tcg_out_insn(s, 3406, ADRP, rd, disp);
603 if (value & 0xfff) {
604 tcg_out_insn(s, 3401, ADDI, type, rd, rd, value & 0xfff);
606 return;
610 /* Would it take fewer insns to begin with MOVN? For the value and its
611 inverse, count the number of 16-bit lanes that are 0. */
612 for (i = wantinv = imask = 0; i < 64; i += 16) {
613 tcg_target_long mask = 0xffffull << i;
614 if ((value & mask) == 0) {
615 wantinv -= 1;
617 if ((ivalue & mask) == 0) {
618 wantinv += 1;
619 imask |= mask;
623 /* If we had more 0xffff than 0x0000, invert VALUE and use MOVN. */
624 insn = I3405_MOVZ;
625 if (wantinv > 0) {
626 value = ivalue;
627 insn = I3405_MOVN;
630 /* Find the lowest lane that is not 0x0000. */
631 shift = ctz64(value) & (63 & -16);
632 tcg_out_insn_3405(s, insn, type, rd, value >> shift, shift);
634 if (wantinv > 0) {
635 /* Re-invert the value, so MOVK sees non-inverted bits. */
636 value = ~value;
637 /* Clear out all the 0xffff lanes. */
638 value ^= imask;
640 /* Clear out the lane that we just set. */
641 value &= ~(0xffffUL << shift);
643 /* Iterate until all lanes have been set, and thus cleared from VALUE. */
644 while (value) {
645 shift = ctz64(value) & (63 & -16);
646 tcg_out_insn(s, 3405, MOVK, type, rd, value >> shift, shift);
647 value &= ~(0xffffUL << shift);
651 /* Define something more legible for general use. */
652 #define tcg_out_ldst_r tcg_out_insn_3310
654 static void tcg_out_ldst(TCGContext *s, AArch64Insn insn,
655 TCGReg rd, TCGReg rn, intptr_t offset)
657 TCGMemOp size = (uint32_t)insn >> 30;
659 /* If the offset is naturally aligned and in range, then we can
660 use the scaled uimm12 encoding */
661 if (offset >= 0 && !(offset & ((1 << size) - 1))) {
662 uintptr_t scaled_uimm = offset >> size;
663 if (scaled_uimm <= 0xfff) {
664 tcg_out_insn_3313(s, insn, rd, rn, scaled_uimm);
665 return;
669 /* Small signed offsets can use the unscaled encoding. */
670 if (offset >= -256 && offset < 256) {
671 tcg_out_insn_3312(s, insn, rd, rn, offset);
672 return;
675 /* Worst-case scenario, move offset to temp register, use reg offset. */
676 tcg_out_movi(s, TCG_TYPE_I64, TCG_REG_TMP, offset);
677 tcg_out_ldst_r(s, insn, rd, rn, TCG_TYPE_I64, TCG_REG_TMP);
680 static inline void tcg_out_mov(TCGContext *s,
681 TCGType type, TCGReg ret, TCGReg arg)
683 if (ret != arg) {
684 tcg_out_movr(s, type, ret, arg);
688 static inline void tcg_out_ld(TCGContext *s, TCGType type, TCGReg arg,
689 TCGReg arg1, intptr_t arg2)
691 tcg_out_ldst(s, type == TCG_TYPE_I32 ? I3312_LDRW : I3312_LDRX,
692 arg, arg1, arg2);
695 static inline void tcg_out_st(TCGContext *s, TCGType type, TCGReg arg,
696 TCGReg arg1, intptr_t arg2)
698 tcg_out_ldst(s, type == TCG_TYPE_I32 ? I3312_STRW : I3312_STRX,
699 arg, arg1, arg2);
702 static inline void tcg_out_bfm(TCGContext *s, TCGType ext, TCGReg rd,
703 TCGReg rn, unsigned int a, unsigned int b)
705 tcg_out_insn(s, 3402, BFM, ext, rd, rn, ext, a, b);
708 static inline void tcg_out_ubfm(TCGContext *s, TCGType ext, TCGReg rd,
709 TCGReg rn, unsigned int a, unsigned int b)
711 tcg_out_insn(s, 3402, UBFM, ext, rd, rn, ext, a, b);
714 static inline void tcg_out_sbfm(TCGContext *s, TCGType ext, TCGReg rd,
715 TCGReg rn, unsigned int a, unsigned int b)
717 tcg_out_insn(s, 3402, SBFM, ext, rd, rn, ext, a, b);
720 static inline void tcg_out_extr(TCGContext *s, TCGType ext, TCGReg rd,
721 TCGReg rn, TCGReg rm, unsigned int a)
723 tcg_out_insn(s, 3403, EXTR, ext, rd, rn, rm, a);
726 static inline void tcg_out_shl(TCGContext *s, TCGType ext,
727 TCGReg rd, TCGReg rn, unsigned int m)
729 int bits = ext ? 64 : 32;
730 int max = bits - 1;
731 tcg_out_ubfm(s, ext, rd, rn, bits - (m & max), max - (m & max));
734 static inline void tcg_out_shr(TCGContext *s, TCGType ext,
735 TCGReg rd, TCGReg rn, unsigned int m)
737 int max = ext ? 63 : 31;
738 tcg_out_ubfm(s, ext, rd, rn, m & max, max);
741 static inline void tcg_out_sar(TCGContext *s, TCGType ext,
742 TCGReg rd, TCGReg rn, unsigned int m)
744 int max = ext ? 63 : 31;
745 tcg_out_sbfm(s, ext, rd, rn, m & max, max);
748 static inline void tcg_out_rotr(TCGContext *s, TCGType ext,
749 TCGReg rd, TCGReg rn, unsigned int m)
751 int max = ext ? 63 : 31;
752 tcg_out_extr(s, ext, rd, rn, rn, m & max);
755 static inline void tcg_out_rotl(TCGContext *s, TCGType ext,
756 TCGReg rd, TCGReg rn, unsigned int m)
758 int bits = ext ? 64 : 32;
759 int max = bits - 1;
760 tcg_out_extr(s, ext, rd, rn, rn, bits - (m & max));
763 static inline void tcg_out_dep(TCGContext *s, TCGType ext, TCGReg rd,
764 TCGReg rn, unsigned lsb, unsigned width)
766 unsigned size = ext ? 64 : 32;
767 unsigned a = (size - lsb) & (size - 1);
768 unsigned b = width - 1;
769 tcg_out_bfm(s, ext, rd, rn, a, b);
772 static void tcg_out_cmp(TCGContext *s, TCGType ext, TCGReg a,
773 tcg_target_long b, bool const_b)
775 if (const_b) {
776 /* Using CMP or CMN aliases. */
777 if (b >= 0) {
778 tcg_out_insn(s, 3401, SUBSI, ext, TCG_REG_XZR, a, b);
779 } else {
780 tcg_out_insn(s, 3401, ADDSI, ext, TCG_REG_XZR, a, -b);
782 } else {
783 /* Using CMP alias SUBS wzr, Wn, Wm */
784 tcg_out_insn(s, 3502, SUBS, ext, TCG_REG_XZR, a, b);
788 static inline void tcg_out_goto(TCGContext *s, tcg_insn_unit *target)
790 ptrdiff_t offset = target - s->code_ptr;
791 assert(offset == sextract64(offset, 0, 26));
792 tcg_out_insn(s, 3206, B, offset);
795 static inline void tcg_out_goto_noaddr(TCGContext *s)
797 /* We pay attention here to not modify the branch target by reading from
798 the buffer. This ensure that caches and memory are kept coherent during
799 retranslation. Mask away possible garbage in the high bits for the
800 first translation, while keeping the offset bits for retranslation. */
801 uint32_t old = tcg_in32(s);
802 tcg_out_insn(s, 3206, B, old);
805 static inline void tcg_out_goto_cond_noaddr(TCGContext *s, TCGCond c)
807 /* See comments in tcg_out_goto_noaddr. */
808 uint32_t old = tcg_in32(s) >> 5;
809 tcg_out_insn(s, 3202, B_C, c, old);
812 static inline void tcg_out_callr(TCGContext *s, TCGReg reg)
814 tcg_out_insn(s, 3207, BLR, reg);
817 static inline void tcg_out_call(TCGContext *s, tcg_insn_unit *target)
819 ptrdiff_t offset = target - s->code_ptr;
820 if (offset == sextract64(offset, 0, 26)) {
821 tcg_out_insn(s, 3206, BL, offset);
822 } else {
823 tcg_out_movi(s, TCG_TYPE_I64, TCG_REG_TMP, (intptr_t)target);
824 tcg_out_callr(s, TCG_REG_TMP);
828 void aarch64_tb_set_jmp_target(uintptr_t jmp_addr, uintptr_t addr)
830 tcg_insn_unit *code_ptr = (tcg_insn_unit *)jmp_addr;
831 tcg_insn_unit *target = (tcg_insn_unit *)addr;
833 reloc_pc26(code_ptr, target);
834 flush_icache_range(jmp_addr, jmp_addr + 4);
837 static inline void tcg_out_goto_label(TCGContext *s, TCGLabel *l)
839 if (!l->has_value) {
840 tcg_out_reloc(s, s->code_ptr, R_AARCH64_JUMP26, l, 0);
841 tcg_out_goto_noaddr(s);
842 } else {
843 tcg_out_goto(s, l->u.value_ptr);
847 static void tcg_out_brcond(TCGContext *s, TCGMemOp ext, TCGCond c, TCGArg a,
848 TCGArg b, bool b_const, TCGLabel *l)
850 intptr_t offset;
851 bool need_cmp;
853 if (b_const && b == 0 && (c == TCG_COND_EQ || c == TCG_COND_NE)) {
854 need_cmp = false;
855 } else {
856 need_cmp = true;
857 tcg_out_cmp(s, ext, a, b, b_const);
860 if (!l->has_value) {
861 tcg_out_reloc(s, s->code_ptr, R_AARCH64_CONDBR19, l, 0);
862 offset = tcg_in32(s) >> 5;
863 } else {
864 offset = l->u.value_ptr - s->code_ptr;
865 assert(offset == sextract64(offset, 0, 19));
868 if (need_cmp) {
869 tcg_out_insn(s, 3202, B_C, c, offset);
870 } else if (c == TCG_COND_EQ) {
871 tcg_out_insn(s, 3201, CBZ, ext, a, offset);
872 } else {
873 tcg_out_insn(s, 3201, CBNZ, ext, a, offset);
877 static inline void tcg_out_rev64(TCGContext *s, TCGReg rd, TCGReg rn)
879 tcg_out_insn(s, 3507, REV64, TCG_TYPE_I64, rd, rn);
882 static inline void tcg_out_rev32(TCGContext *s, TCGReg rd, TCGReg rn)
884 tcg_out_insn(s, 3507, REV32, TCG_TYPE_I32, rd, rn);
887 static inline void tcg_out_rev16(TCGContext *s, TCGReg rd, TCGReg rn)
889 tcg_out_insn(s, 3507, REV16, TCG_TYPE_I32, rd, rn);
892 static inline void tcg_out_sxt(TCGContext *s, TCGType ext, TCGMemOp s_bits,
893 TCGReg rd, TCGReg rn)
895 /* Using ALIASes SXTB, SXTH, SXTW, of SBFM Xd, Xn, #0, #7|15|31 */
896 int bits = (8 << s_bits) - 1;
897 tcg_out_sbfm(s, ext, rd, rn, 0, bits);
900 static inline void tcg_out_uxt(TCGContext *s, TCGMemOp s_bits,
901 TCGReg rd, TCGReg rn)
903 /* Using ALIASes UXTB, UXTH of UBFM Wd, Wn, #0, #7|15 */
904 int bits = (8 << s_bits) - 1;
905 tcg_out_ubfm(s, 0, rd, rn, 0, bits);
908 static void tcg_out_addsubi(TCGContext *s, int ext, TCGReg rd,
909 TCGReg rn, int64_t aimm)
911 if (aimm >= 0) {
912 tcg_out_insn(s, 3401, ADDI, ext, rd, rn, aimm);
913 } else {
914 tcg_out_insn(s, 3401, SUBI, ext, rd, rn, -aimm);
918 static inline void tcg_out_addsub2(TCGContext *s, int ext, TCGReg rl,
919 TCGReg rh, TCGReg al, TCGReg ah,
920 tcg_target_long bl, tcg_target_long bh,
921 bool const_bl, bool const_bh, bool sub)
923 TCGReg orig_rl = rl;
924 AArch64Insn insn;
926 if (rl == ah || (!const_bh && rl == bh)) {
927 rl = TCG_REG_TMP;
930 if (const_bl) {
931 insn = I3401_ADDSI;
932 if ((bl < 0) ^ sub) {
933 insn = I3401_SUBSI;
934 bl = -bl;
936 tcg_out_insn_3401(s, insn, ext, rl, al, bl);
937 } else {
938 tcg_out_insn_3502(s, sub ? I3502_SUBS : I3502_ADDS, ext, rl, al, bl);
941 insn = I3503_ADC;
942 if (const_bh) {
943 /* Note that the only two constants we support are 0 and -1, and
944 that SBC = rn + ~rm + c, so adc -1 is sbc 0, and vice-versa. */
945 if ((bh != 0) ^ sub) {
946 insn = I3503_SBC;
948 bh = TCG_REG_XZR;
949 } else if (sub) {
950 insn = I3503_SBC;
952 tcg_out_insn_3503(s, insn, ext, rh, ah, bh);
954 tcg_out_mov(s, ext, orig_rl, rl);
957 #ifdef CONFIG_SOFTMMU
958 /* helper signature: helper_ret_ld_mmu(CPUState *env, target_ulong addr,
959 * TCGMemOpIdx oi, uintptr_t ra)
961 static void * const qemu_ld_helpers[16] = {
962 [MO_UB] = helper_ret_ldub_mmu,
963 [MO_LEUW] = helper_le_lduw_mmu,
964 [MO_LEUL] = helper_le_ldul_mmu,
965 [MO_LEQ] = helper_le_ldq_mmu,
966 [MO_BEUW] = helper_be_lduw_mmu,
967 [MO_BEUL] = helper_be_ldul_mmu,
968 [MO_BEQ] = helper_be_ldq_mmu,
971 /* helper signature: helper_ret_st_mmu(CPUState *env, target_ulong addr,
972 * uintxx_t val, TCGMemOpIdx oi,
973 * uintptr_t ra)
975 static void * const qemu_st_helpers[16] = {
976 [MO_UB] = helper_ret_stb_mmu,
977 [MO_LEUW] = helper_le_stw_mmu,
978 [MO_LEUL] = helper_le_stl_mmu,
979 [MO_LEQ] = helper_le_stq_mmu,
980 [MO_BEUW] = helper_be_stw_mmu,
981 [MO_BEUL] = helper_be_stl_mmu,
982 [MO_BEQ] = helper_be_stq_mmu,
985 static inline void tcg_out_adr(TCGContext *s, TCGReg rd, void *target)
987 ptrdiff_t offset = tcg_pcrel_diff(s, target);
988 assert(offset == sextract64(offset, 0, 21));
989 tcg_out_insn(s, 3406, ADR, rd, offset);
992 static void tcg_out_qemu_ld_slow_path(TCGContext *s, TCGLabelQemuLdst *lb)
994 TCGMemOpIdx oi = lb->oi;
995 TCGMemOp opc = get_memop(oi);
996 TCGMemOp size = opc & MO_SIZE;
998 reloc_pc19(lb->label_ptr[0], s->code_ptr);
1000 tcg_out_mov(s, TCG_TYPE_PTR, TCG_REG_X0, TCG_AREG0);
1001 tcg_out_mov(s, TARGET_LONG_BITS == 64, TCG_REG_X1, lb->addrlo_reg);
1002 tcg_out_movi(s, TCG_TYPE_I32, TCG_REG_X2, oi);
1003 tcg_out_adr(s, TCG_REG_X3, lb->raddr);
1004 tcg_out_call(s, qemu_ld_helpers[opc & (MO_BSWAP | MO_SIZE)]);
1005 if (opc & MO_SIGN) {
1006 tcg_out_sxt(s, lb->type, size, lb->datalo_reg, TCG_REG_X0);
1007 } else {
1008 tcg_out_mov(s, size == MO_64, lb->datalo_reg, TCG_REG_X0);
1011 tcg_out_goto(s, lb->raddr);
1014 static void tcg_out_qemu_st_slow_path(TCGContext *s, TCGLabelQemuLdst *lb)
1016 TCGMemOpIdx oi = lb->oi;
1017 TCGMemOp opc = get_memop(oi);
1018 TCGMemOp size = opc & MO_SIZE;
1020 reloc_pc19(lb->label_ptr[0], s->code_ptr);
1022 tcg_out_mov(s, TCG_TYPE_PTR, TCG_REG_X0, TCG_AREG0);
1023 tcg_out_mov(s, TARGET_LONG_BITS == 64, TCG_REG_X1, lb->addrlo_reg);
1024 tcg_out_mov(s, size == MO_64, TCG_REG_X2, lb->datalo_reg);
1025 tcg_out_movi(s, TCG_TYPE_I32, TCG_REG_X3, oi);
1026 tcg_out_adr(s, TCG_REG_X4, lb->raddr);
1027 tcg_out_call(s, qemu_st_helpers[opc & (MO_BSWAP | MO_SIZE)]);
1028 tcg_out_goto(s, lb->raddr);
1031 static void add_qemu_ldst_label(TCGContext *s, bool is_ld, TCGMemOpIdx oi,
1032 TCGType ext, TCGReg data_reg, TCGReg addr_reg,
1033 tcg_insn_unit *raddr, tcg_insn_unit *label_ptr)
1035 TCGLabelQemuLdst *label = new_ldst_label(s);
1037 label->is_ld = is_ld;
1038 label->oi = oi;
1039 label->type = ext;
1040 label->datalo_reg = data_reg;
1041 label->addrlo_reg = addr_reg;
1042 label->raddr = raddr;
1043 label->label_ptr[0] = label_ptr;
1046 /* Load and compare a TLB entry, emitting the conditional jump to the
1047 slow path for the failure case, which will be patched later when finalizing
1048 the slow path. Generated code returns the host addend in X1,
1049 clobbers X0,X2,X3,TMP. */
1050 static void tcg_out_tlb_read(TCGContext *s, TCGReg addr_reg, TCGMemOp opc,
1051 tcg_insn_unit **label_ptr, int mem_index,
1052 bool is_read)
1054 int tlb_offset = is_read ?
1055 offsetof(CPUArchState, tlb_table[mem_index][0].addr_read)
1056 : offsetof(CPUArchState, tlb_table[mem_index][0].addr_write);
1057 int s_mask = (1 << (opc & MO_SIZE)) - 1;
1058 TCGReg base = TCG_AREG0, x3;
1059 uint64_t tlb_mask;
1061 /* For aligned accesses, we check the first byte and include the alignment
1062 bits within the address. For unaligned access, we check that we don't
1063 cross pages using the address of the last byte of the access. */
1064 if ((opc & MO_AMASK) == MO_ALIGN || s_mask == 0) {
1065 tlb_mask = TARGET_PAGE_MASK | s_mask;
1066 x3 = addr_reg;
1067 } else {
1068 tcg_out_insn(s, 3401, ADDI, TARGET_LONG_BITS == 64,
1069 TCG_REG_X3, addr_reg, s_mask);
1070 tlb_mask = TARGET_PAGE_MASK;
1071 x3 = TCG_REG_X3;
1074 /* Extract the TLB index from the address into X0.
1075 X0<CPU_TLB_BITS:0> =
1076 addr_reg<TARGET_PAGE_BITS+CPU_TLB_BITS:TARGET_PAGE_BITS> */
1077 tcg_out_ubfm(s, TARGET_LONG_BITS == 64, TCG_REG_X0, addr_reg,
1078 TARGET_PAGE_BITS, TARGET_PAGE_BITS + CPU_TLB_BITS);
1080 /* Store the page mask part of the address into X3. */
1081 tcg_out_logicali(s, I3404_ANDI, TARGET_LONG_BITS == 64,
1082 TCG_REG_X3, x3, tlb_mask);
1084 /* Add any "high bits" from the tlb offset to the env address into X2,
1085 to take advantage of the LSL12 form of the ADDI instruction.
1086 X2 = env + (tlb_offset & 0xfff000) */
1087 if (tlb_offset & 0xfff000) {
1088 tcg_out_insn(s, 3401, ADDI, TCG_TYPE_I64, TCG_REG_X2, base,
1089 tlb_offset & 0xfff000);
1090 base = TCG_REG_X2;
1093 /* Merge the tlb index contribution into X2.
1094 X2 = X2 + (X0 << CPU_TLB_ENTRY_BITS) */
1095 tcg_out_insn(s, 3502S, ADD_LSL, TCG_TYPE_I64, TCG_REG_X2, base,
1096 TCG_REG_X0, CPU_TLB_ENTRY_BITS);
1098 /* Merge "low bits" from tlb offset, load the tlb comparator into X0.
1099 X0 = load [X2 + (tlb_offset & 0x000fff)] */
1100 tcg_out_ldst(s, TARGET_LONG_BITS == 32 ? I3312_LDRW : I3312_LDRX,
1101 TCG_REG_X0, TCG_REG_X2, tlb_offset & 0xfff);
1103 /* Load the tlb addend. Do that early to avoid stalling.
1104 X1 = load [X2 + (tlb_offset & 0xfff) + offsetof(addend)] */
1105 tcg_out_ldst(s, I3312_LDRX, TCG_REG_X1, TCG_REG_X2,
1106 (tlb_offset & 0xfff) + (offsetof(CPUTLBEntry, addend)) -
1107 (is_read ? offsetof(CPUTLBEntry, addr_read)
1108 : offsetof(CPUTLBEntry, addr_write)));
1110 /* Perform the address comparison. */
1111 tcg_out_cmp(s, (TARGET_LONG_BITS == 64), TCG_REG_X0, TCG_REG_X3, 0);
1113 /* If not equal, we jump to the slow path. */
1114 *label_ptr = s->code_ptr;
1115 tcg_out_goto_cond_noaddr(s, TCG_COND_NE);
1118 #endif /* CONFIG_SOFTMMU */
1120 static void tcg_out_qemu_ld_direct(TCGContext *s, TCGMemOp memop, TCGType ext,
1121 TCGReg data_r, TCGReg addr_r,
1122 TCGType otype, TCGReg off_r)
1124 const TCGMemOp bswap = memop & MO_BSWAP;
1126 switch (memop & MO_SSIZE) {
1127 case MO_UB:
1128 tcg_out_ldst_r(s, I3312_LDRB, data_r, addr_r, otype, off_r);
1129 break;
1130 case MO_SB:
1131 tcg_out_ldst_r(s, ext ? I3312_LDRSBX : I3312_LDRSBW,
1132 data_r, addr_r, otype, off_r);
1133 break;
1134 case MO_UW:
1135 tcg_out_ldst_r(s, I3312_LDRH, data_r, addr_r, otype, off_r);
1136 if (bswap) {
1137 tcg_out_rev16(s, data_r, data_r);
1139 break;
1140 case MO_SW:
1141 if (bswap) {
1142 tcg_out_ldst_r(s, I3312_LDRH, data_r, addr_r, otype, off_r);
1143 tcg_out_rev16(s, data_r, data_r);
1144 tcg_out_sxt(s, ext, MO_16, data_r, data_r);
1145 } else {
1146 tcg_out_ldst_r(s, (ext ? I3312_LDRSHX : I3312_LDRSHW),
1147 data_r, addr_r, otype, off_r);
1149 break;
1150 case MO_UL:
1151 tcg_out_ldst_r(s, I3312_LDRW, data_r, addr_r, otype, off_r);
1152 if (bswap) {
1153 tcg_out_rev32(s, data_r, data_r);
1155 break;
1156 case MO_SL:
1157 if (bswap) {
1158 tcg_out_ldst_r(s, I3312_LDRW, data_r, addr_r, otype, off_r);
1159 tcg_out_rev32(s, data_r, data_r);
1160 tcg_out_sxt(s, TCG_TYPE_I64, MO_32, data_r, data_r);
1161 } else {
1162 tcg_out_ldst_r(s, I3312_LDRSWX, data_r, addr_r, otype, off_r);
1164 break;
1165 case MO_Q:
1166 tcg_out_ldst_r(s, I3312_LDRX, data_r, addr_r, otype, off_r);
1167 if (bswap) {
1168 tcg_out_rev64(s, data_r, data_r);
1170 break;
1171 default:
1172 tcg_abort();
1176 static void tcg_out_qemu_st_direct(TCGContext *s, TCGMemOp memop,
1177 TCGReg data_r, TCGReg addr_r,
1178 TCGType otype, TCGReg off_r)
1180 const TCGMemOp bswap = memop & MO_BSWAP;
1182 switch (memop & MO_SIZE) {
1183 case MO_8:
1184 tcg_out_ldst_r(s, I3312_STRB, data_r, addr_r, otype, off_r);
1185 break;
1186 case MO_16:
1187 if (bswap && data_r != TCG_REG_XZR) {
1188 tcg_out_rev16(s, TCG_REG_TMP, data_r);
1189 data_r = TCG_REG_TMP;
1191 tcg_out_ldst_r(s, I3312_STRH, data_r, addr_r, otype, off_r);
1192 break;
1193 case MO_32:
1194 if (bswap && data_r != TCG_REG_XZR) {
1195 tcg_out_rev32(s, TCG_REG_TMP, data_r);
1196 data_r = TCG_REG_TMP;
1198 tcg_out_ldst_r(s, I3312_STRW, data_r, addr_r, otype, off_r);
1199 break;
1200 case MO_64:
1201 if (bswap && data_r != TCG_REG_XZR) {
1202 tcg_out_rev64(s, TCG_REG_TMP, data_r);
1203 data_r = TCG_REG_TMP;
1205 tcg_out_ldst_r(s, I3312_STRX, data_r, addr_r, otype, off_r);
1206 break;
1207 default:
1208 tcg_abort();
1212 static void tcg_out_qemu_ld(TCGContext *s, TCGReg data_reg, TCGReg addr_reg,
1213 TCGMemOpIdx oi, TCGType ext)
1215 TCGMemOp memop = get_memop(oi);
1216 const TCGType otype = TARGET_LONG_BITS == 64 ? TCG_TYPE_I64 : TCG_TYPE_I32;
1217 #ifdef CONFIG_SOFTMMU
1218 unsigned mem_index = get_mmuidx(oi);
1219 tcg_insn_unit *label_ptr;
1221 tcg_out_tlb_read(s, addr_reg, memop, &label_ptr, mem_index, 1);
1222 tcg_out_qemu_ld_direct(s, memop, ext, data_reg,
1223 TCG_REG_X1, otype, addr_reg);
1224 add_qemu_ldst_label(s, true, oi, ext, data_reg, addr_reg,
1225 s->code_ptr, label_ptr);
1226 #else /* !CONFIG_SOFTMMU */
1227 tcg_out_qemu_ld_direct(s, memop, ext, data_reg,
1228 GUEST_BASE ? TCG_REG_GUEST_BASE : TCG_REG_XZR,
1229 otype, addr_reg);
1230 #endif /* CONFIG_SOFTMMU */
1233 static void tcg_out_qemu_st(TCGContext *s, TCGReg data_reg, TCGReg addr_reg,
1234 TCGMemOpIdx oi)
1236 TCGMemOp memop = get_memop(oi);
1237 const TCGType otype = TARGET_LONG_BITS == 64 ? TCG_TYPE_I64 : TCG_TYPE_I32;
1238 #ifdef CONFIG_SOFTMMU
1239 unsigned mem_index = get_mmuidx(oi);
1240 tcg_insn_unit *label_ptr;
1242 tcg_out_tlb_read(s, addr_reg, memop, &label_ptr, mem_index, 0);
1243 tcg_out_qemu_st_direct(s, memop, data_reg,
1244 TCG_REG_X1, otype, addr_reg);
1245 add_qemu_ldst_label(s, false, oi, (memop & MO_SIZE)== MO_64,
1246 data_reg, addr_reg, s->code_ptr, label_ptr);
1247 #else /* !CONFIG_SOFTMMU */
1248 tcg_out_qemu_st_direct(s, memop, data_reg,
1249 GUEST_BASE ? TCG_REG_GUEST_BASE : TCG_REG_XZR,
1250 otype, addr_reg);
1251 #endif /* CONFIG_SOFTMMU */
1254 static tcg_insn_unit *tb_ret_addr;
1256 static void tcg_out_op(TCGContext *s, TCGOpcode opc,
1257 const TCGArg args[TCG_MAX_OP_ARGS],
1258 const int const_args[TCG_MAX_OP_ARGS])
1260 /* 99% of the time, we can signal the use of extension registers
1261 by looking to see if the opcode handles 64-bit data. */
1262 TCGType ext = (tcg_op_defs[opc].flags & TCG_OPF_64BIT) != 0;
1264 /* Hoist the loads of the most common arguments. */
1265 TCGArg a0 = args[0];
1266 TCGArg a1 = args[1];
1267 TCGArg a2 = args[2];
1268 int c2 = const_args[2];
1270 /* Some operands are defined with "rZ" constraint, a register or
1271 the zero register. These need not actually test args[I] == 0. */
1272 #define REG0(I) (const_args[I] ? TCG_REG_XZR : (TCGReg)args[I])
1274 switch (opc) {
1275 case INDEX_op_exit_tb:
1276 tcg_out_movi(s, TCG_TYPE_I64, TCG_REG_X0, a0);
1277 tcg_out_goto(s, tb_ret_addr);
1278 break;
1280 case INDEX_op_goto_tb:
1281 #ifndef USE_DIRECT_JUMP
1282 #error "USE_DIRECT_JUMP required for aarch64"
1283 #endif
1284 assert(s->tb_jmp_offset != NULL); /* consistency for USE_DIRECT_JUMP */
1285 s->tb_jmp_offset[a0] = tcg_current_code_size(s);
1286 /* actual branch destination will be patched by
1287 aarch64_tb_set_jmp_target later, beware retranslation. */
1288 tcg_out_goto_noaddr(s);
1289 s->tb_next_offset[a0] = tcg_current_code_size(s);
1290 break;
1292 case INDEX_op_br:
1293 tcg_out_goto_label(s, arg_label(a0));
1294 break;
1296 case INDEX_op_ld8u_i32:
1297 case INDEX_op_ld8u_i64:
1298 tcg_out_ldst(s, I3312_LDRB, a0, a1, a2);
1299 break;
1300 case INDEX_op_ld8s_i32:
1301 tcg_out_ldst(s, I3312_LDRSBW, a0, a1, a2);
1302 break;
1303 case INDEX_op_ld8s_i64:
1304 tcg_out_ldst(s, I3312_LDRSBX, a0, a1, a2);
1305 break;
1306 case INDEX_op_ld16u_i32:
1307 case INDEX_op_ld16u_i64:
1308 tcg_out_ldst(s, I3312_LDRH, a0, a1, a2);
1309 break;
1310 case INDEX_op_ld16s_i32:
1311 tcg_out_ldst(s, I3312_LDRSHW, a0, a1, a2);
1312 break;
1313 case INDEX_op_ld16s_i64:
1314 tcg_out_ldst(s, I3312_LDRSHX, a0, a1, a2);
1315 break;
1316 case INDEX_op_ld_i32:
1317 case INDEX_op_ld32u_i64:
1318 tcg_out_ldst(s, I3312_LDRW, a0, a1, a2);
1319 break;
1320 case INDEX_op_ld32s_i64:
1321 tcg_out_ldst(s, I3312_LDRSWX, a0, a1, a2);
1322 break;
1323 case INDEX_op_ld_i64:
1324 tcg_out_ldst(s, I3312_LDRX, a0, a1, a2);
1325 break;
1327 case INDEX_op_st8_i32:
1328 case INDEX_op_st8_i64:
1329 tcg_out_ldst(s, I3312_STRB, REG0(0), a1, a2);
1330 break;
1331 case INDEX_op_st16_i32:
1332 case INDEX_op_st16_i64:
1333 tcg_out_ldst(s, I3312_STRH, REG0(0), a1, a2);
1334 break;
1335 case INDEX_op_st_i32:
1336 case INDEX_op_st32_i64:
1337 tcg_out_ldst(s, I3312_STRW, REG0(0), a1, a2);
1338 break;
1339 case INDEX_op_st_i64:
1340 tcg_out_ldst(s, I3312_STRX, REG0(0), a1, a2);
1341 break;
1343 case INDEX_op_add_i32:
1344 a2 = (int32_t)a2;
1345 /* FALLTHRU */
1346 case INDEX_op_add_i64:
1347 if (c2) {
1348 tcg_out_addsubi(s, ext, a0, a1, a2);
1349 } else {
1350 tcg_out_insn(s, 3502, ADD, ext, a0, a1, a2);
1352 break;
1354 case INDEX_op_sub_i32:
1355 a2 = (int32_t)a2;
1356 /* FALLTHRU */
1357 case INDEX_op_sub_i64:
1358 if (c2) {
1359 tcg_out_addsubi(s, ext, a0, a1, -a2);
1360 } else {
1361 tcg_out_insn(s, 3502, SUB, ext, a0, a1, a2);
1363 break;
1365 case INDEX_op_neg_i64:
1366 case INDEX_op_neg_i32:
1367 tcg_out_insn(s, 3502, SUB, ext, a0, TCG_REG_XZR, a1);
1368 break;
1370 case INDEX_op_and_i32:
1371 a2 = (int32_t)a2;
1372 /* FALLTHRU */
1373 case INDEX_op_and_i64:
1374 if (c2) {
1375 tcg_out_logicali(s, I3404_ANDI, ext, a0, a1, a2);
1376 } else {
1377 tcg_out_insn(s, 3510, AND, ext, a0, a1, a2);
1379 break;
1381 case INDEX_op_andc_i32:
1382 a2 = (int32_t)a2;
1383 /* FALLTHRU */
1384 case INDEX_op_andc_i64:
1385 if (c2) {
1386 tcg_out_logicali(s, I3404_ANDI, ext, a0, a1, ~a2);
1387 } else {
1388 tcg_out_insn(s, 3510, BIC, ext, a0, a1, a2);
1390 break;
1392 case INDEX_op_or_i32:
1393 a2 = (int32_t)a2;
1394 /* FALLTHRU */
1395 case INDEX_op_or_i64:
1396 if (c2) {
1397 tcg_out_logicali(s, I3404_ORRI, ext, a0, a1, a2);
1398 } else {
1399 tcg_out_insn(s, 3510, ORR, ext, a0, a1, a2);
1401 break;
1403 case INDEX_op_orc_i32:
1404 a2 = (int32_t)a2;
1405 /* FALLTHRU */
1406 case INDEX_op_orc_i64:
1407 if (c2) {
1408 tcg_out_logicali(s, I3404_ORRI, ext, a0, a1, ~a2);
1409 } else {
1410 tcg_out_insn(s, 3510, ORN, ext, a0, a1, a2);
1412 break;
1414 case INDEX_op_xor_i32:
1415 a2 = (int32_t)a2;
1416 /* FALLTHRU */
1417 case INDEX_op_xor_i64:
1418 if (c2) {
1419 tcg_out_logicali(s, I3404_EORI, ext, a0, a1, a2);
1420 } else {
1421 tcg_out_insn(s, 3510, EOR, ext, a0, a1, a2);
1423 break;
1425 case INDEX_op_eqv_i32:
1426 a2 = (int32_t)a2;
1427 /* FALLTHRU */
1428 case INDEX_op_eqv_i64:
1429 if (c2) {
1430 tcg_out_logicali(s, I3404_EORI, ext, a0, a1, ~a2);
1431 } else {
1432 tcg_out_insn(s, 3510, EON, ext, a0, a1, a2);
1434 break;
1436 case INDEX_op_not_i64:
1437 case INDEX_op_not_i32:
1438 tcg_out_insn(s, 3510, ORN, ext, a0, TCG_REG_XZR, a1);
1439 break;
1441 case INDEX_op_mul_i64:
1442 case INDEX_op_mul_i32:
1443 tcg_out_insn(s, 3509, MADD, ext, a0, a1, a2, TCG_REG_XZR);
1444 break;
1446 case INDEX_op_div_i64:
1447 case INDEX_op_div_i32:
1448 tcg_out_insn(s, 3508, SDIV, ext, a0, a1, a2);
1449 break;
1450 case INDEX_op_divu_i64:
1451 case INDEX_op_divu_i32:
1452 tcg_out_insn(s, 3508, UDIV, ext, a0, a1, a2);
1453 break;
1455 case INDEX_op_rem_i64:
1456 case INDEX_op_rem_i32:
1457 tcg_out_insn(s, 3508, SDIV, ext, TCG_REG_TMP, a1, a2);
1458 tcg_out_insn(s, 3509, MSUB, ext, a0, TCG_REG_TMP, a2, a1);
1459 break;
1460 case INDEX_op_remu_i64:
1461 case INDEX_op_remu_i32:
1462 tcg_out_insn(s, 3508, UDIV, ext, TCG_REG_TMP, a1, a2);
1463 tcg_out_insn(s, 3509, MSUB, ext, a0, TCG_REG_TMP, a2, a1);
1464 break;
1466 case INDEX_op_shl_i64:
1467 case INDEX_op_shl_i32:
1468 if (c2) {
1469 tcg_out_shl(s, ext, a0, a1, a2);
1470 } else {
1471 tcg_out_insn(s, 3508, LSLV, ext, a0, a1, a2);
1473 break;
1475 case INDEX_op_shr_i64:
1476 case INDEX_op_shr_i32:
1477 if (c2) {
1478 tcg_out_shr(s, ext, a0, a1, a2);
1479 } else {
1480 tcg_out_insn(s, 3508, LSRV, ext, a0, a1, a2);
1482 break;
1484 case INDEX_op_sar_i64:
1485 case INDEX_op_sar_i32:
1486 if (c2) {
1487 tcg_out_sar(s, ext, a0, a1, a2);
1488 } else {
1489 tcg_out_insn(s, 3508, ASRV, ext, a0, a1, a2);
1491 break;
1493 case INDEX_op_rotr_i64:
1494 case INDEX_op_rotr_i32:
1495 if (c2) {
1496 tcg_out_rotr(s, ext, a0, a1, a2);
1497 } else {
1498 tcg_out_insn(s, 3508, RORV, ext, a0, a1, a2);
1500 break;
1502 case INDEX_op_rotl_i64:
1503 case INDEX_op_rotl_i32:
1504 if (c2) {
1505 tcg_out_rotl(s, ext, a0, a1, a2);
1506 } else {
1507 tcg_out_insn(s, 3502, SUB, 0, TCG_REG_TMP, TCG_REG_XZR, a2);
1508 tcg_out_insn(s, 3508, RORV, ext, a0, a1, TCG_REG_TMP);
1510 break;
1512 case INDEX_op_brcond_i32:
1513 a1 = (int32_t)a1;
1514 /* FALLTHRU */
1515 case INDEX_op_brcond_i64:
1516 tcg_out_brcond(s, ext, a2, a0, a1, const_args[1], arg_label(args[3]));
1517 break;
1519 case INDEX_op_setcond_i32:
1520 a2 = (int32_t)a2;
1521 /* FALLTHRU */
1522 case INDEX_op_setcond_i64:
1523 tcg_out_cmp(s, ext, a1, a2, c2);
1524 /* Use CSET alias of CSINC Wd, WZR, WZR, invert(cond). */
1525 tcg_out_insn(s, 3506, CSINC, TCG_TYPE_I32, a0, TCG_REG_XZR,
1526 TCG_REG_XZR, tcg_invert_cond(args[3]));
1527 break;
1529 case INDEX_op_movcond_i32:
1530 a2 = (int32_t)a2;
1531 /* FALLTHRU */
1532 case INDEX_op_movcond_i64:
1533 tcg_out_cmp(s, ext, a1, a2, c2);
1534 tcg_out_insn(s, 3506, CSEL, ext, a0, REG0(3), REG0(4), args[5]);
1535 break;
1537 case INDEX_op_qemu_ld_i32:
1538 case INDEX_op_qemu_ld_i64:
1539 tcg_out_qemu_ld(s, a0, a1, a2, ext);
1540 break;
1541 case INDEX_op_qemu_st_i32:
1542 case INDEX_op_qemu_st_i64:
1543 tcg_out_qemu_st(s, REG0(0), a1, a2);
1544 break;
1546 case INDEX_op_bswap64_i64:
1547 tcg_out_rev64(s, a0, a1);
1548 break;
1549 case INDEX_op_bswap32_i64:
1550 case INDEX_op_bswap32_i32:
1551 tcg_out_rev32(s, a0, a1);
1552 break;
1553 case INDEX_op_bswap16_i64:
1554 case INDEX_op_bswap16_i32:
1555 tcg_out_rev16(s, a0, a1);
1556 break;
1558 case INDEX_op_ext8s_i64:
1559 case INDEX_op_ext8s_i32:
1560 tcg_out_sxt(s, ext, MO_8, a0, a1);
1561 break;
1562 case INDEX_op_ext16s_i64:
1563 case INDEX_op_ext16s_i32:
1564 tcg_out_sxt(s, ext, MO_16, a0, a1);
1565 break;
1566 case INDEX_op_ext_i32_i64:
1567 case INDEX_op_ext32s_i64:
1568 tcg_out_sxt(s, TCG_TYPE_I64, MO_32, a0, a1);
1569 break;
1570 case INDEX_op_ext8u_i64:
1571 case INDEX_op_ext8u_i32:
1572 tcg_out_uxt(s, MO_8, a0, a1);
1573 break;
1574 case INDEX_op_ext16u_i64:
1575 case INDEX_op_ext16u_i32:
1576 tcg_out_uxt(s, MO_16, a0, a1);
1577 break;
1578 case INDEX_op_extu_i32_i64:
1579 case INDEX_op_ext32u_i64:
1580 tcg_out_movr(s, TCG_TYPE_I32, a0, a1);
1581 break;
1583 case INDEX_op_deposit_i64:
1584 case INDEX_op_deposit_i32:
1585 tcg_out_dep(s, ext, a0, REG0(2), args[3], args[4]);
1586 break;
1588 case INDEX_op_add2_i32:
1589 tcg_out_addsub2(s, TCG_TYPE_I32, a0, a1, REG0(2), REG0(3),
1590 (int32_t)args[4], args[5], const_args[4],
1591 const_args[5], false);
1592 break;
1593 case INDEX_op_add2_i64:
1594 tcg_out_addsub2(s, TCG_TYPE_I64, a0, a1, REG0(2), REG0(3), args[4],
1595 args[5], const_args[4], const_args[5], false);
1596 break;
1597 case INDEX_op_sub2_i32:
1598 tcg_out_addsub2(s, TCG_TYPE_I32, a0, a1, REG0(2), REG0(3),
1599 (int32_t)args[4], args[5], const_args[4],
1600 const_args[5], true);
1601 break;
1602 case INDEX_op_sub2_i64:
1603 tcg_out_addsub2(s, TCG_TYPE_I64, a0, a1, REG0(2), REG0(3), args[4],
1604 args[5], const_args[4], const_args[5], true);
1605 break;
1607 case INDEX_op_muluh_i64:
1608 tcg_out_insn(s, 3508, UMULH, TCG_TYPE_I64, a0, a1, a2);
1609 break;
1610 case INDEX_op_mulsh_i64:
1611 tcg_out_insn(s, 3508, SMULH, TCG_TYPE_I64, a0, a1, a2);
1612 break;
1614 case INDEX_op_mov_i32: /* Always emitted via tcg_out_mov. */
1615 case INDEX_op_mov_i64:
1616 case INDEX_op_movi_i32: /* Always emitted via tcg_out_movi. */
1617 case INDEX_op_movi_i64:
1618 case INDEX_op_call: /* Always emitted via tcg_out_call. */
1619 default:
1620 tcg_abort();
1623 #undef REG0
1626 static const TCGTargetOpDef aarch64_op_defs[] = {
1627 { INDEX_op_exit_tb, { } },
1628 { INDEX_op_goto_tb, { } },
1629 { INDEX_op_br, { } },
1631 { INDEX_op_ld8u_i32, { "r", "r" } },
1632 { INDEX_op_ld8s_i32, { "r", "r" } },
1633 { INDEX_op_ld16u_i32, { "r", "r" } },
1634 { INDEX_op_ld16s_i32, { "r", "r" } },
1635 { INDEX_op_ld_i32, { "r", "r" } },
1636 { INDEX_op_ld8u_i64, { "r", "r" } },
1637 { INDEX_op_ld8s_i64, { "r", "r" } },
1638 { INDEX_op_ld16u_i64, { "r", "r" } },
1639 { INDEX_op_ld16s_i64, { "r", "r" } },
1640 { INDEX_op_ld32u_i64, { "r", "r" } },
1641 { INDEX_op_ld32s_i64, { "r", "r" } },
1642 { INDEX_op_ld_i64, { "r", "r" } },
1644 { INDEX_op_st8_i32, { "rZ", "r" } },
1645 { INDEX_op_st16_i32, { "rZ", "r" } },
1646 { INDEX_op_st_i32, { "rZ", "r" } },
1647 { INDEX_op_st8_i64, { "rZ", "r" } },
1648 { INDEX_op_st16_i64, { "rZ", "r" } },
1649 { INDEX_op_st32_i64, { "rZ", "r" } },
1650 { INDEX_op_st_i64, { "rZ", "r" } },
1652 { INDEX_op_add_i32, { "r", "r", "rA" } },
1653 { INDEX_op_add_i64, { "r", "r", "rA" } },
1654 { INDEX_op_sub_i32, { "r", "r", "rA" } },
1655 { INDEX_op_sub_i64, { "r", "r", "rA" } },
1656 { INDEX_op_mul_i32, { "r", "r", "r" } },
1657 { INDEX_op_mul_i64, { "r", "r", "r" } },
1658 { INDEX_op_div_i32, { "r", "r", "r" } },
1659 { INDEX_op_div_i64, { "r", "r", "r" } },
1660 { INDEX_op_divu_i32, { "r", "r", "r" } },
1661 { INDEX_op_divu_i64, { "r", "r", "r" } },
1662 { INDEX_op_rem_i32, { "r", "r", "r" } },
1663 { INDEX_op_rem_i64, { "r", "r", "r" } },
1664 { INDEX_op_remu_i32, { "r", "r", "r" } },
1665 { INDEX_op_remu_i64, { "r", "r", "r" } },
1666 { INDEX_op_and_i32, { "r", "r", "rL" } },
1667 { INDEX_op_and_i64, { "r", "r", "rL" } },
1668 { INDEX_op_or_i32, { "r", "r", "rL" } },
1669 { INDEX_op_or_i64, { "r", "r", "rL" } },
1670 { INDEX_op_xor_i32, { "r", "r", "rL" } },
1671 { INDEX_op_xor_i64, { "r", "r", "rL" } },
1672 { INDEX_op_andc_i32, { "r", "r", "rL" } },
1673 { INDEX_op_andc_i64, { "r", "r", "rL" } },
1674 { INDEX_op_orc_i32, { "r", "r", "rL" } },
1675 { INDEX_op_orc_i64, { "r", "r", "rL" } },
1676 { INDEX_op_eqv_i32, { "r", "r", "rL" } },
1677 { INDEX_op_eqv_i64, { "r", "r", "rL" } },
1679 { INDEX_op_neg_i32, { "r", "r" } },
1680 { INDEX_op_neg_i64, { "r", "r" } },
1681 { INDEX_op_not_i32, { "r", "r" } },
1682 { INDEX_op_not_i64, { "r", "r" } },
1684 { INDEX_op_shl_i32, { "r", "r", "ri" } },
1685 { INDEX_op_shr_i32, { "r", "r", "ri" } },
1686 { INDEX_op_sar_i32, { "r", "r", "ri" } },
1687 { INDEX_op_rotl_i32, { "r", "r", "ri" } },
1688 { INDEX_op_rotr_i32, { "r", "r", "ri" } },
1689 { INDEX_op_shl_i64, { "r", "r", "ri" } },
1690 { INDEX_op_shr_i64, { "r", "r", "ri" } },
1691 { INDEX_op_sar_i64, { "r", "r", "ri" } },
1692 { INDEX_op_rotl_i64, { "r", "r", "ri" } },
1693 { INDEX_op_rotr_i64, { "r", "r", "ri" } },
1695 { INDEX_op_brcond_i32, { "r", "rA" } },
1696 { INDEX_op_brcond_i64, { "r", "rA" } },
1697 { INDEX_op_setcond_i32, { "r", "r", "rA" } },
1698 { INDEX_op_setcond_i64, { "r", "r", "rA" } },
1699 { INDEX_op_movcond_i32, { "r", "r", "rA", "rZ", "rZ" } },
1700 { INDEX_op_movcond_i64, { "r", "r", "rA", "rZ", "rZ" } },
1702 { INDEX_op_qemu_ld_i32, { "r", "l" } },
1703 { INDEX_op_qemu_ld_i64, { "r", "l" } },
1704 { INDEX_op_qemu_st_i32, { "lZ", "l" } },
1705 { INDEX_op_qemu_st_i64, { "lZ", "l" } },
1707 { INDEX_op_bswap16_i32, { "r", "r" } },
1708 { INDEX_op_bswap32_i32, { "r", "r" } },
1709 { INDEX_op_bswap16_i64, { "r", "r" } },
1710 { INDEX_op_bswap32_i64, { "r", "r" } },
1711 { INDEX_op_bswap64_i64, { "r", "r" } },
1713 { INDEX_op_ext8s_i32, { "r", "r" } },
1714 { INDEX_op_ext16s_i32, { "r", "r" } },
1715 { INDEX_op_ext8u_i32, { "r", "r" } },
1716 { INDEX_op_ext16u_i32, { "r", "r" } },
1718 { INDEX_op_ext8s_i64, { "r", "r" } },
1719 { INDEX_op_ext16s_i64, { "r", "r" } },
1720 { INDEX_op_ext32s_i64, { "r", "r" } },
1721 { INDEX_op_ext8u_i64, { "r", "r" } },
1722 { INDEX_op_ext16u_i64, { "r", "r" } },
1723 { INDEX_op_ext32u_i64, { "r", "r" } },
1724 { INDEX_op_ext_i32_i64, { "r", "r" } },
1725 { INDEX_op_extu_i32_i64, { "r", "r" } },
1727 { INDEX_op_deposit_i32, { "r", "0", "rZ" } },
1728 { INDEX_op_deposit_i64, { "r", "0", "rZ" } },
1730 { INDEX_op_add2_i32, { "r", "r", "rZ", "rZ", "rA", "rMZ" } },
1731 { INDEX_op_add2_i64, { "r", "r", "rZ", "rZ", "rA", "rMZ" } },
1732 { INDEX_op_sub2_i32, { "r", "r", "rZ", "rZ", "rA", "rMZ" } },
1733 { INDEX_op_sub2_i64, { "r", "r", "rZ", "rZ", "rA", "rMZ" } },
1735 { INDEX_op_muluh_i64, { "r", "r", "r" } },
1736 { INDEX_op_mulsh_i64, { "r", "r", "r" } },
1738 { -1 },
1741 static void tcg_target_init(TCGContext *s)
1743 tcg_regset_set32(tcg_target_available_regs[TCG_TYPE_I32], 0, 0xffffffff);
1744 tcg_regset_set32(tcg_target_available_regs[TCG_TYPE_I64], 0, 0xffffffff);
1746 tcg_regset_set32(tcg_target_call_clobber_regs, 0,
1747 (1 << TCG_REG_X0) | (1 << TCG_REG_X1) |
1748 (1 << TCG_REG_X2) | (1 << TCG_REG_X3) |
1749 (1 << TCG_REG_X4) | (1 << TCG_REG_X5) |
1750 (1 << TCG_REG_X6) | (1 << TCG_REG_X7) |
1751 (1 << TCG_REG_X8) | (1 << TCG_REG_X9) |
1752 (1 << TCG_REG_X10) | (1 << TCG_REG_X11) |
1753 (1 << TCG_REG_X12) | (1 << TCG_REG_X13) |
1754 (1 << TCG_REG_X14) | (1 << TCG_REG_X15) |
1755 (1 << TCG_REG_X16) | (1 << TCG_REG_X17) |
1756 (1 << TCG_REG_X18) | (1 << TCG_REG_X30));
1758 tcg_regset_clear(s->reserved_regs);
1759 tcg_regset_set_reg(s->reserved_regs, TCG_REG_SP);
1760 tcg_regset_set_reg(s->reserved_regs, TCG_REG_FP);
1761 tcg_regset_set_reg(s->reserved_regs, TCG_REG_TMP);
1762 tcg_regset_set_reg(s->reserved_regs, TCG_REG_X18); /* platform register */
1764 tcg_add_target_add_op_defs(aarch64_op_defs);
1767 /* Saving pairs: (X19, X20) .. (X27, X28), (X29(fp), X30(lr)). */
1768 #define PUSH_SIZE ((30 - 19 + 1) * 8)
1770 #define FRAME_SIZE \
1771 ((PUSH_SIZE \
1772 + TCG_STATIC_CALL_ARGS_SIZE \
1773 + CPU_TEMP_BUF_NLONGS * sizeof(long) \
1774 + TCG_TARGET_STACK_ALIGN - 1) \
1775 & ~(TCG_TARGET_STACK_ALIGN - 1))
1777 /* We're expecting a 2 byte uleb128 encoded value. */
1778 QEMU_BUILD_BUG_ON(FRAME_SIZE >= (1 << 14));
1780 /* We're expecting to use a single ADDI insn. */
1781 QEMU_BUILD_BUG_ON(FRAME_SIZE - PUSH_SIZE > 0xfff);
1783 static void tcg_target_qemu_prologue(TCGContext *s)
1785 TCGReg r;
1787 /* Push (FP, LR) and allocate space for all saved registers. */
1788 tcg_out_insn(s, 3314, STP, TCG_REG_FP, TCG_REG_LR,
1789 TCG_REG_SP, -PUSH_SIZE, 1, 1);
1791 /* Set up frame pointer for canonical unwinding. */
1792 tcg_out_movr_sp(s, TCG_TYPE_I64, TCG_REG_FP, TCG_REG_SP);
1794 /* Store callee-preserved regs x19..x28. */
1795 for (r = TCG_REG_X19; r <= TCG_REG_X27; r += 2) {
1796 int ofs = (r - TCG_REG_X19 + 2) * 8;
1797 tcg_out_insn(s, 3314, STP, r, r + 1, TCG_REG_SP, ofs, 1, 0);
1800 /* Make stack space for TCG locals. */
1801 tcg_out_insn(s, 3401, SUBI, TCG_TYPE_I64, TCG_REG_SP, TCG_REG_SP,
1802 FRAME_SIZE - PUSH_SIZE);
1804 /* Inform TCG about how to find TCG locals with register, offset, size. */
1805 tcg_set_frame(s, TCG_REG_SP, TCG_STATIC_CALL_ARGS_SIZE,
1806 CPU_TEMP_BUF_NLONGS * sizeof(long));
1808 #if !defined(CONFIG_SOFTMMU)
1809 if (GUEST_BASE) {
1810 tcg_out_movi(s, TCG_TYPE_PTR, TCG_REG_GUEST_BASE, GUEST_BASE);
1811 tcg_regset_set_reg(s->reserved_regs, TCG_REG_GUEST_BASE);
1813 #endif
1815 tcg_out_mov(s, TCG_TYPE_PTR, TCG_AREG0, tcg_target_call_iarg_regs[0]);
1816 tcg_out_insn(s, 3207, BR, tcg_target_call_iarg_regs[1]);
1818 tb_ret_addr = s->code_ptr;
1820 /* Remove TCG locals stack space. */
1821 tcg_out_insn(s, 3401, ADDI, TCG_TYPE_I64, TCG_REG_SP, TCG_REG_SP,
1822 FRAME_SIZE - PUSH_SIZE);
1824 /* Restore registers x19..x28. */
1825 for (r = TCG_REG_X19; r <= TCG_REG_X27; r += 2) {
1826 int ofs = (r - TCG_REG_X19 + 2) * 8;
1827 tcg_out_insn(s, 3314, LDP, r, r + 1, TCG_REG_SP, ofs, 1, 0);
1830 /* Pop (FP, LR), restore SP to previous frame. */
1831 tcg_out_insn(s, 3314, LDP, TCG_REG_FP, TCG_REG_LR,
1832 TCG_REG_SP, PUSH_SIZE, 0, 1);
1833 tcg_out_insn(s, 3207, RET, TCG_REG_LR);
1836 typedef struct {
1837 DebugFrameHeader h;
1838 uint8_t fde_def_cfa[4];
1839 uint8_t fde_reg_ofs[24];
1840 } DebugFrame;
1842 #define ELF_HOST_MACHINE EM_AARCH64
1844 static const DebugFrame debug_frame = {
1845 .h.cie.len = sizeof(DebugFrameCIE)-4, /* length after .len member */
1846 .h.cie.id = -1,
1847 .h.cie.version = 1,
1848 .h.cie.code_align = 1,
1849 .h.cie.data_align = 0x78, /* sleb128 -8 */
1850 .h.cie.return_column = TCG_REG_LR,
1852 /* Total FDE size does not include the "len" member. */
1853 .h.fde.len = sizeof(DebugFrame) - offsetof(DebugFrame, h.fde.cie_offset),
1855 .fde_def_cfa = {
1856 12, TCG_REG_SP, /* DW_CFA_def_cfa sp, ... */
1857 (FRAME_SIZE & 0x7f) | 0x80, /* ... uleb128 FRAME_SIZE */
1858 (FRAME_SIZE >> 7)
1860 .fde_reg_ofs = {
1861 0x80 + 28, 1, /* DW_CFA_offset, x28, -8 */
1862 0x80 + 27, 2, /* DW_CFA_offset, x27, -16 */
1863 0x80 + 26, 3, /* DW_CFA_offset, x26, -24 */
1864 0x80 + 25, 4, /* DW_CFA_offset, x25, -32 */
1865 0x80 + 24, 5, /* DW_CFA_offset, x24, -40 */
1866 0x80 + 23, 6, /* DW_CFA_offset, x23, -48 */
1867 0x80 + 22, 7, /* DW_CFA_offset, x22, -56 */
1868 0x80 + 21, 8, /* DW_CFA_offset, x21, -64 */
1869 0x80 + 20, 9, /* DW_CFA_offset, x20, -72 */
1870 0x80 + 19, 10, /* DW_CFA_offset, x1p, -80 */
1871 0x80 + 30, 11, /* DW_CFA_offset, lr, -88 */
1872 0x80 + 29, 12, /* DW_CFA_offset, fp, -96 */
1876 void tcg_register_jit(void *buf, size_t buf_size)
1878 tcg_register_jit_int(buf, buf_size, &debug_frame, sizeof(debug_frame));