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-pool.c.inc"
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 #ifdef CONFIG_DEBUG_TCG
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 "v0", "v1", "v2", "v3", "v4", "v5", "v6", "v7",
29 "v8", "v9", "v10", "v11", "v12", "v13", "v14", "v15",
30 "v16", "v17", "v18", "v19", "v20", "v21", "v22", "v23",
31 "v24", "v25", "v26", "v27", "v28", "fp", "v30", "v31",
33 #endif /* CONFIG_DEBUG_TCG */
35 static const int tcg_target_reg_alloc_order[] = {
36 TCG_REG_X20, TCG_REG_X21, TCG_REG_X22, TCG_REG_X23,
37 TCG_REG_X24, TCG_REG_X25, TCG_REG_X26, TCG_REG_X27,
38 TCG_REG_X28, /* we will reserve this for guest_base if configured */
40 TCG_REG_X8, TCG_REG_X9, TCG_REG_X10, TCG_REG_X11,
41 TCG_REG_X12, TCG_REG_X13, TCG_REG_X14, TCG_REG_X15,
42 TCG_REG_X16, TCG_REG_X17,
44 TCG_REG_X0, TCG_REG_X1, TCG_REG_X2, TCG_REG_X3,
45 TCG_REG_X4, TCG_REG_X5, TCG_REG_X6, TCG_REG_X7,
47 /* X18 reserved by system */
48 /* X19 reserved for AREG0 */
49 /* X29 reserved as fp */
50 /* X30 reserved as temporary */
52 TCG_REG_V0, TCG_REG_V1, TCG_REG_V2, TCG_REG_V3,
53 TCG_REG_V4, TCG_REG_V5, TCG_REG_V6, TCG_REG_V7,
54 /* V8 - V15 are call-saved, and skipped. */
55 TCG_REG_V16, TCG_REG_V17, TCG_REG_V18, TCG_REG_V19,
56 TCG_REG_V20, TCG_REG_V21, TCG_REG_V22, TCG_REG_V23,
57 TCG_REG_V24, TCG_REG_V25, TCG_REG_V26, TCG_REG_V27,
58 TCG_REG_V28, TCG_REG_V29, TCG_REG_V30, TCG_REG_V31,
61 static const int tcg_target_call_iarg_regs[8] = {
62 TCG_REG_X0, TCG_REG_X1, TCG_REG_X2, TCG_REG_X3,
63 TCG_REG_X4, TCG_REG_X5, TCG_REG_X6, TCG_REG_X7
65 static const int tcg_target_call_oarg_regs[1] = {
69 #define TCG_REG_TMP TCG_REG_X30
70 #define TCG_VEC_TMP TCG_REG_V31
72 #ifndef CONFIG_SOFTMMU
73 /* Note that XZR cannot be encoded in the address base register slot,
74 as that actaully encodes SP. So if we need to zero-extend the guest
75 address, via the address index register slot, we need to load even
76 a zero guest base into a register. */
77 #define USE_GUEST_BASE (guest_base != 0 || TARGET_LONG_BITS == 32)
78 #define TCG_REG_GUEST_BASE TCG_REG_X28
81 static bool reloc_pc26(tcg_insn_unit *src_rw, const tcg_insn_unit *target)
83 const tcg_insn_unit *src_rx = tcg_splitwx_to_rx(src_rw);
84 ptrdiff_t offset = target - src_rx;
86 if (offset == sextract64(offset, 0, 26)) {
87 /* read instruction, mask away previous PC_REL26 parameter contents,
88 set the proper offset, then write back the instruction. */
89 *src_rw = deposit32(*src_rw, 0, 26, offset);
95 static bool reloc_pc19(tcg_insn_unit *src_rw, const tcg_insn_unit *target)
97 const tcg_insn_unit *src_rx = tcg_splitwx_to_rx(src_rw);
98 ptrdiff_t offset = target - src_rx;
100 if (offset == sextract64(offset, 0, 19)) {
101 *src_rw = deposit32(*src_rw, 5, 19, offset);
107 static bool patch_reloc(tcg_insn_unit *code_ptr, int type,
108 intptr_t value, intptr_t addend)
110 tcg_debug_assert(addend == 0);
112 case R_AARCH64_JUMP26:
113 case R_AARCH64_CALL26:
114 return reloc_pc26(code_ptr, (const tcg_insn_unit *)value);
115 case R_AARCH64_CONDBR19:
116 return reloc_pc19(code_ptr, (const tcg_insn_unit *)value);
118 g_assert_not_reached();
122 #define TCG_CT_CONST_AIMM 0x100
123 #define TCG_CT_CONST_LIMM 0x200
124 #define TCG_CT_CONST_ZERO 0x400
125 #define TCG_CT_CONST_MONE 0x800
126 #define TCG_CT_CONST_ORRI 0x1000
127 #define TCG_CT_CONST_ANDI 0x2000
129 /* parse target specific constraints */
130 static const char *target_parse_constraint(TCGArgConstraint *ct,
131 const char *ct_str, TCGType type)
134 case 'r': /* general registers */
135 ct->regs |= 0xffffffffu;
137 case 'w': /* advsimd registers */
138 ct->regs |= 0xffffffff00000000ull;
140 case 'l': /* qemu_ld / qemu_st address, data_reg */
141 ct->regs = 0xffffffffu;
142 #ifdef CONFIG_SOFTMMU
143 /* x0 and x1 will be overwritten when reading the tlb entry,
144 and x2, and x3 for helper args, better to avoid using them. */
145 tcg_regset_reset_reg(ct->regs, TCG_REG_X0);
146 tcg_regset_reset_reg(ct->regs, TCG_REG_X1);
147 tcg_regset_reset_reg(ct->regs, TCG_REG_X2);
148 tcg_regset_reset_reg(ct->regs, TCG_REG_X3);
151 case 'A': /* Valid for arithmetic immediate (positive or negative). */
152 ct->ct |= TCG_CT_CONST_AIMM;
154 case 'L': /* Valid for logical immediate. */
155 ct->ct |= TCG_CT_CONST_LIMM;
157 case 'M': /* minus one */
158 ct->ct |= TCG_CT_CONST_MONE;
160 case 'O': /* vector orr/bic immediate */
161 ct->ct |= TCG_CT_CONST_ORRI;
163 case 'N': /* vector orr/bic immediate, inverted */
164 ct->ct |= TCG_CT_CONST_ANDI;
167 ct->ct |= TCG_CT_CONST_ZERO;
175 /* Match a constant valid for addition (12-bit, optionally shifted). */
176 static inline bool is_aimm(uint64_t val)
178 return (val & ~0xfff) == 0 || (val & ~0xfff000) == 0;
181 /* Match a constant valid for logical operations. */
182 static inline bool is_limm(uint64_t val)
184 /* Taking a simplified view of the logical immediates for now, ignoring
185 the replication that can happen across the field. Match bit patterns
189 and their inverses. */
191 /* Make things easier below, by testing the form with msb clear. */
192 if ((int64_t)val < 0) {
199 return (val & (val - 1)) == 0;
202 /* Return true if v16 is a valid 16-bit shifted immediate. */
203 static bool is_shimm16(uint16_t v16, int *cmode, int *imm8)
205 if (v16 == (v16 & 0xff)) {
209 } else if (v16 == (v16 & 0xff00)) {
217 /* Return true if v32 is a valid 32-bit shifted immediate. */
218 static bool is_shimm32(uint32_t v32, int *cmode, int *imm8)
220 if (v32 == (v32 & 0xff)) {
224 } else if (v32 == (v32 & 0xff00)) {
226 *imm8 = (v32 >> 8) & 0xff;
228 } else if (v32 == (v32 & 0xff0000)) {
230 *imm8 = (v32 >> 16) & 0xff;
232 } else if (v32 == (v32 & 0xff000000)) {
240 /* Return true if v32 is a valid 32-bit shifting ones immediate. */
241 static bool is_soimm32(uint32_t v32, int *cmode, int *imm8)
243 if ((v32 & 0xffff00ff) == 0xff) {
245 *imm8 = (v32 >> 8) & 0xff;
247 } else if ((v32 & 0xff00ffff) == 0xffff) {
249 *imm8 = (v32 >> 16) & 0xff;
255 /* Return true if v32 is a valid float32 immediate. */
256 static bool is_fimm32(uint32_t v32, int *cmode, int *imm8)
258 if (extract32(v32, 0, 19) == 0
259 && (extract32(v32, 25, 6) == 0x20
260 || extract32(v32, 25, 6) == 0x1f)) {
262 *imm8 = (extract32(v32, 31, 1) << 7)
263 | (extract32(v32, 25, 1) << 6)
264 | extract32(v32, 19, 6);
270 /* Return true if v64 is a valid float64 immediate. */
271 static bool is_fimm64(uint64_t v64, int *cmode, int *imm8)
273 if (extract64(v64, 0, 48) == 0
274 && (extract64(v64, 54, 9) == 0x100
275 || extract64(v64, 54, 9) == 0x0ff)) {
277 *imm8 = (extract64(v64, 63, 1) << 7)
278 | (extract64(v64, 54, 1) << 6)
279 | extract64(v64, 48, 6);
286 * Return non-zero if v32 can be formed by MOVI+ORR.
287 * Place the parameters for MOVI in (cmode, imm8).
288 * Return the cmode for ORR; the imm8 can be had via extraction from v32.
290 static int is_shimm32_pair(uint32_t v32, int *cmode, int *imm8)
294 for (i = 6; i > 0; i -= 2) {
295 /* Mask out one byte we can add with ORR. */
296 uint32_t tmp = v32 & ~(0xffu << (i * 4));
297 if (is_shimm32(tmp, cmode, imm8) ||
298 is_soimm32(tmp, cmode, imm8)) {
305 /* Return true if V is a valid 16-bit or 32-bit shifted immediate. */
306 static bool is_shimm1632(uint32_t v32, int *cmode, int *imm8)
308 if (v32 == deposit32(v32, 16, 16, v32)) {
309 return is_shimm16(v32, cmode, imm8);
311 return is_shimm32(v32, cmode, imm8);
315 static int tcg_target_const_match(tcg_target_long val, TCGType type,
316 const TCGArgConstraint *arg_ct)
320 if (ct & TCG_CT_CONST) {
323 if (type == TCG_TYPE_I32) {
326 if ((ct & TCG_CT_CONST_AIMM) && (is_aimm(val) || is_aimm(-val))) {
329 if ((ct & TCG_CT_CONST_LIMM) && is_limm(val)) {
332 if ((ct & TCG_CT_CONST_ZERO) && val == 0) {
335 if ((ct & TCG_CT_CONST_MONE) && val == -1) {
339 switch (ct & (TCG_CT_CONST_ORRI | TCG_CT_CONST_ANDI)) {
342 case TCG_CT_CONST_ANDI:
345 case TCG_CT_CONST_ORRI:
346 if (val == deposit64(val, 32, 32, val)) {
348 return is_shimm1632(val, &cmode, &imm8);
352 /* Both bits should not be set for the same insn. */
353 g_assert_not_reached();
359 enum aarch64_cond_code {
362 COND_CS = 0x2, /* Unsigned greater or equal */
363 COND_HS = COND_CS, /* ALIAS greater or equal */
364 COND_CC = 0x3, /* Unsigned less than */
365 COND_LO = COND_CC, /* ALIAS Lower */
366 COND_MI = 0x4, /* Negative */
367 COND_PL = 0x5, /* Zero or greater */
368 COND_VS = 0x6, /* Overflow */
369 COND_VC = 0x7, /* No overflow */
370 COND_HI = 0x8, /* Unsigned greater than */
371 COND_LS = 0x9, /* Unsigned less or equal */
377 COND_NV = 0xf, /* behaves like COND_AL here */
380 static const enum aarch64_cond_code tcg_cond_to_aarch64[] = {
381 [TCG_COND_EQ] = COND_EQ,
382 [TCG_COND_NE] = COND_NE,
383 [TCG_COND_LT] = COND_LT,
384 [TCG_COND_GE] = COND_GE,
385 [TCG_COND_LE] = COND_LE,
386 [TCG_COND_GT] = COND_GT,
388 [TCG_COND_LTU] = COND_LO,
389 [TCG_COND_GTU] = COND_HI,
390 [TCG_COND_GEU] = COND_HS,
391 [TCG_COND_LEU] = COND_LS,
395 LDST_ST = 0, /* store */
396 LDST_LD = 1, /* load */
397 LDST_LD_S_X = 2, /* load and sign-extend into Xt */
398 LDST_LD_S_W = 3, /* load and sign-extend into Wt */
401 /* We encode the format of the insn into the beginning of the name, so that
402 we can have the preprocessor help "typecheck" the insn vs the output
403 function. Arm didn't provide us with nice names for the formats, so we
404 use the section number of the architecture reference manual in which the
405 instruction group is described. */
407 /* Compare and branch (immediate). */
408 I3201_CBZ = 0x34000000,
409 I3201_CBNZ = 0x35000000,
411 /* Conditional branch (immediate). */
412 I3202_B_C = 0x54000000,
414 /* Unconditional branch (immediate). */
415 I3206_B = 0x14000000,
416 I3206_BL = 0x94000000,
418 /* Unconditional branch (register). */
419 I3207_BR = 0xd61f0000,
420 I3207_BLR = 0xd63f0000,
421 I3207_RET = 0xd65f0000,
423 /* AdvSIMD load/store single structure. */
424 I3303_LD1R = 0x0d40c000,
426 /* Load literal for loading the address at pc-relative offset */
427 I3305_LDR = 0x58000000,
428 I3305_LDR_v64 = 0x5c000000,
429 I3305_LDR_v128 = 0x9c000000,
431 /* Load/store register. Described here as 3.3.12, but the helper
432 that emits them can transform to 3.3.10 or 3.3.13. */
433 I3312_STRB = 0x38000000 | LDST_ST << 22 | MO_8 << 30,
434 I3312_STRH = 0x38000000 | LDST_ST << 22 | MO_16 << 30,
435 I3312_STRW = 0x38000000 | LDST_ST << 22 | MO_32 << 30,
436 I3312_STRX = 0x38000000 | LDST_ST << 22 | MO_64 << 30,
438 I3312_LDRB = 0x38000000 | LDST_LD << 22 | MO_8 << 30,
439 I3312_LDRH = 0x38000000 | LDST_LD << 22 | MO_16 << 30,
440 I3312_LDRW = 0x38000000 | LDST_LD << 22 | MO_32 << 30,
441 I3312_LDRX = 0x38000000 | LDST_LD << 22 | MO_64 << 30,
443 I3312_LDRSBW = 0x38000000 | LDST_LD_S_W << 22 | MO_8 << 30,
444 I3312_LDRSHW = 0x38000000 | LDST_LD_S_W << 22 | MO_16 << 30,
446 I3312_LDRSBX = 0x38000000 | LDST_LD_S_X << 22 | MO_8 << 30,
447 I3312_LDRSHX = 0x38000000 | LDST_LD_S_X << 22 | MO_16 << 30,
448 I3312_LDRSWX = 0x38000000 | LDST_LD_S_X << 22 | MO_32 << 30,
450 I3312_LDRVS = 0x3c000000 | LDST_LD << 22 | MO_32 << 30,
451 I3312_STRVS = 0x3c000000 | LDST_ST << 22 | MO_32 << 30,
453 I3312_LDRVD = 0x3c000000 | LDST_LD << 22 | MO_64 << 30,
454 I3312_STRVD = 0x3c000000 | LDST_ST << 22 | MO_64 << 30,
456 I3312_LDRVQ = 0x3c000000 | 3 << 22 | 0 << 30,
457 I3312_STRVQ = 0x3c000000 | 2 << 22 | 0 << 30,
459 I3312_TO_I3310 = 0x00200800,
460 I3312_TO_I3313 = 0x01000000,
462 /* Load/store register pair instructions. */
463 I3314_LDP = 0x28400000,
464 I3314_STP = 0x28000000,
466 /* Add/subtract immediate instructions. */
467 I3401_ADDI = 0x11000000,
468 I3401_ADDSI = 0x31000000,
469 I3401_SUBI = 0x51000000,
470 I3401_SUBSI = 0x71000000,
472 /* Bitfield instructions. */
473 I3402_BFM = 0x33000000,
474 I3402_SBFM = 0x13000000,
475 I3402_UBFM = 0x53000000,
477 /* Extract instruction. */
478 I3403_EXTR = 0x13800000,
480 /* Logical immediate instructions. */
481 I3404_ANDI = 0x12000000,
482 I3404_ORRI = 0x32000000,
483 I3404_EORI = 0x52000000,
485 /* Move wide immediate instructions. */
486 I3405_MOVN = 0x12800000,
487 I3405_MOVZ = 0x52800000,
488 I3405_MOVK = 0x72800000,
490 /* PC relative addressing instructions. */
491 I3406_ADR = 0x10000000,
492 I3406_ADRP = 0x90000000,
494 /* Add/subtract shifted register instructions (without a shift). */
495 I3502_ADD = 0x0b000000,
496 I3502_ADDS = 0x2b000000,
497 I3502_SUB = 0x4b000000,
498 I3502_SUBS = 0x6b000000,
500 /* Add/subtract shifted register instructions (with a shift). */
501 I3502S_ADD_LSL = I3502_ADD,
503 /* Add/subtract with carry instructions. */
504 I3503_ADC = 0x1a000000,
505 I3503_SBC = 0x5a000000,
507 /* Conditional select instructions. */
508 I3506_CSEL = 0x1a800000,
509 I3506_CSINC = 0x1a800400,
510 I3506_CSINV = 0x5a800000,
511 I3506_CSNEG = 0x5a800400,
513 /* Data-processing (1 source) instructions. */
514 I3507_CLZ = 0x5ac01000,
515 I3507_RBIT = 0x5ac00000,
516 I3507_REV16 = 0x5ac00400,
517 I3507_REV32 = 0x5ac00800,
518 I3507_REV64 = 0x5ac00c00,
520 /* Data-processing (2 source) instructions. */
521 I3508_LSLV = 0x1ac02000,
522 I3508_LSRV = 0x1ac02400,
523 I3508_ASRV = 0x1ac02800,
524 I3508_RORV = 0x1ac02c00,
525 I3508_SMULH = 0x9b407c00,
526 I3508_UMULH = 0x9bc07c00,
527 I3508_UDIV = 0x1ac00800,
528 I3508_SDIV = 0x1ac00c00,
530 /* Data-processing (3 source) instructions. */
531 I3509_MADD = 0x1b000000,
532 I3509_MSUB = 0x1b008000,
534 /* Logical shifted register instructions (without a shift). */
535 I3510_AND = 0x0a000000,
536 I3510_BIC = 0x0a200000,
537 I3510_ORR = 0x2a000000,
538 I3510_ORN = 0x2a200000,
539 I3510_EOR = 0x4a000000,
540 I3510_EON = 0x4a200000,
541 I3510_ANDS = 0x6a000000,
543 /* Logical shifted register instructions (with a shift). */
544 I3502S_AND_LSR = I3510_AND | (1 << 22),
547 I3605_DUP = 0x0e000400,
548 I3605_INS = 0x4e001c00,
549 I3605_UMOV = 0x0e003c00,
551 /* AdvSIMD modified immediate */
552 I3606_MOVI = 0x0f000400,
553 I3606_MVNI = 0x2f000400,
554 I3606_BIC = 0x2f001400,
555 I3606_ORR = 0x0f001400,
557 /* AdvSIMD shift by immediate */
558 I3614_SSHR = 0x0f000400,
559 I3614_SSRA = 0x0f001400,
560 I3614_SHL = 0x0f005400,
561 I3614_SLI = 0x2f005400,
562 I3614_USHR = 0x2f000400,
563 I3614_USRA = 0x2f001400,
565 /* AdvSIMD three same. */
566 I3616_ADD = 0x0e208400,
567 I3616_AND = 0x0e201c00,
568 I3616_BIC = 0x0e601c00,
569 I3616_BIF = 0x2ee01c00,
570 I3616_BIT = 0x2ea01c00,
571 I3616_BSL = 0x2e601c00,
572 I3616_EOR = 0x2e201c00,
573 I3616_MUL = 0x0e209c00,
574 I3616_ORR = 0x0ea01c00,
575 I3616_ORN = 0x0ee01c00,
576 I3616_SUB = 0x2e208400,
577 I3616_CMGT = 0x0e203400,
578 I3616_CMGE = 0x0e203c00,
579 I3616_CMTST = 0x0e208c00,
580 I3616_CMHI = 0x2e203400,
581 I3616_CMHS = 0x2e203c00,
582 I3616_CMEQ = 0x2e208c00,
583 I3616_SMAX = 0x0e206400,
584 I3616_SMIN = 0x0e206c00,
585 I3616_SSHL = 0x0e204400,
586 I3616_SQADD = 0x0e200c00,
587 I3616_SQSUB = 0x0e202c00,
588 I3616_UMAX = 0x2e206400,
589 I3616_UMIN = 0x2e206c00,
590 I3616_UQADD = 0x2e200c00,
591 I3616_UQSUB = 0x2e202c00,
592 I3616_USHL = 0x2e204400,
594 /* AdvSIMD two-reg misc. */
595 I3617_CMGT0 = 0x0e208800,
596 I3617_CMEQ0 = 0x0e209800,
597 I3617_CMLT0 = 0x0e20a800,
598 I3617_CMGE0 = 0x2e208800,
599 I3617_CMLE0 = 0x2e20a800,
600 I3617_NOT = 0x2e205800,
601 I3617_ABS = 0x0e20b800,
602 I3617_NEG = 0x2e20b800,
604 /* System instructions. */
606 DMB_ISH = 0xd50338bf,
611 static inline uint32_t tcg_in32(TCGContext *s)
613 uint32_t v = *(uint32_t *)s->code_ptr;
617 /* Emit an opcode with "type-checking" of the format. */
618 #define tcg_out_insn(S, FMT, OP, ...) \
619 glue(tcg_out_insn_,FMT)(S, glue(glue(glue(I,FMT),_),OP), ## __VA_ARGS__)
621 static void tcg_out_insn_3303(TCGContext *s, AArch64Insn insn, bool q,
622 TCGReg rt, TCGReg rn, unsigned size)
624 tcg_out32(s, insn | (rt & 0x1f) | (rn << 5) | (size << 10) | (q << 30));
627 static void tcg_out_insn_3305(TCGContext *s, AArch64Insn insn,
628 int imm19, TCGReg rt)
630 tcg_out32(s, insn | (imm19 & 0x7ffff) << 5 | rt);
633 static void tcg_out_insn_3201(TCGContext *s, AArch64Insn insn, TCGType ext,
634 TCGReg rt, int imm19)
636 tcg_out32(s, insn | ext << 31 | (imm19 & 0x7ffff) << 5 | rt);
639 static void tcg_out_insn_3202(TCGContext *s, AArch64Insn insn,
640 TCGCond c, int imm19)
642 tcg_out32(s, insn | tcg_cond_to_aarch64[c] | (imm19 & 0x7ffff) << 5);
645 static void tcg_out_insn_3206(TCGContext *s, AArch64Insn insn, int imm26)
647 tcg_out32(s, insn | (imm26 & 0x03ffffff));
650 static void tcg_out_insn_3207(TCGContext *s, AArch64Insn insn, TCGReg rn)
652 tcg_out32(s, insn | rn << 5);
655 static void tcg_out_insn_3314(TCGContext *s, AArch64Insn insn,
656 TCGReg r1, TCGReg r2, TCGReg rn,
657 tcg_target_long ofs, bool pre, bool w)
659 insn |= 1u << 31; /* ext */
663 tcg_debug_assert(ofs >= -0x200 && ofs < 0x200 && (ofs & 7) == 0);
664 insn |= (ofs & (0x7f << 3)) << (15 - 3);
666 tcg_out32(s, insn | r2 << 10 | rn << 5 | r1);
669 static void tcg_out_insn_3401(TCGContext *s, AArch64Insn insn, TCGType ext,
670 TCGReg rd, TCGReg rn, uint64_t aimm)
673 tcg_debug_assert((aimm & 0xfff) == 0);
675 tcg_debug_assert(aimm <= 0xfff);
676 aimm |= 1 << 12; /* apply LSL 12 */
678 tcg_out32(s, insn | ext << 31 | aimm << 10 | rn << 5 | rd);
681 /* This function can be used for both 3.4.2 (Bitfield) and 3.4.4
682 (Logical immediate). Both insn groups have N, IMMR and IMMS fields
683 that feed the DecodeBitMasks pseudo function. */
684 static void tcg_out_insn_3402(TCGContext *s, AArch64Insn insn, TCGType ext,
685 TCGReg rd, TCGReg rn, int n, int immr, int imms)
687 tcg_out32(s, insn | ext << 31 | n << 22 | immr << 16 | imms << 10
691 #define tcg_out_insn_3404 tcg_out_insn_3402
693 static void tcg_out_insn_3403(TCGContext *s, AArch64Insn insn, TCGType ext,
694 TCGReg rd, TCGReg rn, TCGReg rm, int imms)
696 tcg_out32(s, insn | ext << 31 | ext << 22 | rm << 16 | imms << 10
700 /* This function is used for the Move (wide immediate) instruction group.
701 Note that SHIFT is a full shift count, not the 2 bit HW field. */
702 static void tcg_out_insn_3405(TCGContext *s, AArch64Insn insn, TCGType ext,
703 TCGReg rd, uint16_t half, unsigned shift)
705 tcg_debug_assert((shift & ~0x30) == 0);
706 tcg_out32(s, insn | ext << 31 | shift << (21 - 4) | half << 5 | rd);
709 static void tcg_out_insn_3406(TCGContext *s, AArch64Insn insn,
710 TCGReg rd, int64_t disp)
712 tcg_out32(s, insn | (disp & 3) << 29 | (disp & 0x1ffffc) << (5 - 2) | rd);
715 /* This function is for both 3.5.2 (Add/Subtract shifted register), for
716 the rare occasion when we actually want to supply a shift amount. */
717 static inline void tcg_out_insn_3502S(TCGContext *s, AArch64Insn insn,
718 TCGType ext, TCGReg rd, TCGReg rn,
721 tcg_out32(s, insn | ext << 31 | rm << 16 | imm6 << 10 | rn << 5 | rd);
724 /* This function is for 3.5.2 (Add/subtract shifted register),
725 and 3.5.10 (Logical shifted register), for the vast majorty of cases
726 when we don't want to apply a shift. Thus it can also be used for
727 3.5.3 (Add/subtract with carry) and 3.5.8 (Data processing 2 source). */
728 static void tcg_out_insn_3502(TCGContext *s, AArch64Insn insn, TCGType ext,
729 TCGReg rd, TCGReg rn, TCGReg rm)
731 tcg_out32(s, insn | ext << 31 | rm << 16 | rn << 5 | rd);
734 #define tcg_out_insn_3503 tcg_out_insn_3502
735 #define tcg_out_insn_3508 tcg_out_insn_3502
736 #define tcg_out_insn_3510 tcg_out_insn_3502
738 static void tcg_out_insn_3506(TCGContext *s, AArch64Insn insn, TCGType ext,
739 TCGReg rd, TCGReg rn, TCGReg rm, TCGCond c)
741 tcg_out32(s, insn | ext << 31 | rm << 16 | rn << 5 | rd
742 | tcg_cond_to_aarch64[c] << 12);
745 static void tcg_out_insn_3507(TCGContext *s, AArch64Insn insn, TCGType ext,
746 TCGReg rd, TCGReg rn)
748 tcg_out32(s, insn | ext << 31 | rn << 5 | rd);
751 static void tcg_out_insn_3509(TCGContext *s, AArch64Insn insn, TCGType ext,
752 TCGReg rd, TCGReg rn, TCGReg rm, TCGReg ra)
754 tcg_out32(s, insn | ext << 31 | rm << 16 | ra << 10 | rn << 5 | rd);
757 static void tcg_out_insn_3605(TCGContext *s, AArch64Insn insn, bool q,
758 TCGReg rd, TCGReg rn, int dst_idx, int src_idx)
760 /* Note that bit 11 set means general register input. Therefore
761 we can handle both register sets with one function. */
762 tcg_out32(s, insn | q << 30 | (dst_idx << 16) | (src_idx << 11)
763 | (rd & 0x1f) | (~rn & 0x20) << 6 | (rn & 0x1f) << 5);
766 static void tcg_out_insn_3606(TCGContext *s, AArch64Insn insn, bool q,
767 TCGReg rd, bool op, int cmode, uint8_t imm8)
769 tcg_out32(s, insn | q << 30 | op << 29 | cmode << 12 | (rd & 0x1f)
770 | (imm8 & 0xe0) << (16 - 5) | (imm8 & 0x1f) << 5);
773 static void tcg_out_insn_3614(TCGContext *s, AArch64Insn insn, bool q,
774 TCGReg rd, TCGReg rn, unsigned immhb)
776 tcg_out32(s, insn | q << 30 | immhb << 16
777 | (rn & 0x1f) << 5 | (rd & 0x1f));
780 static void tcg_out_insn_3616(TCGContext *s, AArch64Insn insn, bool q,
781 unsigned size, TCGReg rd, TCGReg rn, TCGReg rm)
783 tcg_out32(s, insn | q << 30 | (size << 22) | (rm & 0x1f) << 16
784 | (rn & 0x1f) << 5 | (rd & 0x1f));
787 static void tcg_out_insn_3617(TCGContext *s, AArch64Insn insn, bool q,
788 unsigned size, TCGReg rd, TCGReg rn)
790 tcg_out32(s, insn | q << 30 | (size << 22)
791 | (rn & 0x1f) << 5 | (rd & 0x1f));
794 static void tcg_out_insn_3310(TCGContext *s, AArch64Insn insn,
795 TCGReg rd, TCGReg base, TCGType ext,
798 /* Note the AArch64Insn constants above are for C3.3.12. Adjust. */
799 tcg_out32(s, insn | I3312_TO_I3310 | regoff << 16 |
800 0x4000 | ext << 13 | base << 5 | (rd & 0x1f));
803 static void tcg_out_insn_3312(TCGContext *s, AArch64Insn insn,
804 TCGReg rd, TCGReg rn, intptr_t offset)
806 tcg_out32(s, insn | (offset & 0x1ff) << 12 | rn << 5 | (rd & 0x1f));
809 static void tcg_out_insn_3313(TCGContext *s, AArch64Insn insn,
810 TCGReg rd, TCGReg rn, uintptr_t scaled_uimm)
812 /* Note the AArch64Insn constants above are for C3.3.12. Adjust. */
813 tcg_out32(s, insn | I3312_TO_I3313 | scaled_uimm << 10
814 | rn << 5 | (rd & 0x1f));
817 /* Register to register move using ORR (shifted register with no shift). */
818 static void tcg_out_movr(TCGContext *s, TCGType ext, TCGReg rd, TCGReg rm)
820 tcg_out_insn(s, 3510, ORR, ext, rd, TCG_REG_XZR, rm);
823 /* Register to register move using ADDI (move to/from SP). */
824 static void tcg_out_movr_sp(TCGContext *s, TCGType ext, TCGReg rd, TCGReg rn)
826 tcg_out_insn(s, 3401, ADDI, ext, rd, rn, 0);
829 /* This function is used for the Logical (immediate) instruction group.
830 The value of LIMM must satisfy IS_LIMM. See the comment above about
831 only supporting simplified logical immediates. */
832 static void tcg_out_logicali(TCGContext *s, AArch64Insn insn, TCGType ext,
833 TCGReg rd, TCGReg rn, uint64_t limm)
837 tcg_debug_assert(is_limm(limm));
842 r = 0; /* form 0....01....1 */
843 c = ctz64(~limm) - 1;
845 r = clz64(~limm); /* form 1..10..01..1 */
849 r = 64 - l; /* form 1....10....0 or 0..01..10..0 */
852 if (ext == TCG_TYPE_I32) {
857 tcg_out_insn_3404(s, insn, ext, rd, rn, ext, r, c);
860 static void tcg_out_dupi_vec(TCGContext *s, TCGType type, unsigned vece,
861 TCGReg rd, int64_t v64)
863 bool q = type == TCG_TYPE_V128;
866 /* Test all bytes equal first. */
869 tcg_out_insn(s, 3606, MOVI, q, rd, 0, 0xe, imm8);
874 * Test all bytes 0x00 or 0xff second. This can match cases that
875 * might otherwise take 2 or 3 insns for MO_16 or MO_32 below.
877 for (i = imm8 = 0; i < 8; i++) {
878 uint8_t byte = v64 >> (i * 8);
881 } else if (byte != 0) {
885 tcg_out_insn(s, 3606, MOVI, q, rd, 1, 0xe, imm8);
890 * Tests for various replications. For each element width, if we
891 * cannot find an expansion there's no point checking a larger
892 * width because we already know by replication it cannot match.
897 if (is_shimm16(v16, &cmode, &imm8)) {
898 tcg_out_insn(s, 3606, MOVI, q, rd, 0, cmode, imm8);
901 if (is_shimm16(~v16, &cmode, &imm8)) {
902 tcg_out_insn(s, 3606, MVNI, q, rd, 0, cmode, imm8);
907 * Otherwise, all remaining constants can be loaded in two insns:
908 * rd = v16 & 0xff, rd |= v16 & 0xff00.
910 tcg_out_insn(s, 3606, MOVI, q, rd, 0, 0x8, v16 & 0xff);
911 tcg_out_insn(s, 3606, ORR, q, rd, 0, 0xa, v16 >> 8);
913 } else if (vece == MO_32) {
917 if (is_shimm32(v32, &cmode, &imm8) ||
918 is_soimm32(v32, &cmode, &imm8) ||
919 is_fimm32(v32, &cmode, &imm8)) {
920 tcg_out_insn(s, 3606, MOVI, q, rd, 0, cmode, imm8);
923 if (is_shimm32(n32, &cmode, &imm8) ||
924 is_soimm32(n32, &cmode, &imm8)) {
925 tcg_out_insn(s, 3606, MVNI, q, rd, 0, cmode, imm8);
930 * Restrict the set of constants to those we can load with
931 * two instructions. Others we load from the pool.
933 i = is_shimm32_pair(v32, &cmode, &imm8);
935 tcg_out_insn(s, 3606, MOVI, q, rd, 0, cmode, imm8);
936 tcg_out_insn(s, 3606, ORR, q, rd, 0, i, extract32(v32, i * 4, 8));
939 i = is_shimm32_pair(n32, &cmode, &imm8);
941 tcg_out_insn(s, 3606, MVNI, q, rd, 0, cmode, imm8);
942 tcg_out_insn(s, 3606, BIC, q, rd, 0, i, extract32(n32, i * 4, 8));
945 } else if (is_fimm64(v64, &cmode, &imm8)) {
946 tcg_out_insn(s, 3606, MOVI, q, rd, 1, cmode, imm8);
951 * As a last resort, load from the constant pool. Sadly there
952 * is no LD1R (literal), so store the full 16-byte vector.
954 if (type == TCG_TYPE_V128) {
955 new_pool_l2(s, R_AARCH64_CONDBR19, s->code_ptr, 0, v64, v64);
956 tcg_out_insn(s, 3305, LDR_v128, 0, rd);
958 new_pool_label(s, v64, R_AARCH64_CONDBR19, s->code_ptr, 0);
959 tcg_out_insn(s, 3305, LDR_v64, 0, rd);
963 static bool tcg_out_dup_vec(TCGContext *s, TCGType type, unsigned vece,
964 TCGReg rd, TCGReg rs)
966 int is_q = type - TCG_TYPE_V64;
967 tcg_out_insn(s, 3605, DUP, is_q, rd, rs, 1 << vece, 0);
971 static bool tcg_out_dupm_vec(TCGContext *s, TCGType type, unsigned vece,
972 TCGReg r, TCGReg base, intptr_t offset)
974 TCGReg temp = TCG_REG_TMP;
976 if (offset < -0xffffff || offset > 0xffffff) {
977 tcg_out_movi(s, TCG_TYPE_PTR, temp, offset);
978 tcg_out_insn(s, 3502, ADD, 1, temp, temp, base);
981 AArch64Insn add_insn = I3401_ADDI;
984 add_insn = I3401_SUBI;
987 if (offset & 0xfff000) {
988 tcg_out_insn_3401(s, add_insn, 1, temp, base, offset & 0xfff000);
991 if (offset & 0xfff) {
992 tcg_out_insn_3401(s, add_insn, 1, temp, base, offset & 0xfff);
996 tcg_out_insn(s, 3303, LD1R, type == TCG_TYPE_V128, r, base, vece);
1000 static void tcg_out_movi(TCGContext *s, TCGType type, TCGReg rd,
1001 tcg_target_long value)
1003 tcg_target_long svalue = value;
1004 tcg_target_long ivalue = ~value;
1005 tcg_target_long t0, t1, t2;
1012 tcg_debug_assert(rd < 32);
1015 g_assert_not_reached();
1018 /* For 32-bit values, discard potential garbage in value. For 64-bit
1019 values within [2**31, 2**32-1], we can create smaller sequences by
1020 interpreting this as a negative 32-bit number, while ensuring that
1021 the high 32 bits are cleared by setting SF=0. */
1022 if (type == TCG_TYPE_I32 || (value & ~0xffffffffull) == 0) {
1023 svalue = (int32_t)value;
1024 value = (uint32_t)value;
1025 ivalue = (uint32_t)ivalue;
1026 type = TCG_TYPE_I32;
1029 /* Speed things up by handling the common case of small positive
1030 and negative values specially. */
1031 if ((value & ~0xffffull) == 0) {
1032 tcg_out_insn(s, 3405, MOVZ, type, rd, value, 0);
1034 } else if ((ivalue & ~0xffffull) == 0) {
1035 tcg_out_insn(s, 3405, MOVN, type, rd, ivalue, 0);
1039 /* Check for bitfield immediates. For the benefit of 32-bit quantities,
1040 use the sign-extended value. That lets us match rotated values such
1041 as 0xff0000ff with the same 64-bit logic matching 0xffffffffff0000ff. */
1042 if (is_limm(svalue)) {
1043 tcg_out_logicali(s, I3404_ORRI, type, rd, TCG_REG_XZR, svalue);
1047 /* Look for host pointer values within 4G of the PC. This happens
1048 often when loading pointers to QEMU's own data structures. */
1049 if (type == TCG_TYPE_I64) {
1050 intptr_t src_rx = (intptr_t)tcg_splitwx_to_rx(s->code_ptr);
1051 tcg_target_long disp = value - src_rx;
1052 if (disp == sextract64(disp, 0, 21)) {
1053 tcg_out_insn(s, 3406, ADR, rd, disp);
1056 disp = (value >> 12) - (src_rx >> 12);
1057 if (disp == sextract64(disp, 0, 21)) {
1058 tcg_out_insn(s, 3406, ADRP, rd, disp);
1059 if (value & 0xfff) {
1060 tcg_out_insn(s, 3401, ADDI, type, rd, rd, value & 0xfff);
1066 /* Would it take fewer insns to begin with MOVN? */
1067 if (ctpop64(value) >= 32) {
1074 s0 = ctz64(t0) & (63 & -16);
1075 t1 = t0 & ~(0xffffUL << s0);
1076 s1 = ctz64(t1) & (63 & -16);
1077 t2 = t1 & ~(0xffffUL << s1);
1079 tcg_out_insn_3405(s, opc, type, rd, t0 >> s0, s0);
1081 tcg_out_insn(s, 3405, MOVK, type, rd, value >> s1, s1);
1086 /* For more than 2 insns, dump it into the constant pool. */
1087 new_pool_label(s, value, R_AARCH64_CONDBR19, s->code_ptr, 0);
1088 tcg_out_insn(s, 3305, LDR, 0, rd);
1091 /* Define something more legible for general use. */
1092 #define tcg_out_ldst_r tcg_out_insn_3310
1094 static void tcg_out_ldst(TCGContext *s, AArch64Insn insn, TCGReg rd,
1095 TCGReg rn, intptr_t offset, int lgsize)
1097 /* If the offset is naturally aligned and in range, then we can
1098 use the scaled uimm12 encoding */
1099 if (offset >= 0 && !(offset & ((1 << lgsize) - 1))) {
1100 uintptr_t scaled_uimm = offset >> lgsize;
1101 if (scaled_uimm <= 0xfff) {
1102 tcg_out_insn_3313(s, insn, rd, rn, scaled_uimm);
1107 /* Small signed offsets can use the unscaled encoding. */
1108 if (offset >= -256 && offset < 256) {
1109 tcg_out_insn_3312(s, insn, rd, rn, offset);
1113 /* Worst-case scenario, move offset to temp register, use reg offset. */
1114 tcg_out_movi(s, TCG_TYPE_I64, TCG_REG_TMP, offset);
1115 tcg_out_ldst_r(s, insn, rd, rn, TCG_TYPE_I64, TCG_REG_TMP);
1118 static bool tcg_out_mov(TCGContext *s, TCGType type, TCGReg ret, TCGReg arg)
1126 if (ret < 32 && arg < 32) {
1127 tcg_out_movr(s, type, ret, arg);
1129 } else if (ret < 32) {
1130 tcg_out_insn(s, 3605, UMOV, type, ret, arg, 0, 0);
1132 } else if (arg < 32) {
1133 tcg_out_insn(s, 3605, INS, 0, ret, arg, 4 << type, 0);
1139 tcg_debug_assert(ret >= 32 && arg >= 32);
1140 tcg_out_insn(s, 3616, ORR, 0, 0, ret, arg, arg);
1143 tcg_debug_assert(ret >= 32 && arg >= 32);
1144 tcg_out_insn(s, 3616, ORR, 1, 0, ret, arg, arg);
1148 g_assert_not_reached();
1153 static void tcg_out_ld(TCGContext *s, TCGType type, TCGReg ret,
1154 TCGReg base, intptr_t ofs)
1161 insn = (ret < 32 ? I3312_LDRW : I3312_LDRVS);
1165 insn = (ret < 32 ? I3312_LDRX : I3312_LDRVD);
1177 g_assert_not_reached();
1179 tcg_out_ldst(s, insn, ret, base, ofs, lgsz);
1182 static void tcg_out_st(TCGContext *s, TCGType type, TCGReg src,
1183 TCGReg base, intptr_t ofs)
1190 insn = (src < 32 ? I3312_STRW : I3312_STRVS);
1194 insn = (src < 32 ? I3312_STRX : I3312_STRVD);
1206 g_assert_not_reached();
1208 tcg_out_ldst(s, insn, src, base, ofs, lgsz);
1211 static inline bool tcg_out_sti(TCGContext *s, TCGType type, TCGArg val,
1212 TCGReg base, intptr_t ofs)
1214 if (type <= TCG_TYPE_I64 && val == 0) {
1215 tcg_out_st(s, type, TCG_REG_XZR, base, ofs);
1221 static inline void tcg_out_bfm(TCGContext *s, TCGType ext, TCGReg rd,
1222 TCGReg rn, unsigned int a, unsigned int b)
1224 tcg_out_insn(s, 3402, BFM, ext, rd, rn, ext, a, b);
1227 static inline void tcg_out_ubfm(TCGContext *s, TCGType ext, TCGReg rd,
1228 TCGReg rn, unsigned int a, unsigned int b)
1230 tcg_out_insn(s, 3402, UBFM, ext, rd, rn, ext, a, b);
1233 static inline void tcg_out_sbfm(TCGContext *s, TCGType ext, TCGReg rd,
1234 TCGReg rn, unsigned int a, unsigned int b)
1236 tcg_out_insn(s, 3402, SBFM, ext, rd, rn, ext, a, b);
1239 static inline void tcg_out_extr(TCGContext *s, TCGType ext, TCGReg rd,
1240 TCGReg rn, TCGReg rm, unsigned int a)
1242 tcg_out_insn(s, 3403, EXTR, ext, rd, rn, rm, a);
1245 static inline void tcg_out_shl(TCGContext *s, TCGType ext,
1246 TCGReg rd, TCGReg rn, unsigned int m)
1248 int bits = ext ? 64 : 32;
1250 tcg_out_ubfm(s, ext, rd, rn, bits - (m & max), max - (m & max));
1253 static inline void tcg_out_shr(TCGContext *s, TCGType ext,
1254 TCGReg rd, TCGReg rn, unsigned int m)
1256 int max = ext ? 63 : 31;
1257 tcg_out_ubfm(s, ext, rd, rn, m & max, max);
1260 static inline void tcg_out_sar(TCGContext *s, TCGType ext,
1261 TCGReg rd, TCGReg rn, unsigned int m)
1263 int max = ext ? 63 : 31;
1264 tcg_out_sbfm(s, ext, rd, rn, m & max, max);
1267 static inline void tcg_out_rotr(TCGContext *s, TCGType ext,
1268 TCGReg rd, TCGReg rn, unsigned int m)
1270 int max = ext ? 63 : 31;
1271 tcg_out_extr(s, ext, rd, rn, rn, m & max);
1274 static inline void tcg_out_rotl(TCGContext *s, TCGType ext,
1275 TCGReg rd, TCGReg rn, unsigned int m)
1277 int bits = ext ? 64 : 32;
1279 tcg_out_extr(s, ext, rd, rn, rn, bits - (m & max));
1282 static inline void tcg_out_dep(TCGContext *s, TCGType ext, TCGReg rd,
1283 TCGReg rn, unsigned lsb, unsigned width)
1285 unsigned size = ext ? 64 : 32;
1286 unsigned a = (size - lsb) & (size - 1);
1287 unsigned b = width - 1;
1288 tcg_out_bfm(s, ext, rd, rn, a, b);
1291 static void tcg_out_cmp(TCGContext *s, TCGType ext, TCGReg a,
1292 tcg_target_long b, bool const_b)
1295 /* Using CMP or CMN aliases. */
1297 tcg_out_insn(s, 3401, SUBSI, ext, TCG_REG_XZR, a, b);
1299 tcg_out_insn(s, 3401, ADDSI, ext, TCG_REG_XZR, a, -b);
1302 /* Using CMP alias SUBS wzr, Wn, Wm */
1303 tcg_out_insn(s, 3502, SUBS, ext, TCG_REG_XZR, a, b);
1307 static void tcg_out_goto(TCGContext *s, const tcg_insn_unit *target)
1309 ptrdiff_t offset = tcg_pcrel_diff(s, target) >> 2;
1310 tcg_debug_assert(offset == sextract64(offset, 0, 26));
1311 tcg_out_insn(s, 3206, B, offset);
1314 static void tcg_out_goto_long(TCGContext *s, const tcg_insn_unit *target)
1316 ptrdiff_t offset = tcg_pcrel_diff(s, target) >> 2;
1317 if (offset == sextract64(offset, 0, 26)) {
1318 tcg_out_insn(s, 3206, B, offset);
1320 tcg_out_movi(s, TCG_TYPE_I64, TCG_REG_TMP, (intptr_t)target);
1321 tcg_out_insn(s, 3207, BR, TCG_REG_TMP);
1325 static inline void tcg_out_callr(TCGContext *s, TCGReg reg)
1327 tcg_out_insn(s, 3207, BLR, reg);
1330 static void tcg_out_call(TCGContext *s, const tcg_insn_unit *target)
1332 ptrdiff_t offset = tcg_pcrel_diff(s, target) >> 2;
1333 if (offset == sextract64(offset, 0, 26)) {
1334 tcg_out_insn(s, 3206, BL, offset);
1336 tcg_out_movi(s, TCG_TYPE_I64, TCG_REG_TMP, (intptr_t)target);
1337 tcg_out_callr(s, TCG_REG_TMP);
1341 void tb_target_set_jmp_target(uintptr_t tc_ptr, uintptr_t jmp_rx,
1342 uintptr_t jmp_rw, uintptr_t addr)
1344 tcg_insn_unit i1, i2;
1345 TCGType rt = TCG_TYPE_I64;
1346 TCGReg rd = TCG_REG_TMP;
1349 ptrdiff_t offset = addr - jmp_rx;
1351 if (offset == sextract64(offset, 0, 26)) {
1352 i1 = I3206_B | ((offset >> 2) & 0x3ffffff);
1355 offset = (addr >> 12) - (jmp_rx >> 12);
1358 i1 = I3406_ADRP | (offset & 3) << 29 | (offset & 0x1ffffc) << (5 - 2) | rd;
1360 i2 = I3401_ADDI | rt << 31 | (addr & 0xfff) << 10 | rd << 5 | rd;
1362 pair = (uint64_t)i2 << 32 | i1;
1363 qatomic_set((uint64_t *)jmp_rw, pair);
1364 flush_idcache_range(jmp_rx, jmp_rw, 8);
1367 static inline void tcg_out_goto_label(TCGContext *s, TCGLabel *l)
1369 if (!l->has_value) {
1370 tcg_out_reloc(s, s->code_ptr, R_AARCH64_JUMP26, l, 0);
1371 tcg_out_insn(s, 3206, B, 0);
1373 tcg_out_goto(s, l->u.value_ptr);
1377 static void tcg_out_brcond(TCGContext *s, TCGType ext, TCGCond c, TCGArg a,
1378 TCGArg b, bool b_const, TCGLabel *l)
1383 if (b_const && b == 0 && (c == TCG_COND_EQ || c == TCG_COND_NE)) {
1387 tcg_out_cmp(s, ext, a, b, b_const);
1390 if (!l->has_value) {
1391 tcg_out_reloc(s, s->code_ptr, R_AARCH64_CONDBR19, l, 0);
1392 offset = tcg_in32(s) >> 5;
1394 offset = tcg_pcrel_diff(s, l->u.value_ptr) >> 2;
1395 tcg_debug_assert(offset == sextract64(offset, 0, 19));
1399 tcg_out_insn(s, 3202, B_C, c, offset);
1400 } else if (c == TCG_COND_EQ) {
1401 tcg_out_insn(s, 3201, CBZ, ext, a, offset);
1403 tcg_out_insn(s, 3201, CBNZ, ext, a, offset);
1407 static inline void tcg_out_rev64(TCGContext *s, TCGReg rd, TCGReg rn)
1409 tcg_out_insn(s, 3507, REV64, TCG_TYPE_I64, rd, rn);
1412 static inline void tcg_out_rev32(TCGContext *s, TCGReg rd, TCGReg rn)
1414 tcg_out_insn(s, 3507, REV32, TCG_TYPE_I32, rd, rn);
1417 static inline void tcg_out_rev16(TCGContext *s, TCGReg rd, TCGReg rn)
1419 tcg_out_insn(s, 3507, REV16, TCG_TYPE_I32, rd, rn);
1422 static inline void tcg_out_sxt(TCGContext *s, TCGType ext, MemOp s_bits,
1423 TCGReg rd, TCGReg rn)
1425 /* Using ALIASes SXTB, SXTH, SXTW, of SBFM Xd, Xn, #0, #7|15|31 */
1426 int bits = (8 << s_bits) - 1;
1427 tcg_out_sbfm(s, ext, rd, rn, 0, bits);
1430 static inline void tcg_out_uxt(TCGContext *s, MemOp s_bits,
1431 TCGReg rd, TCGReg rn)
1433 /* Using ALIASes UXTB, UXTH of UBFM Wd, Wn, #0, #7|15 */
1434 int bits = (8 << s_bits) - 1;
1435 tcg_out_ubfm(s, 0, rd, rn, 0, bits);
1438 static void tcg_out_addsubi(TCGContext *s, int ext, TCGReg rd,
1439 TCGReg rn, int64_t aimm)
1442 tcg_out_insn(s, 3401, ADDI, ext, rd, rn, aimm);
1444 tcg_out_insn(s, 3401, SUBI, ext, rd, rn, -aimm);
1448 static inline void tcg_out_addsub2(TCGContext *s, TCGType ext, TCGReg rl,
1449 TCGReg rh, TCGReg al, TCGReg ah,
1450 tcg_target_long bl, tcg_target_long bh,
1451 bool const_bl, bool const_bh, bool sub)
1453 TCGReg orig_rl = rl;
1456 if (rl == ah || (!const_bh && rl == bh)) {
1462 if ((bl < 0) ^ sub) {
1466 if (unlikely(al == TCG_REG_XZR)) {
1467 /* ??? We want to allow al to be zero for the benefit of
1468 negation via subtraction. However, that leaves open the
1469 possibility of adding 0+const in the low part, and the
1470 immediate add instructions encode XSP not XZR. Don't try
1471 anything more elaborate here than loading another zero. */
1473 tcg_out_movi(s, ext, al, 0);
1475 tcg_out_insn_3401(s, insn, ext, rl, al, bl);
1477 tcg_out_insn_3502(s, sub ? I3502_SUBS : I3502_ADDS, ext, rl, al, bl);
1482 /* Note that the only two constants we support are 0 and -1, and
1483 that SBC = rn + ~rm + c, so adc -1 is sbc 0, and vice-versa. */
1484 if ((bh != 0) ^ sub) {
1491 tcg_out_insn_3503(s, insn, ext, rh, ah, bh);
1493 tcg_out_mov(s, ext, orig_rl, rl);
1496 static inline void tcg_out_mb(TCGContext *s, TCGArg a0)
1498 static const uint32_t sync[] = {
1499 [0 ... TCG_MO_ALL] = DMB_ISH | DMB_LD | DMB_ST,
1500 [TCG_MO_ST_ST] = DMB_ISH | DMB_ST,
1501 [TCG_MO_LD_LD] = DMB_ISH | DMB_LD,
1502 [TCG_MO_LD_ST] = DMB_ISH | DMB_LD,
1503 [TCG_MO_LD_ST | TCG_MO_LD_LD] = DMB_ISH | DMB_LD,
1505 tcg_out32(s, sync[a0 & TCG_MO_ALL]);
1508 static void tcg_out_cltz(TCGContext *s, TCGType ext, TCGReg d,
1509 TCGReg a0, TCGArg b, bool const_b, bool is_ctz)
1514 tcg_out_insn(s, 3507, RBIT, ext, a1, a0);
1516 if (const_b && b == (ext ? 64 : 32)) {
1517 tcg_out_insn(s, 3507, CLZ, ext, d, a1);
1519 AArch64Insn sel = I3506_CSEL;
1521 tcg_out_cmp(s, ext, a0, 0, 1);
1522 tcg_out_insn(s, 3507, CLZ, ext, TCG_REG_TMP, a1);
1528 } else if (b == 0) {
1531 tcg_out_movi(s, ext, d, b);
1535 tcg_out_insn_3506(s, sel, ext, d, TCG_REG_TMP, b, TCG_COND_NE);
1539 #ifdef CONFIG_SOFTMMU
1540 #include "../tcg-ldst.c.inc"
1542 /* helper signature: helper_ret_ld_mmu(CPUState *env, target_ulong addr,
1543 * TCGMemOpIdx oi, uintptr_t ra)
1545 static void * const qemu_ld_helpers[16] = {
1546 [MO_UB] = helper_ret_ldub_mmu,
1547 [MO_LEUW] = helper_le_lduw_mmu,
1548 [MO_LEUL] = helper_le_ldul_mmu,
1549 [MO_LEQ] = helper_le_ldq_mmu,
1550 [MO_BEUW] = helper_be_lduw_mmu,
1551 [MO_BEUL] = helper_be_ldul_mmu,
1552 [MO_BEQ] = helper_be_ldq_mmu,
1555 /* helper signature: helper_ret_st_mmu(CPUState *env, target_ulong addr,
1556 * uintxx_t val, TCGMemOpIdx oi,
1559 static void * const qemu_st_helpers[16] = {
1560 [MO_UB] = helper_ret_stb_mmu,
1561 [MO_LEUW] = helper_le_stw_mmu,
1562 [MO_LEUL] = helper_le_stl_mmu,
1563 [MO_LEQ] = helper_le_stq_mmu,
1564 [MO_BEUW] = helper_be_stw_mmu,
1565 [MO_BEUL] = helper_be_stl_mmu,
1566 [MO_BEQ] = helper_be_stq_mmu,
1569 static inline void tcg_out_adr(TCGContext *s, TCGReg rd, const void *target)
1571 ptrdiff_t offset = tcg_pcrel_diff(s, target);
1572 tcg_debug_assert(offset == sextract64(offset, 0, 21));
1573 tcg_out_insn(s, 3406, ADR, rd, offset);
1576 static bool tcg_out_qemu_ld_slow_path(TCGContext *s, TCGLabelQemuLdst *lb)
1578 TCGMemOpIdx oi = lb->oi;
1579 MemOp opc = get_memop(oi);
1580 MemOp size = opc & MO_SIZE;
1582 if (!reloc_pc19(lb->label_ptr[0], tcg_splitwx_to_rx(s->code_ptr))) {
1586 tcg_out_mov(s, TCG_TYPE_PTR, TCG_REG_X0, TCG_AREG0);
1587 tcg_out_mov(s, TARGET_LONG_BITS == 64, TCG_REG_X1, lb->addrlo_reg);
1588 tcg_out_movi(s, TCG_TYPE_I32, TCG_REG_X2, oi);
1589 tcg_out_adr(s, TCG_REG_X3, lb->raddr);
1590 tcg_out_call(s, qemu_ld_helpers[opc & (MO_BSWAP | MO_SIZE)]);
1591 if (opc & MO_SIGN) {
1592 tcg_out_sxt(s, lb->type, size, lb->datalo_reg, TCG_REG_X0);
1594 tcg_out_mov(s, size == MO_64, lb->datalo_reg, TCG_REG_X0);
1597 tcg_out_goto(s, lb->raddr);
1601 static bool tcg_out_qemu_st_slow_path(TCGContext *s, TCGLabelQemuLdst *lb)
1603 TCGMemOpIdx oi = lb->oi;
1604 MemOp opc = get_memop(oi);
1605 MemOp size = opc & MO_SIZE;
1607 if (!reloc_pc19(lb->label_ptr[0], tcg_splitwx_to_rx(s->code_ptr))) {
1611 tcg_out_mov(s, TCG_TYPE_PTR, TCG_REG_X0, TCG_AREG0);
1612 tcg_out_mov(s, TARGET_LONG_BITS == 64, TCG_REG_X1, lb->addrlo_reg);
1613 tcg_out_mov(s, size == MO_64, TCG_REG_X2, lb->datalo_reg);
1614 tcg_out_movi(s, TCG_TYPE_I32, TCG_REG_X3, oi);
1615 tcg_out_adr(s, TCG_REG_X4, lb->raddr);
1616 tcg_out_call(s, qemu_st_helpers[opc & (MO_BSWAP | MO_SIZE)]);
1617 tcg_out_goto(s, lb->raddr);
1621 static void add_qemu_ldst_label(TCGContext *s, bool is_ld, TCGMemOpIdx oi,
1622 TCGType ext, TCGReg data_reg, TCGReg addr_reg,
1623 tcg_insn_unit *raddr, tcg_insn_unit *label_ptr)
1625 TCGLabelQemuLdst *label = new_ldst_label(s);
1627 label->is_ld = is_ld;
1630 label->datalo_reg = data_reg;
1631 label->addrlo_reg = addr_reg;
1632 label->raddr = tcg_splitwx_to_rx(raddr);
1633 label->label_ptr[0] = label_ptr;
1636 /* We expect to use a 7-bit scaled negative offset from ENV. */
1637 QEMU_BUILD_BUG_ON(TLB_MASK_TABLE_OFS(0) > 0);
1638 QEMU_BUILD_BUG_ON(TLB_MASK_TABLE_OFS(0) < -512);
1640 /* These offsets are built into the LDP below. */
1641 QEMU_BUILD_BUG_ON(offsetof(CPUTLBDescFast, mask) != 0);
1642 QEMU_BUILD_BUG_ON(offsetof(CPUTLBDescFast, table) != 8);
1644 /* Load and compare a TLB entry, emitting the conditional jump to the
1645 slow path for the failure case, which will be patched later when finalizing
1646 the slow path. Generated code returns the host addend in X1,
1647 clobbers X0,X2,X3,TMP. */
1648 static void tcg_out_tlb_read(TCGContext *s, TCGReg addr_reg, MemOp opc,
1649 tcg_insn_unit **label_ptr, int mem_index,
1652 unsigned a_bits = get_alignment_bits(opc);
1653 unsigned s_bits = opc & MO_SIZE;
1654 unsigned a_mask = (1u << a_bits) - 1;
1655 unsigned s_mask = (1u << s_bits) - 1;
1658 uint64_t compare_mask;
1660 mask_type = (TARGET_PAGE_BITS + CPU_TLB_DYN_MAX_BITS > 32
1661 ? TCG_TYPE_I64 : TCG_TYPE_I32);
1663 /* Load env_tlb(env)->f[mmu_idx].{mask,table} into {x0,x1}. */
1664 tcg_out_insn(s, 3314, LDP, TCG_REG_X0, TCG_REG_X1, TCG_AREG0,
1665 TLB_MASK_TABLE_OFS(mem_index), 1, 0);
1667 /* Extract the TLB index from the address into X0. */
1668 tcg_out_insn(s, 3502S, AND_LSR, mask_type == TCG_TYPE_I64,
1669 TCG_REG_X0, TCG_REG_X0, addr_reg,
1670 TARGET_PAGE_BITS - CPU_TLB_ENTRY_BITS);
1672 /* Add the tlb_table pointer, creating the CPUTLBEntry address into X1. */
1673 tcg_out_insn(s, 3502, ADD, 1, TCG_REG_X1, TCG_REG_X1, TCG_REG_X0);
1675 /* Load the tlb comparator into X0, and the fast path addend into X1. */
1676 tcg_out_ld(s, TCG_TYPE_TL, TCG_REG_X0, TCG_REG_X1, is_read
1677 ? offsetof(CPUTLBEntry, addr_read)
1678 : offsetof(CPUTLBEntry, addr_write));
1679 tcg_out_ld(s, TCG_TYPE_PTR, TCG_REG_X1, TCG_REG_X1,
1680 offsetof(CPUTLBEntry, addend));
1682 /* For aligned accesses, we check the first byte and include the alignment
1683 bits within the address. For unaligned access, we check that we don't
1684 cross pages using the address of the last byte of the access. */
1685 if (a_bits >= s_bits) {
1688 tcg_out_insn(s, 3401, ADDI, TARGET_LONG_BITS == 64,
1689 TCG_REG_X3, addr_reg, s_mask - a_mask);
1692 compare_mask = (uint64_t)TARGET_PAGE_MASK | a_mask;
1694 /* Store the page mask part of the address into X3. */
1695 tcg_out_logicali(s, I3404_ANDI, TARGET_LONG_BITS == 64,
1696 TCG_REG_X3, x3, compare_mask);
1698 /* Perform the address comparison. */
1699 tcg_out_cmp(s, TARGET_LONG_BITS == 64, TCG_REG_X0, TCG_REG_X3, 0);
1701 /* If not equal, we jump to the slow path. */
1702 *label_ptr = s->code_ptr;
1703 tcg_out_insn(s, 3202, B_C, TCG_COND_NE, 0);
1706 #endif /* CONFIG_SOFTMMU */
1708 static void tcg_out_qemu_ld_direct(TCGContext *s, MemOp memop, TCGType ext,
1709 TCGReg data_r, TCGReg addr_r,
1710 TCGType otype, TCGReg off_r)
1712 const MemOp bswap = memop & MO_BSWAP;
1714 switch (memop & MO_SSIZE) {
1716 tcg_out_ldst_r(s, I3312_LDRB, data_r, addr_r, otype, off_r);
1719 tcg_out_ldst_r(s, ext ? I3312_LDRSBX : I3312_LDRSBW,
1720 data_r, addr_r, otype, off_r);
1723 tcg_out_ldst_r(s, I3312_LDRH, data_r, addr_r, otype, off_r);
1725 tcg_out_rev16(s, data_r, data_r);
1730 tcg_out_ldst_r(s, I3312_LDRH, data_r, addr_r, otype, off_r);
1731 tcg_out_rev16(s, data_r, data_r);
1732 tcg_out_sxt(s, ext, MO_16, data_r, data_r);
1734 tcg_out_ldst_r(s, (ext ? I3312_LDRSHX : I3312_LDRSHW),
1735 data_r, addr_r, otype, off_r);
1739 tcg_out_ldst_r(s, I3312_LDRW, data_r, addr_r, otype, off_r);
1741 tcg_out_rev32(s, data_r, data_r);
1746 tcg_out_ldst_r(s, I3312_LDRW, data_r, addr_r, otype, off_r);
1747 tcg_out_rev32(s, data_r, data_r);
1748 tcg_out_sxt(s, TCG_TYPE_I64, MO_32, data_r, data_r);
1750 tcg_out_ldst_r(s, I3312_LDRSWX, data_r, addr_r, otype, off_r);
1754 tcg_out_ldst_r(s, I3312_LDRX, data_r, addr_r, otype, off_r);
1756 tcg_out_rev64(s, data_r, data_r);
1764 static void tcg_out_qemu_st_direct(TCGContext *s, MemOp memop,
1765 TCGReg data_r, TCGReg addr_r,
1766 TCGType otype, TCGReg off_r)
1768 const MemOp bswap = memop & MO_BSWAP;
1770 switch (memop & MO_SIZE) {
1772 tcg_out_ldst_r(s, I3312_STRB, data_r, addr_r, otype, off_r);
1775 if (bswap && data_r != TCG_REG_XZR) {
1776 tcg_out_rev16(s, TCG_REG_TMP, data_r);
1777 data_r = TCG_REG_TMP;
1779 tcg_out_ldst_r(s, I3312_STRH, data_r, addr_r, otype, off_r);
1782 if (bswap && data_r != TCG_REG_XZR) {
1783 tcg_out_rev32(s, TCG_REG_TMP, data_r);
1784 data_r = TCG_REG_TMP;
1786 tcg_out_ldst_r(s, I3312_STRW, data_r, addr_r, otype, off_r);
1789 if (bswap && data_r != TCG_REG_XZR) {
1790 tcg_out_rev64(s, TCG_REG_TMP, data_r);
1791 data_r = TCG_REG_TMP;
1793 tcg_out_ldst_r(s, I3312_STRX, data_r, addr_r, otype, off_r);
1800 static void tcg_out_qemu_ld(TCGContext *s, TCGReg data_reg, TCGReg addr_reg,
1801 TCGMemOpIdx oi, TCGType ext)
1803 MemOp memop = get_memop(oi);
1804 const TCGType otype = TARGET_LONG_BITS == 64 ? TCG_TYPE_I64 : TCG_TYPE_I32;
1805 #ifdef CONFIG_SOFTMMU
1806 unsigned mem_index = get_mmuidx(oi);
1807 tcg_insn_unit *label_ptr;
1809 tcg_out_tlb_read(s, addr_reg, memop, &label_ptr, mem_index, 1);
1810 tcg_out_qemu_ld_direct(s, memop, ext, data_reg,
1811 TCG_REG_X1, otype, addr_reg);
1812 add_qemu_ldst_label(s, true, oi, ext, data_reg, addr_reg,
1813 s->code_ptr, label_ptr);
1814 #else /* !CONFIG_SOFTMMU */
1815 if (USE_GUEST_BASE) {
1816 tcg_out_qemu_ld_direct(s, memop, ext, data_reg,
1817 TCG_REG_GUEST_BASE, otype, addr_reg);
1819 tcg_out_qemu_ld_direct(s, memop, ext, data_reg,
1820 addr_reg, TCG_TYPE_I64, TCG_REG_XZR);
1822 #endif /* CONFIG_SOFTMMU */
1825 static void tcg_out_qemu_st(TCGContext *s, TCGReg data_reg, TCGReg addr_reg,
1828 MemOp memop = get_memop(oi);
1829 const TCGType otype = TARGET_LONG_BITS == 64 ? TCG_TYPE_I64 : TCG_TYPE_I32;
1830 #ifdef CONFIG_SOFTMMU
1831 unsigned mem_index = get_mmuidx(oi);
1832 tcg_insn_unit *label_ptr;
1834 tcg_out_tlb_read(s, addr_reg, memop, &label_ptr, mem_index, 0);
1835 tcg_out_qemu_st_direct(s, memop, data_reg,
1836 TCG_REG_X1, otype, addr_reg);
1837 add_qemu_ldst_label(s, false, oi, (memop & MO_SIZE)== MO_64,
1838 data_reg, addr_reg, s->code_ptr, label_ptr);
1839 #else /* !CONFIG_SOFTMMU */
1840 if (USE_GUEST_BASE) {
1841 tcg_out_qemu_st_direct(s, memop, data_reg,
1842 TCG_REG_GUEST_BASE, otype, addr_reg);
1844 tcg_out_qemu_st_direct(s, memop, data_reg,
1845 addr_reg, TCG_TYPE_I64, TCG_REG_XZR);
1847 #endif /* CONFIG_SOFTMMU */
1850 static const tcg_insn_unit *tb_ret_addr;
1852 static void tcg_out_op(TCGContext *s, TCGOpcode opc,
1853 const TCGArg args[TCG_MAX_OP_ARGS],
1854 const int const_args[TCG_MAX_OP_ARGS])
1856 /* 99% of the time, we can signal the use of extension registers
1857 by looking to see if the opcode handles 64-bit data. */
1858 TCGType ext = (tcg_op_defs[opc].flags & TCG_OPF_64BIT) != 0;
1860 /* Hoist the loads of the most common arguments. */
1861 TCGArg a0 = args[0];
1862 TCGArg a1 = args[1];
1863 TCGArg a2 = args[2];
1864 int c2 = const_args[2];
1866 /* Some operands are defined with "rZ" constraint, a register or
1867 the zero register. These need not actually test args[I] == 0. */
1868 #define REG0(I) (const_args[I] ? TCG_REG_XZR : (TCGReg)args[I])
1871 case INDEX_op_exit_tb:
1872 /* Reuse the zeroing that exists for goto_ptr. */
1874 tcg_out_goto_long(s, tcg_code_gen_epilogue);
1876 tcg_out_movi(s, TCG_TYPE_I64, TCG_REG_X0, a0);
1877 tcg_out_goto_long(s, tb_ret_addr);
1881 case INDEX_op_goto_tb:
1882 if (s->tb_jmp_insn_offset != NULL) {
1883 /* TCG_TARGET_HAS_direct_jump */
1884 /* Ensure that ADRP+ADD are 8-byte aligned so that an atomic
1885 write can be used to patch the target address. */
1886 if ((uintptr_t)s->code_ptr & 7) {
1889 s->tb_jmp_insn_offset[a0] = tcg_current_code_size(s);
1890 /* actual branch destination will be patched by
1891 tb_target_set_jmp_target later. */
1892 tcg_out_insn(s, 3406, ADRP, TCG_REG_TMP, 0);
1893 tcg_out_insn(s, 3401, ADDI, TCG_TYPE_I64, TCG_REG_TMP, TCG_REG_TMP, 0);
1895 /* !TCG_TARGET_HAS_direct_jump */
1896 tcg_debug_assert(s->tb_jmp_target_addr != NULL);
1897 intptr_t offset = tcg_pcrel_diff(s, (s->tb_jmp_target_addr + a0)) >> 2;
1898 tcg_out_insn(s, 3305, LDR, offset, TCG_REG_TMP);
1900 tcg_out_insn(s, 3207, BR, TCG_REG_TMP);
1901 set_jmp_reset_offset(s, a0);
1904 case INDEX_op_goto_ptr:
1905 tcg_out_insn(s, 3207, BR, a0);
1909 tcg_out_goto_label(s, arg_label(a0));
1912 case INDEX_op_ld8u_i32:
1913 case INDEX_op_ld8u_i64:
1914 tcg_out_ldst(s, I3312_LDRB, a0, a1, a2, 0);
1916 case INDEX_op_ld8s_i32:
1917 tcg_out_ldst(s, I3312_LDRSBW, a0, a1, a2, 0);
1919 case INDEX_op_ld8s_i64:
1920 tcg_out_ldst(s, I3312_LDRSBX, a0, a1, a2, 0);
1922 case INDEX_op_ld16u_i32:
1923 case INDEX_op_ld16u_i64:
1924 tcg_out_ldst(s, I3312_LDRH, a0, a1, a2, 1);
1926 case INDEX_op_ld16s_i32:
1927 tcg_out_ldst(s, I3312_LDRSHW, a0, a1, a2, 1);
1929 case INDEX_op_ld16s_i64:
1930 tcg_out_ldst(s, I3312_LDRSHX, a0, a1, a2, 1);
1932 case INDEX_op_ld_i32:
1933 case INDEX_op_ld32u_i64:
1934 tcg_out_ldst(s, I3312_LDRW, a0, a1, a2, 2);
1936 case INDEX_op_ld32s_i64:
1937 tcg_out_ldst(s, I3312_LDRSWX, a0, a1, a2, 2);
1939 case INDEX_op_ld_i64:
1940 tcg_out_ldst(s, I3312_LDRX, a0, a1, a2, 3);
1943 case INDEX_op_st8_i32:
1944 case INDEX_op_st8_i64:
1945 tcg_out_ldst(s, I3312_STRB, REG0(0), a1, a2, 0);
1947 case INDEX_op_st16_i32:
1948 case INDEX_op_st16_i64:
1949 tcg_out_ldst(s, I3312_STRH, REG0(0), a1, a2, 1);
1951 case INDEX_op_st_i32:
1952 case INDEX_op_st32_i64:
1953 tcg_out_ldst(s, I3312_STRW, REG0(0), a1, a2, 2);
1955 case INDEX_op_st_i64:
1956 tcg_out_ldst(s, I3312_STRX, REG0(0), a1, a2, 3);
1959 case INDEX_op_add_i32:
1962 case INDEX_op_add_i64:
1964 tcg_out_addsubi(s, ext, a0, a1, a2);
1966 tcg_out_insn(s, 3502, ADD, ext, a0, a1, a2);
1970 case INDEX_op_sub_i32:
1973 case INDEX_op_sub_i64:
1975 tcg_out_addsubi(s, ext, a0, a1, -a2);
1977 tcg_out_insn(s, 3502, SUB, ext, a0, a1, a2);
1981 case INDEX_op_neg_i64:
1982 case INDEX_op_neg_i32:
1983 tcg_out_insn(s, 3502, SUB, ext, a0, TCG_REG_XZR, a1);
1986 case INDEX_op_and_i32:
1989 case INDEX_op_and_i64:
1991 tcg_out_logicali(s, I3404_ANDI, ext, a0, a1, a2);
1993 tcg_out_insn(s, 3510, AND, ext, a0, a1, a2);
1997 case INDEX_op_andc_i32:
2000 case INDEX_op_andc_i64:
2002 tcg_out_logicali(s, I3404_ANDI, ext, a0, a1, ~a2);
2004 tcg_out_insn(s, 3510, BIC, ext, a0, a1, a2);
2008 case INDEX_op_or_i32:
2011 case INDEX_op_or_i64:
2013 tcg_out_logicali(s, I3404_ORRI, ext, a0, a1, a2);
2015 tcg_out_insn(s, 3510, ORR, ext, a0, a1, a2);
2019 case INDEX_op_orc_i32:
2022 case INDEX_op_orc_i64:
2024 tcg_out_logicali(s, I3404_ORRI, ext, a0, a1, ~a2);
2026 tcg_out_insn(s, 3510, ORN, ext, a0, a1, a2);
2030 case INDEX_op_xor_i32:
2033 case INDEX_op_xor_i64:
2035 tcg_out_logicali(s, I3404_EORI, ext, a0, a1, a2);
2037 tcg_out_insn(s, 3510, EOR, ext, a0, a1, a2);
2041 case INDEX_op_eqv_i32:
2044 case INDEX_op_eqv_i64:
2046 tcg_out_logicali(s, I3404_EORI, ext, a0, a1, ~a2);
2048 tcg_out_insn(s, 3510, EON, ext, a0, a1, a2);
2052 case INDEX_op_not_i64:
2053 case INDEX_op_not_i32:
2054 tcg_out_insn(s, 3510, ORN, ext, a0, TCG_REG_XZR, a1);
2057 case INDEX_op_mul_i64:
2058 case INDEX_op_mul_i32:
2059 tcg_out_insn(s, 3509, MADD, ext, a0, a1, a2, TCG_REG_XZR);
2062 case INDEX_op_div_i64:
2063 case INDEX_op_div_i32:
2064 tcg_out_insn(s, 3508, SDIV, ext, a0, a1, a2);
2066 case INDEX_op_divu_i64:
2067 case INDEX_op_divu_i32:
2068 tcg_out_insn(s, 3508, UDIV, ext, a0, a1, a2);
2071 case INDEX_op_rem_i64:
2072 case INDEX_op_rem_i32:
2073 tcg_out_insn(s, 3508, SDIV, ext, TCG_REG_TMP, a1, a2);
2074 tcg_out_insn(s, 3509, MSUB, ext, a0, TCG_REG_TMP, a2, a1);
2076 case INDEX_op_remu_i64:
2077 case INDEX_op_remu_i32:
2078 tcg_out_insn(s, 3508, UDIV, ext, TCG_REG_TMP, a1, a2);
2079 tcg_out_insn(s, 3509, MSUB, ext, a0, TCG_REG_TMP, a2, a1);
2082 case INDEX_op_shl_i64:
2083 case INDEX_op_shl_i32:
2085 tcg_out_shl(s, ext, a0, a1, a2);
2087 tcg_out_insn(s, 3508, LSLV, ext, a0, a1, a2);
2091 case INDEX_op_shr_i64:
2092 case INDEX_op_shr_i32:
2094 tcg_out_shr(s, ext, a0, a1, a2);
2096 tcg_out_insn(s, 3508, LSRV, ext, a0, a1, a2);
2100 case INDEX_op_sar_i64:
2101 case INDEX_op_sar_i32:
2103 tcg_out_sar(s, ext, a0, a1, a2);
2105 tcg_out_insn(s, 3508, ASRV, ext, a0, a1, a2);
2109 case INDEX_op_rotr_i64:
2110 case INDEX_op_rotr_i32:
2112 tcg_out_rotr(s, ext, a0, a1, a2);
2114 tcg_out_insn(s, 3508, RORV, ext, a0, a1, a2);
2118 case INDEX_op_rotl_i64:
2119 case INDEX_op_rotl_i32:
2121 tcg_out_rotl(s, ext, a0, a1, a2);
2123 tcg_out_insn(s, 3502, SUB, 0, TCG_REG_TMP, TCG_REG_XZR, a2);
2124 tcg_out_insn(s, 3508, RORV, ext, a0, a1, TCG_REG_TMP);
2128 case INDEX_op_clz_i64:
2129 case INDEX_op_clz_i32:
2130 tcg_out_cltz(s, ext, a0, a1, a2, c2, false);
2132 case INDEX_op_ctz_i64:
2133 case INDEX_op_ctz_i32:
2134 tcg_out_cltz(s, ext, a0, a1, a2, c2, true);
2137 case INDEX_op_brcond_i32:
2140 case INDEX_op_brcond_i64:
2141 tcg_out_brcond(s, ext, a2, a0, a1, const_args[1], arg_label(args[3]));
2144 case INDEX_op_setcond_i32:
2147 case INDEX_op_setcond_i64:
2148 tcg_out_cmp(s, ext, a1, a2, c2);
2149 /* Use CSET alias of CSINC Wd, WZR, WZR, invert(cond). */
2150 tcg_out_insn(s, 3506, CSINC, TCG_TYPE_I32, a0, TCG_REG_XZR,
2151 TCG_REG_XZR, tcg_invert_cond(args[3]));
2154 case INDEX_op_movcond_i32:
2157 case INDEX_op_movcond_i64:
2158 tcg_out_cmp(s, ext, a1, a2, c2);
2159 tcg_out_insn(s, 3506, CSEL, ext, a0, REG0(3), REG0(4), args[5]);
2162 case INDEX_op_qemu_ld_i32:
2163 case INDEX_op_qemu_ld_i64:
2164 tcg_out_qemu_ld(s, a0, a1, a2, ext);
2166 case INDEX_op_qemu_st_i32:
2167 case INDEX_op_qemu_st_i64:
2168 tcg_out_qemu_st(s, REG0(0), a1, a2);
2171 case INDEX_op_bswap64_i64:
2172 tcg_out_rev64(s, a0, a1);
2174 case INDEX_op_bswap32_i64:
2175 case INDEX_op_bswap32_i32:
2176 tcg_out_rev32(s, a0, a1);
2178 case INDEX_op_bswap16_i64:
2179 case INDEX_op_bswap16_i32:
2180 tcg_out_rev16(s, a0, a1);
2183 case INDEX_op_ext8s_i64:
2184 case INDEX_op_ext8s_i32:
2185 tcg_out_sxt(s, ext, MO_8, a0, a1);
2187 case INDEX_op_ext16s_i64:
2188 case INDEX_op_ext16s_i32:
2189 tcg_out_sxt(s, ext, MO_16, a0, a1);
2191 case INDEX_op_ext_i32_i64:
2192 case INDEX_op_ext32s_i64:
2193 tcg_out_sxt(s, TCG_TYPE_I64, MO_32, a0, a1);
2195 case INDEX_op_ext8u_i64:
2196 case INDEX_op_ext8u_i32:
2197 tcg_out_uxt(s, MO_8, a0, a1);
2199 case INDEX_op_ext16u_i64:
2200 case INDEX_op_ext16u_i32:
2201 tcg_out_uxt(s, MO_16, a0, a1);
2203 case INDEX_op_extu_i32_i64:
2204 case INDEX_op_ext32u_i64:
2205 tcg_out_movr(s, TCG_TYPE_I32, a0, a1);
2208 case INDEX_op_deposit_i64:
2209 case INDEX_op_deposit_i32:
2210 tcg_out_dep(s, ext, a0, REG0(2), args[3], args[4]);
2213 case INDEX_op_extract_i64:
2214 case INDEX_op_extract_i32:
2215 tcg_out_ubfm(s, ext, a0, a1, a2, a2 + args[3] - 1);
2218 case INDEX_op_sextract_i64:
2219 case INDEX_op_sextract_i32:
2220 tcg_out_sbfm(s, ext, a0, a1, a2, a2 + args[3] - 1);
2223 case INDEX_op_extract2_i64:
2224 case INDEX_op_extract2_i32:
2225 tcg_out_extr(s, ext, a0, REG0(2), REG0(1), args[3]);
2228 case INDEX_op_add2_i32:
2229 tcg_out_addsub2(s, TCG_TYPE_I32, a0, a1, REG0(2), REG0(3),
2230 (int32_t)args[4], args[5], const_args[4],
2231 const_args[5], false);
2233 case INDEX_op_add2_i64:
2234 tcg_out_addsub2(s, TCG_TYPE_I64, a0, a1, REG0(2), REG0(3), args[4],
2235 args[5], const_args[4], const_args[5], false);
2237 case INDEX_op_sub2_i32:
2238 tcg_out_addsub2(s, TCG_TYPE_I32, a0, a1, REG0(2), REG0(3),
2239 (int32_t)args[4], args[5], const_args[4],
2240 const_args[5], true);
2242 case INDEX_op_sub2_i64:
2243 tcg_out_addsub2(s, TCG_TYPE_I64, a0, a1, REG0(2), REG0(3), args[4],
2244 args[5], const_args[4], const_args[5], true);
2247 case INDEX_op_muluh_i64:
2248 tcg_out_insn(s, 3508, UMULH, TCG_TYPE_I64, a0, a1, a2);
2250 case INDEX_op_mulsh_i64:
2251 tcg_out_insn(s, 3508, SMULH, TCG_TYPE_I64, a0, a1, a2);
2258 case INDEX_op_mov_i32: /* Always emitted via tcg_out_mov. */
2259 case INDEX_op_mov_i64:
2260 case INDEX_op_call: /* Always emitted via tcg_out_call. */
2262 g_assert_not_reached();
2268 static void tcg_out_vec_op(TCGContext *s, TCGOpcode opc,
2269 unsigned vecl, unsigned vece,
2270 const TCGArg *args, const int *const_args)
2272 static const AArch64Insn cmp_insn[16] = {
2273 [TCG_COND_EQ] = I3616_CMEQ,
2274 [TCG_COND_GT] = I3616_CMGT,
2275 [TCG_COND_GE] = I3616_CMGE,
2276 [TCG_COND_GTU] = I3616_CMHI,
2277 [TCG_COND_GEU] = I3616_CMHS,
2279 static const AArch64Insn cmp0_insn[16] = {
2280 [TCG_COND_EQ] = I3617_CMEQ0,
2281 [TCG_COND_GT] = I3617_CMGT0,
2282 [TCG_COND_GE] = I3617_CMGE0,
2283 [TCG_COND_LT] = I3617_CMLT0,
2284 [TCG_COND_LE] = I3617_CMLE0,
2287 TCGType type = vecl + TCG_TYPE_V64;
2288 unsigned is_q = vecl;
2289 TCGArg a0, a1, a2, a3;
2297 case INDEX_op_ld_vec:
2298 tcg_out_ld(s, type, a0, a1, a2);
2300 case INDEX_op_st_vec:
2301 tcg_out_st(s, type, a0, a1, a2);
2303 case INDEX_op_dupm_vec:
2304 tcg_out_dupm_vec(s, type, vece, a0, a1, a2);
2306 case INDEX_op_add_vec:
2307 tcg_out_insn(s, 3616, ADD, is_q, vece, a0, a1, a2);
2309 case INDEX_op_sub_vec:
2310 tcg_out_insn(s, 3616, SUB, is_q, vece, a0, a1, a2);
2312 case INDEX_op_mul_vec:
2313 tcg_out_insn(s, 3616, MUL, is_q, vece, a0, a1, a2);
2315 case INDEX_op_neg_vec:
2316 tcg_out_insn(s, 3617, NEG, is_q, vece, a0, a1);
2318 case INDEX_op_abs_vec:
2319 tcg_out_insn(s, 3617, ABS, is_q, vece, a0, a1);
2321 case INDEX_op_and_vec:
2322 if (const_args[2]) {
2323 is_shimm1632(~a2, &cmode, &imm8);
2325 tcg_out_insn(s, 3606, BIC, is_q, a0, 0, cmode, imm8);
2328 tcg_out_insn(s, 3606, MVNI, is_q, a0, 0, cmode, imm8);
2331 tcg_out_insn(s, 3616, AND, is_q, 0, a0, a1, a2);
2333 case INDEX_op_or_vec:
2334 if (const_args[2]) {
2335 is_shimm1632(a2, &cmode, &imm8);
2337 tcg_out_insn(s, 3606, ORR, is_q, a0, 0, cmode, imm8);
2340 tcg_out_insn(s, 3606, MOVI, is_q, a0, 0, cmode, imm8);
2343 tcg_out_insn(s, 3616, ORR, is_q, 0, a0, a1, a2);
2345 case INDEX_op_andc_vec:
2346 if (const_args[2]) {
2347 is_shimm1632(a2, &cmode, &imm8);
2349 tcg_out_insn(s, 3606, BIC, is_q, a0, 0, cmode, imm8);
2352 tcg_out_insn(s, 3606, MOVI, is_q, a0, 0, cmode, imm8);
2355 tcg_out_insn(s, 3616, BIC, is_q, 0, a0, a1, a2);
2357 case INDEX_op_orc_vec:
2358 if (const_args[2]) {
2359 is_shimm1632(~a2, &cmode, &imm8);
2361 tcg_out_insn(s, 3606, ORR, is_q, a0, 0, cmode, imm8);
2364 tcg_out_insn(s, 3606, MVNI, is_q, a0, 0, cmode, imm8);
2367 tcg_out_insn(s, 3616, ORN, is_q, 0, a0, a1, a2);
2369 case INDEX_op_xor_vec:
2370 tcg_out_insn(s, 3616, EOR, is_q, 0, a0, a1, a2);
2372 case INDEX_op_ssadd_vec:
2373 tcg_out_insn(s, 3616, SQADD, is_q, vece, a0, a1, a2);
2375 case INDEX_op_sssub_vec:
2376 tcg_out_insn(s, 3616, SQSUB, is_q, vece, a0, a1, a2);
2378 case INDEX_op_usadd_vec:
2379 tcg_out_insn(s, 3616, UQADD, is_q, vece, a0, a1, a2);
2381 case INDEX_op_ussub_vec:
2382 tcg_out_insn(s, 3616, UQSUB, is_q, vece, a0, a1, a2);
2384 case INDEX_op_smax_vec:
2385 tcg_out_insn(s, 3616, SMAX, is_q, vece, a0, a1, a2);
2387 case INDEX_op_smin_vec:
2388 tcg_out_insn(s, 3616, SMIN, is_q, vece, a0, a1, a2);
2390 case INDEX_op_umax_vec:
2391 tcg_out_insn(s, 3616, UMAX, is_q, vece, a0, a1, a2);
2393 case INDEX_op_umin_vec:
2394 tcg_out_insn(s, 3616, UMIN, is_q, vece, a0, a1, a2);
2396 case INDEX_op_not_vec:
2397 tcg_out_insn(s, 3617, NOT, is_q, 0, a0, a1);
2399 case INDEX_op_shli_vec:
2400 tcg_out_insn(s, 3614, SHL, is_q, a0, a1, a2 + (8 << vece));
2402 case INDEX_op_shri_vec:
2403 tcg_out_insn(s, 3614, USHR, is_q, a0, a1, (16 << vece) - a2);
2405 case INDEX_op_sari_vec:
2406 tcg_out_insn(s, 3614, SSHR, is_q, a0, a1, (16 << vece) - a2);
2408 case INDEX_op_aa64_sli_vec:
2409 tcg_out_insn(s, 3614, SLI, is_q, a0, a2, args[3] + (8 << vece));
2411 case INDEX_op_shlv_vec:
2412 tcg_out_insn(s, 3616, USHL, is_q, vece, a0, a1, a2);
2414 case INDEX_op_aa64_sshl_vec:
2415 tcg_out_insn(s, 3616, SSHL, is_q, vece, a0, a1, a2);
2417 case INDEX_op_cmp_vec:
2419 TCGCond cond = args[3];
2422 if (cond == TCG_COND_NE) {
2423 if (const_args[2]) {
2424 tcg_out_insn(s, 3616, CMTST, is_q, vece, a0, a1, a1);
2426 tcg_out_insn(s, 3616, CMEQ, is_q, vece, a0, a1, a2);
2427 tcg_out_insn(s, 3617, NOT, is_q, 0, a0, a0);
2430 if (const_args[2]) {
2431 insn = cmp0_insn[cond];
2433 tcg_out_insn_3617(s, insn, is_q, vece, a0, a1);
2436 tcg_out_dupi_vec(s, type, MO_8, TCG_VEC_TMP, 0);
2439 insn = cmp_insn[cond];
2442 t = a1, a1 = a2, a2 = t;
2443 cond = tcg_swap_cond(cond);
2444 insn = cmp_insn[cond];
2445 tcg_debug_assert(insn != 0);
2447 tcg_out_insn_3616(s, insn, is_q, vece, a0, a1, a2);
2452 case INDEX_op_bitsel_vec:
2455 tcg_out_insn(s, 3616, BIT, is_q, 0, a0, a2, a1);
2456 } else if (a0 == a2) {
2457 tcg_out_insn(s, 3616, BIF, is_q, 0, a0, a3, a1);
2460 tcg_out_mov(s, type, a0, a1);
2462 tcg_out_insn(s, 3616, BSL, is_q, 0, a0, a2, a3);
2466 case INDEX_op_mov_vec: /* Always emitted via tcg_out_mov. */
2467 case INDEX_op_dup_vec: /* Always emitted via tcg_out_dup_vec. */
2469 g_assert_not_reached();
2473 int tcg_can_emit_vec_op(TCGOpcode opc, TCGType type, unsigned vece)
2476 case INDEX_op_add_vec:
2477 case INDEX_op_sub_vec:
2478 case INDEX_op_and_vec:
2479 case INDEX_op_or_vec:
2480 case INDEX_op_xor_vec:
2481 case INDEX_op_andc_vec:
2482 case INDEX_op_orc_vec:
2483 case INDEX_op_neg_vec:
2484 case INDEX_op_abs_vec:
2485 case INDEX_op_not_vec:
2486 case INDEX_op_cmp_vec:
2487 case INDEX_op_shli_vec:
2488 case INDEX_op_shri_vec:
2489 case INDEX_op_sari_vec:
2490 case INDEX_op_ssadd_vec:
2491 case INDEX_op_sssub_vec:
2492 case INDEX_op_usadd_vec:
2493 case INDEX_op_ussub_vec:
2494 case INDEX_op_shlv_vec:
2495 case INDEX_op_bitsel_vec:
2497 case INDEX_op_rotli_vec:
2498 case INDEX_op_shrv_vec:
2499 case INDEX_op_sarv_vec:
2500 case INDEX_op_rotlv_vec:
2501 case INDEX_op_rotrv_vec:
2503 case INDEX_op_mul_vec:
2504 case INDEX_op_smax_vec:
2505 case INDEX_op_smin_vec:
2506 case INDEX_op_umax_vec:
2507 case INDEX_op_umin_vec:
2508 return vece < MO_64;
2515 void tcg_expand_vec_op(TCGOpcode opc, TCGType type, unsigned vece,
2519 TCGv_vec v0, v1, v2, t1, t2, c1;
2523 v0 = temp_tcgv_vec(arg_temp(a0));
2524 v1 = temp_tcgv_vec(arg_temp(va_arg(va, TCGArg)));
2525 a2 = va_arg(va, TCGArg);
2526 v2 = temp_tcgv_vec(arg_temp(a2));
2529 case INDEX_op_rotli_vec:
2530 t1 = tcg_temp_new_vec(type);
2531 tcg_gen_shri_vec(vece, t1, v1, -a2 & ((8 << vece) - 1));
2532 vec_gen_4(INDEX_op_aa64_sli_vec, type, vece,
2533 tcgv_vec_arg(v0), tcgv_vec_arg(t1), tcgv_vec_arg(v1), a2);
2534 tcg_temp_free_vec(t1);
2537 case INDEX_op_shrv_vec:
2538 case INDEX_op_sarv_vec:
2539 /* Right shifts are negative left shifts for AArch64. */
2540 t1 = tcg_temp_new_vec(type);
2541 tcg_gen_neg_vec(vece, t1, v2);
2542 opc = (opc == INDEX_op_shrv_vec
2543 ? INDEX_op_shlv_vec : INDEX_op_aa64_sshl_vec);
2544 vec_gen_3(opc, type, vece, tcgv_vec_arg(v0),
2545 tcgv_vec_arg(v1), tcgv_vec_arg(t1));
2546 tcg_temp_free_vec(t1);
2549 case INDEX_op_rotlv_vec:
2550 t1 = tcg_temp_new_vec(type);
2551 c1 = tcg_constant_vec(type, vece, 8 << vece);
2552 tcg_gen_sub_vec(vece, t1, v2, c1);
2553 /* Right shifts are negative left shifts for AArch64. */
2554 vec_gen_3(INDEX_op_shlv_vec, type, vece, tcgv_vec_arg(t1),
2555 tcgv_vec_arg(v1), tcgv_vec_arg(t1));
2556 vec_gen_3(INDEX_op_shlv_vec, type, vece, tcgv_vec_arg(v0),
2557 tcgv_vec_arg(v1), tcgv_vec_arg(v2));
2558 tcg_gen_or_vec(vece, v0, v0, t1);
2559 tcg_temp_free_vec(t1);
2562 case INDEX_op_rotrv_vec:
2563 t1 = tcg_temp_new_vec(type);
2564 t2 = tcg_temp_new_vec(type);
2565 c1 = tcg_constant_vec(type, vece, 8 << vece);
2566 tcg_gen_neg_vec(vece, t1, v2);
2567 tcg_gen_sub_vec(vece, t2, c1, v2);
2568 /* Right shifts are negative left shifts for AArch64. */
2569 vec_gen_3(INDEX_op_shlv_vec, type, vece, tcgv_vec_arg(t1),
2570 tcgv_vec_arg(v1), tcgv_vec_arg(t1));
2571 vec_gen_3(INDEX_op_shlv_vec, type, vece, tcgv_vec_arg(t2),
2572 tcgv_vec_arg(v1), tcgv_vec_arg(t2));
2573 tcg_gen_or_vec(vece, v0, t1, t2);
2574 tcg_temp_free_vec(t1);
2575 tcg_temp_free_vec(t2);
2579 g_assert_not_reached();
2585 static const TCGTargetOpDef *tcg_target_op_def(TCGOpcode op)
2587 static const TCGTargetOpDef r = { .args_ct_str = { "r" } };
2588 static const TCGTargetOpDef r_r = { .args_ct_str = { "r", "r" } };
2589 static const TCGTargetOpDef w_w = { .args_ct_str = { "w", "w" } };
2590 static const TCGTargetOpDef w_r = { .args_ct_str = { "w", "r" } };
2591 static const TCGTargetOpDef w_wr = { .args_ct_str = { "w", "wr" } };
2592 static const TCGTargetOpDef r_l = { .args_ct_str = { "r", "l" } };
2593 static const TCGTargetOpDef r_rA = { .args_ct_str = { "r", "rA" } };
2594 static const TCGTargetOpDef rZ_r = { .args_ct_str = { "rZ", "r" } };
2595 static const TCGTargetOpDef lZ_l = { .args_ct_str = { "lZ", "l" } };
2596 static const TCGTargetOpDef r_r_r = { .args_ct_str = { "r", "r", "r" } };
2597 static const TCGTargetOpDef w_w_w = { .args_ct_str = { "w", "w", "w" } };
2598 static const TCGTargetOpDef w_0_w = { .args_ct_str = { "w", "0", "w" } };
2599 static const TCGTargetOpDef w_w_wO = { .args_ct_str = { "w", "w", "wO" } };
2600 static const TCGTargetOpDef w_w_wN = { .args_ct_str = { "w", "w", "wN" } };
2601 static const TCGTargetOpDef w_w_wZ = { .args_ct_str = { "w", "w", "wZ" } };
2602 static const TCGTargetOpDef r_r_ri = { .args_ct_str = { "r", "r", "ri" } };
2603 static const TCGTargetOpDef r_r_rA = { .args_ct_str = { "r", "r", "rA" } };
2604 static const TCGTargetOpDef r_r_rL = { .args_ct_str = { "r", "r", "rL" } };
2605 static const TCGTargetOpDef r_r_rAL
2606 = { .args_ct_str = { "r", "r", "rAL" } };
2607 static const TCGTargetOpDef dep
2608 = { .args_ct_str = { "r", "0", "rZ" } };
2609 static const TCGTargetOpDef ext2
2610 = { .args_ct_str = { "r", "rZ", "rZ" } };
2611 static const TCGTargetOpDef movc
2612 = { .args_ct_str = { "r", "r", "rA", "rZ", "rZ" } };
2613 static const TCGTargetOpDef add2
2614 = { .args_ct_str = { "r", "r", "rZ", "rZ", "rA", "rMZ" } };
2615 static const TCGTargetOpDef w_w_w_w
2616 = { .args_ct_str = { "w", "w", "w", "w" } };
2619 case INDEX_op_goto_ptr:
2622 case INDEX_op_ld8u_i32:
2623 case INDEX_op_ld8s_i32:
2624 case INDEX_op_ld16u_i32:
2625 case INDEX_op_ld16s_i32:
2626 case INDEX_op_ld_i32:
2627 case INDEX_op_ld8u_i64:
2628 case INDEX_op_ld8s_i64:
2629 case INDEX_op_ld16u_i64:
2630 case INDEX_op_ld16s_i64:
2631 case INDEX_op_ld32u_i64:
2632 case INDEX_op_ld32s_i64:
2633 case INDEX_op_ld_i64:
2634 case INDEX_op_neg_i32:
2635 case INDEX_op_neg_i64:
2636 case INDEX_op_not_i32:
2637 case INDEX_op_not_i64:
2638 case INDEX_op_bswap16_i32:
2639 case INDEX_op_bswap32_i32:
2640 case INDEX_op_bswap16_i64:
2641 case INDEX_op_bswap32_i64:
2642 case INDEX_op_bswap64_i64:
2643 case INDEX_op_ext8s_i32:
2644 case INDEX_op_ext16s_i32:
2645 case INDEX_op_ext8u_i32:
2646 case INDEX_op_ext16u_i32:
2647 case INDEX_op_ext8s_i64:
2648 case INDEX_op_ext16s_i64:
2649 case INDEX_op_ext32s_i64:
2650 case INDEX_op_ext8u_i64:
2651 case INDEX_op_ext16u_i64:
2652 case INDEX_op_ext32u_i64:
2653 case INDEX_op_ext_i32_i64:
2654 case INDEX_op_extu_i32_i64:
2655 case INDEX_op_extract_i32:
2656 case INDEX_op_extract_i64:
2657 case INDEX_op_sextract_i32:
2658 case INDEX_op_sextract_i64:
2661 case INDEX_op_st8_i32:
2662 case INDEX_op_st16_i32:
2663 case INDEX_op_st_i32:
2664 case INDEX_op_st8_i64:
2665 case INDEX_op_st16_i64:
2666 case INDEX_op_st32_i64:
2667 case INDEX_op_st_i64:
2670 case INDEX_op_add_i32:
2671 case INDEX_op_add_i64:
2672 case INDEX_op_sub_i32:
2673 case INDEX_op_sub_i64:
2674 case INDEX_op_setcond_i32:
2675 case INDEX_op_setcond_i64:
2678 case INDEX_op_mul_i32:
2679 case INDEX_op_mul_i64:
2680 case INDEX_op_div_i32:
2681 case INDEX_op_div_i64:
2682 case INDEX_op_divu_i32:
2683 case INDEX_op_divu_i64:
2684 case INDEX_op_rem_i32:
2685 case INDEX_op_rem_i64:
2686 case INDEX_op_remu_i32:
2687 case INDEX_op_remu_i64:
2688 case INDEX_op_muluh_i64:
2689 case INDEX_op_mulsh_i64:
2692 case INDEX_op_and_i32:
2693 case INDEX_op_and_i64:
2694 case INDEX_op_or_i32:
2695 case INDEX_op_or_i64:
2696 case INDEX_op_xor_i32:
2697 case INDEX_op_xor_i64:
2698 case INDEX_op_andc_i32:
2699 case INDEX_op_andc_i64:
2700 case INDEX_op_orc_i32:
2701 case INDEX_op_orc_i64:
2702 case INDEX_op_eqv_i32:
2703 case INDEX_op_eqv_i64:
2706 case INDEX_op_shl_i32:
2707 case INDEX_op_shr_i32:
2708 case INDEX_op_sar_i32:
2709 case INDEX_op_rotl_i32:
2710 case INDEX_op_rotr_i32:
2711 case INDEX_op_shl_i64:
2712 case INDEX_op_shr_i64:
2713 case INDEX_op_sar_i64:
2714 case INDEX_op_rotl_i64:
2715 case INDEX_op_rotr_i64:
2718 case INDEX_op_clz_i32:
2719 case INDEX_op_ctz_i32:
2720 case INDEX_op_clz_i64:
2721 case INDEX_op_ctz_i64:
2724 case INDEX_op_brcond_i32:
2725 case INDEX_op_brcond_i64:
2728 case INDEX_op_movcond_i32:
2729 case INDEX_op_movcond_i64:
2732 case INDEX_op_qemu_ld_i32:
2733 case INDEX_op_qemu_ld_i64:
2735 case INDEX_op_qemu_st_i32:
2736 case INDEX_op_qemu_st_i64:
2739 case INDEX_op_deposit_i32:
2740 case INDEX_op_deposit_i64:
2743 case INDEX_op_extract2_i32:
2744 case INDEX_op_extract2_i64:
2747 case INDEX_op_add2_i32:
2748 case INDEX_op_add2_i64:
2749 case INDEX_op_sub2_i32:
2750 case INDEX_op_sub2_i64:
2753 case INDEX_op_add_vec:
2754 case INDEX_op_sub_vec:
2755 case INDEX_op_mul_vec:
2756 case INDEX_op_xor_vec:
2757 case INDEX_op_ssadd_vec:
2758 case INDEX_op_sssub_vec:
2759 case INDEX_op_usadd_vec:
2760 case INDEX_op_ussub_vec:
2761 case INDEX_op_smax_vec:
2762 case INDEX_op_smin_vec:
2763 case INDEX_op_umax_vec:
2764 case INDEX_op_umin_vec:
2765 case INDEX_op_shlv_vec:
2766 case INDEX_op_shrv_vec:
2767 case INDEX_op_sarv_vec:
2768 case INDEX_op_aa64_sshl_vec:
2770 case INDEX_op_not_vec:
2771 case INDEX_op_neg_vec:
2772 case INDEX_op_abs_vec:
2773 case INDEX_op_shli_vec:
2774 case INDEX_op_shri_vec:
2775 case INDEX_op_sari_vec:
2777 case INDEX_op_ld_vec:
2778 case INDEX_op_st_vec:
2779 case INDEX_op_dupm_vec:
2781 case INDEX_op_dup_vec:
2783 case INDEX_op_or_vec:
2784 case INDEX_op_andc_vec:
2786 case INDEX_op_and_vec:
2787 case INDEX_op_orc_vec:
2789 case INDEX_op_cmp_vec:
2791 case INDEX_op_bitsel_vec:
2793 case INDEX_op_aa64_sli_vec:
2801 static void tcg_target_init(TCGContext *s)
2803 tcg_target_available_regs[TCG_TYPE_I32] = 0xffffffffu;
2804 tcg_target_available_regs[TCG_TYPE_I64] = 0xffffffffu;
2805 tcg_target_available_regs[TCG_TYPE_V64] = 0xffffffff00000000ull;
2806 tcg_target_available_regs[TCG_TYPE_V128] = 0xffffffff00000000ull;
2808 tcg_target_call_clobber_regs = -1ull;
2809 tcg_regset_reset_reg(tcg_target_call_clobber_regs, TCG_REG_X19);
2810 tcg_regset_reset_reg(tcg_target_call_clobber_regs, TCG_REG_X20);
2811 tcg_regset_reset_reg(tcg_target_call_clobber_regs, TCG_REG_X21);
2812 tcg_regset_reset_reg(tcg_target_call_clobber_regs, TCG_REG_X22);
2813 tcg_regset_reset_reg(tcg_target_call_clobber_regs, TCG_REG_X23);
2814 tcg_regset_reset_reg(tcg_target_call_clobber_regs, TCG_REG_X24);
2815 tcg_regset_reset_reg(tcg_target_call_clobber_regs, TCG_REG_X25);
2816 tcg_regset_reset_reg(tcg_target_call_clobber_regs, TCG_REG_X26);
2817 tcg_regset_reset_reg(tcg_target_call_clobber_regs, TCG_REG_X27);
2818 tcg_regset_reset_reg(tcg_target_call_clobber_regs, TCG_REG_X28);
2819 tcg_regset_reset_reg(tcg_target_call_clobber_regs, TCG_REG_X29);
2820 tcg_regset_reset_reg(tcg_target_call_clobber_regs, TCG_REG_V8);
2821 tcg_regset_reset_reg(tcg_target_call_clobber_regs, TCG_REG_V9);
2822 tcg_regset_reset_reg(tcg_target_call_clobber_regs, TCG_REG_V10);
2823 tcg_regset_reset_reg(tcg_target_call_clobber_regs, TCG_REG_V11);
2824 tcg_regset_reset_reg(tcg_target_call_clobber_regs, TCG_REG_V12);
2825 tcg_regset_reset_reg(tcg_target_call_clobber_regs, TCG_REG_V13);
2826 tcg_regset_reset_reg(tcg_target_call_clobber_regs, TCG_REG_V14);
2827 tcg_regset_reset_reg(tcg_target_call_clobber_regs, TCG_REG_V15);
2829 s->reserved_regs = 0;
2830 tcg_regset_set_reg(s->reserved_regs, TCG_REG_SP);
2831 tcg_regset_set_reg(s->reserved_regs, TCG_REG_FP);
2832 tcg_regset_set_reg(s->reserved_regs, TCG_REG_TMP);
2833 tcg_regset_set_reg(s->reserved_regs, TCG_REG_X18); /* platform register */
2834 tcg_regset_set_reg(s->reserved_regs, TCG_VEC_TMP);
2837 /* Saving pairs: (X19, X20) .. (X27, X28), (X29(fp), X30(lr)). */
2838 #define PUSH_SIZE ((30 - 19 + 1) * 8)
2840 #define FRAME_SIZE \
2842 + TCG_STATIC_CALL_ARGS_SIZE \
2843 + CPU_TEMP_BUF_NLONGS * sizeof(long) \
2844 + TCG_TARGET_STACK_ALIGN - 1) \
2845 & ~(TCG_TARGET_STACK_ALIGN - 1))
2847 /* We're expecting a 2 byte uleb128 encoded value. */
2848 QEMU_BUILD_BUG_ON(FRAME_SIZE >= (1 << 14));
2850 /* We're expecting to use a single ADDI insn. */
2851 QEMU_BUILD_BUG_ON(FRAME_SIZE - PUSH_SIZE > 0xfff);
2853 static void tcg_target_qemu_prologue(TCGContext *s)
2857 /* Push (FP, LR) and allocate space for all saved registers. */
2858 tcg_out_insn(s, 3314, STP, TCG_REG_FP, TCG_REG_LR,
2859 TCG_REG_SP, -PUSH_SIZE, 1, 1);
2861 /* Set up frame pointer for canonical unwinding. */
2862 tcg_out_movr_sp(s, TCG_TYPE_I64, TCG_REG_FP, TCG_REG_SP);
2864 /* Store callee-preserved regs x19..x28. */
2865 for (r = TCG_REG_X19; r <= TCG_REG_X27; r += 2) {
2866 int ofs = (r - TCG_REG_X19 + 2) * 8;
2867 tcg_out_insn(s, 3314, STP, r, r + 1, TCG_REG_SP, ofs, 1, 0);
2870 /* Make stack space for TCG locals. */
2871 tcg_out_insn(s, 3401, SUBI, TCG_TYPE_I64, TCG_REG_SP, TCG_REG_SP,
2872 FRAME_SIZE - PUSH_SIZE);
2874 /* Inform TCG about how to find TCG locals with register, offset, size. */
2875 tcg_set_frame(s, TCG_REG_SP, TCG_STATIC_CALL_ARGS_SIZE,
2876 CPU_TEMP_BUF_NLONGS * sizeof(long));
2878 #if !defined(CONFIG_SOFTMMU)
2879 if (USE_GUEST_BASE) {
2880 tcg_out_movi(s, TCG_TYPE_PTR, TCG_REG_GUEST_BASE, guest_base);
2881 tcg_regset_set_reg(s->reserved_regs, TCG_REG_GUEST_BASE);
2885 tcg_out_mov(s, TCG_TYPE_PTR, TCG_AREG0, tcg_target_call_iarg_regs[0]);
2886 tcg_out_insn(s, 3207, BR, tcg_target_call_iarg_regs[1]);
2889 * Return path for goto_ptr. Set return value to 0, a-la exit_tb,
2890 * and fall through to the rest of the epilogue.
2892 tcg_code_gen_epilogue = tcg_splitwx_to_rx(s->code_ptr);
2893 tcg_out_movi(s, TCG_TYPE_REG, TCG_REG_X0, 0);
2896 tb_ret_addr = tcg_splitwx_to_rx(s->code_ptr);
2898 /* Remove TCG locals stack space. */
2899 tcg_out_insn(s, 3401, ADDI, TCG_TYPE_I64, TCG_REG_SP, TCG_REG_SP,
2900 FRAME_SIZE - PUSH_SIZE);
2902 /* Restore registers x19..x28. */
2903 for (r = TCG_REG_X19; r <= TCG_REG_X27; r += 2) {
2904 int ofs = (r - TCG_REG_X19 + 2) * 8;
2905 tcg_out_insn(s, 3314, LDP, r, r + 1, TCG_REG_SP, ofs, 1, 0);
2908 /* Pop (FP, LR), restore SP to previous frame. */
2909 tcg_out_insn(s, 3314, LDP, TCG_REG_FP, TCG_REG_LR,
2910 TCG_REG_SP, PUSH_SIZE, 0, 1);
2911 tcg_out_insn(s, 3207, RET, TCG_REG_LR);
2914 static void tcg_out_nop_fill(tcg_insn_unit *p, int count)
2917 for (i = 0; i < count; ++i) {
2924 uint8_t fde_def_cfa[4];
2925 uint8_t fde_reg_ofs[24];
2928 #define ELF_HOST_MACHINE EM_AARCH64
2930 static const DebugFrame debug_frame = {
2931 .h.cie.len = sizeof(DebugFrameCIE)-4, /* length after .len member */
2934 .h.cie.code_align = 1,
2935 .h.cie.data_align = 0x78, /* sleb128 -8 */
2936 .h.cie.return_column = TCG_REG_LR,
2938 /* Total FDE size does not include the "len" member. */
2939 .h.fde.len = sizeof(DebugFrame) - offsetof(DebugFrame, h.fde.cie_offset),
2942 12, TCG_REG_SP, /* DW_CFA_def_cfa sp, ... */
2943 (FRAME_SIZE & 0x7f) | 0x80, /* ... uleb128 FRAME_SIZE */
2947 0x80 + 28, 1, /* DW_CFA_offset, x28, -8 */
2948 0x80 + 27, 2, /* DW_CFA_offset, x27, -16 */
2949 0x80 + 26, 3, /* DW_CFA_offset, x26, -24 */
2950 0x80 + 25, 4, /* DW_CFA_offset, x25, -32 */
2951 0x80 + 24, 5, /* DW_CFA_offset, x24, -40 */
2952 0x80 + 23, 6, /* DW_CFA_offset, x23, -48 */
2953 0x80 + 22, 7, /* DW_CFA_offset, x22, -56 */
2954 0x80 + 21, 8, /* DW_CFA_offset, x21, -64 */
2955 0x80 + 20, 9, /* DW_CFA_offset, x20, -72 */
2956 0x80 + 19, 10, /* DW_CFA_offset, x1p, -80 */
2957 0x80 + 30, 11, /* DW_CFA_offset, lr, -88 */
2958 0x80 + 29, 12, /* DW_CFA_offset, fp, -96 */
2962 void tcg_register_jit(const void *buf, size_t buf_size)
2964 tcg_register_jit_int(buf, buf_size, &debug_frame, sizeof(debug_frame));