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.inc.c"
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 inline bool reloc_pc26(tcg_insn_unit
*code_ptr
, tcg_insn_unit
*target
)
83 ptrdiff_t offset
= target
- code_ptr
;
84 if (offset
== sextract64(offset
, 0, 26)) {
85 /* read instruction, mask away previous PC_REL26 parameter contents,
86 set the proper offset, then write back the instruction. */
87 *code_ptr
= deposit32(*code_ptr
, 0, 26, offset
);
93 static inline bool reloc_pc19(tcg_insn_unit
*code_ptr
, tcg_insn_unit
*target
)
95 ptrdiff_t offset
= target
- code_ptr
;
96 if (offset
== sextract64(offset
, 0, 19)) {
97 *code_ptr
= deposit32(*code_ptr
, 5, 19, offset
);
103 static inline bool patch_reloc(tcg_insn_unit
*code_ptr
, int type
,
104 intptr_t value
, intptr_t addend
)
106 tcg_debug_assert(addend
== 0);
108 case R_AARCH64_JUMP26
:
109 case R_AARCH64_CALL26
:
110 return reloc_pc26(code_ptr
, (tcg_insn_unit
*)value
);
111 case R_AARCH64_CONDBR19
:
112 return reloc_pc19(code_ptr
, (tcg_insn_unit
*)value
);
114 g_assert_not_reached();
118 #define TCG_CT_CONST_AIMM 0x100
119 #define TCG_CT_CONST_LIMM 0x200
120 #define TCG_CT_CONST_ZERO 0x400
121 #define TCG_CT_CONST_MONE 0x800
123 /* parse target specific constraints */
124 static const char *target_parse_constraint(TCGArgConstraint
*ct
,
125 const char *ct_str
, TCGType type
)
128 case 'r': /* general registers */
129 ct
->ct
|= TCG_CT_REG
;
130 ct
->u
.regs
|= 0xffffffffu
;
132 case 'w': /* advsimd registers */
133 ct
->ct
|= TCG_CT_REG
;
134 ct
->u
.regs
|= 0xffffffff00000000ull
;
136 case 'l': /* qemu_ld / qemu_st address, data_reg */
137 ct
->ct
|= TCG_CT_REG
;
138 ct
->u
.regs
= 0xffffffffu
;
139 #ifdef CONFIG_SOFTMMU
140 /* x0 and x1 will be overwritten when reading the tlb entry,
141 and x2, and x3 for helper args, better to avoid using them. */
142 tcg_regset_reset_reg(ct
->u
.regs
, TCG_REG_X0
);
143 tcg_regset_reset_reg(ct
->u
.regs
, TCG_REG_X1
);
144 tcg_regset_reset_reg(ct
->u
.regs
, TCG_REG_X2
);
145 tcg_regset_reset_reg(ct
->u
.regs
, TCG_REG_X3
);
148 case 'A': /* Valid for arithmetic immediate (positive or negative). */
149 ct
->ct
|= TCG_CT_CONST_AIMM
;
151 case 'L': /* Valid for logical immediate. */
152 ct
->ct
|= TCG_CT_CONST_LIMM
;
154 case 'M': /* minus one */
155 ct
->ct
|= TCG_CT_CONST_MONE
;
158 ct
->ct
|= TCG_CT_CONST_ZERO
;
166 /* Match a constant valid for addition (12-bit, optionally shifted). */
167 static inline bool is_aimm(uint64_t val
)
169 return (val
& ~0xfff) == 0 || (val
& ~0xfff000) == 0;
172 /* Match a constant valid for logical operations. */
173 static inline bool is_limm(uint64_t val
)
175 /* Taking a simplified view of the logical immediates for now, ignoring
176 the replication that can happen across the field. Match bit patterns
180 and their inverses. */
182 /* Make things easier below, by testing the form with msb clear. */
183 if ((int64_t)val
< 0) {
190 return (val
& (val
- 1)) == 0;
193 /* Match a constant that is valid for vectors. */
194 static bool is_fimm(uint64_t v64
, int *op
, int *cmode
, int *imm8
)
199 /* Match replication across 8 bits. */
200 if (v64
== dup_const(MO_8
, v64
)) {
205 /* Match replication across 16 bits. */
206 if (v64
== dup_const(MO_16
, v64
)) {
209 if (v16
== (v16
& 0xff)) {
213 } else if (v16
== (v16
& 0xff00)) {
219 /* Match replication across 32 bits. */
220 if (v64
== dup_const(MO_32
, v64
)) {
223 if (v32
== (v32
& 0xff)) {
227 } else if (v32
== (v32
& 0xff00)) {
229 *imm8
= (v32
>> 8) & 0xff;
231 } else if (v32
== (v32
& 0xff0000)) {
233 *imm8
= (v32
>> 16) & 0xff;
235 } else if (v32
== (v32
& 0xff000000)) {
239 } else if ((v32
& 0xffff00ff) == 0xff) {
241 *imm8
= (v32
>> 8) & 0xff;
243 } else if ((v32
& 0xff00ffff) == 0xffff) {
245 *imm8
= (v32
>> 16) & 0xff;
248 /* Match forms of a float32. */
249 if (extract32(v32
, 0, 19) == 0
250 && (extract32(v32
, 25, 6) == 0x20
251 || extract32(v32
, 25, 6) == 0x1f)) {
253 *imm8
= (extract32(v32
, 31, 1) << 7)
254 | (extract32(v32
, 25, 1) << 6)
255 | extract32(v32
, 19, 6);
259 /* Match forms of a float64. */
260 if (extract64(v64
, 0, 48) == 0
261 && (extract64(v64
, 54, 9) == 0x100
262 || extract64(v64
, 54, 9) == 0x0ff)) {
265 *imm8
= (extract64(v64
, 63, 1) << 7)
266 | (extract64(v64
, 54, 1) << 6)
267 | extract64(v64
, 48, 6);
270 /* Match bytes of 0x00 and 0xff. */
271 for (i
= 0; i
< 64; i
+= 8) {
272 uint64_t byte
= extract64(v64
, i
, 8);
273 if (byte
!= 0 && byte
!= 0xff) {
280 *imm8
= (extract64(v64
, 0, 1) << 0)
281 | (extract64(v64
, 8, 1) << 1)
282 | (extract64(v64
, 16, 1) << 2)
283 | (extract64(v64
, 24, 1) << 3)
284 | (extract64(v64
, 32, 1) << 4)
285 | (extract64(v64
, 40, 1) << 5)
286 | (extract64(v64
, 48, 1) << 6)
287 | (extract64(v64
, 56, 1) << 7);
293 static int tcg_target_const_match(tcg_target_long val
, TCGType type
,
294 const TCGArgConstraint
*arg_ct
)
298 if (ct
& TCG_CT_CONST
) {
301 if (type
== TCG_TYPE_I32
) {
304 if ((ct
& TCG_CT_CONST_AIMM
) && (is_aimm(val
) || is_aimm(-val
))) {
307 if ((ct
& TCG_CT_CONST_LIMM
) && is_limm(val
)) {
310 if ((ct
& TCG_CT_CONST_ZERO
) && val
== 0) {
313 if ((ct
& TCG_CT_CONST_MONE
) && val
== -1) {
320 enum aarch64_cond_code
{
323 COND_CS
= 0x2, /* Unsigned greater or equal */
324 COND_HS
= COND_CS
, /* ALIAS greater or equal */
325 COND_CC
= 0x3, /* Unsigned less than */
326 COND_LO
= COND_CC
, /* ALIAS Lower */
327 COND_MI
= 0x4, /* Negative */
328 COND_PL
= 0x5, /* Zero or greater */
329 COND_VS
= 0x6, /* Overflow */
330 COND_VC
= 0x7, /* No overflow */
331 COND_HI
= 0x8, /* Unsigned greater than */
332 COND_LS
= 0x9, /* Unsigned less or equal */
338 COND_NV
= 0xf, /* behaves like COND_AL here */
341 static const enum aarch64_cond_code tcg_cond_to_aarch64
[] = {
342 [TCG_COND_EQ
] = COND_EQ
,
343 [TCG_COND_NE
] = COND_NE
,
344 [TCG_COND_LT
] = COND_LT
,
345 [TCG_COND_GE
] = COND_GE
,
346 [TCG_COND_LE
] = COND_LE
,
347 [TCG_COND_GT
] = COND_GT
,
349 [TCG_COND_LTU
] = COND_LO
,
350 [TCG_COND_GTU
] = COND_HI
,
351 [TCG_COND_GEU
] = COND_HS
,
352 [TCG_COND_LEU
] = COND_LS
,
356 LDST_ST
= 0, /* store */
357 LDST_LD
= 1, /* load */
358 LDST_LD_S_X
= 2, /* load and sign-extend into Xt */
359 LDST_LD_S_W
= 3, /* load and sign-extend into Wt */
362 /* We encode the format of the insn into the beginning of the name, so that
363 we can have the preprocessor help "typecheck" the insn vs the output
364 function. Arm didn't provide us with nice names for the formats, so we
365 use the section number of the architecture reference manual in which the
366 instruction group is described. */
368 /* Compare and branch (immediate). */
369 I3201_CBZ
= 0x34000000,
370 I3201_CBNZ
= 0x35000000,
372 /* Conditional branch (immediate). */
373 I3202_B_C
= 0x54000000,
375 /* Unconditional branch (immediate). */
376 I3206_B
= 0x14000000,
377 I3206_BL
= 0x94000000,
379 /* Unconditional branch (register). */
380 I3207_BR
= 0xd61f0000,
381 I3207_BLR
= 0xd63f0000,
382 I3207_RET
= 0xd65f0000,
384 /* Load literal for loading the address at pc-relative offset */
385 I3305_LDR
= 0x58000000,
386 I3305_LDR_v64
= 0x5c000000,
387 I3305_LDR_v128
= 0x9c000000,
389 /* Load/store register. Described here as 3.3.12, but the helper
390 that emits them can transform to 3.3.10 or 3.3.13. */
391 I3312_STRB
= 0x38000000 | LDST_ST
<< 22 | MO_8
<< 30,
392 I3312_STRH
= 0x38000000 | LDST_ST
<< 22 | MO_16
<< 30,
393 I3312_STRW
= 0x38000000 | LDST_ST
<< 22 | MO_32
<< 30,
394 I3312_STRX
= 0x38000000 | LDST_ST
<< 22 | MO_64
<< 30,
396 I3312_LDRB
= 0x38000000 | LDST_LD
<< 22 | MO_8
<< 30,
397 I3312_LDRH
= 0x38000000 | LDST_LD
<< 22 | MO_16
<< 30,
398 I3312_LDRW
= 0x38000000 | LDST_LD
<< 22 | MO_32
<< 30,
399 I3312_LDRX
= 0x38000000 | LDST_LD
<< 22 | MO_64
<< 30,
401 I3312_LDRSBW
= 0x38000000 | LDST_LD_S_W
<< 22 | MO_8
<< 30,
402 I3312_LDRSHW
= 0x38000000 | LDST_LD_S_W
<< 22 | MO_16
<< 30,
404 I3312_LDRSBX
= 0x38000000 | LDST_LD_S_X
<< 22 | MO_8
<< 30,
405 I3312_LDRSHX
= 0x38000000 | LDST_LD_S_X
<< 22 | MO_16
<< 30,
406 I3312_LDRSWX
= 0x38000000 | LDST_LD_S_X
<< 22 | MO_32
<< 30,
408 I3312_LDRVS
= 0x3c000000 | LDST_LD
<< 22 | MO_32
<< 30,
409 I3312_STRVS
= 0x3c000000 | LDST_ST
<< 22 | MO_32
<< 30,
411 I3312_LDRVD
= 0x3c000000 | LDST_LD
<< 22 | MO_64
<< 30,
412 I3312_STRVD
= 0x3c000000 | LDST_ST
<< 22 | MO_64
<< 30,
414 I3312_LDRVQ
= 0x3c000000 | 3 << 22 | 0 << 30,
415 I3312_STRVQ
= 0x3c000000 | 2 << 22 | 0 << 30,
417 I3312_TO_I3310
= 0x00200800,
418 I3312_TO_I3313
= 0x01000000,
420 /* Load/store register pair instructions. */
421 I3314_LDP
= 0x28400000,
422 I3314_STP
= 0x28000000,
424 /* Add/subtract immediate instructions. */
425 I3401_ADDI
= 0x11000000,
426 I3401_ADDSI
= 0x31000000,
427 I3401_SUBI
= 0x51000000,
428 I3401_SUBSI
= 0x71000000,
430 /* Bitfield instructions. */
431 I3402_BFM
= 0x33000000,
432 I3402_SBFM
= 0x13000000,
433 I3402_UBFM
= 0x53000000,
435 /* Extract instruction. */
436 I3403_EXTR
= 0x13800000,
438 /* Logical immediate instructions. */
439 I3404_ANDI
= 0x12000000,
440 I3404_ORRI
= 0x32000000,
441 I3404_EORI
= 0x52000000,
443 /* Move wide immediate instructions. */
444 I3405_MOVN
= 0x12800000,
445 I3405_MOVZ
= 0x52800000,
446 I3405_MOVK
= 0x72800000,
448 /* PC relative addressing instructions. */
449 I3406_ADR
= 0x10000000,
450 I3406_ADRP
= 0x90000000,
452 /* Add/subtract shifted register instructions (without a shift). */
453 I3502_ADD
= 0x0b000000,
454 I3502_ADDS
= 0x2b000000,
455 I3502_SUB
= 0x4b000000,
456 I3502_SUBS
= 0x6b000000,
458 /* Add/subtract shifted register instructions (with a shift). */
459 I3502S_ADD_LSL
= I3502_ADD
,
461 /* Add/subtract with carry instructions. */
462 I3503_ADC
= 0x1a000000,
463 I3503_SBC
= 0x5a000000,
465 /* Conditional select instructions. */
466 I3506_CSEL
= 0x1a800000,
467 I3506_CSINC
= 0x1a800400,
468 I3506_CSINV
= 0x5a800000,
469 I3506_CSNEG
= 0x5a800400,
471 /* Data-processing (1 source) instructions. */
472 I3507_CLZ
= 0x5ac01000,
473 I3507_RBIT
= 0x5ac00000,
474 I3507_REV16
= 0x5ac00400,
475 I3507_REV32
= 0x5ac00800,
476 I3507_REV64
= 0x5ac00c00,
478 /* Data-processing (2 source) instructions. */
479 I3508_LSLV
= 0x1ac02000,
480 I3508_LSRV
= 0x1ac02400,
481 I3508_ASRV
= 0x1ac02800,
482 I3508_RORV
= 0x1ac02c00,
483 I3508_SMULH
= 0x9b407c00,
484 I3508_UMULH
= 0x9bc07c00,
485 I3508_UDIV
= 0x1ac00800,
486 I3508_SDIV
= 0x1ac00c00,
488 /* Data-processing (3 source) instructions. */
489 I3509_MADD
= 0x1b000000,
490 I3509_MSUB
= 0x1b008000,
492 /* Logical shifted register instructions (without a shift). */
493 I3510_AND
= 0x0a000000,
494 I3510_BIC
= 0x0a200000,
495 I3510_ORR
= 0x2a000000,
496 I3510_ORN
= 0x2a200000,
497 I3510_EOR
= 0x4a000000,
498 I3510_EON
= 0x4a200000,
499 I3510_ANDS
= 0x6a000000,
502 I3605_DUP
= 0x0e000400,
503 I3605_INS
= 0x4e001c00,
504 I3605_UMOV
= 0x0e003c00,
506 /* AdvSIMD modified immediate */
507 I3606_MOVI
= 0x0f000400,
509 /* AdvSIMD shift by immediate */
510 I3614_SSHR
= 0x0f000400,
511 I3614_SSRA
= 0x0f001400,
512 I3614_SHL
= 0x0f005400,
513 I3614_USHR
= 0x2f000400,
514 I3614_USRA
= 0x2f001400,
516 /* AdvSIMD three same. */
517 I3616_ADD
= 0x0e208400,
518 I3616_AND
= 0x0e201c00,
519 I3616_BIC
= 0x0e601c00,
520 I3616_EOR
= 0x2e201c00,
521 I3616_MUL
= 0x0e209c00,
522 I3616_ORR
= 0x0ea01c00,
523 I3616_ORN
= 0x0ee01c00,
524 I3616_SUB
= 0x2e208400,
525 I3616_CMGT
= 0x0e203400,
526 I3616_CMGE
= 0x0e203c00,
527 I3616_CMTST
= 0x0e208c00,
528 I3616_CMHI
= 0x2e203400,
529 I3616_CMHS
= 0x2e203c00,
530 I3616_CMEQ
= 0x2e208c00,
532 /* AdvSIMD two-reg misc. */
533 I3617_CMGT0
= 0x0e208800,
534 I3617_CMEQ0
= 0x0e209800,
535 I3617_CMLT0
= 0x0e20a800,
536 I3617_CMGE0
= 0x2e208800,
537 I3617_CMLE0
= 0x2e20a800,
538 I3617_NOT
= 0x2e205800,
539 I3617_NEG
= 0x2e20b800,
541 /* System instructions. */
543 DMB_ISH
= 0xd50338bf,
548 static inline uint32_t tcg_in32(TCGContext
*s
)
550 uint32_t v
= *(uint32_t *)s
->code_ptr
;
554 /* Emit an opcode with "type-checking" of the format. */
555 #define tcg_out_insn(S, FMT, OP, ...) \
556 glue(tcg_out_insn_,FMT)(S, glue(glue(glue(I,FMT),_),OP), ## __VA_ARGS__)
558 static void tcg_out_insn_3305(TCGContext
*s
, AArch64Insn insn
, int imm19
, TCGReg rt
)
560 tcg_out32(s
, insn
| (imm19
& 0x7ffff) << 5 | rt
);
563 static void tcg_out_insn_3201(TCGContext
*s
, AArch64Insn insn
, TCGType ext
,
564 TCGReg rt
, int imm19
)
566 tcg_out32(s
, insn
| ext
<< 31 | (imm19
& 0x7ffff) << 5 | rt
);
569 static void tcg_out_insn_3202(TCGContext
*s
, AArch64Insn insn
,
570 TCGCond c
, int imm19
)
572 tcg_out32(s
, insn
| tcg_cond_to_aarch64
[c
] | (imm19
& 0x7ffff) << 5);
575 static void tcg_out_insn_3206(TCGContext
*s
, AArch64Insn insn
, int imm26
)
577 tcg_out32(s
, insn
| (imm26
& 0x03ffffff));
580 static void tcg_out_insn_3207(TCGContext
*s
, AArch64Insn insn
, TCGReg rn
)
582 tcg_out32(s
, insn
| rn
<< 5);
585 static void tcg_out_insn_3314(TCGContext
*s
, AArch64Insn insn
,
586 TCGReg r1
, TCGReg r2
, TCGReg rn
,
587 tcg_target_long ofs
, bool pre
, bool w
)
589 insn
|= 1u << 31; /* ext */
593 tcg_debug_assert(ofs
>= -0x200 && ofs
< 0x200 && (ofs
& 7) == 0);
594 insn
|= (ofs
& (0x7f << 3)) << (15 - 3);
596 tcg_out32(s
, insn
| r2
<< 10 | rn
<< 5 | r1
);
599 static void tcg_out_insn_3401(TCGContext
*s
, AArch64Insn insn
, TCGType ext
,
600 TCGReg rd
, TCGReg rn
, uint64_t aimm
)
603 tcg_debug_assert((aimm
& 0xfff) == 0);
605 tcg_debug_assert(aimm
<= 0xfff);
606 aimm
|= 1 << 12; /* apply LSL 12 */
608 tcg_out32(s
, insn
| ext
<< 31 | aimm
<< 10 | rn
<< 5 | rd
);
611 /* This function can be used for both 3.4.2 (Bitfield) and 3.4.4
612 (Logical immediate). Both insn groups have N, IMMR and IMMS fields
613 that feed the DecodeBitMasks pseudo function. */
614 static void tcg_out_insn_3402(TCGContext
*s
, AArch64Insn insn
, TCGType ext
,
615 TCGReg rd
, TCGReg rn
, int n
, int immr
, int imms
)
617 tcg_out32(s
, insn
| ext
<< 31 | n
<< 22 | immr
<< 16 | imms
<< 10
621 #define tcg_out_insn_3404 tcg_out_insn_3402
623 static void tcg_out_insn_3403(TCGContext
*s
, AArch64Insn insn
, TCGType ext
,
624 TCGReg rd
, TCGReg rn
, TCGReg rm
, int imms
)
626 tcg_out32(s
, insn
| ext
<< 31 | ext
<< 22 | rm
<< 16 | imms
<< 10
630 /* This function is used for the Move (wide immediate) instruction group.
631 Note that SHIFT is a full shift count, not the 2 bit HW field. */
632 static void tcg_out_insn_3405(TCGContext
*s
, AArch64Insn insn
, TCGType ext
,
633 TCGReg rd
, uint16_t half
, unsigned shift
)
635 tcg_debug_assert((shift
& ~0x30) == 0);
636 tcg_out32(s
, insn
| ext
<< 31 | shift
<< (21 - 4) | half
<< 5 | rd
);
639 static void tcg_out_insn_3406(TCGContext
*s
, AArch64Insn insn
,
640 TCGReg rd
, int64_t disp
)
642 tcg_out32(s
, insn
| (disp
& 3) << 29 | (disp
& 0x1ffffc) << (5 - 2) | rd
);
645 /* This function is for both 3.5.2 (Add/Subtract shifted register), for
646 the rare occasion when we actually want to supply a shift amount. */
647 static inline void tcg_out_insn_3502S(TCGContext
*s
, AArch64Insn insn
,
648 TCGType ext
, TCGReg rd
, TCGReg rn
,
651 tcg_out32(s
, insn
| ext
<< 31 | rm
<< 16 | imm6
<< 10 | rn
<< 5 | rd
);
654 /* This function is for 3.5.2 (Add/subtract shifted register),
655 and 3.5.10 (Logical shifted register), for the vast majorty of cases
656 when we don't want to apply a shift. Thus it can also be used for
657 3.5.3 (Add/subtract with carry) and 3.5.8 (Data processing 2 source). */
658 static void tcg_out_insn_3502(TCGContext
*s
, AArch64Insn insn
, TCGType ext
,
659 TCGReg rd
, TCGReg rn
, TCGReg rm
)
661 tcg_out32(s
, insn
| ext
<< 31 | rm
<< 16 | rn
<< 5 | rd
);
664 #define tcg_out_insn_3503 tcg_out_insn_3502
665 #define tcg_out_insn_3508 tcg_out_insn_3502
666 #define tcg_out_insn_3510 tcg_out_insn_3502
668 static void tcg_out_insn_3506(TCGContext
*s
, AArch64Insn insn
, TCGType ext
,
669 TCGReg rd
, TCGReg rn
, TCGReg rm
, TCGCond c
)
671 tcg_out32(s
, insn
| ext
<< 31 | rm
<< 16 | rn
<< 5 | rd
672 | tcg_cond_to_aarch64
[c
] << 12);
675 static void tcg_out_insn_3507(TCGContext
*s
, AArch64Insn insn
, TCGType ext
,
676 TCGReg rd
, TCGReg rn
)
678 tcg_out32(s
, insn
| ext
<< 31 | rn
<< 5 | rd
);
681 static void tcg_out_insn_3509(TCGContext
*s
, AArch64Insn insn
, TCGType ext
,
682 TCGReg rd
, TCGReg rn
, TCGReg rm
, TCGReg ra
)
684 tcg_out32(s
, insn
| ext
<< 31 | rm
<< 16 | ra
<< 10 | rn
<< 5 | rd
);
687 static void tcg_out_insn_3605(TCGContext
*s
, AArch64Insn insn
, bool q
,
688 TCGReg rd
, TCGReg rn
, int dst_idx
, int src_idx
)
690 /* Note that bit 11 set means general register input. Therefore
691 we can handle both register sets with one function. */
692 tcg_out32(s
, insn
| q
<< 30 | (dst_idx
<< 16) | (src_idx
<< 11)
693 | (rd
& 0x1f) | (~rn
& 0x20) << 6 | (rn
& 0x1f) << 5);
696 static void tcg_out_insn_3606(TCGContext
*s
, AArch64Insn insn
, bool q
,
697 TCGReg rd
, bool op
, int cmode
, uint8_t imm8
)
699 tcg_out32(s
, insn
| q
<< 30 | op
<< 29 | cmode
<< 12 | (rd
& 0x1f)
700 | (imm8
& 0xe0) << (16 - 5) | (imm8
& 0x1f) << 5);
703 static void tcg_out_insn_3614(TCGContext
*s
, AArch64Insn insn
, bool q
,
704 TCGReg rd
, TCGReg rn
, unsigned immhb
)
706 tcg_out32(s
, insn
| q
<< 30 | immhb
<< 16
707 | (rn
& 0x1f) << 5 | (rd
& 0x1f));
710 static void tcg_out_insn_3616(TCGContext
*s
, AArch64Insn insn
, bool q
,
711 unsigned size
, TCGReg rd
, TCGReg rn
, TCGReg rm
)
713 tcg_out32(s
, insn
| q
<< 30 | (size
<< 22) | (rm
& 0x1f) << 16
714 | (rn
& 0x1f) << 5 | (rd
& 0x1f));
717 static void tcg_out_insn_3617(TCGContext
*s
, AArch64Insn insn
, bool q
,
718 unsigned size
, TCGReg rd
, TCGReg rn
)
720 tcg_out32(s
, insn
| q
<< 30 | (size
<< 22)
721 | (rn
& 0x1f) << 5 | (rd
& 0x1f));
724 static void tcg_out_insn_3310(TCGContext
*s
, AArch64Insn insn
,
725 TCGReg rd
, TCGReg base
, TCGType ext
,
728 /* Note the AArch64Insn constants above are for C3.3.12. Adjust. */
729 tcg_out32(s
, insn
| I3312_TO_I3310
| regoff
<< 16 |
730 0x4000 | ext
<< 13 | base
<< 5 | (rd
& 0x1f));
733 static void tcg_out_insn_3312(TCGContext
*s
, AArch64Insn insn
,
734 TCGReg rd
, TCGReg rn
, intptr_t offset
)
736 tcg_out32(s
, insn
| (offset
& 0x1ff) << 12 | rn
<< 5 | (rd
& 0x1f));
739 static void tcg_out_insn_3313(TCGContext
*s
, AArch64Insn insn
,
740 TCGReg rd
, TCGReg rn
, uintptr_t scaled_uimm
)
742 /* Note the AArch64Insn constants above are for C3.3.12. Adjust. */
743 tcg_out32(s
, insn
| I3312_TO_I3313
| scaled_uimm
<< 10
744 | rn
<< 5 | (rd
& 0x1f));
747 /* Register to register move using ORR (shifted register with no shift). */
748 static void tcg_out_movr(TCGContext
*s
, TCGType ext
, TCGReg rd
, TCGReg rm
)
750 tcg_out_insn(s
, 3510, ORR
, ext
, rd
, TCG_REG_XZR
, rm
);
753 /* Register to register move using ADDI (move to/from SP). */
754 static void tcg_out_movr_sp(TCGContext
*s
, TCGType ext
, TCGReg rd
, TCGReg rn
)
756 tcg_out_insn(s
, 3401, ADDI
, ext
, rd
, rn
, 0);
759 /* This function is used for the Logical (immediate) instruction group.
760 The value of LIMM must satisfy IS_LIMM. See the comment above about
761 only supporting simplified logical immediates. */
762 static void tcg_out_logicali(TCGContext
*s
, AArch64Insn insn
, TCGType ext
,
763 TCGReg rd
, TCGReg rn
, uint64_t limm
)
767 tcg_debug_assert(is_limm(limm
));
772 r
= 0; /* form 0....01....1 */
773 c
= ctz64(~limm
) - 1;
775 r
= clz64(~limm
); /* form 1..10..01..1 */
779 r
= 64 - l
; /* form 1....10....0 or 0..01..10..0 */
782 if (ext
== TCG_TYPE_I32
) {
787 tcg_out_insn_3404(s
, insn
, ext
, rd
, rn
, ext
, r
, c
);
790 static void tcg_out_dupi_vec(TCGContext
*s
, TCGType type
,
791 TCGReg rd
, uint64_t v64
)
795 if (is_fimm(v64
, &op
, &cmode
, &imm8
)) {
796 tcg_out_insn(s
, 3606, MOVI
, type
== TCG_TYPE_V128
, rd
, op
, cmode
, imm8
);
797 } else if (type
== TCG_TYPE_V128
) {
798 new_pool_l2(s
, R_AARCH64_CONDBR19
, s
->code_ptr
, 0, v64
, v64
);
799 tcg_out_insn(s
, 3305, LDR_v128
, 0, rd
);
801 new_pool_label(s
, v64
, R_AARCH64_CONDBR19
, s
->code_ptr
, 0);
802 tcg_out_insn(s
, 3305, LDR_v64
, 0, rd
);
806 static void tcg_out_movi(TCGContext
*s
, TCGType type
, TCGReg rd
,
807 tcg_target_long value
)
809 tcg_target_long svalue
= value
;
810 tcg_target_long ivalue
= ~value
;
811 tcg_target_long t0
, t1
, t2
;
818 tcg_debug_assert(rd
< 32);
823 tcg_debug_assert(rd
>= 32);
824 tcg_out_dupi_vec(s
, type
, rd
, value
);
828 g_assert_not_reached();
831 /* For 32-bit values, discard potential garbage in value. For 64-bit
832 values within [2**31, 2**32-1], we can create smaller sequences by
833 interpreting this as a negative 32-bit number, while ensuring that
834 the high 32 bits are cleared by setting SF=0. */
835 if (type
== TCG_TYPE_I32
|| (value
& ~0xffffffffull
) == 0) {
836 svalue
= (int32_t)value
;
837 value
= (uint32_t)value
;
838 ivalue
= (uint32_t)ivalue
;
842 /* Speed things up by handling the common case of small positive
843 and negative values specially. */
844 if ((value
& ~0xffffull
) == 0) {
845 tcg_out_insn(s
, 3405, MOVZ
, type
, rd
, value
, 0);
847 } else if ((ivalue
& ~0xffffull
) == 0) {
848 tcg_out_insn(s
, 3405, MOVN
, type
, rd
, ivalue
, 0);
852 /* Check for bitfield immediates. For the benefit of 32-bit quantities,
853 use the sign-extended value. That lets us match rotated values such
854 as 0xff0000ff with the same 64-bit logic matching 0xffffffffff0000ff. */
855 if (is_limm(svalue
)) {
856 tcg_out_logicali(s
, I3404_ORRI
, type
, rd
, TCG_REG_XZR
, svalue
);
860 /* Look for host pointer values within 4G of the PC. This happens
861 often when loading pointers to QEMU's own data structures. */
862 if (type
== TCG_TYPE_I64
) {
863 tcg_target_long disp
= value
- (intptr_t)s
->code_ptr
;
864 if (disp
== sextract64(disp
, 0, 21)) {
865 tcg_out_insn(s
, 3406, ADR
, rd
, disp
);
868 disp
= (value
>> 12) - ((intptr_t)s
->code_ptr
>> 12);
869 if (disp
== sextract64(disp
, 0, 21)) {
870 tcg_out_insn(s
, 3406, ADRP
, rd
, disp
);
872 tcg_out_insn(s
, 3401, ADDI
, type
, rd
, rd
, value
& 0xfff);
878 /* Would it take fewer insns to begin with MOVN? */
879 if (ctpop64(value
) >= 32) {
886 s0
= ctz64(t0
) & (63 & -16);
887 t1
= t0
& ~(0xffffUL
<< s0
);
888 s1
= ctz64(t1
) & (63 & -16);
889 t2
= t1
& ~(0xffffUL
<< s1
);
891 tcg_out_insn_3405(s
, opc
, type
, rd
, t0
>> s0
, s0
);
893 tcg_out_insn(s
, 3405, MOVK
, type
, rd
, value
>> s1
, s1
);
898 /* For more than 2 insns, dump it into the constant pool. */
899 new_pool_label(s
, value
, R_AARCH64_CONDBR19
, s
->code_ptr
, 0);
900 tcg_out_insn(s
, 3305, LDR
, 0, rd
);
903 /* Define something more legible for general use. */
904 #define tcg_out_ldst_r tcg_out_insn_3310
906 static void tcg_out_ldst(TCGContext
*s
, AArch64Insn insn
, TCGReg rd
,
907 TCGReg rn
, intptr_t offset
, int lgsize
)
909 /* If the offset is naturally aligned and in range, then we can
910 use the scaled uimm12 encoding */
911 if (offset
>= 0 && !(offset
& ((1 << lgsize
) - 1))) {
912 uintptr_t scaled_uimm
= offset
>> lgsize
;
913 if (scaled_uimm
<= 0xfff) {
914 tcg_out_insn_3313(s
, insn
, rd
, rn
, scaled_uimm
);
919 /* Small signed offsets can use the unscaled encoding. */
920 if (offset
>= -256 && offset
< 256) {
921 tcg_out_insn_3312(s
, insn
, rd
, rn
, offset
);
925 /* Worst-case scenario, move offset to temp register, use reg offset. */
926 tcg_out_movi(s
, TCG_TYPE_I64
, TCG_REG_TMP
, offset
);
927 tcg_out_ldst_r(s
, insn
, rd
, rn
, TCG_TYPE_I64
, TCG_REG_TMP
);
930 static void tcg_out_mov(TCGContext
*s
, TCGType type
, TCGReg ret
, TCGReg arg
)
938 if (ret
< 32 && arg
< 32) {
939 tcg_out_movr(s
, type
, ret
, arg
);
941 } else if (ret
< 32) {
942 tcg_out_insn(s
, 3605, UMOV
, type
, ret
, arg
, 0, 0);
944 } else if (arg
< 32) {
945 tcg_out_insn(s
, 3605, INS
, 0, ret
, arg
, 4 << type
, 0);
951 tcg_debug_assert(ret
>= 32 && arg
>= 32);
952 tcg_out_insn(s
, 3616, ORR
, 0, 0, ret
, arg
, arg
);
955 tcg_debug_assert(ret
>= 32 && arg
>= 32);
956 tcg_out_insn(s
, 3616, ORR
, 1, 0, ret
, arg
, arg
);
960 g_assert_not_reached();
964 static void tcg_out_ld(TCGContext
*s
, TCGType type
, TCGReg ret
,
965 TCGReg base
, intptr_t ofs
)
972 insn
= (ret
< 32 ? I3312_LDRW
: I3312_LDRVS
);
976 insn
= (ret
< 32 ? I3312_LDRX
: I3312_LDRVD
);
988 g_assert_not_reached();
990 tcg_out_ldst(s
, insn
, ret
, base
, ofs
, lgsz
);
993 static void tcg_out_st(TCGContext
*s
, TCGType type
, TCGReg src
,
994 TCGReg base
, intptr_t ofs
)
1001 insn
= (src
< 32 ? I3312_STRW
: I3312_STRVS
);
1005 insn
= (src
< 32 ? I3312_STRX
: I3312_STRVD
);
1017 g_assert_not_reached();
1019 tcg_out_ldst(s
, insn
, src
, base
, ofs
, lgsz
);
1022 static inline bool tcg_out_sti(TCGContext
*s
, TCGType type
, TCGArg val
,
1023 TCGReg base
, intptr_t ofs
)
1025 if (type
<= TCG_TYPE_I64
&& val
== 0) {
1026 tcg_out_st(s
, type
, TCG_REG_XZR
, base
, ofs
);
1032 static inline void tcg_out_bfm(TCGContext
*s
, TCGType ext
, TCGReg rd
,
1033 TCGReg rn
, unsigned int a
, unsigned int b
)
1035 tcg_out_insn(s
, 3402, BFM
, ext
, rd
, rn
, ext
, a
, b
);
1038 static inline void tcg_out_ubfm(TCGContext
*s
, TCGType ext
, TCGReg rd
,
1039 TCGReg rn
, unsigned int a
, unsigned int b
)
1041 tcg_out_insn(s
, 3402, UBFM
, ext
, rd
, rn
, ext
, a
, b
);
1044 static inline void tcg_out_sbfm(TCGContext
*s
, TCGType ext
, TCGReg rd
,
1045 TCGReg rn
, unsigned int a
, unsigned int b
)
1047 tcg_out_insn(s
, 3402, SBFM
, ext
, rd
, rn
, ext
, a
, b
);
1050 static inline void tcg_out_extr(TCGContext
*s
, TCGType ext
, TCGReg rd
,
1051 TCGReg rn
, TCGReg rm
, unsigned int a
)
1053 tcg_out_insn(s
, 3403, EXTR
, ext
, rd
, rn
, rm
, a
);
1056 static inline void tcg_out_shl(TCGContext
*s
, TCGType ext
,
1057 TCGReg rd
, TCGReg rn
, unsigned int m
)
1059 int bits
= ext
? 64 : 32;
1061 tcg_out_ubfm(s
, ext
, rd
, rn
, bits
- (m
& max
), max
- (m
& max
));
1064 static inline void tcg_out_shr(TCGContext
*s
, TCGType ext
,
1065 TCGReg rd
, TCGReg rn
, unsigned int m
)
1067 int max
= ext
? 63 : 31;
1068 tcg_out_ubfm(s
, ext
, rd
, rn
, m
& max
, max
);
1071 static inline void tcg_out_sar(TCGContext
*s
, TCGType ext
,
1072 TCGReg rd
, TCGReg rn
, unsigned int m
)
1074 int max
= ext
? 63 : 31;
1075 tcg_out_sbfm(s
, ext
, rd
, rn
, m
& max
, max
);
1078 static inline void tcg_out_rotr(TCGContext
*s
, TCGType ext
,
1079 TCGReg rd
, TCGReg rn
, unsigned int m
)
1081 int max
= ext
? 63 : 31;
1082 tcg_out_extr(s
, ext
, rd
, rn
, rn
, m
& max
);
1085 static inline void tcg_out_rotl(TCGContext
*s
, TCGType ext
,
1086 TCGReg rd
, TCGReg rn
, unsigned int m
)
1088 int bits
= ext
? 64 : 32;
1090 tcg_out_extr(s
, ext
, rd
, rn
, rn
, bits
- (m
& max
));
1093 static inline void tcg_out_dep(TCGContext
*s
, TCGType ext
, TCGReg rd
,
1094 TCGReg rn
, unsigned lsb
, unsigned width
)
1096 unsigned size
= ext
? 64 : 32;
1097 unsigned a
= (size
- lsb
) & (size
- 1);
1098 unsigned b
= width
- 1;
1099 tcg_out_bfm(s
, ext
, rd
, rn
, a
, b
);
1102 static void tcg_out_cmp(TCGContext
*s
, TCGType ext
, TCGReg a
,
1103 tcg_target_long b
, bool const_b
)
1106 /* Using CMP or CMN aliases. */
1108 tcg_out_insn(s
, 3401, SUBSI
, ext
, TCG_REG_XZR
, a
, b
);
1110 tcg_out_insn(s
, 3401, ADDSI
, ext
, TCG_REG_XZR
, a
, -b
);
1113 /* Using CMP alias SUBS wzr, Wn, Wm */
1114 tcg_out_insn(s
, 3502, SUBS
, ext
, TCG_REG_XZR
, a
, b
);
1118 static inline void tcg_out_goto(TCGContext
*s
, tcg_insn_unit
*target
)
1120 ptrdiff_t offset
= target
- s
->code_ptr
;
1121 tcg_debug_assert(offset
== sextract64(offset
, 0, 26));
1122 tcg_out_insn(s
, 3206, B
, offset
);
1125 static inline void tcg_out_goto_long(TCGContext
*s
, tcg_insn_unit
*target
)
1127 ptrdiff_t offset
= target
- s
->code_ptr
;
1128 if (offset
== sextract64(offset
, 0, 26)) {
1129 tcg_out_insn(s
, 3206, BL
, offset
);
1131 tcg_out_movi(s
, TCG_TYPE_I64
, TCG_REG_TMP
, (intptr_t)target
);
1132 tcg_out_insn(s
, 3207, BR
, TCG_REG_TMP
);
1136 static inline void tcg_out_callr(TCGContext
*s
, TCGReg reg
)
1138 tcg_out_insn(s
, 3207, BLR
, reg
);
1141 static inline void tcg_out_call(TCGContext
*s
, tcg_insn_unit
*target
)
1143 ptrdiff_t offset
= target
- s
->code_ptr
;
1144 if (offset
== sextract64(offset
, 0, 26)) {
1145 tcg_out_insn(s
, 3206, BL
, offset
);
1147 tcg_out_movi(s
, TCG_TYPE_I64
, TCG_REG_TMP
, (intptr_t)target
);
1148 tcg_out_callr(s
, TCG_REG_TMP
);
1152 void tb_target_set_jmp_target(uintptr_t tc_ptr
, uintptr_t jmp_addr
,
1155 tcg_insn_unit i1
, i2
;
1156 TCGType rt
= TCG_TYPE_I64
;
1157 TCGReg rd
= TCG_REG_TMP
;
1160 ptrdiff_t offset
= addr
- jmp_addr
;
1162 if (offset
== sextract64(offset
, 0, 26)) {
1163 i1
= I3206_B
| ((offset
>> 2) & 0x3ffffff);
1166 offset
= (addr
>> 12) - (jmp_addr
>> 12);
1169 i1
= I3406_ADRP
| (offset
& 3) << 29 | (offset
& 0x1ffffc) << (5 - 2) | rd
;
1171 i2
= I3401_ADDI
| rt
<< 31 | (addr
& 0xfff) << 10 | rd
<< 5 | rd
;
1173 pair
= (uint64_t)i2
<< 32 | i1
;
1174 atomic_set((uint64_t *)jmp_addr
, pair
);
1175 flush_icache_range(jmp_addr
, jmp_addr
+ 8);
1178 static inline void tcg_out_goto_label(TCGContext
*s
, TCGLabel
*l
)
1180 if (!l
->has_value
) {
1181 tcg_out_reloc(s
, s
->code_ptr
, R_AARCH64_JUMP26
, l
, 0);
1182 tcg_out_insn(s
, 3206, B
, 0);
1184 tcg_out_goto(s
, l
->u
.value_ptr
);
1188 static void tcg_out_brcond(TCGContext
*s
, TCGType ext
, TCGCond c
, TCGArg a
,
1189 TCGArg b
, bool b_const
, TCGLabel
*l
)
1194 if (b_const
&& b
== 0 && (c
== TCG_COND_EQ
|| c
== TCG_COND_NE
)) {
1198 tcg_out_cmp(s
, ext
, a
, b
, b_const
);
1201 if (!l
->has_value
) {
1202 tcg_out_reloc(s
, s
->code_ptr
, R_AARCH64_CONDBR19
, l
, 0);
1203 offset
= tcg_in32(s
) >> 5;
1205 offset
= l
->u
.value_ptr
- s
->code_ptr
;
1206 tcg_debug_assert(offset
== sextract64(offset
, 0, 19));
1210 tcg_out_insn(s
, 3202, B_C
, c
, offset
);
1211 } else if (c
== TCG_COND_EQ
) {
1212 tcg_out_insn(s
, 3201, CBZ
, ext
, a
, offset
);
1214 tcg_out_insn(s
, 3201, CBNZ
, ext
, a
, offset
);
1218 static inline void tcg_out_rev64(TCGContext
*s
, TCGReg rd
, TCGReg rn
)
1220 tcg_out_insn(s
, 3507, REV64
, TCG_TYPE_I64
, rd
, rn
);
1223 static inline void tcg_out_rev32(TCGContext
*s
, TCGReg rd
, TCGReg rn
)
1225 tcg_out_insn(s
, 3507, REV32
, TCG_TYPE_I32
, rd
, rn
);
1228 static inline void tcg_out_rev16(TCGContext
*s
, TCGReg rd
, TCGReg rn
)
1230 tcg_out_insn(s
, 3507, REV16
, TCG_TYPE_I32
, rd
, rn
);
1233 static inline void tcg_out_sxt(TCGContext
*s
, TCGType ext
, TCGMemOp s_bits
,
1234 TCGReg rd
, TCGReg rn
)
1236 /* Using ALIASes SXTB, SXTH, SXTW, of SBFM Xd, Xn, #0, #7|15|31 */
1237 int bits
= (8 << s_bits
) - 1;
1238 tcg_out_sbfm(s
, ext
, rd
, rn
, 0, bits
);
1241 static inline void tcg_out_uxt(TCGContext
*s
, TCGMemOp s_bits
,
1242 TCGReg rd
, TCGReg rn
)
1244 /* Using ALIASes UXTB, UXTH of UBFM Wd, Wn, #0, #7|15 */
1245 int bits
= (8 << s_bits
) - 1;
1246 tcg_out_ubfm(s
, 0, rd
, rn
, 0, bits
);
1249 static void tcg_out_addsubi(TCGContext
*s
, int ext
, TCGReg rd
,
1250 TCGReg rn
, int64_t aimm
)
1253 tcg_out_insn(s
, 3401, ADDI
, ext
, rd
, rn
, aimm
);
1255 tcg_out_insn(s
, 3401, SUBI
, ext
, rd
, rn
, -aimm
);
1259 static inline void tcg_out_addsub2(TCGContext
*s
, TCGType ext
, TCGReg rl
,
1260 TCGReg rh
, TCGReg al
, TCGReg ah
,
1261 tcg_target_long bl
, tcg_target_long bh
,
1262 bool const_bl
, bool const_bh
, bool sub
)
1264 TCGReg orig_rl
= rl
;
1267 if (rl
== ah
|| (!const_bh
&& rl
== bh
)) {
1273 if ((bl
< 0) ^ sub
) {
1277 if (unlikely(al
== TCG_REG_XZR
)) {
1278 /* ??? We want to allow al to be zero for the benefit of
1279 negation via subtraction. However, that leaves open the
1280 possibility of adding 0+const in the low part, and the
1281 immediate add instructions encode XSP not XZR. Don't try
1282 anything more elaborate here than loading another zero. */
1284 tcg_out_movi(s
, ext
, al
, 0);
1286 tcg_out_insn_3401(s
, insn
, ext
, rl
, al
, bl
);
1288 tcg_out_insn_3502(s
, sub
? I3502_SUBS
: I3502_ADDS
, ext
, rl
, al
, bl
);
1293 /* Note that the only two constants we support are 0 and -1, and
1294 that SBC = rn + ~rm + c, so adc -1 is sbc 0, and vice-versa. */
1295 if ((bh
!= 0) ^ sub
) {
1302 tcg_out_insn_3503(s
, insn
, ext
, rh
, ah
, bh
);
1304 tcg_out_mov(s
, ext
, orig_rl
, rl
);
1307 static inline void tcg_out_mb(TCGContext
*s
, TCGArg a0
)
1309 static const uint32_t sync
[] = {
1310 [0 ... TCG_MO_ALL
] = DMB_ISH
| DMB_LD
| DMB_ST
,
1311 [TCG_MO_ST_ST
] = DMB_ISH
| DMB_ST
,
1312 [TCG_MO_LD_LD
] = DMB_ISH
| DMB_LD
,
1313 [TCG_MO_LD_ST
] = DMB_ISH
| DMB_LD
,
1314 [TCG_MO_LD_ST
| TCG_MO_LD_LD
] = DMB_ISH
| DMB_LD
,
1316 tcg_out32(s
, sync
[a0
& TCG_MO_ALL
]);
1319 static void tcg_out_cltz(TCGContext
*s
, TCGType ext
, TCGReg d
,
1320 TCGReg a0
, TCGArg b
, bool const_b
, bool is_ctz
)
1325 tcg_out_insn(s
, 3507, RBIT
, ext
, a1
, a0
);
1327 if (const_b
&& b
== (ext
? 64 : 32)) {
1328 tcg_out_insn(s
, 3507, CLZ
, ext
, d
, a1
);
1330 AArch64Insn sel
= I3506_CSEL
;
1332 tcg_out_cmp(s
, ext
, a0
, 0, 1);
1333 tcg_out_insn(s
, 3507, CLZ
, ext
, TCG_REG_TMP
, a1
);
1339 } else if (b
== 0) {
1342 tcg_out_movi(s
, ext
, d
, b
);
1346 tcg_out_insn_3506(s
, sel
, ext
, d
, TCG_REG_TMP
, b
, TCG_COND_NE
);
1350 #ifdef CONFIG_SOFTMMU
1351 #include "tcg-ldst.inc.c"
1353 /* helper signature: helper_ret_ld_mmu(CPUState *env, target_ulong addr,
1354 * TCGMemOpIdx oi, uintptr_t ra)
1356 static void * const qemu_ld_helpers
[16] = {
1357 [MO_UB
] = helper_ret_ldub_mmu
,
1358 [MO_LEUW
] = helper_le_lduw_mmu
,
1359 [MO_LEUL
] = helper_le_ldul_mmu
,
1360 [MO_LEQ
] = helper_le_ldq_mmu
,
1361 [MO_BEUW
] = helper_be_lduw_mmu
,
1362 [MO_BEUL
] = helper_be_ldul_mmu
,
1363 [MO_BEQ
] = helper_be_ldq_mmu
,
1366 /* helper signature: helper_ret_st_mmu(CPUState *env, target_ulong addr,
1367 * uintxx_t val, TCGMemOpIdx oi,
1370 static void * const qemu_st_helpers
[16] = {
1371 [MO_UB
] = helper_ret_stb_mmu
,
1372 [MO_LEUW
] = helper_le_stw_mmu
,
1373 [MO_LEUL
] = helper_le_stl_mmu
,
1374 [MO_LEQ
] = helper_le_stq_mmu
,
1375 [MO_BEUW
] = helper_be_stw_mmu
,
1376 [MO_BEUL
] = helper_be_stl_mmu
,
1377 [MO_BEQ
] = helper_be_stq_mmu
,
1380 static inline void tcg_out_adr(TCGContext
*s
, TCGReg rd
, void *target
)
1382 ptrdiff_t offset
= tcg_pcrel_diff(s
, target
);
1383 tcg_debug_assert(offset
== sextract64(offset
, 0, 21));
1384 tcg_out_insn(s
, 3406, ADR
, rd
, offset
);
1387 static void tcg_out_qemu_ld_slow_path(TCGContext
*s
, TCGLabelQemuLdst
*lb
)
1389 TCGMemOpIdx oi
= lb
->oi
;
1390 TCGMemOp opc
= get_memop(oi
);
1391 TCGMemOp size
= opc
& MO_SIZE
;
1393 bool ok
= reloc_pc19(lb
->label_ptr
[0], s
->code_ptr
);
1394 tcg_debug_assert(ok
);
1396 tcg_out_mov(s
, TCG_TYPE_PTR
, TCG_REG_X0
, TCG_AREG0
);
1397 tcg_out_mov(s
, TARGET_LONG_BITS
== 64, TCG_REG_X1
, lb
->addrlo_reg
);
1398 tcg_out_movi(s
, TCG_TYPE_I32
, TCG_REG_X2
, oi
);
1399 tcg_out_adr(s
, TCG_REG_X3
, lb
->raddr
);
1400 tcg_out_call(s
, qemu_ld_helpers
[opc
& (MO_BSWAP
| MO_SIZE
)]);
1401 if (opc
& MO_SIGN
) {
1402 tcg_out_sxt(s
, lb
->type
, size
, lb
->datalo_reg
, TCG_REG_X0
);
1404 tcg_out_mov(s
, size
== MO_64
, lb
->datalo_reg
, TCG_REG_X0
);
1407 tcg_out_goto(s
, lb
->raddr
);
1410 static void tcg_out_qemu_st_slow_path(TCGContext
*s
, TCGLabelQemuLdst
*lb
)
1412 TCGMemOpIdx oi
= lb
->oi
;
1413 TCGMemOp opc
= get_memop(oi
);
1414 TCGMemOp size
= opc
& MO_SIZE
;
1416 bool ok
= reloc_pc19(lb
->label_ptr
[0], s
->code_ptr
);
1417 tcg_debug_assert(ok
);
1419 tcg_out_mov(s
, TCG_TYPE_PTR
, TCG_REG_X0
, TCG_AREG0
);
1420 tcg_out_mov(s
, TARGET_LONG_BITS
== 64, TCG_REG_X1
, lb
->addrlo_reg
);
1421 tcg_out_mov(s
, size
== MO_64
, TCG_REG_X2
, lb
->datalo_reg
);
1422 tcg_out_movi(s
, TCG_TYPE_I32
, TCG_REG_X3
, oi
);
1423 tcg_out_adr(s
, TCG_REG_X4
, lb
->raddr
);
1424 tcg_out_call(s
, qemu_st_helpers
[opc
& (MO_BSWAP
| MO_SIZE
)]);
1425 tcg_out_goto(s
, lb
->raddr
);
1428 static void add_qemu_ldst_label(TCGContext
*s
, bool is_ld
, TCGMemOpIdx oi
,
1429 TCGType ext
, TCGReg data_reg
, TCGReg addr_reg
,
1430 tcg_insn_unit
*raddr
, tcg_insn_unit
*label_ptr
)
1432 TCGLabelQemuLdst
*label
= new_ldst_label(s
);
1434 label
->is_ld
= is_ld
;
1437 label
->datalo_reg
= data_reg
;
1438 label
->addrlo_reg
= addr_reg
;
1439 label
->raddr
= raddr
;
1440 label
->label_ptr
[0] = label_ptr
;
1443 /* Load and compare a TLB entry, emitting the conditional jump to the
1444 slow path for the failure case, which will be patched later when finalizing
1445 the slow path. Generated code returns the host addend in X1,
1446 clobbers X0,X2,X3,TMP. */
1447 static void tcg_out_tlb_read(TCGContext
*s
, TCGReg addr_reg
, TCGMemOp opc
,
1448 tcg_insn_unit
**label_ptr
, int mem_index
,
1451 int tlb_offset
= is_read
?
1452 offsetof(CPUArchState
, tlb_table
[mem_index
][0].addr_read
)
1453 : offsetof(CPUArchState
, tlb_table
[mem_index
][0].addr_write
);
1454 unsigned a_bits
= get_alignment_bits(opc
);
1455 unsigned s_bits
= opc
& MO_SIZE
;
1456 unsigned a_mask
= (1u << a_bits
) - 1;
1457 unsigned s_mask
= (1u << s_bits
) - 1;
1458 TCGReg base
= TCG_AREG0
, x3
;
1461 /* For aligned accesses, we check the first byte and include the alignment
1462 bits within the address. For unaligned access, we check that we don't
1463 cross pages using the address of the last byte of the access. */
1464 if (a_bits
>= s_bits
) {
1467 tcg_out_insn(s
, 3401, ADDI
, TARGET_LONG_BITS
== 64,
1468 TCG_REG_X3
, addr_reg
, s_mask
- a_mask
);
1471 tlb_mask
= (uint64_t)TARGET_PAGE_MASK
| a_mask
;
1473 /* Extract the TLB index from the address into X0.
1474 X0<CPU_TLB_BITS:0> =
1475 addr_reg<TARGET_PAGE_BITS+CPU_TLB_BITS:TARGET_PAGE_BITS> */
1476 tcg_out_ubfm(s
, TARGET_LONG_BITS
== 64, TCG_REG_X0
, addr_reg
,
1477 TARGET_PAGE_BITS
, TARGET_PAGE_BITS
+ CPU_TLB_BITS
);
1479 /* Store the page mask part of the address into X3. */
1480 tcg_out_logicali(s
, I3404_ANDI
, TARGET_LONG_BITS
== 64,
1481 TCG_REG_X3
, x3
, tlb_mask
);
1483 /* Add any "high bits" from the tlb offset to the env address into X2,
1484 to take advantage of the LSL12 form of the ADDI instruction.
1485 X2 = env + (tlb_offset & 0xfff000) */
1486 if (tlb_offset
& 0xfff000) {
1487 tcg_out_insn(s
, 3401, ADDI
, TCG_TYPE_I64
, TCG_REG_X2
, base
,
1488 tlb_offset
& 0xfff000);
1492 /* Merge the tlb index contribution into X2.
1493 X2 = X2 + (X0 << CPU_TLB_ENTRY_BITS) */
1494 tcg_out_insn(s
, 3502S
, ADD_LSL
, TCG_TYPE_I64
, TCG_REG_X2
, base
,
1495 TCG_REG_X0
, CPU_TLB_ENTRY_BITS
);
1497 /* Merge "low bits" from tlb offset, load the tlb comparator into X0.
1498 X0 = load [X2 + (tlb_offset & 0x000fff)] */
1499 tcg_out_ldst(s
, TARGET_LONG_BITS
== 32 ? I3312_LDRW
: I3312_LDRX
,
1500 TCG_REG_X0
, TCG_REG_X2
, tlb_offset
& 0xfff,
1501 TARGET_LONG_BITS
== 32 ? 2 : 3);
1503 /* Load the tlb addend. Do that early to avoid stalling.
1504 X1 = load [X2 + (tlb_offset & 0xfff) + offsetof(addend)] */
1505 tcg_out_ldst(s
, I3312_LDRX
, TCG_REG_X1
, TCG_REG_X2
,
1506 (tlb_offset
& 0xfff) + (offsetof(CPUTLBEntry
, addend
)) -
1507 (is_read
? offsetof(CPUTLBEntry
, addr_read
)
1508 : offsetof(CPUTLBEntry
, addr_write
)), 3);
1510 /* Perform the address comparison. */
1511 tcg_out_cmp(s
, (TARGET_LONG_BITS
== 64), TCG_REG_X0
, TCG_REG_X3
, 0);
1513 /* If not equal, we jump to the slow path. */
1514 *label_ptr
= s
->code_ptr
;
1515 tcg_out_insn(s
, 3202, B_C
, TCG_COND_NE
, 0);
1518 #endif /* CONFIG_SOFTMMU */
1520 static void tcg_out_qemu_ld_direct(TCGContext
*s
, TCGMemOp memop
, TCGType ext
,
1521 TCGReg data_r
, TCGReg addr_r
,
1522 TCGType otype
, TCGReg off_r
)
1524 const TCGMemOp bswap
= memop
& MO_BSWAP
;
1526 switch (memop
& MO_SSIZE
) {
1528 tcg_out_ldst_r(s
, I3312_LDRB
, data_r
, addr_r
, otype
, off_r
);
1531 tcg_out_ldst_r(s
, ext
? I3312_LDRSBX
: I3312_LDRSBW
,
1532 data_r
, addr_r
, otype
, off_r
);
1535 tcg_out_ldst_r(s
, I3312_LDRH
, data_r
, addr_r
, otype
, off_r
);
1537 tcg_out_rev16(s
, data_r
, data_r
);
1542 tcg_out_ldst_r(s
, I3312_LDRH
, data_r
, addr_r
, otype
, off_r
);
1543 tcg_out_rev16(s
, data_r
, data_r
);
1544 tcg_out_sxt(s
, ext
, MO_16
, data_r
, data_r
);
1546 tcg_out_ldst_r(s
, (ext
? I3312_LDRSHX
: I3312_LDRSHW
),
1547 data_r
, addr_r
, otype
, off_r
);
1551 tcg_out_ldst_r(s
, I3312_LDRW
, data_r
, addr_r
, otype
, off_r
);
1553 tcg_out_rev32(s
, data_r
, data_r
);
1558 tcg_out_ldst_r(s
, I3312_LDRW
, data_r
, addr_r
, otype
, off_r
);
1559 tcg_out_rev32(s
, data_r
, data_r
);
1560 tcg_out_sxt(s
, TCG_TYPE_I64
, MO_32
, data_r
, data_r
);
1562 tcg_out_ldst_r(s
, I3312_LDRSWX
, data_r
, addr_r
, otype
, off_r
);
1566 tcg_out_ldst_r(s
, I3312_LDRX
, data_r
, addr_r
, otype
, off_r
);
1568 tcg_out_rev64(s
, data_r
, data_r
);
1576 static void tcg_out_qemu_st_direct(TCGContext
*s
, TCGMemOp memop
,
1577 TCGReg data_r
, TCGReg addr_r
,
1578 TCGType otype
, TCGReg off_r
)
1580 const TCGMemOp bswap
= memop
& MO_BSWAP
;
1582 switch (memop
& MO_SIZE
) {
1584 tcg_out_ldst_r(s
, I3312_STRB
, data_r
, addr_r
, otype
, off_r
);
1587 if (bswap
&& data_r
!= TCG_REG_XZR
) {
1588 tcg_out_rev16(s
, TCG_REG_TMP
, data_r
);
1589 data_r
= TCG_REG_TMP
;
1591 tcg_out_ldst_r(s
, I3312_STRH
, data_r
, addr_r
, otype
, off_r
);
1594 if (bswap
&& data_r
!= TCG_REG_XZR
) {
1595 tcg_out_rev32(s
, TCG_REG_TMP
, data_r
);
1596 data_r
= TCG_REG_TMP
;
1598 tcg_out_ldst_r(s
, I3312_STRW
, data_r
, addr_r
, otype
, off_r
);
1601 if (bswap
&& data_r
!= TCG_REG_XZR
) {
1602 tcg_out_rev64(s
, TCG_REG_TMP
, data_r
);
1603 data_r
= TCG_REG_TMP
;
1605 tcg_out_ldst_r(s
, I3312_STRX
, data_r
, addr_r
, otype
, off_r
);
1612 static void tcg_out_qemu_ld(TCGContext
*s
, TCGReg data_reg
, TCGReg addr_reg
,
1613 TCGMemOpIdx oi
, TCGType ext
)
1615 TCGMemOp memop
= get_memop(oi
);
1616 const TCGType otype
= TARGET_LONG_BITS
== 64 ? TCG_TYPE_I64
: TCG_TYPE_I32
;
1617 #ifdef CONFIG_SOFTMMU
1618 unsigned mem_index
= get_mmuidx(oi
);
1619 tcg_insn_unit
*label_ptr
;
1621 tcg_out_tlb_read(s
, addr_reg
, memop
, &label_ptr
, mem_index
, 1);
1622 tcg_out_qemu_ld_direct(s
, memop
, ext
, data_reg
,
1623 TCG_REG_X1
, otype
, addr_reg
);
1624 add_qemu_ldst_label(s
, true, oi
, ext
, data_reg
, addr_reg
,
1625 s
->code_ptr
, label_ptr
);
1626 #else /* !CONFIG_SOFTMMU */
1627 if (USE_GUEST_BASE
) {
1628 tcg_out_qemu_ld_direct(s
, memop
, ext
, data_reg
,
1629 TCG_REG_GUEST_BASE
, otype
, addr_reg
);
1631 tcg_out_qemu_ld_direct(s
, memop
, ext
, data_reg
,
1632 addr_reg
, TCG_TYPE_I64
, TCG_REG_XZR
);
1634 #endif /* CONFIG_SOFTMMU */
1637 static void tcg_out_qemu_st(TCGContext
*s
, TCGReg data_reg
, TCGReg addr_reg
,
1640 TCGMemOp memop
= get_memop(oi
);
1641 const TCGType otype
= TARGET_LONG_BITS
== 64 ? TCG_TYPE_I64
: TCG_TYPE_I32
;
1642 #ifdef CONFIG_SOFTMMU
1643 unsigned mem_index
= get_mmuidx(oi
);
1644 tcg_insn_unit
*label_ptr
;
1646 tcg_out_tlb_read(s
, addr_reg
, memop
, &label_ptr
, mem_index
, 0);
1647 tcg_out_qemu_st_direct(s
, memop
, data_reg
,
1648 TCG_REG_X1
, otype
, addr_reg
);
1649 add_qemu_ldst_label(s
, false, oi
, (memop
& MO_SIZE
)== MO_64
,
1650 data_reg
, addr_reg
, s
->code_ptr
, label_ptr
);
1651 #else /* !CONFIG_SOFTMMU */
1652 if (USE_GUEST_BASE
) {
1653 tcg_out_qemu_st_direct(s
, memop
, data_reg
,
1654 TCG_REG_GUEST_BASE
, otype
, addr_reg
);
1656 tcg_out_qemu_st_direct(s
, memop
, data_reg
,
1657 addr_reg
, TCG_TYPE_I64
, TCG_REG_XZR
);
1659 #endif /* CONFIG_SOFTMMU */
1662 static tcg_insn_unit
*tb_ret_addr
;
1664 static void tcg_out_op(TCGContext
*s
, TCGOpcode opc
,
1665 const TCGArg args
[TCG_MAX_OP_ARGS
],
1666 const int const_args
[TCG_MAX_OP_ARGS
])
1668 /* 99% of the time, we can signal the use of extension registers
1669 by looking to see if the opcode handles 64-bit data. */
1670 TCGType ext
= (tcg_op_defs
[opc
].flags
& TCG_OPF_64BIT
) != 0;
1672 /* Hoist the loads of the most common arguments. */
1673 TCGArg a0
= args
[0];
1674 TCGArg a1
= args
[1];
1675 TCGArg a2
= args
[2];
1676 int c2
= const_args
[2];
1678 /* Some operands are defined with "rZ" constraint, a register or
1679 the zero register. These need not actually test args[I] == 0. */
1680 #define REG0(I) (const_args[I] ? TCG_REG_XZR : (TCGReg)args[I])
1683 case INDEX_op_exit_tb
:
1684 /* Reuse the zeroing that exists for goto_ptr. */
1686 tcg_out_goto_long(s
, s
->code_gen_epilogue
);
1688 tcg_out_movi(s
, TCG_TYPE_I64
, TCG_REG_X0
, a0
);
1689 tcg_out_goto_long(s
, tb_ret_addr
);
1693 case INDEX_op_goto_tb
:
1694 if (s
->tb_jmp_insn_offset
!= NULL
) {
1695 /* TCG_TARGET_HAS_direct_jump */
1696 /* Ensure that ADRP+ADD are 8-byte aligned so that an atomic
1697 write can be used to patch the target address. */
1698 if ((uintptr_t)s
->code_ptr
& 7) {
1701 s
->tb_jmp_insn_offset
[a0
] = tcg_current_code_size(s
);
1702 /* actual branch destination will be patched by
1703 tb_target_set_jmp_target later. */
1704 tcg_out_insn(s
, 3406, ADRP
, TCG_REG_TMP
, 0);
1705 tcg_out_insn(s
, 3401, ADDI
, TCG_TYPE_I64
, TCG_REG_TMP
, TCG_REG_TMP
, 0);
1707 /* !TCG_TARGET_HAS_direct_jump */
1708 tcg_debug_assert(s
->tb_jmp_target_addr
!= NULL
);
1709 intptr_t offset
= tcg_pcrel_diff(s
, (s
->tb_jmp_target_addr
+ a0
)) >> 2;
1710 tcg_out_insn(s
, 3305, LDR
, offset
, TCG_REG_TMP
);
1712 tcg_out_insn(s
, 3207, BR
, TCG_REG_TMP
);
1713 set_jmp_reset_offset(s
, a0
);
1716 case INDEX_op_goto_ptr
:
1717 tcg_out_insn(s
, 3207, BR
, a0
);
1721 tcg_out_goto_label(s
, arg_label(a0
));
1724 case INDEX_op_ld8u_i32
:
1725 case INDEX_op_ld8u_i64
:
1726 tcg_out_ldst(s
, I3312_LDRB
, a0
, a1
, a2
, 0);
1728 case INDEX_op_ld8s_i32
:
1729 tcg_out_ldst(s
, I3312_LDRSBW
, a0
, a1
, a2
, 0);
1731 case INDEX_op_ld8s_i64
:
1732 tcg_out_ldst(s
, I3312_LDRSBX
, a0
, a1
, a2
, 0);
1734 case INDEX_op_ld16u_i32
:
1735 case INDEX_op_ld16u_i64
:
1736 tcg_out_ldst(s
, I3312_LDRH
, a0
, a1
, a2
, 1);
1738 case INDEX_op_ld16s_i32
:
1739 tcg_out_ldst(s
, I3312_LDRSHW
, a0
, a1
, a2
, 1);
1741 case INDEX_op_ld16s_i64
:
1742 tcg_out_ldst(s
, I3312_LDRSHX
, a0
, a1
, a2
, 1);
1744 case INDEX_op_ld_i32
:
1745 case INDEX_op_ld32u_i64
:
1746 tcg_out_ldst(s
, I3312_LDRW
, a0
, a1
, a2
, 2);
1748 case INDEX_op_ld32s_i64
:
1749 tcg_out_ldst(s
, I3312_LDRSWX
, a0
, a1
, a2
, 2);
1751 case INDEX_op_ld_i64
:
1752 tcg_out_ldst(s
, I3312_LDRX
, a0
, a1
, a2
, 3);
1755 case INDEX_op_st8_i32
:
1756 case INDEX_op_st8_i64
:
1757 tcg_out_ldst(s
, I3312_STRB
, REG0(0), a1
, a2
, 0);
1759 case INDEX_op_st16_i32
:
1760 case INDEX_op_st16_i64
:
1761 tcg_out_ldst(s
, I3312_STRH
, REG0(0), a1
, a2
, 1);
1763 case INDEX_op_st_i32
:
1764 case INDEX_op_st32_i64
:
1765 tcg_out_ldst(s
, I3312_STRW
, REG0(0), a1
, a2
, 2);
1767 case INDEX_op_st_i64
:
1768 tcg_out_ldst(s
, I3312_STRX
, REG0(0), a1
, a2
, 3);
1771 case INDEX_op_add_i32
:
1774 case INDEX_op_add_i64
:
1776 tcg_out_addsubi(s
, ext
, a0
, a1
, a2
);
1778 tcg_out_insn(s
, 3502, ADD
, ext
, a0
, a1
, a2
);
1782 case INDEX_op_sub_i32
:
1785 case INDEX_op_sub_i64
:
1787 tcg_out_addsubi(s
, ext
, a0
, a1
, -a2
);
1789 tcg_out_insn(s
, 3502, SUB
, ext
, a0
, a1
, a2
);
1793 case INDEX_op_neg_i64
:
1794 case INDEX_op_neg_i32
:
1795 tcg_out_insn(s
, 3502, SUB
, ext
, a0
, TCG_REG_XZR
, a1
);
1798 case INDEX_op_and_i32
:
1801 case INDEX_op_and_i64
:
1803 tcg_out_logicali(s
, I3404_ANDI
, ext
, a0
, a1
, a2
);
1805 tcg_out_insn(s
, 3510, AND
, ext
, a0
, a1
, a2
);
1809 case INDEX_op_andc_i32
:
1812 case INDEX_op_andc_i64
:
1814 tcg_out_logicali(s
, I3404_ANDI
, ext
, a0
, a1
, ~a2
);
1816 tcg_out_insn(s
, 3510, BIC
, ext
, a0
, a1
, a2
);
1820 case INDEX_op_or_i32
:
1823 case INDEX_op_or_i64
:
1825 tcg_out_logicali(s
, I3404_ORRI
, ext
, a0
, a1
, a2
);
1827 tcg_out_insn(s
, 3510, ORR
, ext
, a0
, a1
, a2
);
1831 case INDEX_op_orc_i32
:
1834 case INDEX_op_orc_i64
:
1836 tcg_out_logicali(s
, I3404_ORRI
, ext
, a0
, a1
, ~a2
);
1838 tcg_out_insn(s
, 3510, ORN
, ext
, a0
, a1
, a2
);
1842 case INDEX_op_xor_i32
:
1845 case INDEX_op_xor_i64
:
1847 tcg_out_logicali(s
, I3404_EORI
, ext
, a0
, a1
, a2
);
1849 tcg_out_insn(s
, 3510, EOR
, ext
, a0
, a1
, a2
);
1853 case INDEX_op_eqv_i32
:
1856 case INDEX_op_eqv_i64
:
1858 tcg_out_logicali(s
, I3404_EORI
, ext
, a0
, a1
, ~a2
);
1860 tcg_out_insn(s
, 3510, EON
, ext
, a0
, a1
, a2
);
1864 case INDEX_op_not_i64
:
1865 case INDEX_op_not_i32
:
1866 tcg_out_insn(s
, 3510, ORN
, ext
, a0
, TCG_REG_XZR
, a1
);
1869 case INDEX_op_mul_i64
:
1870 case INDEX_op_mul_i32
:
1871 tcg_out_insn(s
, 3509, MADD
, ext
, a0
, a1
, a2
, TCG_REG_XZR
);
1874 case INDEX_op_div_i64
:
1875 case INDEX_op_div_i32
:
1876 tcg_out_insn(s
, 3508, SDIV
, ext
, a0
, a1
, a2
);
1878 case INDEX_op_divu_i64
:
1879 case INDEX_op_divu_i32
:
1880 tcg_out_insn(s
, 3508, UDIV
, ext
, a0
, a1
, a2
);
1883 case INDEX_op_rem_i64
:
1884 case INDEX_op_rem_i32
:
1885 tcg_out_insn(s
, 3508, SDIV
, ext
, TCG_REG_TMP
, a1
, a2
);
1886 tcg_out_insn(s
, 3509, MSUB
, ext
, a0
, TCG_REG_TMP
, a2
, a1
);
1888 case INDEX_op_remu_i64
:
1889 case INDEX_op_remu_i32
:
1890 tcg_out_insn(s
, 3508, UDIV
, ext
, TCG_REG_TMP
, a1
, a2
);
1891 tcg_out_insn(s
, 3509, MSUB
, ext
, a0
, TCG_REG_TMP
, a2
, a1
);
1894 case INDEX_op_shl_i64
:
1895 case INDEX_op_shl_i32
:
1897 tcg_out_shl(s
, ext
, a0
, a1
, a2
);
1899 tcg_out_insn(s
, 3508, LSLV
, ext
, a0
, a1
, a2
);
1903 case INDEX_op_shr_i64
:
1904 case INDEX_op_shr_i32
:
1906 tcg_out_shr(s
, ext
, a0
, a1
, a2
);
1908 tcg_out_insn(s
, 3508, LSRV
, ext
, a0
, a1
, a2
);
1912 case INDEX_op_sar_i64
:
1913 case INDEX_op_sar_i32
:
1915 tcg_out_sar(s
, ext
, a0
, a1
, a2
);
1917 tcg_out_insn(s
, 3508, ASRV
, ext
, a0
, a1
, a2
);
1921 case INDEX_op_rotr_i64
:
1922 case INDEX_op_rotr_i32
:
1924 tcg_out_rotr(s
, ext
, a0
, a1
, a2
);
1926 tcg_out_insn(s
, 3508, RORV
, ext
, a0
, a1
, a2
);
1930 case INDEX_op_rotl_i64
:
1931 case INDEX_op_rotl_i32
:
1933 tcg_out_rotl(s
, ext
, a0
, a1
, a2
);
1935 tcg_out_insn(s
, 3502, SUB
, 0, TCG_REG_TMP
, TCG_REG_XZR
, a2
);
1936 tcg_out_insn(s
, 3508, RORV
, ext
, a0
, a1
, TCG_REG_TMP
);
1940 case INDEX_op_clz_i64
:
1941 case INDEX_op_clz_i32
:
1942 tcg_out_cltz(s
, ext
, a0
, a1
, a2
, c2
, false);
1944 case INDEX_op_ctz_i64
:
1945 case INDEX_op_ctz_i32
:
1946 tcg_out_cltz(s
, ext
, a0
, a1
, a2
, c2
, true);
1949 case INDEX_op_brcond_i32
:
1952 case INDEX_op_brcond_i64
:
1953 tcg_out_brcond(s
, ext
, a2
, a0
, a1
, const_args
[1], arg_label(args
[3]));
1956 case INDEX_op_setcond_i32
:
1959 case INDEX_op_setcond_i64
:
1960 tcg_out_cmp(s
, ext
, a1
, a2
, c2
);
1961 /* Use CSET alias of CSINC Wd, WZR, WZR, invert(cond). */
1962 tcg_out_insn(s
, 3506, CSINC
, TCG_TYPE_I32
, a0
, TCG_REG_XZR
,
1963 TCG_REG_XZR
, tcg_invert_cond(args
[3]));
1966 case INDEX_op_movcond_i32
:
1969 case INDEX_op_movcond_i64
:
1970 tcg_out_cmp(s
, ext
, a1
, a2
, c2
);
1971 tcg_out_insn(s
, 3506, CSEL
, ext
, a0
, REG0(3), REG0(4), args
[5]);
1974 case INDEX_op_qemu_ld_i32
:
1975 case INDEX_op_qemu_ld_i64
:
1976 tcg_out_qemu_ld(s
, a0
, a1
, a2
, ext
);
1978 case INDEX_op_qemu_st_i32
:
1979 case INDEX_op_qemu_st_i64
:
1980 tcg_out_qemu_st(s
, REG0(0), a1
, a2
);
1983 case INDEX_op_bswap64_i64
:
1984 tcg_out_rev64(s
, a0
, a1
);
1986 case INDEX_op_bswap32_i64
:
1987 case INDEX_op_bswap32_i32
:
1988 tcg_out_rev32(s
, a0
, a1
);
1990 case INDEX_op_bswap16_i64
:
1991 case INDEX_op_bswap16_i32
:
1992 tcg_out_rev16(s
, a0
, a1
);
1995 case INDEX_op_ext8s_i64
:
1996 case INDEX_op_ext8s_i32
:
1997 tcg_out_sxt(s
, ext
, MO_8
, a0
, a1
);
1999 case INDEX_op_ext16s_i64
:
2000 case INDEX_op_ext16s_i32
:
2001 tcg_out_sxt(s
, ext
, MO_16
, a0
, a1
);
2003 case INDEX_op_ext_i32_i64
:
2004 case INDEX_op_ext32s_i64
:
2005 tcg_out_sxt(s
, TCG_TYPE_I64
, MO_32
, a0
, a1
);
2007 case INDEX_op_ext8u_i64
:
2008 case INDEX_op_ext8u_i32
:
2009 tcg_out_uxt(s
, MO_8
, a0
, a1
);
2011 case INDEX_op_ext16u_i64
:
2012 case INDEX_op_ext16u_i32
:
2013 tcg_out_uxt(s
, MO_16
, a0
, a1
);
2015 case INDEX_op_extu_i32_i64
:
2016 case INDEX_op_ext32u_i64
:
2017 tcg_out_movr(s
, TCG_TYPE_I32
, a0
, a1
);
2020 case INDEX_op_deposit_i64
:
2021 case INDEX_op_deposit_i32
:
2022 tcg_out_dep(s
, ext
, a0
, REG0(2), args
[3], args
[4]);
2025 case INDEX_op_extract_i64
:
2026 case INDEX_op_extract_i32
:
2027 tcg_out_ubfm(s
, ext
, a0
, a1
, a2
, a2
+ args
[3] - 1);
2030 case INDEX_op_sextract_i64
:
2031 case INDEX_op_sextract_i32
:
2032 tcg_out_sbfm(s
, ext
, a0
, a1
, a2
, a2
+ args
[3] - 1);
2035 case INDEX_op_add2_i32
:
2036 tcg_out_addsub2(s
, TCG_TYPE_I32
, a0
, a1
, REG0(2), REG0(3),
2037 (int32_t)args
[4], args
[5], const_args
[4],
2038 const_args
[5], false);
2040 case INDEX_op_add2_i64
:
2041 tcg_out_addsub2(s
, TCG_TYPE_I64
, a0
, a1
, REG0(2), REG0(3), args
[4],
2042 args
[5], const_args
[4], const_args
[5], false);
2044 case INDEX_op_sub2_i32
:
2045 tcg_out_addsub2(s
, TCG_TYPE_I32
, a0
, a1
, REG0(2), REG0(3),
2046 (int32_t)args
[4], args
[5], const_args
[4],
2047 const_args
[5], true);
2049 case INDEX_op_sub2_i64
:
2050 tcg_out_addsub2(s
, TCG_TYPE_I64
, a0
, a1
, REG0(2), REG0(3), args
[4],
2051 args
[5], const_args
[4], const_args
[5], true);
2054 case INDEX_op_muluh_i64
:
2055 tcg_out_insn(s
, 3508, UMULH
, TCG_TYPE_I64
, a0
, a1
, a2
);
2057 case INDEX_op_mulsh_i64
:
2058 tcg_out_insn(s
, 3508, SMULH
, TCG_TYPE_I64
, a0
, a1
, a2
);
2065 case INDEX_op_mov_i32
: /* Always emitted via tcg_out_mov. */
2066 case INDEX_op_mov_i64
:
2067 case INDEX_op_mov_vec
:
2068 case INDEX_op_movi_i32
: /* Always emitted via tcg_out_movi. */
2069 case INDEX_op_movi_i64
:
2070 case INDEX_op_dupi_vec
:
2071 case INDEX_op_call
: /* Always emitted via tcg_out_call. */
2073 g_assert_not_reached();
2079 static void tcg_out_vec_op(TCGContext
*s
, TCGOpcode opc
,
2080 unsigned vecl
, unsigned vece
,
2081 const TCGArg
*args
, const int *const_args
)
2083 static const AArch64Insn cmp_insn
[16] = {
2084 [TCG_COND_EQ
] = I3616_CMEQ
,
2085 [TCG_COND_GT
] = I3616_CMGT
,
2086 [TCG_COND_GE
] = I3616_CMGE
,
2087 [TCG_COND_GTU
] = I3616_CMHI
,
2088 [TCG_COND_GEU
] = I3616_CMHS
,
2090 static const AArch64Insn cmp0_insn
[16] = {
2091 [TCG_COND_EQ
] = I3617_CMEQ0
,
2092 [TCG_COND_GT
] = I3617_CMGT0
,
2093 [TCG_COND_GE
] = I3617_CMGE0
,
2094 [TCG_COND_LT
] = I3617_CMLT0
,
2095 [TCG_COND_LE
] = I3617_CMLE0
,
2098 TCGType type
= vecl
+ TCG_TYPE_V64
;
2099 unsigned is_q
= vecl
;
2107 case INDEX_op_ld_vec
:
2108 tcg_out_ld(s
, type
, a0
, a1
, a2
);
2110 case INDEX_op_st_vec
:
2111 tcg_out_st(s
, type
, a0
, a1
, a2
);
2113 case INDEX_op_add_vec
:
2114 tcg_out_insn(s
, 3616, ADD
, is_q
, vece
, a0
, a1
, a2
);
2116 case INDEX_op_sub_vec
:
2117 tcg_out_insn(s
, 3616, SUB
, is_q
, vece
, a0
, a1
, a2
);
2119 case INDEX_op_mul_vec
:
2120 tcg_out_insn(s
, 3616, MUL
, is_q
, vece
, a0
, a1
, a2
);
2122 case INDEX_op_neg_vec
:
2123 tcg_out_insn(s
, 3617, NEG
, is_q
, vece
, a0
, a1
);
2125 case INDEX_op_and_vec
:
2126 tcg_out_insn(s
, 3616, AND
, is_q
, 0, a0
, a1
, a2
);
2128 case INDEX_op_or_vec
:
2129 tcg_out_insn(s
, 3616, ORR
, is_q
, 0, a0
, a1
, a2
);
2131 case INDEX_op_xor_vec
:
2132 tcg_out_insn(s
, 3616, EOR
, is_q
, 0, a0
, a1
, a2
);
2134 case INDEX_op_andc_vec
:
2135 tcg_out_insn(s
, 3616, BIC
, is_q
, 0, a0
, a1
, a2
);
2137 case INDEX_op_orc_vec
:
2138 tcg_out_insn(s
, 3616, ORN
, is_q
, 0, a0
, a1
, a2
);
2140 case INDEX_op_not_vec
:
2141 tcg_out_insn(s
, 3617, NOT
, is_q
, 0, a0
, a1
);
2143 case INDEX_op_dup_vec
:
2144 tcg_out_insn(s
, 3605, DUP
, is_q
, a0
, a1
, 1 << vece
, 0);
2146 case INDEX_op_shli_vec
:
2147 tcg_out_insn(s
, 3614, SHL
, is_q
, a0
, a1
, a2
+ (8 << vece
));
2149 case INDEX_op_shri_vec
:
2150 tcg_out_insn(s
, 3614, USHR
, is_q
, a0
, a1
, (16 << vece
) - a2
);
2152 case INDEX_op_sari_vec
:
2153 tcg_out_insn(s
, 3614, SSHR
, is_q
, a0
, a1
, (16 << vece
) - a2
);
2155 case INDEX_op_cmp_vec
:
2157 TCGCond cond
= args
[3];
2160 if (cond
== TCG_COND_NE
) {
2161 if (const_args
[2]) {
2162 tcg_out_insn(s
, 3616, CMTST
, is_q
, vece
, a0
, a1
, a1
);
2164 tcg_out_insn(s
, 3616, CMEQ
, is_q
, vece
, a0
, a1
, a2
);
2165 tcg_out_insn(s
, 3617, NOT
, is_q
, 0, a0
, a0
);
2168 if (const_args
[2]) {
2169 insn
= cmp0_insn
[cond
];
2171 tcg_out_insn_3617(s
, insn
, is_q
, vece
, a0
, a1
);
2174 tcg_out_dupi_vec(s
, type
, TCG_VEC_TMP
, 0);
2177 insn
= cmp_insn
[cond
];
2180 t
= a1
, a1
= a2
, a2
= t
;
2181 cond
= tcg_swap_cond(cond
);
2182 insn
= cmp_insn
[cond
];
2183 tcg_debug_assert(insn
!= 0);
2185 tcg_out_insn_3616(s
, insn
, is_q
, vece
, a0
, a1
, a2
);
2190 g_assert_not_reached();
2194 int tcg_can_emit_vec_op(TCGOpcode opc
, TCGType type
, unsigned vece
)
2197 case INDEX_op_add_vec
:
2198 case INDEX_op_sub_vec
:
2199 case INDEX_op_and_vec
:
2200 case INDEX_op_or_vec
:
2201 case INDEX_op_xor_vec
:
2202 case INDEX_op_andc_vec
:
2203 case INDEX_op_orc_vec
:
2204 case INDEX_op_neg_vec
:
2205 case INDEX_op_not_vec
:
2206 case INDEX_op_cmp_vec
:
2207 case INDEX_op_shli_vec
:
2208 case INDEX_op_shri_vec
:
2209 case INDEX_op_sari_vec
:
2211 case INDEX_op_mul_vec
:
2212 return vece
< MO_64
;
2219 void tcg_expand_vec_op(TCGOpcode opc
, TCGType type
, unsigned vece
,
2224 static const TCGTargetOpDef
*tcg_target_op_def(TCGOpcode op
)
2226 static const TCGTargetOpDef r
= { .args_ct_str
= { "r" } };
2227 static const TCGTargetOpDef r_r
= { .args_ct_str
= { "r", "r" } };
2228 static const TCGTargetOpDef w_w
= { .args_ct_str
= { "w", "w" } };
2229 static const TCGTargetOpDef w_r
= { .args_ct_str
= { "w", "r" } };
2230 static const TCGTargetOpDef w_wr
= { .args_ct_str
= { "w", "wr" } };
2231 static const TCGTargetOpDef r_l
= { .args_ct_str
= { "r", "l" } };
2232 static const TCGTargetOpDef r_rA
= { .args_ct_str
= { "r", "rA" } };
2233 static const TCGTargetOpDef rZ_r
= { .args_ct_str
= { "rZ", "r" } };
2234 static const TCGTargetOpDef lZ_l
= { .args_ct_str
= { "lZ", "l" } };
2235 static const TCGTargetOpDef r_r_r
= { .args_ct_str
= { "r", "r", "r" } };
2236 static const TCGTargetOpDef w_w_w
= { .args_ct_str
= { "w", "w", "w" } };
2237 static const TCGTargetOpDef w_w_wZ
= { .args_ct_str
= { "w", "w", "wZ" } };
2238 static const TCGTargetOpDef r_r_ri
= { .args_ct_str
= { "r", "r", "ri" } };
2239 static const TCGTargetOpDef r_r_rA
= { .args_ct_str
= { "r", "r", "rA" } };
2240 static const TCGTargetOpDef r_r_rL
= { .args_ct_str
= { "r", "r", "rL" } };
2241 static const TCGTargetOpDef r_r_rAL
2242 = { .args_ct_str
= { "r", "r", "rAL" } };
2243 static const TCGTargetOpDef dep
2244 = { .args_ct_str
= { "r", "0", "rZ" } };
2245 static const TCGTargetOpDef movc
2246 = { .args_ct_str
= { "r", "r", "rA", "rZ", "rZ" } };
2247 static const TCGTargetOpDef add2
2248 = { .args_ct_str
= { "r", "r", "rZ", "rZ", "rA", "rMZ" } };
2251 case INDEX_op_goto_ptr
:
2254 case INDEX_op_ld8u_i32
:
2255 case INDEX_op_ld8s_i32
:
2256 case INDEX_op_ld16u_i32
:
2257 case INDEX_op_ld16s_i32
:
2258 case INDEX_op_ld_i32
:
2259 case INDEX_op_ld8u_i64
:
2260 case INDEX_op_ld8s_i64
:
2261 case INDEX_op_ld16u_i64
:
2262 case INDEX_op_ld16s_i64
:
2263 case INDEX_op_ld32u_i64
:
2264 case INDEX_op_ld32s_i64
:
2265 case INDEX_op_ld_i64
:
2266 case INDEX_op_neg_i32
:
2267 case INDEX_op_neg_i64
:
2268 case INDEX_op_not_i32
:
2269 case INDEX_op_not_i64
:
2270 case INDEX_op_bswap16_i32
:
2271 case INDEX_op_bswap32_i32
:
2272 case INDEX_op_bswap16_i64
:
2273 case INDEX_op_bswap32_i64
:
2274 case INDEX_op_bswap64_i64
:
2275 case INDEX_op_ext8s_i32
:
2276 case INDEX_op_ext16s_i32
:
2277 case INDEX_op_ext8u_i32
:
2278 case INDEX_op_ext16u_i32
:
2279 case INDEX_op_ext8s_i64
:
2280 case INDEX_op_ext16s_i64
:
2281 case INDEX_op_ext32s_i64
:
2282 case INDEX_op_ext8u_i64
:
2283 case INDEX_op_ext16u_i64
:
2284 case INDEX_op_ext32u_i64
:
2285 case INDEX_op_ext_i32_i64
:
2286 case INDEX_op_extu_i32_i64
:
2287 case INDEX_op_extract_i32
:
2288 case INDEX_op_extract_i64
:
2289 case INDEX_op_sextract_i32
:
2290 case INDEX_op_sextract_i64
:
2293 case INDEX_op_st8_i32
:
2294 case INDEX_op_st16_i32
:
2295 case INDEX_op_st_i32
:
2296 case INDEX_op_st8_i64
:
2297 case INDEX_op_st16_i64
:
2298 case INDEX_op_st32_i64
:
2299 case INDEX_op_st_i64
:
2302 case INDEX_op_add_i32
:
2303 case INDEX_op_add_i64
:
2304 case INDEX_op_sub_i32
:
2305 case INDEX_op_sub_i64
:
2306 case INDEX_op_setcond_i32
:
2307 case INDEX_op_setcond_i64
:
2310 case INDEX_op_mul_i32
:
2311 case INDEX_op_mul_i64
:
2312 case INDEX_op_div_i32
:
2313 case INDEX_op_div_i64
:
2314 case INDEX_op_divu_i32
:
2315 case INDEX_op_divu_i64
:
2316 case INDEX_op_rem_i32
:
2317 case INDEX_op_rem_i64
:
2318 case INDEX_op_remu_i32
:
2319 case INDEX_op_remu_i64
:
2320 case INDEX_op_muluh_i64
:
2321 case INDEX_op_mulsh_i64
:
2324 case INDEX_op_and_i32
:
2325 case INDEX_op_and_i64
:
2326 case INDEX_op_or_i32
:
2327 case INDEX_op_or_i64
:
2328 case INDEX_op_xor_i32
:
2329 case INDEX_op_xor_i64
:
2330 case INDEX_op_andc_i32
:
2331 case INDEX_op_andc_i64
:
2332 case INDEX_op_orc_i32
:
2333 case INDEX_op_orc_i64
:
2334 case INDEX_op_eqv_i32
:
2335 case INDEX_op_eqv_i64
:
2338 case INDEX_op_shl_i32
:
2339 case INDEX_op_shr_i32
:
2340 case INDEX_op_sar_i32
:
2341 case INDEX_op_rotl_i32
:
2342 case INDEX_op_rotr_i32
:
2343 case INDEX_op_shl_i64
:
2344 case INDEX_op_shr_i64
:
2345 case INDEX_op_sar_i64
:
2346 case INDEX_op_rotl_i64
:
2347 case INDEX_op_rotr_i64
:
2350 case INDEX_op_clz_i32
:
2351 case INDEX_op_ctz_i32
:
2352 case INDEX_op_clz_i64
:
2353 case INDEX_op_ctz_i64
:
2356 case INDEX_op_brcond_i32
:
2357 case INDEX_op_brcond_i64
:
2360 case INDEX_op_movcond_i32
:
2361 case INDEX_op_movcond_i64
:
2364 case INDEX_op_qemu_ld_i32
:
2365 case INDEX_op_qemu_ld_i64
:
2367 case INDEX_op_qemu_st_i32
:
2368 case INDEX_op_qemu_st_i64
:
2371 case INDEX_op_deposit_i32
:
2372 case INDEX_op_deposit_i64
:
2375 case INDEX_op_add2_i32
:
2376 case INDEX_op_add2_i64
:
2377 case INDEX_op_sub2_i32
:
2378 case INDEX_op_sub2_i64
:
2381 case INDEX_op_add_vec
:
2382 case INDEX_op_sub_vec
:
2383 case INDEX_op_mul_vec
:
2384 case INDEX_op_and_vec
:
2385 case INDEX_op_or_vec
:
2386 case INDEX_op_xor_vec
:
2387 case INDEX_op_andc_vec
:
2388 case INDEX_op_orc_vec
:
2390 case INDEX_op_not_vec
:
2391 case INDEX_op_neg_vec
:
2392 case INDEX_op_shli_vec
:
2393 case INDEX_op_shri_vec
:
2394 case INDEX_op_sari_vec
:
2396 case INDEX_op_ld_vec
:
2397 case INDEX_op_st_vec
:
2399 case INDEX_op_dup_vec
:
2401 case INDEX_op_cmp_vec
:
2409 static void tcg_target_init(TCGContext
*s
)
2411 tcg_target_available_regs
[TCG_TYPE_I32
] = 0xffffffffu
;
2412 tcg_target_available_regs
[TCG_TYPE_I64
] = 0xffffffffu
;
2413 tcg_target_available_regs
[TCG_TYPE_V64
] = 0xffffffff00000000ull
;
2414 tcg_target_available_regs
[TCG_TYPE_V128
] = 0xffffffff00000000ull
;
2416 tcg_target_call_clobber_regs
= -1ull;
2417 tcg_regset_reset_reg(tcg_target_call_clobber_regs
, TCG_REG_X19
);
2418 tcg_regset_reset_reg(tcg_target_call_clobber_regs
, TCG_REG_X20
);
2419 tcg_regset_reset_reg(tcg_target_call_clobber_regs
, TCG_REG_X21
);
2420 tcg_regset_reset_reg(tcg_target_call_clobber_regs
, TCG_REG_X22
);
2421 tcg_regset_reset_reg(tcg_target_call_clobber_regs
, TCG_REG_X23
);
2422 tcg_regset_reset_reg(tcg_target_call_clobber_regs
, TCG_REG_X24
);
2423 tcg_regset_reset_reg(tcg_target_call_clobber_regs
, TCG_REG_X25
);
2424 tcg_regset_reset_reg(tcg_target_call_clobber_regs
, TCG_REG_X26
);
2425 tcg_regset_reset_reg(tcg_target_call_clobber_regs
, TCG_REG_X27
);
2426 tcg_regset_reset_reg(tcg_target_call_clobber_regs
, TCG_REG_X28
);
2427 tcg_regset_reset_reg(tcg_target_call_clobber_regs
, TCG_REG_X29
);
2428 tcg_regset_reset_reg(tcg_target_call_clobber_regs
, TCG_REG_V8
);
2429 tcg_regset_reset_reg(tcg_target_call_clobber_regs
, TCG_REG_V9
);
2430 tcg_regset_reset_reg(tcg_target_call_clobber_regs
, TCG_REG_V10
);
2431 tcg_regset_reset_reg(tcg_target_call_clobber_regs
, TCG_REG_V11
);
2432 tcg_regset_reset_reg(tcg_target_call_clobber_regs
, TCG_REG_V12
);
2433 tcg_regset_reset_reg(tcg_target_call_clobber_regs
, TCG_REG_V13
);
2434 tcg_regset_reset_reg(tcg_target_call_clobber_regs
, TCG_REG_V14
);
2435 tcg_regset_reset_reg(tcg_target_call_clobber_regs
, TCG_REG_V15
);
2437 s
->reserved_regs
= 0;
2438 tcg_regset_set_reg(s
->reserved_regs
, TCG_REG_SP
);
2439 tcg_regset_set_reg(s
->reserved_regs
, TCG_REG_FP
);
2440 tcg_regset_set_reg(s
->reserved_regs
, TCG_REG_TMP
);
2441 tcg_regset_set_reg(s
->reserved_regs
, TCG_REG_X18
); /* platform register */
2442 tcg_regset_set_reg(s
->reserved_regs
, TCG_VEC_TMP
);
2445 /* Saving pairs: (X19, X20) .. (X27, X28), (X29(fp), X30(lr)). */
2446 #define PUSH_SIZE ((30 - 19 + 1) * 8)
2448 #define FRAME_SIZE \
2450 + TCG_STATIC_CALL_ARGS_SIZE \
2451 + CPU_TEMP_BUF_NLONGS * sizeof(long) \
2452 + TCG_TARGET_STACK_ALIGN - 1) \
2453 & ~(TCG_TARGET_STACK_ALIGN - 1))
2455 /* We're expecting a 2 byte uleb128 encoded value. */
2456 QEMU_BUILD_BUG_ON(FRAME_SIZE
>= (1 << 14));
2458 /* We're expecting to use a single ADDI insn. */
2459 QEMU_BUILD_BUG_ON(FRAME_SIZE
- PUSH_SIZE
> 0xfff);
2461 static void tcg_target_qemu_prologue(TCGContext
*s
)
2465 /* Push (FP, LR) and allocate space for all saved registers. */
2466 tcg_out_insn(s
, 3314, STP
, TCG_REG_FP
, TCG_REG_LR
,
2467 TCG_REG_SP
, -PUSH_SIZE
, 1, 1);
2469 /* Set up frame pointer for canonical unwinding. */
2470 tcg_out_movr_sp(s
, TCG_TYPE_I64
, TCG_REG_FP
, TCG_REG_SP
);
2472 /* Store callee-preserved regs x19..x28. */
2473 for (r
= TCG_REG_X19
; r
<= TCG_REG_X27
; r
+= 2) {
2474 int ofs
= (r
- TCG_REG_X19
+ 2) * 8;
2475 tcg_out_insn(s
, 3314, STP
, r
, r
+ 1, TCG_REG_SP
, ofs
, 1, 0);
2478 /* Make stack space for TCG locals. */
2479 tcg_out_insn(s
, 3401, SUBI
, TCG_TYPE_I64
, TCG_REG_SP
, TCG_REG_SP
,
2480 FRAME_SIZE
- PUSH_SIZE
);
2482 /* Inform TCG about how to find TCG locals with register, offset, size. */
2483 tcg_set_frame(s
, TCG_REG_SP
, TCG_STATIC_CALL_ARGS_SIZE
,
2484 CPU_TEMP_BUF_NLONGS
* sizeof(long));
2486 #if !defined(CONFIG_SOFTMMU)
2487 if (USE_GUEST_BASE
) {
2488 tcg_out_movi(s
, TCG_TYPE_PTR
, TCG_REG_GUEST_BASE
, guest_base
);
2489 tcg_regset_set_reg(s
->reserved_regs
, TCG_REG_GUEST_BASE
);
2493 tcg_out_mov(s
, TCG_TYPE_PTR
, TCG_AREG0
, tcg_target_call_iarg_regs
[0]);
2494 tcg_out_insn(s
, 3207, BR
, tcg_target_call_iarg_regs
[1]);
2497 * Return path for goto_ptr. Set return value to 0, a-la exit_tb,
2498 * and fall through to the rest of the epilogue.
2500 s
->code_gen_epilogue
= s
->code_ptr
;
2501 tcg_out_movi(s
, TCG_TYPE_REG
, TCG_REG_X0
, 0);
2504 tb_ret_addr
= s
->code_ptr
;
2506 /* Remove TCG locals stack space. */
2507 tcg_out_insn(s
, 3401, ADDI
, TCG_TYPE_I64
, TCG_REG_SP
, TCG_REG_SP
,
2508 FRAME_SIZE
- PUSH_SIZE
);
2510 /* Restore registers x19..x28. */
2511 for (r
= TCG_REG_X19
; r
<= TCG_REG_X27
; r
+= 2) {
2512 int ofs
= (r
- TCG_REG_X19
+ 2) * 8;
2513 tcg_out_insn(s
, 3314, LDP
, r
, r
+ 1, TCG_REG_SP
, ofs
, 1, 0);
2516 /* Pop (FP, LR), restore SP to previous frame. */
2517 tcg_out_insn(s
, 3314, LDP
, TCG_REG_FP
, TCG_REG_LR
,
2518 TCG_REG_SP
, PUSH_SIZE
, 0, 1);
2519 tcg_out_insn(s
, 3207, RET
, TCG_REG_LR
);
2522 static void tcg_out_nop_fill(tcg_insn_unit
*p
, int count
)
2525 for (i
= 0; i
< count
; ++i
) {
2532 uint8_t fde_def_cfa
[4];
2533 uint8_t fde_reg_ofs
[24];
2536 #define ELF_HOST_MACHINE EM_AARCH64
2538 static const DebugFrame debug_frame
= {
2539 .h
.cie
.len
= sizeof(DebugFrameCIE
)-4, /* length after .len member */
2542 .h
.cie
.code_align
= 1,
2543 .h
.cie
.data_align
= 0x78, /* sleb128 -8 */
2544 .h
.cie
.return_column
= TCG_REG_LR
,
2546 /* Total FDE size does not include the "len" member. */
2547 .h
.fde
.len
= sizeof(DebugFrame
) - offsetof(DebugFrame
, h
.fde
.cie_offset
),
2550 12, TCG_REG_SP
, /* DW_CFA_def_cfa sp, ... */
2551 (FRAME_SIZE
& 0x7f) | 0x80, /* ... uleb128 FRAME_SIZE */
2555 0x80 + 28, 1, /* DW_CFA_offset, x28, -8 */
2556 0x80 + 27, 2, /* DW_CFA_offset, x27, -16 */
2557 0x80 + 26, 3, /* DW_CFA_offset, x26, -24 */
2558 0x80 + 25, 4, /* DW_CFA_offset, x25, -32 */
2559 0x80 + 24, 5, /* DW_CFA_offset, x24, -40 */
2560 0x80 + 23, 6, /* DW_CFA_offset, x23, -48 */
2561 0x80 + 22, 7, /* DW_CFA_offset, x22, -56 */
2562 0x80 + 21, 8, /* DW_CFA_offset, x21, -64 */
2563 0x80 + 20, 9, /* DW_CFA_offset, x20, -72 */
2564 0x80 + 19, 10, /* DW_CFA_offset, x1p, -80 */
2565 0x80 + 30, 11, /* DW_CFA_offset, lr, -88 */
2566 0x80 + 29, 12, /* DW_CFA_offset, fp, -96 */
2570 void tcg_register_jit(void *buf
, size_t buf_size
)
2572 tcg_register_jit_int(buf
, buf_size
, &debug_frame
, sizeof(debug_frame
));