rtl8139: Do not consume the packet during overflow in standard mode.
[qemu.git] / tcg / aarch64 / tcg-target.c
blobbad8b1de96f6b638245c943a18c8fc54639c3e53
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 /* Note that XZR cannot be encoded in the address base register slot,
60 as that actaully encodes SP. So if we need to zero-extend the guest
61 address, via the address index register slot, we need to load even
62 a zero guest base into a register. */
63 #define USE_GUEST_BASE (GUEST_BASE != 0 || TARGET_LONG_BITS == 32)
65 # ifdef CONFIG_USE_GUEST_BASE
66 # define TCG_REG_GUEST_BASE TCG_REG_X28
67 # else
68 # define TCG_REG_GUEST_BASE TCG_REG_XZR
69 # endif
70 #endif
72 static inline void reloc_pc26(tcg_insn_unit *code_ptr, tcg_insn_unit *target)
74 ptrdiff_t offset = target - code_ptr;
75 assert(offset == sextract64(offset, 0, 26));
76 /* read instruction, mask away previous PC_REL26 parameter contents,
77 set the proper offset, then write back the instruction. */
78 *code_ptr = deposit32(*code_ptr, 0, 26, offset);
81 static inline void reloc_pc19(tcg_insn_unit *code_ptr, tcg_insn_unit *target)
83 ptrdiff_t offset = target - code_ptr;
84 assert(offset == sextract64(offset, 0, 19));
85 *code_ptr = deposit32(*code_ptr, 5, 19, offset);
88 static inline void patch_reloc(tcg_insn_unit *code_ptr, int type,
89 intptr_t value, intptr_t addend)
91 assert(addend == 0);
92 switch (type) {
93 case R_AARCH64_JUMP26:
94 case R_AARCH64_CALL26:
95 reloc_pc26(code_ptr, (tcg_insn_unit *)value);
96 break;
97 case R_AARCH64_CONDBR19:
98 reloc_pc19(code_ptr, (tcg_insn_unit *)value);
99 break;
100 default:
101 tcg_abort();
105 #define TCG_CT_CONST_AIMM 0x100
106 #define TCG_CT_CONST_LIMM 0x200
107 #define TCG_CT_CONST_ZERO 0x400
108 #define TCG_CT_CONST_MONE 0x800
110 /* parse target specific constraints */
111 static int target_parse_constraint(TCGArgConstraint *ct,
112 const char **pct_str)
114 const char *ct_str = *pct_str;
116 switch (ct_str[0]) {
117 case 'r':
118 ct->ct |= TCG_CT_REG;
119 tcg_regset_set32(ct->u.regs, 0, (1ULL << TCG_TARGET_NB_REGS) - 1);
120 break;
121 case 'l': /* qemu_ld / qemu_st address, data_reg */
122 ct->ct |= TCG_CT_REG;
123 tcg_regset_set32(ct->u.regs, 0, (1ULL << TCG_TARGET_NB_REGS) - 1);
124 #ifdef CONFIG_SOFTMMU
125 /* x0 and x1 will be overwritten when reading the tlb entry,
126 and x2, and x3 for helper args, better to avoid using them. */
127 tcg_regset_reset_reg(ct->u.regs, TCG_REG_X0);
128 tcg_regset_reset_reg(ct->u.regs, TCG_REG_X1);
129 tcg_regset_reset_reg(ct->u.regs, TCG_REG_X2);
130 tcg_regset_reset_reg(ct->u.regs, TCG_REG_X3);
131 #endif
132 break;
133 case 'A': /* Valid for arithmetic immediate (positive or negative). */
134 ct->ct |= TCG_CT_CONST_AIMM;
135 break;
136 case 'L': /* Valid for logical immediate. */
137 ct->ct |= TCG_CT_CONST_LIMM;
138 break;
139 case 'M': /* minus one */
140 ct->ct |= TCG_CT_CONST_MONE;
141 break;
142 case 'Z': /* zero */
143 ct->ct |= TCG_CT_CONST_ZERO;
144 break;
145 default:
146 return -1;
149 ct_str++;
150 *pct_str = ct_str;
151 return 0;
154 static inline bool is_aimm(uint64_t val)
156 return (val & ~0xfff) == 0 || (val & ~0xfff000) == 0;
159 static inline bool is_limm(uint64_t val)
161 /* Taking a simplified view of the logical immediates for now, ignoring
162 the replication that can happen across the field. Match bit patterns
163 of the forms
164 0....01....1
165 0..01..10..0
166 and their inverses. */
168 /* Make things easier below, by testing the form with msb clear. */
169 if ((int64_t)val < 0) {
170 val = ~val;
172 if (val == 0) {
173 return false;
175 val += val & -val;
176 return (val & (val - 1)) == 0;
179 static int tcg_target_const_match(tcg_target_long val, TCGType type,
180 const TCGArgConstraint *arg_ct)
182 int ct = arg_ct->ct;
184 if (ct & TCG_CT_CONST) {
185 return 1;
187 if (type == TCG_TYPE_I32) {
188 val = (int32_t)val;
190 if ((ct & TCG_CT_CONST_AIMM) && (is_aimm(val) || is_aimm(-val))) {
191 return 1;
193 if ((ct & TCG_CT_CONST_LIMM) && is_limm(val)) {
194 return 1;
196 if ((ct & TCG_CT_CONST_ZERO) && val == 0) {
197 return 1;
199 if ((ct & TCG_CT_CONST_MONE) && val == -1) {
200 return 1;
203 return 0;
206 enum aarch64_cond_code {
207 COND_EQ = 0x0,
208 COND_NE = 0x1,
209 COND_CS = 0x2, /* Unsigned greater or equal */
210 COND_HS = COND_CS, /* ALIAS greater or equal */
211 COND_CC = 0x3, /* Unsigned less than */
212 COND_LO = COND_CC, /* ALIAS Lower */
213 COND_MI = 0x4, /* Negative */
214 COND_PL = 0x5, /* Zero or greater */
215 COND_VS = 0x6, /* Overflow */
216 COND_VC = 0x7, /* No overflow */
217 COND_HI = 0x8, /* Unsigned greater than */
218 COND_LS = 0x9, /* Unsigned less or equal */
219 COND_GE = 0xa,
220 COND_LT = 0xb,
221 COND_GT = 0xc,
222 COND_LE = 0xd,
223 COND_AL = 0xe,
224 COND_NV = 0xf, /* behaves like COND_AL here */
227 static const enum aarch64_cond_code tcg_cond_to_aarch64[] = {
228 [TCG_COND_EQ] = COND_EQ,
229 [TCG_COND_NE] = COND_NE,
230 [TCG_COND_LT] = COND_LT,
231 [TCG_COND_GE] = COND_GE,
232 [TCG_COND_LE] = COND_LE,
233 [TCG_COND_GT] = COND_GT,
234 /* unsigned */
235 [TCG_COND_LTU] = COND_LO,
236 [TCG_COND_GTU] = COND_HI,
237 [TCG_COND_GEU] = COND_HS,
238 [TCG_COND_LEU] = COND_LS,
241 typedef enum {
242 LDST_ST = 0, /* store */
243 LDST_LD = 1, /* load */
244 LDST_LD_S_X = 2, /* load and sign-extend into Xt */
245 LDST_LD_S_W = 3, /* load and sign-extend into Wt */
246 } AArch64LdstType;
248 /* We encode the format of the insn into the beginning of the name, so that
249 we can have the preprocessor help "typecheck" the insn vs the output
250 function. Arm didn't provide us with nice names for the formats, so we
251 use the section number of the architecture reference manual in which the
252 instruction group is described. */
253 typedef enum {
254 /* Compare and branch (immediate). */
255 I3201_CBZ = 0x34000000,
256 I3201_CBNZ = 0x35000000,
258 /* Conditional branch (immediate). */
259 I3202_B_C = 0x54000000,
261 /* Unconditional branch (immediate). */
262 I3206_B = 0x14000000,
263 I3206_BL = 0x94000000,
265 /* Unconditional branch (register). */
266 I3207_BR = 0xd61f0000,
267 I3207_BLR = 0xd63f0000,
268 I3207_RET = 0xd65f0000,
270 /* Load/store register. Described here as 3.3.12, but the helper
271 that emits them can transform to 3.3.10 or 3.3.13. */
272 I3312_STRB = 0x38000000 | LDST_ST << 22 | MO_8 << 30,
273 I3312_STRH = 0x38000000 | LDST_ST << 22 | MO_16 << 30,
274 I3312_STRW = 0x38000000 | LDST_ST << 22 | MO_32 << 30,
275 I3312_STRX = 0x38000000 | LDST_ST << 22 | MO_64 << 30,
277 I3312_LDRB = 0x38000000 | LDST_LD << 22 | MO_8 << 30,
278 I3312_LDRH = 0x38000000 | LDST_LD << 22 | MO_16 << 30,
279 I3312_LDRW = 0x38000000 | LDST_LD << 22 | MO_32 << 30,
280 I3312_LDRX = 0x38000000 | LDST_LD << 22 | MO_64 << 30,
282 I3312_LDRSBW = 0x38000000 | LDST_LD_S_W << 22 | MO_8 << 30,
283 I3312_LDRSHW = 0x38000000 | LDST_LD_S_W << 22 | MO_16 << 30,
285 I3312_LDRSBX = 0x38000000 | LDST_LD_S_X << 22 | MO_8 << 30,
286 I3312_LDRSHX = 0x38000000 | LDST_LD_S_X << 22 | MO_16 << 30,
287 I3312_LDRSWX = 0x38000000 | LDST_LD_S_X << 22 | MO_32 << 30,
289 I3312_TO_I3310 = 0x00200800,
290 I3312_TO_I3313 = 0x01000000,
292 /* Load/store register pair instructions. */
293 I3314_LDP = 0x28400000,
294 I3314_STP = 0x28000000,
296 /* Add/subtract immediate instructions. */
297 I3401_ADDI = 0x11000000,
298 I3401_ADDSI = 0x31000000,
299 I3401_SUBI = 0x51000000,
300 I3401_SUBSI = 0x71000000,
302 /* Bitfield instructions. */
303 I3402_BFM = 0x33000000,
304 I3402_SBFM = 0x13000000,
305 I3402_UBFM = 0x53000000,
307 /* Extract instruction. */
308 I3403_EXTR = 0x13800000,
310 /* Logical immediate instructions. */
311 I3404_ANDI = 0x12000000,
312 I3404_ORRI = 0x32000000,
313 I3404_EORI = 0x52000000,
315 /* Move wide immediate instructions. */
316 I3405_MOVN = 0x12800000,
317 I3405_MOVZ = 0x52800000,
318 I3405_MOVK = 0x72800000,
320 /* PC relative addressing instructions. */
321 I3406_ADR = 0x10000000,
322 I3406_ADRP = 0x90000000,
324 /* Add/subtract shifted register instructions (without a shift). */
325 I3502_ADD = 0x0b000000,
326 I3502_ADDS = 0x2b000000,
327 I3502_SUB = 0x4b000000,
328 I3502_SUBS = 0x6b000000,
330 /* Add/subtract shifted register instructions (with a shift). */
331 I3502S_ADD_LSL = I3502_ADD,
333 /* Add/subtract with carry instructions. */
334 I3503_ADC = 0x1a000000,
335 I3503_SBC = 0x5a000000,
337 /* Conditional select instructions. */
338 I3506_CSEL = 0x1a800000,
339 I3506_CSINC = 0x1a800400,
341 /* Data-processing (1 source) instructions. */
342 I3507_REV16 = 0x5ac00400,
343 I3507_REV32 = 0x5ac00800,
344 I3507_REV64 = 0x5ac00c00,
346 /* Data-processing (2 source) instructions. */
347 I3508_LSLV = 0x1ac02000,
348 I3508_LSRV = 0x1ac02400,
349 I3508_ASRV = 0x1ac02800,
350 I3508_RORV = 0x1ac02c00,
351 I3508_SMULH = 0x9b407c00,
352 I3508_UMULH = 0x9bc07c00,
353 I3508_UDIV = 0x1ac00800,
354 I3508_SDIV = 0x1ac00c00,
356 /* Data-processing (3 source) instructions. */
357 I3509_MADD = 0x1b000000,
358 I3509_MSUB = 0x1b008000,
360 /* Logical shifted register instructions (without a shift). */
361 I3510_AND = 0x0a000000,
362 I3510_BIC = 0x0a200000,
363 I3510_ORR = 0x2a000000,
364 I3510_ORN = 0x2a200000,
365 I3510_EOR = 0x4a000000,
366 I3510_EON = 0x4a200000,
367 I3510_ANDS = 0x6a000000,
368 } AArch64Insn;
370 static inline uint32_t tcg_in32(TCGContext *s)
372 uint32_t v = *(uint32_t *)s->code_ptr;
373 return v;
376 /* Emit an opcode with "type-checking" of the format. */
377 #define tcg_out_insn(S, FMT, OP, ...) \
378 glue(tcg_out_insn_,FMT)(S, glue(glue(glue(I,FMT),_),OP), ## __VA_ARGS__)
380 static void tcg_out_insn_3201(TCGContext *s, AArch64Insn insn, TCGType ext,
381 TCGReg rt, int imm19)
383 tcg_out32(s, insn | ext << 31 | (imm19 & 0x7ffff) << 5 | rt);
386 static void tcg_out_insn_3202(TCGContext *s, AArch64Insn insn,
387 TCGCond c, int imm19)
389 tcg_out32(s, insn | tcg_cond_to_aarch64[c] | (imm19 & 0x7ffff) << 5);
392 static void tcg_out_insn_3206(TCGContext *s, AArch64Insn insn, int imm26)
394 tcg_out32(s, insn | (imm26 & 0x03ffffff));
397 static void tcg_out_insn_3207(TCGContext *s, AArch64Insn insn, TCGReg rn)
399 tcg_out32(s, insn | rn << 5);
402 static void tcg_out_insn_3314(TCGContext *s, AArch64Insn insn,
403 TCGReg r1, TCGReg r2, TCGReg rn,
404 tcg_target_long ofs, bool pre, bool w)
406 insn |= 1u << 31; /* ext */
407 insn |= pre << 24;
408 insn |= w << 23;
410 assert(ofs >= -0x200 && ofs < 0x200 && (ofs & 7) == 0);
411 insn |= (ofs & (0x7f << 3)) << (15 - 3);
413 tcg_out32(s, insn | r2 << 10 | rn << 5 | r1);
416 static void tcg_out_insn_3401(TCGContext *s, AArch64Insn insn, TCGType ext,
417 TCGReg rd, TCGReg rn, uint64_t aimm)
419 if (aimm > 0xfff) {
420 assert((aimm & 0xfff) == 0);
421 aimm >>= 12;
422 assert(aimm <= 0xfff);
423 aimm |= 1 << 12; /* apply LSL 12 */
425 tcg_out32(s, insn | ext << 31 | aimm << 10 | rn << 5 | rd);
428 /* This function can be used for both 3.4.2 (Bitfield) and 3.4.4
429 (Logical immediate). Both insn groups have N, IMMR and IMMS fields
430 that feed the DecodeBitMasks pseudo function. */
431 static void tcg_out_insn_3402(TCGContext *s, AArch64Insn insn, TCGType ext,
432 TCGReg rd, TCGReg rn, int n, int immr, int imms)
434 tcg_out32(s, insn | ext << 31 | n << 22 | immr << 16 | imms << 10
435 | rn << 5 | rd);
438 #define tcg_out_insn_3404 tcg_out_insn_3402
440 static void tcg_out_insn_3403(TCGContext *s, AArch64Insn insn, TCGType ext,
441 TCGReg rd, TCGReg rn, TCGReg rm, int imms)
443 tcg_out32(s, insn | ext << 31 | ext << 22 | rm << 16 | imms << 10
444 | rn << 5 | rd);
447 /* This function is used for the Move (wide immediate) instruction group.
448 Note that SHIFT is a full shift count, not the 2 bit HW field. */
449 static void tcg_out_insn_3405(TCGContext *s, AArch64Insn insn, TCGType ext,
450 TCGReg rd, uint16_t half, unsigned shift)
452 assert((shift & ~0x30) == 0);
453 tcg_out32(s, insn | ext << 31 | shift << (21 - 4) | half << 5 | rd);
456 static void tcg_out_insn_3406(TCGContext *s, AArch64Insn insn,
457 TCGReg rd, int64_t disp)
459 tcg_out32(s, insn | (disp & 3) << 29 | (disp & 0x1ffffc) << (5 - 2) | rd);
462 /* This function is for both 3.5.2 (Add/Subtract shifted register), for
463 the rare occasion when we actually want to supply a shift amount. */
464 static inline void tcg_out_insn_3502S(TCGContext *s, AArch64Insn insn,
465 TCGType ext, TCGReg rd, TCGReg rn,
466 TCGReg rm, int imm6)
468 tcg_out32(s, insn | ext << 31 | rm << 16 | imm6 << 10 | rn << 5 | rd);
471 /* This function is for 3.5.2 (Add/subtract shifted register),
472 and 3.5.10 (Logical shifted register), for the vast majorty of cases
473 when we don't want to apply a shift. Thus it can also be used for
474 3.5.3 (Add/subtract with carry) and 3.5.8 (Data processing 2 source). */
475 static void tcg_out_insn_3502(TCGContext *s, AArch64Insn insn, TCGType ext,
476 TCGReg rd, TCGReg rn, TCGReg rm)
478 tcg_out32(s, insn | ext << 31 | rm << 16 | rn << 5 | rd);
481 #define tcg_out_insn_3503 tcg_out_insn_3502
482 #define tcg_out_insn_3508 tcg_out_insn_3502
483 #define tcg_out_insn_3510 tcg_out_insn_3502
485 static void tcg_out_insn_3506(TCGContext *s, AArch64Insn insn, TCGType ext,
486 TCGReg rd, TCGReg rn, TCGReg rm, TCGCond c)
488 tcg_out32(s, insn | ext << 31 | rm << 16 | rn << 5 | rd
489 | tcg_cond_to_aarch64[c] << 12);
492 static void tcg_out_insn_3507(TCGContext *s, AArch64Insn insn, TCGType ext,
493 TCGReg rd, TCGReg rn)
495 tcg_out32(s, insn | ext << 31 | rn << 5 | rd);
498 static void tcg_out_insn_3509(TCGContext *s, AArch64Insn insn, TCGType ext,
499 TCGReg rd, TCGReg rn, TCGReg rm, TCGReg ra)
501 tcg_out32(s, insn | ext << 31 | rm << 16 | ra << 10 | rn << 5 | rd);
504 static void tcg_out_insn_3310(TCGContext *s, AArch64Insn insn,
505 TCGReg rd, TCGReg base, TCGType ext,
506 TCGReg regoff)
508 /* Note the AArch64Insn constants above are for C3.3.12. Adjust. */
509 tcg_out32(s, insn | I3312_TO_I3310 | regoff << 16 |
510 0x4000 | ext << 13 | base << 5 | rd);
513 static void tcg_out_insn_3312(TCGContext *s, AArch64Insn insn,
514 TCGReg rd, TCGReg rn, intptr_t offset)
516 tcg_out32(s, insn | (offset & 0x1ff) << 12 | rn << 5 | rd);
519 static void tcg_out_insn_3313(TCGContext *s, AArch64Insn insn,
520 TCGReg rd, TCGReg rn, uintptr_t scaled_uimm)
522 /* Note the AArch64Insn constants above are for C3.3.12. Adjust. */
523 tcg_out32(s, insn | I3312_TO_I3313 | scaled_uimm << 10 | rn << 5 | rd);
526 /* Register to register move using ORR (shifted register with no shift). */
527 static void tcg_out_movr(TCGContext *s, TCGType ext, TCGReg rd, TCGReg rm)
529 tcg_out_insn(s, 3510, ORR, ext, rd, TCG_REG_XZR, rm);
532 /* Register to register move using ADDI (move to/from SP). */
533 static void tcg_out_movr_sp(TCGContext *s, TCGType ext, TCGReg rd, TCGReg rn)
535 tcg_out_insn(s, 3401, ADDI, ext, rd, rn, 0);
538 /* This function is used for the Logical (immediate) instruction group.
539 The value of LIMM must satisfy IS_LIMM. See the comment above about
540 only supporting simplified logical immediates. */
541 static void tcg_out_logicali(TCGContext *s, AArch64Insn insn, TCGType ext,
542 TCGReg rd, TCGReg rn, uint64_t limm)
544 unsigned h, l, r, c;
546 assert(is_limm(limm));
548 h = clz64(limm);
549 l = ctz64(limm);
550 if (l == 0) {
551 r = 0; /* form 0....01....1 */
552 c = ctz64(~limm) - 1;
553 if (h == 0) {
554 r = clz64(~limm); /* form 1..10..01..1 */
555 c += r;
557 } else {
558 r = 64 - l; /* form 1....10....0 or 0..01..10..0 */
559 c = r - h - 1;
561 if (ext == TCG_TYPE_I32) {
562 r &= 31;
563 c &= 31;
566 tcg_out_insn_3404(s, insn, ext, rd, rn, ext, r, c);
569 static void tcg_out_movi(TCGContext *s, TCGType type, TCGReg rd,
570 tcg_target_long value)
572 AArch64Insn insn;
573 int i, wantinv, shift;
574 tcg_target_long svalue = value;
575 tcg_target_long ivalue = ~value;
576 tcg_target_long imask;
578 /* For 32-bit values, discard potential garbage in value. For 64-bit
579 values within [2**31, 2**32-1], we can create smaller sequences by
580 interpreting this as a negative 32-bit number, while ensuring that
581 the high 32 bits are cleared by setting SF=0. */
582 if (type == TCG_TYPE_I32 || (value & ~0xffffffffull) == 0) {
583 svalue = (int32_t)value;
584 value = (uint32_t)value;
585 ivalue = (uint32_t)ivalue;
586 type = TCG_TYPE_I32;
589 /* Speed things up by handling the common case of small positive
590 and negative values specially. */
591 if ((value & ~0xffffull) == 0) {
592 tcg_out_insn(s, 3405, MOVZ, type, rd, value, 0);
593 return;
594 } else if ((ivalue & ~0xffffull) == 0) {
595 tcg_out_insn(s, 3405, MOVN, type, rd, ivalue, 0);
596 return;
599 /* Check for bitfield immediates. For the benefit of 32-bit quantities,
600 use the sign-extended value. That lets us match rotated values such
601 as 0xff0000ff with the same 64-bit logic matching 0xffffffffff0000ff. */
602 if (is_limm(svalue)) {
603 tcg_out_logicali(s, I3404_ORRI, type, rd, TCG_REG_XZR, svalue);
604 return;
607 /* Look for host pointer values within 4G of the PC. This happens
608 often when loading pointers to QEMU's own data structures. */
609 if (type == TCG_TYPE_I64) {
610 tcg_target_long disp = (value >> 12) - ((intptr_t)s->code_ptr >> 12);
611 if (disp == sextract64(disp, 0, 21)) {
612 tcg_out_insn(s, 3406, ADRP, rd, disp);
613 if (value & 0xfff) {
614 tcg_out_insn(s, 3401, ADDI, type, rd, rd, value & 0xfff);
616 return;
620 /* Would it take fewer insns to begin with MOVN? For the value and its
621 inverse, count the number of 16-bit lanes that are 0. */
622 for (i = wantinv = imask = 0; i < 64; i += 16) {
623 tcg_target_long mask = 0xffffull << i;
624 if ((value & mask) == 0) {
625 wantinv -= 1;
627 if ((ivalue & mask) == 0) {
628 wantinv += 1;
629 imask |= mask;
633 /* If we had more 0xffff than 0x0000, invert VALUE and use MOVN. */
634 insn = I3405_MOVZ;
635 if (wantinv > 0) {
636 value = ivalue;
637 insn = I3405_MOVN;
640 /* Find the lowest lane that is not 0x0000. */
641 shift = ctz64(value) & (63 & -16);
642 tcg_out_insn_3405(s, insn, type, rd, value >> shift, shift);
644 if (wantinv > 0) {
645 /* Re-invert the value, so MOVK sees non-inverted bits. */
646 value = ~value;
647 /* Clear out all the 0xffff lanes. */
648 value ^= imask;
650 /* Clear out the lane that we just set. */
651 value &= ~(0xffffUL << shift);
653 /* Iterate until all lanes have been set, and thus cleared from VALUE. */
654 while (value) {
655 shift = ctz64(value) & (63 & -16);
656 tcg_out_insn(s, 3405, MOVK, type, rd, value >> shift, shift);
657 value &= ~(0xffffUL << shift);
661 /* Define something more legible for general use. */
662 #define tcg_out_ldst_r tcg_out_insn_3310
664 static void tcg_out_ldst(TCGContext *s, AArch64Insn insn,
665 TCGReg rd, TCGReg rn, intptr_t offset)
667 TCGMemOp size = (uint32_t)insn >> 30;
669 /* If the offset is naturally aligned and in range, then we can
670 use the scaled uimm12 encoding */
671 if (offset >= 0 && !(offset & ((1 << size) - 1))) {
672 uintptr_t scaled_uimm = offset >> size;
673 if (scaled_uimm <= 0xfff) {
674 tcg_out_insn_3313(s, insn, rd, rn, scaled_uimm);
675 return;
679 /* Small signed offsets can use the unscaled encoding. */
680 if (offset >= -256 && offset < 256) {
681 tcg_out_insn_3312(s, insn, rd, rn, offset);
682 return;
685 /* Worst-case scenario, move offset to temp register, use reg offset. */
686 tcg_out_movi(s, TCG_TYPE_I64, TCG_REG_TMP, offset);
687 tcg_out_ldst_r(s, insn, rd, rn, TCG_TYPE_I64, TCG_REG_TMP);
690 static inline void tcg_out_mov(TCGContext *s,
691 TCGType type, TCGReg ret, TCGReg arg)
693 if (ret != arg) {
694 tcg_out_movr(s, type, ret, arg);
698 static inline void tcg_out_ld(TCGContext *s, TCGType type, TCGReg arg,
699 TCGReg arg1, intptr_t arg2)
701 tcg_out_ldst(s, type == TCG_TYPE_I32 ? I3312_LDRW : I3312_LDRX,
702 arg, arg1, arg2);
705 static inline void tcg_out_st(TCGContext *s, TCGType type, TCGReg arg,
706 TCGReg arg1, intptr_t arg2)
708 tcg_out_ldst(s, type == TCG_TYPE_I32 ? I3312_STRW : I3312_STRX,
709 arg, arg1, arg2);
712 static inline void tcg_out_bfm(TCGContext *s, TCGType ext, TCGReg rd,
713 TCGReg rn, unsigned int a, unsigned int b)
715 tcg_out_insn(s, 3402, BFM, ext, rd, rn, ext, a, b);
718 static inline void tcg_out_ubfm(TCGContext *s, TCGType ext, TCGReg rd,
719 TCGReg rn, unsigned int a, unsigned int b)
721 tcg_out_insn(s, 3402, UBFM, ext, rd, rn, ext, a, b);
724 static inline void tcg_out_sbfm(TCGContext *s, TCGType ext, TCGReg rd,
725 TCGReg rn, unsigned int a, unsigned int b)
727 tcg_out_insn(s, 3402, SBFM, ext, rd, rn, ext, a, b);
730 static inline void tcg_out_extr(TCGContext *s, TCGType ext, TCGReg rd,
731 TCGReg rn, TCGReg rm, unsigned int a)
733 tcg_out_insn(s, 3403, EXTR, ext, rd, rn, rm, a);
736 static inline void tcg_out_shl(TCGContext *s, TCGType ext,
737 TCGReg rd, TCGReg rn, unsigned int m)
739 int bits = ext ? 64 : 32;
740 int max = bits - 1;
741 tcg_out_ubfm(s, ext, rd, rn, bits - (m & max), max - (m & max));
744 static inline void tcg_out_shr(TCGContext *s, TCGType ext,
745 TCGReg rd, TCGReg rn, unsigned int m)
747 int max = ext ? 63 : 31;
748 tcg_out_ubfm(s, ext, rd, rn, m & max, max);
751 static inline void tcg_out_sar(TCGContext *s, TCGType ext,
752 TCGReg rd, TCGReg rn, unsigned int m)
754 int max = ext ? 63 : 31;
755 tcg_out_sbfm(s, ext, rd, rn, m & max, max);
758 static inline void tcg_out_rotr(TCGContext *s, TCGType ext,
759 TCGReg rd, TCGReg rn, unsigned int m)
761 int max = ext ? 63 : 31;
762 tcg_out_extr(s, ext, rd, rn, rn, m & max);
765 static inline void tcg_out_rotl(TCGContext *s, TCGType ext,
766 TCGReg rd, TCGReg rn, unsigned int m)
768 int bits = ext ? 64 : 32;
769 int max = bits - 1;
770 tcg_out_extr(s, ext, rd, rn, rn, bits - (m & max));
773 static inline void tcg_out_dep(TCGContext *s, TCGType ext, TCGReg rd,
774 TCGReg rn, unsigned lsb, unsigned width)
776 unsigned size = ext ? 64 : 32;
777 unsigned a = (size - lsb) & (size - 1);
778 unsigned b = width - 1;
779 tcg_out_bfm(s, ext, rd, rn, a, b);
782 static void tcg_out_cmp(TCGContext *s, TCGType ext, TCGReg a,
783 tcg_target_long b, bool const_b)
785 if (const_b) {
786 /* Using CMP or CMN aliases. */
787 if (b >= 0) {
788 tcg_out_insn(s, 3401, SUBSI, ext, TCG_REG_XZR, a, b);
789 } else {
790 tcg_out_insn(s, 3401, ADDSI, ext, TCG_REG_XZR, a, -b);
792 } else {
793 /* Using CMP alias SUBS wzr, Wn, Wm */
794 tcg_out_insn(s, 3502, SUBS, ext, TCG_REG_XZR, a, b);
798 static inline void tcg_out_goto(TCGContext *s, tcg_insn_unit *target)
800 ptrdiff_t offset = target - s->code_ptr;
801 assert(offset == sextract64(offset, 0, 26));
802 tcg_out_insn(s, 3206, B, offset);
805 static inline void tcg_out_goto_noaddr(TCGContext *s)
807 /* We pay attention here to not modify the branch target by reading from
808 the buffer. This ensure that caches and memory are kept coherent during
809 retranslation. Mask away possible garbage in the high bits for the
810 first translation, while keeping the offset bits for retranslation. */
811 uint32_t old = tcg_in32(s);
812 tcg_out_insn(s, 3206, B, old);
815 static inline void tcg_out_goto_cond_noaddr(TCGContext *s, TCGCond c)
817 /* See comments in tcg_out_goto_noaddr. */
818 uint32_t old = tcg_in32(s) >> 5;
819 tcg_out_insn(s, 3202, B_C, c, old);
822 static inline void tcg_out_callr(TCGContext *s, TCGReg reg)
824 tcg_out_insn(s, 3207, BLR, reg);
827 static inline void tcg_out_call(TCGContext *s, tcg_insn_unit *target)
829 ptrdiff_t offset = target - s->code_ptr;
830 if (offset == sextract64(offset, 0, 26)) {
831 tcg_out_insn(s, 3206, BL, offset);
832 } else {
833 tcg_out_movi(s, TCG_TYPE_I64, TCG_REG_TMP, (intptr_t)target);
834 tcg_out_callr(s, TCG_REG_TMP);
838 void aarch64_tb_set_jmp_target(uintptr_t jmp_addr, uintptr_t addr)
840 tcg_insn_unit *code_ptr = (tcg_insn_unit *)jmp_addr;
841 tcg_insn_unit *target = (tcg_insn_unit *)addr;
843 reloc_pc26(code_ptr, target);
844 flush_icache_range(jmp_addr, jmp_addr + 4);
847 static inline void tcg_out_goto_label(TCGContext *s, TCGLabel *l)
849 if (!l->has_value) {
850 tcg_out_reloc(s, s->code_ptr, R_AARCH64_JUMP26, l, 0);
851 tcg_out_goto_noaddr(s);
852 } else {
853 tcg_out_goto(s, l->u.value_ptr);
857 static void tcg_out_brcond(TCGContext *s, TCGMemOp ext, TCGCond c, TCGArg a,
858 TCGArg b, bool b_const, TCGLabel *l)
860 intptr_t offset;
861 bool need_cmp;
863 if (b_const && b == 0 && (c == TCG_COND_EQ || c == TCG_COND_NE)) {
864 need_cmp = false;
865 } else {
866 need_cmp = true;
867 tcg_out_cmp(s, ext, a, b, b_const);
870 if (!l->has_value) {
871 tcg_out_reloc(s, s->code_ptr, R_AARCH64_CONDBR19, l, 0);
872 offset = tcg_in32(s) >> 5;
873 } else {
874 offset = l->u.value_ptr - s->code_ptr;
875 assert(offset == sextract64(offset, 0, 19));
878 if (need_cmp) {
879 tcg_out_insn(s, 3202, B_C, c, offset);
880 } else if (c == TCG_COND_EQ) {
881 tcg_out_insn(s, 3201, CBZ, ext, a, offset);
882 } else {
883 tcg_out_insn(s, 3201, CBNZ, ext, a, offset);
887 static inline void tcg_out_rev64(TCGContext *s, TCGReg rd, TCGReg rn)
889 tcg_out_insn(s, 3507, REV64, TCG_TYPE_I64, rd, rn);
892 static inline void tcg_out_rev32(TCGContext *s, TCGReg rd, TCGReg rn)
894 tcg_out_insn(s, 3507, REV32, TCG_TYPE_I32, rd, rn);
897 static inline void tcg_out_rev16(TCGContext *s, TCGReg rd, TCGReg rn)
899 tcg_out_insn(s, 3507, REV16, TCG_TYPE_I32, rd, rn);
902 static inline void tcg_out_sxt(TCGContext *s, TCGType ext, TCGMemOp s_bits,
903 TCGReg rd, TCGReg rn)
905 /* Using ALIASes SXTB, SXTH, SXTW, of SBFM Xd, Xn, #0, #7|15|31 */
906 int bits = (8 << s_bits) - 1;
907 tcg_out_sbfm(s, ext, rd, rn, 0, bits);
910 static inline void tcg_out_uxt(TCGContext *s, TCGMemOp s_bits,
911 TCGReg rd, TCGReg rn)
913 /* Using ALIASes UXTB, UXTH of UBFM Wd, Wn, #0, #7|15 */
914 int bits = (8 << s_bits) - 1;
915 tcg_out_ubfm(s, 0, rd, rn, 0, bits);
918 static void tcg_out_addsubi(TCGContext *s, int ext, TCGReg rd,
919 TCGReg rn, int64_t aimm)
921 if (aimm >= 0) {
922 tcg_out_insn(s, 3401, ADDI, ext, rd, rn, aimm);
923 } else {
924 tcg_out_insn(s, 3401, SUBI, ext, rd, rn, -aimm);
928 static inline void tcg_out_addsub2(TCGContext *s, int ext, TCGReg rl,
929 TCGReg rh, TCGReg al, TCGReg ah,
930 tcg_target_long bl, tcg_target_long bh,
931 bool const_bl, bool const_bh, bool sub)
933 TCGReg orig_rl = rl;
934 AArch64Insn insn;
936 if (rl == ah || (!const_bh && rl == bh)) {
937 rl = TCG_REG_TMP;
940 if (const_bl) {
941 insn = I3401_ADDSI;
942 if ((bl < 0) ^ sub) {
943 insn = I3401_SUBSI;
944 bl = -bl;
946 tcg_out_insn_3401(s, insn, ext, rl, al, bl);
947 } else {
948 tcg_out_insn_3502(s, sub ? I3502_SUBS : I3502_ADDS, ext, rl, al, bl);
951 insn = I3503_ADC;
952 if (const_bh) {
953 /* Note that the only two constants we support are 0 and -1, and
954 that SBC = rn + ~rm + c, so adc -1 is sbc 0, and vice-versa. */
955 if ((bh != 0) ^ sub) {
956 insn = I3503_SBC;
958 bh = TCG_REG_XZR;
959 } else if (sub) {
960 insn = I3503_SBC;
962 tcg_out_insn_3503(s, insn, ext, rh, ah, bh);
964 tcg_out_mov(s, ext, orig_rl, rl);
967 #ifdef CONFIG_SOFTMMU
968 /* helper signature: helper_ret_ld_mmu(CPUState *env, target_ulong addr,
969 * TCGMemOpIdx oi, uintptr_t ra)
971 static void * const qemu_ld_helpers[16] = {
972 [MO_UB] = helper_ret_ldub_mmu,
973 [MO_LEUW] = helper_le_lduw_mmu,
974 [MO_LEUL] = helper_le_ldul_mmu,
975 [MO_LEQ] = helper_le_ldq_mmu,
976 [MO_BEUW] = helper_be_lduw_mmu,
977 [MO_BEUL] = helper_be_ldul_mmu,
978 [MO_BEQ] = helper_be_ldq_mmu,
981 /* helper signature: helper_ret_st_mmu(CPUState *env, target_ulong addr,
982 * uintxx_t val, TCGMemOpIdx oi,
983 * uintptr_t ra)
985 static void * const qemu_st_helpers[16] = {
986 [MO_UB] = helper_ret_stb_mmu,
987 [MO_LEUW] = helper_le_stw_mmu,
988 [MO_LEUL] = helper_le_stl_mmu,
989 [MO_LEQ] = helper_le_stq_mmu,
990 [MO_BEUW] = helper_be_stw_mmu,
991 [MO_BEUL] = helper_be_stl_mmu,
992 [MO_BEQ] = helper_be_stq_mmu,
995 static inline void tcg_out_adr(TCGContext *s, TCGReg rd, void *target)
997 ptrdiff_t offset = tcg_pcrel_diff(s, target);
998 assert(offset == sextract64(offset, 0, 21));
999 tcg_out_insn(s, 3406, ADR, rd, offset);
1002 static void tcg_out_qemu_ld_slow_path(TCGContext *s, TCGLabelQemuLdst *lb)
1004 TCGMemOpIdx oi = lb->oi;
1005 TCGMemOp opc = get_memop(oi);
1006 TCGMemOp size = opc & MO_SIZE;
1008 reloc_pc19(lb->label_ptr[0], s->code_ptr);
1010 tcg_out_mov(s, TCG_TYPE_PTR, TCG_REG_X0, TCG_AREG0);
1011 tcg_out_mov(s, TARGET_LONG_BITS == 64, TCG_REG_X1, lb->addrlo_reg);
1012 tcg_out_movi(s, TCG_TYPE_I32, TCG_REG_X2, oi);
1013 tcg_out_adr(s, TCG_REG_X3, lb->raddr);
1014 tcg_out_call(s, qemu_ld_helpers[opc & (MO_BSWAP | MO_SIZE)]);
1015 if (opc & MO_SIGN) {
1016 tcg_out_sxt(s, lb->type, size, lb->datalo_reg, TCG_REG_X0);
1017 } else {
1018 tcg_out_mov(s, size == MO_64, lb->datalo_reg, TCG_REG_X0);
1021 tcg_out_goto(s, lb->raddr);
1024 static void tcg_out_qemu_st_slow_path(TCGContext *s, TCGLabelQemuLdst *lb)
1026 TCGMemOpIdx oi = lb->oi;
1027 TCGMemOp opc = get_memop(oi);
1028 TCGMemOp size = opc & MO_SIZE;
1030 reloc_pc19(lb->label_ptr[0], s->code_ptr);
1032 tcg_out_mov(s, TCG_TYPE_PTR, TCG_REG_X0, TCG_AREG0);
1033 tcg_out_mov(s, TARGET_LONG_BITS == 64, TCG_REG_X1, lb->addrlo_reg);
1034 tcg_out_mov(s, size == MO_64, TCG_REG_X2, lb->datalo_reg);
1035 tcg_out_movi(s, TCG_TYPE_I32, TCG_REG_X3, oi);
1036 tcg_out_adr(s, TCG_REG_X4, lb->raddr);
1037 tcg_out_call(s, qemu_st_helpers[opc & (MO_BSWAP | MO_SIZE)]);
1038 tcg_out_goto(s, lb->raddr);
1041 static void add_qemu_ldst_label(TCGContext *s, bool is_ld, TCGMemOpIdx oi,
1042 TCGType ext, TCGReg data_reg, TCGReg addr_reg,
1043 tcg_insn_unit *raddr, tcg_insn_unit *label_ptr)
1045 TCGLabelQemuLdst *label = new_ldst_label(s);
1047 label->is_ld = is_ld;
1048 label->oi = oi;
1049 label->type = ext;
1050 label->datalo_reg = data_reg;
1051 label->addrlo_reg = addr_reg;
1052 label->raddr = raddr;
1053 label->label_ptr[0] = label_ptr;
1056 /* Load and compare a TLB entry, emitting the conditional jump to the
1057 slow path for the failure case, which will be patched later when finalizing
1058 the slow path. Generated code returns the host addend in X1,
1059 clobbers X0,X2,X3,TMP. */
1060 static void tcg_out_tlb_read(TCGContext *s, TCGReg addr_reg, TCGMemOp s_bits,
1061 tcg_insn_unit **label_ptr, int mem_index,
1062 bool is_read)
1064 TCGReg base = TCG_AREG0;
1065 int tlb_offset = is_read ?
1066 offsetof(CPUArchState, tlb_table[mem_index][0].addr_read)
1067 : offsetof(CPUArchState, tlb_table[mem_index][0].addr_write);
1069 /* Extract the TLB index from the address into X0.
1070 X0<CPU_TLB_BITS:0> =
1071 addr_reg<TARGET_PAGE_BITS+CPU_TLB_BITS:TARGET_PAGE_BITS> */
1072 tcg_out_ubfm(s, TARGET_LONG_BITS == 64, TCG_REG_X0, addr_reg,
1073 TARGET_PAGE_BITS, TARGET_PAGE_BITS + CPU_TLB_BITS);
1075 /* Store the page mask part of the address and the low s_bits into X3.
1076 Later this allows checking for equality and alignment at the same time.
1077 X3 = addr_reg & (PAGE_MASK | ((1 << s_bits) - 1)) */
1078 tcg_out_logicali(s, I3404_ANDI, TARGET_LONG_BITS == 64, TCG_REG_X3,
1079 addr_reg, TARGET_PAGE_MASK | ((1 << s_bits) - 1));
1081 /* Add any "high bits" from the tlb offset to the env address into X2,
1082 to take advantage of the LSL12 form of the ADDI instruction.
1083 X2 = env + (tlb_offset & 0xfff000) */
1084 if (tlb_offset & 0xfff000) {
1085 tcg_out_insn(s, 3401, ADDI, TCG_TYPE_I64, TCG_REG_X2, base,
1086 tlb_offset & 0xfff000);
1087 base = TCG_REG_X2;
1090 /* Merge the tlb index contribution into X2.
1091 X2 = X2 + (X0 << CPU_TLB_ENTRY_BITS) */
1092 tcg_out_insn(s, 3502S, ADD_LSL, TCG_TYPE_I64, TCG_REG_X2, base,
1093 TCG_REG_X0, CPU_TLB_ENTRY_BITS);
1095 /* Merge "low bits" from tlb offset, load the tlb comparator into X0.
1096 X0 = load [X2 + (tlb_offset & 0x000fff)] */
1097 tcg_out_ldst(s, TARGET_LONG_BITS == 32 ? I3312_LDRW : I3312_LDRX,
1098 TCG_REG_X0, TCG_REG_X2, tlb_offset & 0xfff);
1100 /* Load the tlb addend. Do that early to avoid stalling.
1101 X1 = load [X2 + (tlb_offset & 0xfff) + offsetof(addend)] */
1102 tcg_out_ldst(s, I3312_LDRX, TCG_REG_X1, TCG_REG_X2,
1103 (tlb_offset & 0xfff) + (offsetof(CPUTLBEntry, addend)) -
1104 (is_read ? offsetof(CPUTLBEntry, addr_read)
1105 : offsetof(CPUTLBEntry, addr_write)));
1107 /* Perform the address comparison. */
1108 tcg_out_cmp(s, (TARGET_LONG_BITS == 64), TCG_REG_X0, TCG_REG_X3, 0);
1110 /* If not equal, we jump to the slow path. */
1111 *label_ptr = s->code_ptr;
1112 tcg_out_goto_cond_noaddr(s, TCG_COND_NE);
1115 #endif /* CONFIG_SOFTMMU */
1117 static void tcg_out_qemu_ld_direct(TCGContext *s, TCGMemOp memop, TCGType ext,
1118 TCGReg data_r, TCGReg addr_r,
1119 TCGType otype, TCGReg off_r)
1121 const TCGMemOp bswap = memop & MO_BSWAP;
1123 switch (memop & MO_SSIZE) {
1124 case MO_UB:
1125 tcg_out_ldst_r(s, I3312_LDRB, data_r, addr_r, otype, off_r);
1126 break;
1127 case MO_SB:
1128 tcg_out_ldst_r(s, ext ? I3312_LDRSBX : I3312_LDRSBW,
1129 data_r, addr_r, otype, off_r);
1130 break;
1131 case MO_UW:
1132 tcg_out_ldst_r(s, I3312_LDRH, data_r, addr_r, otype, off_r);
1133 if (bswap) {
1134 tcg_out_rev16(s, data_r, data_r);
1136 break;
1137 case MO_SW:
1138 if (bswap) {
1139 tcg_out_ldst_r(s, I3312_LDRH, data_r, addr_r, otype, off_r);
1140 tcg_out_rev16(s, data_r, data_r);
1141 tcg_out_sxt(s, ext, MO_16, data_r, data_r);
1142 } else {
1143 tcg_out_ldst_r(s, (ext ? I3312_LDRSHX : I3312_LDRSHW),
1144 data_r, addr_r, otype, off_r);
1146 break;
1147 case MO_UL:
1148 tcg_out_ldst_r(s, I3312_LDRW, data_r, addr_r, otype, off_r);
1149 if (bswap) {
1150 tcg_out_rev32(s, data_r, data_r);
1152 break;
1153 case MO_SL:
1154 if (bswap) {
1155 tcg_out_ldst_r(s, I3312_LDRW, data_r, addr_r, otype, off_r);
1156 tcg_out_rev32(s, data_r, data_r);
1157 tcg_out_sxt(s, TCG_TYPE_I64, MO_32, data_r, data_r);
1158 } else {
1159 tcg_out_ldst_r(s, I3312_LDRSWX, data_r, addr_r, otype, off_r);
1161 break;
1162 case MO_Q:
1163 tcg_out_ldst_r(s, I3312_LDRX, data_r, addr_r, otype, off_r);
1164 if (bswap) {
1165 tcg_out_rev64(s, data_r, data_r);
1167 break;
1168 default:
1169 tcg_abort();
1173 static void tcg_out_qemu_st_direct(TCGContext *s, TCGMemOp memop,
1174 TCGReg data_r, TCGReg addr_r,
1175 TCGType otype, TCGReg off_r)
1177 const TCGMemOp bswap = memop & MO_BSWAP;
1179 switch (memop & MO_SIZE) {
1180 case MO_8:
1181 tcg_out_ldst_r(s, I3312_STRB, data_r, addr_r, otype, off_r);
1182 break;
1183 case MO_16:
1184 if (bswap && data_r != TCG_REG_XZR) {
1185 tcg_out_rev16(s, TCG_REG_TMP, data_r);
1186 data_r = TCG_REG_TMP;
1188 tcg_out_ldst_r(s, I3312_STRH, data_r, addr_r, otype, off_r);
1189 break;
1190 case MO_32:
1191 if (bswap && data_r != TCG_REG_XZR) {
1192 tcg_out_rev32(s, TCG_REG_TMP, data_r);
1193 data_r = TCG_REG_TMP;
1195 tcg_out_ldst_r(s, I3312_STRW, data_r, addr_r, otype, off_r);
1196 break;
1197 case MO_64:
1198 if (bswap && data_r != TCG_REG_XZR) {
1199 tcg_out_rev64(s, TCG_REG_TMP, data_r);
1200 data_r = TCG_REG_TMP;
1202 tcg_out_ldst_r(s, I3312_STRX, data_r, addr_r, otype, off_r);
1203 break;
1204 default:
1205 tcg_abort();
1209 static void tcg_out_qemu_ld(TCGContext *s, TCGReg data_reg, TCGReg addr_reg,
1210 TCGMemOpIdx oi, TCGType ext)
1212 TCGMemOp memop = get_memop(oi);
1213 const TCGType otype = TARGET_LONG_BITS == 64 ? TCG_TYPE_I64 : TCG_TYPE_I32;
1214 #ifdef CONFIG_SOFTMMU
1215 unsigned mem_index = get_mmuidx(oi);
1216 TCGMemOp s_bits = memop & MO_SIZE;
1217 tcg_insn_unit *label_ptr;
1219 tcg_out_tlb_read(s, addr_reg, s_bits, &label_ptr, mem_index, 1);
1220 tcg_out_qemu_ld_direct(s, memop, ext, data_reg,
1221 TCG_REG_X1, otype, addr_reg);
1222 add_qemu_ldst_label(s, true, oi, ext, data_reg, addr_reg,
1223 s->code_ptr, label_ptr);
1224 #else /* !CONFIG_SOFTMMU */
1225 if (USE_GUEST_BASE) {
1226 tcg_out_qemu_ld_direct(s, memop, ext, data_reg,
1227 TCG_REG_GUEST_BASE, otype, addr_reg);
1228 } else {
1229 tcg_out_qemu_ld_direct(s, memop, ext, data_reg,
1230 addr_reg, TCG_TYPE_I64, TCG_REG_XZR);
1232 #endif /* CONFIG_SOFTMMU */
1235 static void tcg_out_qemu_st(TCGContext *s, TCGReg data_reg, TCGReg addr_reg,
1236 TCGMemOpIdx oi)
1238 TCGMemOp memop = get_memop(oi);
1239 const TCGType otype = TARGET_LONG_BITS == 64 ? TCG_TYPE_I64 : TCG_TYPE_I32;
1240 #ifdef CONFIG_SOFTMMU
1241 unsigned mem_index = get_mmuidx(oi);
1242 TCGMemOp s_bits = memop & MO_SIZE;
1243 tcg_insn_unit *label_ptr;
1245 tcg_out_tlb_read(s, addr_reg, s_bits, &label_ptr, mem_index, 0);
1246 tcg_out_qemu_st_direct(s, memop, data_reg,
1247 TCG_REG_X1, otype, addr_reg);
1248 add_qemu_ldst_label(s, false, oi, s_bits == MO_64, data_reg, addr_reg,
1249 s->code_ptr, label_ptr);
1250 #else /* !CONFIG_SOFTMMU */
1251 if (USE_GUEST_BASE) {
1252 tcg_out_qemu_st_direct(s, memop, data_reg,
1253 TCG_REG_GUEST_BASE, otype, addr_reg);
1254 } else {
1255 tcg_out_qemu_st_direct(s, memop, data_reg,
1256 addr_reg, TCG_TYPE_I64, TCG_REG_XZR);
1258 #endif /* CONFIG_SOFTMMU */
1261 static tcg_insn_unit *tb_ret_addr;
1263 static void tcg_out_op(TCGContext *s, TCGOpcode opc,
1264 const TCGArg args[TCG_MAX_OP_ARGS],
1265 const int const_args[TCG_MAX_OP_ARGS])
1267 /* 99% of the time, we can signal the use of extension registers
1268 by looking to see if the opcode handles 64-bit data. */
1269 TCGType ext = (tcg_op_defs[opc].flags & TCG_OPF_64BIT) != 0;
1271 /* Hoist the loads of the most common arguments. */
1272 TCGArg a0 = args[0];
1273 TCGArg a1 = args[1];
1274 TCGArg a2 = args[2];
1275 int c2 = const_args[2];
1277 /* Some operands are defined with "rZ" constraint, a register or
1278 the zero register. These need not actually test args[I] == 0. */
1279 #define REG0(I) (const_args[I] ? TCG_REG_XZR : (TCGReg)args[I])
1281 switch (opc) {
1282 case INDEX_op_exit_tb:
1283 tcg_out_movi(s, TCG_TYPE_I64, TCG_REG_X0, a0);
1284 tcg_out_goto(s, tb_ret_addr);
1285 break;
1287 case INDEX_op_goto_tb:
1288 #ifndef USE_DIRECT_JUMP
1289 #error "USE_DIRECT_JUMP required for aarch64"
1290 #endif
1291 assert(s->tb_jmp_offset != NULL); /* consistency for USE_DIRECT_JUMP */
1292 s->tb_jmp_offset[a0] = tcg_current_code_size(s);
1293 /* actual branch destination will be patched by
1294 aarch64_tb_set_jmp_target later, beware retranslation. */
1295 tcg_out_goto_noaddr(s);
1296 s->tb_next_offset[a0] = tcg_current_code_size(s);
1297 break;
1299 case INDEX_op_br:
1300 tcg_out_goto_label(s, arg_label(a0));
1301 break;
1303 case INDEX_op_ld8u_i32:
1304 case INDEX_op_ld8u_i64:
1305 tcg_out_ldst(s, I3312_LDRB, a0, a1, a2);
1306 break;
1307 case INDEX_op_ld8s_i32:
1308 tcg_out_ldst(s, I3312_LDRSBW, a0, a1, a2);
1309 break;
1310 case INDEX_op_ld8s_i64:
1311 tcg_out_ldst(s, I3312_LDRSBX, a0, a1, a2);
1312 break;
1313 case INDEX_op_ld16u_i32:
1314 case INDEX_op_ld16u_i64:
1315 tcg_out_ldst(s, I3312_LDRH, a0, a1, a2);
1316 break;
1317 case INDEX_op_ld16s_i32:
1318 tcg_out_ldst(s, I3312_LDRSHW, a0, a1, a2);
1319 break;
1320 case INDEX_op_ld16s_i64:
1321 tcg_out_ldst(s, I3312_LDRSHX, a0, a1, a2);
1322 break;
1323 case INDEX_op_ld_i32:
1324 case INDEX_op_ld32u_i64:
1325 tcg_out_ldst(s, I3312_LDRW, a0, a1, a2);
1326 break;
1327 case INDEX_op_ld32s_i64:
1328 tcg_out_ldst(s, I3312_LDRSWX, a0, a1, a2);
1329 break;
1330 case INDEX_op_ld_i64:
1331 tcg_out_ldst(s, I3312_LDRX, a0, a1, a2);
1332 break;
1334 case INDEX_op_st8_i32:
1335 case INDEX_op_st8_i64:
1336 tcg_out_ldst(s, I3312_STRB, REG0(0), a1, a2);
1337 break;
1338 case INDEX_op_st16_i32:
1339 case INDEX_op_st16_i64:
1340 tcg_out_ldst(s, I3312_STRH, REG0(0), a1, a2);
1341 break;
1342 case INDEX_op_st_i32:
1343 case INDEX_op_st32_i64:
1344 tcg_out_ldst(s, I3312_STRW, REG0(0), a1, a2);
1345 break;
1346 case INDEX_op_st_i64:
1347 tcg_out_ldst(s, I3312_STRX, REG0(0), a1, a2);
1348 break;
1350 case INDEX_op_add_i32:
1351 a2 = (int32_t)a2;
1352 /* FALLTHRU */
1353 case INDEX_op_add_i64:
1354 if (c2) {
1355 tcg_out_addsubi(s, ext, a0, a1, a2);
1356 } else {
1357 tcg_out_insn(s, 3502, ADD, ext, a0, a1, a2);
1359 break;
1361 case INDEX_op_sub_i32:
1362 a2 = (int32_t)a2;
1363 /* FALLTHRU */
1364 case INDEX_op_sub_i64:
1365 if (c2) {
1366 tcg_out_addsubi(s, ext, a0, a1, -a2);
1367 } else {
1368 tcg_out_insn(s, 3502, SUB, ext, a0, a1, a2);
1370 break;
1372 case INDEX_op_neg_i64:
1373 case INDEX_op_neg_i32:
1374 tcg_out_insn(s, 3502, SUB, ext, a0, TCG_REG_XZR, a1);
1375 break;
1377 case INDEX_op_and_i32:
1378 a2 = (int32_t)a2;
1379 /* FALLTHRU */
1380 case INDEX_op_and_i64:
1381 if (c2) {
1382 tcg_out_logicali(s, I3404_ANDI, ext, a0, a1, a2);
1383 } else {
1384 tcg_out_insn(s, 3510, AND, ext, a0, a1, a2);
1386 break;
1388 case INDEX_op_andc_i32:
1389 a2 = (int32_t)a2;
1390 /* FALLTHRU */
1391 case INDEX_op_andc_i64:
1392 if (c2) {
1393 tcg_out_logicali(s, I3404_ANDI, ext, a0, a1, ~a2);
1394 } else {
1395 tcg_out_insn(s, 3510, BIC, ext, a0, a1, a2);
1397 break;
1399 case INDEX_op_or_i32:
1400 a2 = (int32_t)a2;
1401 /* FALLTHRU */
1402 case INDEX_op_or_i64:
1403 if (c2) {
1404 tcg_out_logicali(s, I3404_ORRI, ext, a0, a1, a2);
1405 } else {
1406 tcg_out_insn(s, 3510, ORR, ext, a0, a1, a2);
1408 break;
1410 case INDEX_op_orc_i32:
1411 a2 = (int32_t)a2;
1412 /* FALLTHRU */
1413 case INDEX_op_orc_i64:
1414 if (c2) {
1415 tcg_out_logicali(s, I3404_ORRI, ext, a0, a1, ~a2);
1416 } else {
1417 tcg_out_insn(s, 3510, ORN, ext, a0, a1, a2);
1419 break;
1421 case INDEX_op_xor_i32:
1422 a2 = (int32_t)a2;
1423 /* FALLTHRU */
1424 case INDEX_op_xor_i64:
1425 if (c2) {
1426 tcg_out_logicali(s, I3404_EORI, ext, a0, a1, a2);
1427 } else {
1428 tcg_out_insn(s, 3510, EOR, ext, a0, a1, a2);
1430 break;
1432 case INDEX_op_eqv_i32:
1433 a2 = (int32_t)a2;
1434 /* FALLTHRU */
1435 case INDEX_op_eqv_i64:
1436 if (c2) {
1437 tcg_out_logicali(s, I3404_EORI, ext, a0, a1, ~a2);
1438 } else {
1439 tcg_out_insn(s, 3510, EON, ext, a0, a1, a2);
1441 break;
1443 case INDEX_op_not_i64:
1444 case INDEX_op_not_i32:
1445 tcg_out_insn(s, 3510, ORN, ext, a0, TCG_REG_XZR, a1);
1446 break;
1448 case INDEX_op_mul_i64:
1449 case INDEX_op_mul_i32:
1450 tcg_out_insn(s, 3509, MADD, ext, a0, a1, a2, TCG_REG_XZR);
1451 break;
1453 case INDEX_op_div_i64:
1454 case INDEX_op_div_i32:
1455 tcg_out_insn(s, 3508, SDIV, ext, a0, a1, a2);
1456 break;
1457 case INDEX_op_divu_i64:
1458 case INDEX_op_divu_i32:
1459 tcg_out_insn(s, 3508, UDIV, ext, a0, a1, a2);
1460 break;
1462 case INDEX_op_rem_i64:
1463 case INDEX_op_rem_i32:
1464 tcg_out_insn(s, 3508, SDIV, ext, TCG_REG_TMP, a1, a2);
1465 tcg_out_insn(s, 3509, MSUB, ext, a0, TCG_REG_TMP, a2, a1);
1466 break;
1467 case INDEX_op_remu_i64:
1468 case INDEX_op_remu_i32:
1469 tcg_out_insn(s, 3508, UDIV, ext, TCG_REG_TMP, a1, a2);
1470 tcg_out_insn(s, 3509, MSUB, ext, a0, TCG_REG_TMP, a2, a1);
1471 break;
1473 case INDEX_op_shl_i64:
1474 case INDEX_op_shl_i32:
1475 if (c2) {
1476 tcg_out_shl(s, ext, a0, a1, a2);
1477 } else {
1478 tcg_out_insn(s, 3508, LSLV, ext, a0, a1, a2);
1480 break;
1482 case INDEX_op_shr_i64:
1483 case INDEX_op_shr_i32:
1484 if (c2) {
1485 tcg_out_shr(s, ext, a0, a1, a2);
1486 } else {
1487 tcg_out_insn(s, 3508, LSRV, ext, a0, a1, a2);
1489 break;
1491 case INDEX_op_sar_i64:
1492 case INDEX_op_sar_i32:
1493 if (c2) {
1494 tcg_out_sar(s, ext, a0, a1, a2);
1495 } else {
1496 tcg_out_insn(s, 3508, ASRV, ext, a0, a1, a2);
1498 break;
1500 case INDEX_op_rotr_i64:
1501 case INDEX_op_rotr_i32:
1502 if (c2) {
1503 tcg_out_rotr(s, ext, a0, a1, a2);
1504 } else {
1505 tcg_out_insn(s, 3508, RORV, ext, a0, a1, a2);
1507 break;
1509 case INDEX_op_rotl_i64:
1510 case INDEX_op_rotl_i32:
1511 if (c2) {
1512 tcg_out_rotl(s, ext, a0, a1, a2);
1513 } else {
1514 tcg_out_insn(s, 3502, SUB, 0, TCG_REG_TMP, TCG_REG_XZR, a2);
1515 tcg_out_insn(s, 3508, RORV, ext, a0, a1, TCG_REG_TMP);
1517 break;
1519 case INDEX_op_brcond_i32:
1520 a1 = (int32_t)a1;
1521 /* FALLTHRU */
1522 case INDEX_op_brcond_i64:
1523 tcg_out_brcond(s, ext, a2, a0, a1, const_args[1], arg_label(args[3]));
1524 break;
1526 case INDEX_op_setcond_i32:
1527 a2 = (int32_t)a2;
1528 /* FALLTHRU */
1529 case INDEX_op_setcond_i64:
1530 tcg_out_cmp(s, ext, a1, a2, c2);
1531 /* Use CSET alias of CSINC Wd, WZR, WZR, invert(cond). */
1532 tcg_out_insn(s, 3506, CSINC, TCG_TYPE_I32, a0, TCG_REG_XZR,
1533 TCG_REG_XZR, tcg_invert_cond(args[3]));
1534 break;
1536 case INDEX_op_movcond_i32:
1537 a2 = (int32_t)a2;
1538 /* FALLTHRU */
1539 case INDEX_op_movcond_i64:
1540 tcg_out_cmp(s, ext, a1, a2, c2);
1541 tcg_out_insn(s, 3506, CSEL, ext, a0, REG0(3), REG0(4), args[5]);
1542 break;
1544 case INDEX_op_qemu_ld_i32:
1545 case INDEX_op_qemu_ld_i64:
1546 tcg_out_qemu_ld(s, a0, a1, a2, ext);
1547 break;
1548 case INDEX_op_qemu_st_i32:
1549 case INDEX_op_qemu_st_i64:
1550 tcg_out_qemu_st(s, REG0(0), a1, a2);
1551 break;
1553 case INDEX_op_bswap64_i64:
1554 tcg_out_rev64(s, a0, a1);
1555 break;
1556 case INDEX_op_bswap32_i64:
1557 case INDEX_op_bswap32_i32:
1558 tcg_out_rev32(s, a0, a1);
1559 break;
1560 case INDEX_op_bswap16_i64:
1561 case INDEX_op_bswap16_i32:
1562 tcg_out_rev16(s, a0, a1);
1563 break;
1565 case INDEX_op_ext8s_i64:
1566 case INDEX_op_ext8s_i32:
1567 tcg_out_sxt(s, ext, MO_8, a0, a1);
1568 break;
1569 case INDEX_op_ext16s_i64:
1570 case INDEX_op_ext16s_i32:
1571 tcg_out_sxt(s, ext, MO_16, a0, a1);
1572 break;
1573 case INDEX_op_ext32s_i64:
1574 tcg_out_sxt(s, TCG_TYPE_I64, MO_32, a0, a1);
1575 break;
1576 case INDEX_op_ext8u_i64:
1577 case INDEX_op_ext8u_i32:
1578 tcg_out_uxt(s, MO_8, a0, a1);
1579 break;
1580 case INDEX_op_ext16u_i64:
1581 case INDEX_op_ext16u_i32:
1582 tcg_out_uxt(s, MO_16, a0, a1);
1583 break;
1584 case INDEX_op_ext32u_i64:
1585 tcg_out_movr(s, TCG_TYPE_I32, a0, a1);
1586 break;
1588 case INDEX_op_deposit_i64:
1589 case INDEX_op_deposit_i32:
1590 tcg_out_dep(s, ext, a0, REG0(2), args[3], args[4]);
1591 break;
1593 case INDEX_op_add2_i32:
1594 tcg_out_addsub2(s, TCG_TYPE_I32, a0, a1, REG0(2), REG0(3),
1595 (int32_t)args[4], args[5], const_args[4],
1596 const_args[5], false);
1597 break;
1598 case INDEX_op_add2_i64:
1599 tcg_out_addsub2(s, TCG_TYPE_I64, a0, a1, REG0(2), REG0(3), args[4],
1600 args[5], const_args[4], const_args[5], false);
1601 break;
1602 case INDEX_op_sub2_i32:
1603 tcg_out_addsub2(s, TCG_TYPE_I32, a0, a1, REG0(2), REG0(3),
1604 (int32_t)args[4], args[5], const_args[4],
1605 const_args[5], true);
1606 break;
1607 case INDEX_op_sub2_i64:
1608 tcg_out_addsub2(s, TCG_TYPE_I64, a0, a1, REG0(2), REG0(3), args[4],
1609 args[5], const_args[4], const_args[5], true);
1610 break;
1612 case INDEX_op_muluh_i64:
1613 tcg_out_insn(s, 3508, UMULH, TCG_TYPE_I64, a0, a1, a2);
1614 break;
1615 case INDEX_op_mulsh_i64:
1616 tcg_out_insn(s, 3508, SMULH, TCG_TYPE_I64, a0, a1, a2);
1617 break;
1619 case INDEX_op_mov_i32: /* Always emitted via tcg_out_mov. */
1620 case INDEX_op_mov_i64:
1621 case INDEX_op_movi_i32: /* Always emitted via tcg_out_movi. */
1622 case INDEX_op_movi_i64:
1623 case INDEX_op_call: /* Always emitted via tcg_out_call. */
1624 default:
1625 tcg_abort();
1628 #undef REG0
1631 static const TCGTargetOpDef aarch64_op_defs[] = {
1632 { INDEX_op_exit_tb, { } },
1633 { INDEX_op_goto_tb, { } },
1634 { INDEX_op_br, { } },
1636 { INDEX_op_ld8u_i32, { "r", "r" } },
1637 { INDEX_op_ld8s_i32, { "r", "r" } },
1638 { INDEX_op_ld16u_i32, { "r", "r" } },
1639 { INDEX_op_ld16s_i32, { "r", "r" } },
1640 { INDEX_op_ld_i32, { "r", "r" } },
1641 { INDEX_op_ld8u_i64, { "r", "r" } },
1642 { INDEX_op_ld8s_i64, { "r", "r" } },
1643 { INDEX_op_ld16u_i64, { "r", "r" } },
1644 { INDEX_op_ld16s_i64, { "r", "r" } },
1645 { INDEX_op_ld32u_i64, { "r", "r" } },
1646 { INDEX_op_ld32s_i64, { "r", "r" } },
1647 { INDEX_op_ld_i64, { "r", "r" } },
1649 { INDEX_op_st8_i32, { "rZ", "r" } },
1650 { INDEX_op_st16_i32, { "rZ", "r" } },
1651 { INDEX_op_st_i32, { "rZ", "r" } },
1652 { INDEX_op_st8_i64, { "rZ", "r" } },
1653 { INDEX_op_st16_i64, { "rZ", "r" } },
1654 { INDEX_op_st32_i64, { "rZ", "r" } },
1655 { INDEX_op_st_i64, { "rZ", "r" } },
1657 { INDEX_op_add_i32, { "r", "r", "rA" } },
1658 { INDEX_op_add_i64, { "r", "r", "rA" } },
1659 { INDEX_op_sub_i32, { "r", "r", "rA" } },
1660 { INDEX_op_sub_i64, { "r", "r", "rA" } },
1661 { INDEX_op_mul_i32, { "r", "r", "r" } },
1662 { INDEX_op_mul_i64, { "r", "r", "r" } },
1663 { INDEX_op_div_i32, { "r", "r", "r" } },
1664 { INDEX_op_div_i64, { "r", "r", "r" } },
1665 { INDEX_op_divu_i32, { "r", "r", "r" } },
1666 { INDEX_op_divu_i64, { "r", "r", "r" } },
1667 { INDEX_op_rem_i32, { "r", "r", "r" } },
1668 { INDEX_op_rem_i64, { "r", "r", "r" } },
1669 { INDEX_op_remu_i32, { "r", "r", "r" } },
1670 { INDEX_op_remu_i64, { "r", "r", "r" } },
1671 { INDEX_op_and_i32, { "r", "r", "rL" } },
1672 { INDEX_op_and_i64, { "r", "r", "rL" } },
1673 { INDEX_op_or_i32, { "r", "r", "rL" } },
1674 { INDEX_op_or_i64, { "r", "r", "rL" } },
1675 { INDEX_op_xor_i32, { "r", "r", "rL" } },
1676 { INDEX_op_xor_i64, { "r", "r", "rL" } },
1677 { INDEX_op_andc_i32, { "r", "r", "rL" } },
1678 { INDEX_op_andc_i64, { "r", "r", "rL" } },
1679 { INDEX_op_orc_i32, { "r", "r", "rL" } },
1680 { INDEX_op_orc_i64, { "r", "r", "rL" } },
1681 { INDEX_op_eqv_i32, { "r", "r", "rL" } },
1682 { INDEX_op_eqv_i64, { "r", "r", "rL" } },
1684 { INDEX_op_neg_i32, { "r", "r" } },
1685 { INDEX_op_neg_i64, { "r", "r" } },
1686 { INDEX_op_not_i32, { "r", "r" } },
1687 { INDEX_op_not_i64, { "r", "r" } },
1689 { INDEX_op_shl_i32, { "r", "r", "ri" } },
1690 { INDEX_op_shr_i32, { "r", "r", "ri" } },
1691 { INDEX_op_sar_i32, { "r", "r", "ri" } },
1692 { INDEX_op_rotl_i32, { "r", "r", "ri" } },
1693 { INDEX_op_rotr_i32, { "r", "r", "ri" } },
1694 { INDEX_op_shl_i64, { "r", "r", "ri" } },
1695 { INDEX_op_shr_i64, { "r", "r", "ri" } },
1696 { INDEX_op_sar_i64, { "r", "r", "ri" } },
1697 { INDEX_op_rotl_i64, { "r", "r", "ri" } },
1698 { INDEX_op_rotr_i64, { "r", "r", "ri" } },
1700 { INDEX_op_brcond_i32, { "r", "rA" } },
1701 { INDEX_op_brcond_i64, { "r", "rA" } },
1702 { INDEX_op_setcond_i32, { "r", "r", "rA" } },
1703 { INDEX_op_setcond_i64, { "r", "r", "rA" } },
1704 { INDEX_op_movcond_i32, { "r", "r", "rA", "rZ", "rZ" } },
1705 { INDEX_op_movcond_i64, { "r", "r", "rA", "rZ", "rZ" } },
1707 { INDEX_op_qemu_ld_i32, { "r", "l" } },
1708 { INDEX_op_qemu_ld_i64, { "r", "l" } },
1709 { INDEX_op_qemu_st_i32, { "lZ", "l" } },
1710 { INDEX_op_qemu_st_i64, { "lZ", "l" } },
1712 { INDEX_op_bswap16_i32, { "r", "r" } },
1713 { INDEX_op_bswap32_i32, { "r", "r" } },
1714 { INDEX_op_bswap16_i64, { "r", "r" } },
1715 { INDEX_op_bswap32_i64, { "r", "r" } },
1716 { INDEX_op_bswap64_i64, { "r", "r" } },
1718 { INDEX_op_ext8s_i32, { "r", "r" } },
1719 { INDEX_op_ext16s_i32, { "r", "r" } },
1720 { INDEX_op_ext8u_i32, { "r", "r" } },
1721 { INDEX_op_ext16u_i32, { "r", "r" } },
1723 { INDEX_op_ext8s_i64, { "r", "r" } },
1724 { INDEX_op_ext16s_i64, { "r", "r" } },
1725 { INDEX_op_ext32s_i64, { "r", "r" } },
1726 { INDEX_op_ext8u_i64, { "r", "r" } },
1727 { INDEX_op_ext16u_i64, { "r", "r" } },
1728 { INDEX_op_ext32u_i64, { "r", "r" } },
1730 { INDEX_op_deposit_i32, { "r", "0", "rZ" } },
1731 { INDEX_op_deposit_i64, { "r", "0", "rZ" } },
1733 { INDEX_op_add2_i32, { "r", "r", "rZ", "rZ", "rA", "rMZ" } },
1734 { INDEX_op_add2_i64, { "r", "r", "rZ", "rZ", "rA", "rMZ" } },
1735 { INDEX_op_sub2_i32, { "r", "r", "rZ", "rZ", "rA", "rMZ" } },
1736 { INDEX_op_sub2_i64, { "r", "r", "rZ", "rZ", "rA", "rMZ" } },
1738 { INDEX_op_muluh_i64, { "r", "r", "r" } },
1739 { INDEX_op_mulsh_i64, { "r", "r", "r" } },
1741 { -1 },
1744 static void tcg_target_init(TCGContext *s)
1746 tcg_regset_set32(tcg_target_available_regs[TCG_TYPE_I32], 0, 0xffffffff);
1747 tcg_regset_set32(tcg_target_available_regs[TCG_TYPE_I64], 0, 0xffffffff);
1749 tcg_regset_set32(tcg_target_call_clobber_regs, 0,
1750 (1 << TCG_REG_X0) | (1 << TCG_REG_X1) |
1751 (1 << TCG_REG_X2) | (1 << TCG_REG_X3) |
1752 (1 << TCG_REG_X4) | (1 << TCG_REG_X5) |
1753 (1 << TCG_REG_X6) | (1 << TCG_REG_X7) |
1754 (1 << TCG_REG_X8) | (1 << TCG_REG_X9) |
1755 (1 << TCG_REG_X10) | (1 << TCG_REG_X11) |
1756 (1 << TCG_REG_X12) | (1 << TCG_REG_X13) |
1757 (1 << TCG_REG_X14) | (1 << TCG_REG_X15) |
1758 (1 << TCG_REG_X16) | (1 << TCG_REG_X17) |
1759 (1 << TCG_REG_X18) | (1 << TCG_REG_X30));
1761 tcg_regset_clear(s->reserved_regs);
1762 tcg_regset_set_reg(s->reserved_regs, TCG_REG_SP);
1763 tcg_regset_set_reg(s->reserved_regs, TCG_REG_FP);
1764 tcg_regset_set_reg(s->reserved_regs, TCG_REG_TMP);
1765 tcg_regset_set_reg(s->reserved_regs, TCG_REG_X18); /* platform register */
1767 tcg_add_target_add_op_defs(aarch64_op_defs);
1770 /* Saving pairs: (X19, X20) .. (X27, X28), (X29(fp), X30(lr)). */
1771 #define PUSH_SIZE ((30 - 19 + 1) * 8)
1773 #define FRAME_SIZE \
1774 ((PUSH_SIZE \
1775 + TCG_STATIC_CALL_ARGS_SIZE \
1776 + CPU_TEMP_BUF_NLONGS * sizeof(long) \
1777 + TCG_TARGET_STACK_ALIGN - 1) \
1778 & ~(TCG_TARGET_STACK_ALIGN - 1))
1780 /* We're expecting a 2 byte uleb128 encoded value. */
1781 QEMU_BUILD_BUG_ON(FRAME_SIZE >= (1 << 14));
1783 /* We're expecting to use a single ADDI insn. */
1784 QEMU_BUILD_BUG_ON(FRAME_SIZE - PUSH_SIZE > 0xfff);
1786 static void tcg_target_qemu_prologue(TCGContext *s)
1788 TCGReg r;
1790 /* Push (FP, LR) and allocate space for all saved registers. */
1791 tcg_out_insn(s, 3314, STP, TCG_REG_FP, TCG_REG_LR,
1792 TCG_REG_SP, -PUSH_SIZE, 1, 1);
1794 /* Set up frame pointer for canonical unwinding. */
1795 tcg_out_movr_sp(s, TCG_TYPE_I64, TCG_REG_FP, TCG_REG_SP);
1797 /* Store callee-preserved regs x19..x28. */
1798 for (r = TCG_REG_X19; r <= TCG_REG_X27; r += 2) {
1799 int ofs = (r - TCG_REG_X19 + 2) * 8;
1800 tcg_out_insn(s, 3314, STP, r, r + 1, TCG_REG_SP, ofs, 1, 0);
1803 /* Make stack space for TCG locals. */
1804 tcg_out_insn(s, 3401, SUBI, TCG_TYPE_I64, TCG_REG_SP, TCG_REG_SP,
1805 FRAME_SIZE - PUSH_SIZE);
1807 /* Inform TCG about how to find TCG locals with register, offset, size. */
1808 tcg_set_frame(s, TCG_REG_SP, TCG_STATIC_CALL_ARGS_SIZE,
1809 CPU_TEMP_BUF_NLONGS * sizeof(long));
1811 #if defined(CONFIG_USE_GUEST_BASE)
1812 if (USE_GUEST_BASE) {
1813 tcg_out_movi(s, TCG_TYPE_PTR, TCG_REG_GUEST_BASE, GUEST_BASE);
1814 tcg_regset_set_reg(s->reserved_regs, TCG_REG_GUEST_BASE);
1816 #endif
1818 tcg_out_mov(s, TCG_TYPE_PTR, TCG_AREG0, tcg_target_call_iarg_regs[0]);
1819 tcg_out_insn(s, 3207, BR, tcg_target_call_iarg_regs[1]);
1821 tb_ret_addr = s->code_ptr;
1823 /* Remove TCG locals stack space. */
1824 tcg_out_insn(s, 3401, ADDI, TCG_TYPE_I64, TCG_REG_SP, TCG_REG_SP,
1825 FRAME_SIZE - PUSH_SIZE);
1827 /* Restore registers x19..x28. */
1828 for (r = TCG_REG_X19; r <= TCG_REG_X27; r += 2) {
1829 int ofs = (r - TCG_REG_X19 + 2) * 8;
1830 tcg_out_insn(s, 3314, LDP, r, r + 1, TCG_REG_SP, ofs, 1, 0);
1833 /* Pop (FP, LR), restore SP to previous frame. */
1834 tcg_out_insn(s, 3314, LDP, TCG_REG_FP, TCG_REG_LR,
1835 TCG_REG_SP, PUSH_SIZE, 0, 1);
1836 tcg_out_insn(s, 3207, RET, TCG_REG_LR);
1839 typedef struct {
1840 DebugFrameHeader h;
1841 uint8_t fde_def_cfa[4];
1842 uint8_t fde_reg_ofs[24];
1843 } DebugFrame;
1845 #define ELF_HOST_MACHINE EM_AARCH64
1847 static const DebugFrame debug_frame = {
1848 .h.cie.len = sizeof(DebugFrameCIE)-4, /* length after .len member */
1849 .h.cie.id = -1,
1850 .h.cie.version = 1,
1851 .h.cie.code_align = 1,
1852 .h.cie.data_align = 0x78, /* sleb128 -8 */
1853 .h.cie.return_column = TCG_REG_LR,
1855 /* Total FDE size does not include the "len" member. */
1856 .h.fde.len = sizeof(DebugFrame) - offsetof(DebugFrame, h.fde.cie_offset),
1858 .fde_def_cfa = {
1859 12, TCG_REG_SP, /* DW_CFA_def_cfa sp, ... */
1860 (FRAME_SIZE & 0x7f) | 0x80, /* ... uleb128 FRAME_SIZE */
1861 (FRAME_SIZE >> 7)
1863 .fde_reg_ofs = {
1864 0x80 + 28, 1, /* DW_CFA_offset, x28, -8 */
1865 0x80 + 27, 2, /* DW_CFA_offset, x27, -16 */
1866 0x80 + 26, 3, /* DW_CFA_offset, x26, -24 */
1867 0x80 + 25, 4, /* DW_CFA_offset, x25, -32 */
1868 0x80 + 24, 5, /* DW_CFA_offset, x24, -40 */
1869 0x80 + 23, 6, /* DW_CFA_offset, x23, -48 */
1870 0x80 + 22, 7, /* DW_CFA_offset, x22, -56 */
1871 0x80 + 21, 8, /* DW_CFA_offset, x21, -64 */
1872 0x80 + 20, 9, /* DW_CFA_offset, x20, -72 */
1873 0x80 + 19, 10, /* DW_CFA_offset, x1p, -80 */
1874 0x80 + 30, 11, /* DW_CFA_offset, lr, -88 */
1875 0x80 + 29, 12, /* DW_CFA_offset, fp, -96 */
1879 void tcg_register_jit(void *buf, size_t buf_size)
1881 tcg_register_jit_int(buf, buf_size, &debug_frame, sizeof(debug_frame));