2 * Initial TCG Implementation for aarch64
4 * Copyright (c) 2013 Huawei Technologies Duesseldorf GmbH
5 * Written by Claudio Fontana
7 * This work is licensed under the terms of the GNU GPL, version 2 or
8 * (at your option) any later version.
10 * See the COPYING file in the top-level directory for details.
13 #include "tcg-be-ldst.h"
14 #include "qemu/bitops.h"
16 /* We're going to re-use TCGType in setting of the SF bit, which controls
17 the size of the operation performed. If we know the values match, it
18 makes things much cleaner. */
19 QEMU_BUILD_BUG_ON(TCG_TYPE_I32
!= 0 || TCG_TYPE_I64
!= 1);
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",
27 "%fp", /* frame pointer */
28 "%lr", /* link register */
29 "%sp", /* stack pointer */
33 #ifdef TARGET_WORDS_BIGENDIAN
34 #define TCG_LDST_BSWAP 1
36 #define TCG_LDST_BSWAP 0
39 static const int tcg_target_reg_alloc_order
[] = {
40 TCG_REG_X20
, TCG_REG_X21
, TCG_REG_X22
, TCG_REG_X23
,
41 TCG_REG_X24
, TCG_REG_X25
, TCG_REG_X26
, TCG_REG_X27
,
42 TCG_REG_X28
, /* we will reserve this for GUEST_BASE if configured */
44 TCG_REG_X9
, TCG_REG_X10
, TCG_REG_X11
, TCG_REG_X12
,
45 TCG_REG_X13
, TCG_REG_X14
, TCG_REG_X15
,
46 TCG_REG_X16
, TCG_REG_X17
,
48 TCG_REG_X18
, TCG_REG_X19
, /* will not use these, see tcg_target_init */
50 TCG_REG_X0
, TCG_REG_X1
, TCG_REG_X2
, TCG_REG_X3
,
51 TCG_REG_X4
, TCG_REG_X5
, TCG_REG_X6
, TCG_REG_X7
,
53 TCG_REG_X8
, /* will not use, see tcg_target_init */
56 static const int tcg_target_call_iarg_regs
[8] = {
57 TCG_REG_X0
, TCG_REG_X1
, TCG_REG_X2
, TCG_REG_X3
,
58 TCG_REG_X4
, TCG_REG_X5
, TCG_REG_X6
, TCG_REG_X7
60 static const int tcg_target_call_oarg_regs
[1] = {
64 #define TCG_REG_TMP TCG_REG_X8
66 #ifndef CONFIG_SOFTMMU
67 # if defined(CONFIG_USE_GUEST_BASE)
68 # define TCG_REG_GUEST_BASE TCG_REG_X28
70 # define TCG_REG_GUEST_BASE TCG_REG_XZR
74 static inline void reloc_pc26(void *code_ptr
, intptr_t target
)
76 intptr_t offset
= (target
- (intptr_t)code_ptr
) / 4;
77 /* read instruction, mask away previous PC_REL26 parameter contents,
78 set the proper offset, then write back the instruction. */
79 uint32_t insn
= *(uint32_t *)code_ptr
;
80 insn
= deposit32(insn
, 0, 26, offset
);
81 *(uint32_t *)code_ptr
= insn
;
84 static inline void reloc_pc19(void *code_ptr
, intptr_t target
)
86 intptr_t offset
= (target
- (intptr_t)code_ptr
) / 4;
87 /* read instruction, mask away previous PC_REL19 parameter contents,
88 set the proper offset, then write back the instruction. */
89 uint32_t insn
= *(uint32_t *)code_ptr
;
90 insn
= deposit32(insn
, 5, 19, offset
);
91 *(uint32_t *)code_ptr
= insn
;
94 static inline void patch_reloc(uint8_t *code_ptr
, int type
,
95 intptr_t value
, intptr_t addend
)
100 case R_AARCH64_JUMP26
:
101 case R_AARCH64_CALL26
:
102 reloc_pc26(code_ptr
, value
);
104 case R_AARCH64_CONDBR19
:
105 reloc_pc19(code_ptr
, value
);
113 #define TCG_CT_CONST_IS32 0x100
114 #define TCG_CT_CONST_AIMM 0x200
115 #define TCG_CT_CONST_LIMM 0x400
116 #define TCG_CT_CONST_ZERO 0x800
117 #define TCG_CT_CONST_MONE 0x1000
119 /* parse target specific constraints */
120 static int target_parse_constraint(TCGArgConstraint
*ct
,
121 const char **pct_str
)
123 const char *ct_str
= *pct_str
;
127 ct
->ct
|= TCG_CT_REG
;
128 tcg_regset_set32(ct
->u
.regs
, 0, (1ULL << TCG_TARGET_NB_REGS
) - 1);
130 case 'l': /* qemu_ld / qemu_st address, data_reg */
131 ct
->ct
|= TCG_CT_REG
;
132 tcg_regset_set32(ct
->u
.regs
, 0, (1ULL << TCG_TARGET_NB_REGS
) - 1);
133 #ifdef CONFIG_SOFTMMU
134 /* x0 and x1 will be overwritten when reading the tlb entry,
135 and x2, and x3 for helper args, better to avoid using them. */
136 tcg_regset_reset_reg(ct
->u
.regs
, TCG_REG_X0
);
137 tcg_regset_reset_reg(ct
->u
.regs
, TCG_REG_X1
);
138 tcg_regset_reset_reg(ct
->u
.regs
, TCG_REG_X2
);
139 tcg_regset_reset_reg(ct
->u
.regs
, TCG_REG_X3
);
142 case 'w': /* The operand should be considered 32-bit. */
143 ct
->ct
|= TCG_CT_CONST_IS32
;
145 case 'A': /* Valid for arithmetic immediate (positive or negative). */
146 ct
->ct
|= TCG_CT_CONST_AIMM
;
148 case 'L': /* Valid for logical immediate. */
149 ct
->ct
|= TCG_CT_CONST_LIMM
;
151 case 'M': /* minus one */
152 ct
->ct
|= TCG_CT_CONST_MONE
;
155 ct
->ct
|= TCG_CT_CONST_ZERO
;
166 static inline bool is_aimm(uint64_t val
)
168 return (val
& ~0xfff) == 0 || (val
& ~0xfff000) == 0;
171 static inline bool is_limm(uint64_t val
)
173 /* Taking a simplified view of the logical immediates for now, ignoring
174 the replication that can happen across the field. Match bit patterns
178 and their inverses. */
180 /* Make things easier below, by testing the form with msb clear. */
181 if ((int64_t)val
< 0) {
188 return (val
& (val
- 1)) == 0;
191 static int tcg_target_const_match(tcg_target_long val
,
192 const TCGArgConstraint
*arg_ct
)
196 if (ct
& TCG_CT_CONST
) {
199 if (ct
& TCG_CT_CONST_IS32
) {
202 if ((ct
& TCG_CT_CONST_AIMM
) && (is_aimm(val
) || is_aimm(-val
))) {
205 if ((ct
& TCG_CT_CONST_LIMM
) && is_limm(val
)) {
208 if ((ct
& TCG_CT_CONST_ZERO
) && val
== 0) {
211 if ((ct
& TCG_CT_CONST_MONE
) && val
== -1) {
218 enum aarch64_cond_code
{
221 COND_CS
= 0x2, /* Unsigned greater or equal */
222 COND_HS
= COND_CS
, /* ALIAS greater or equal */
223 COND_CC
= 0x3, /* Unsigned less than */
224 COND_LO
= COND_CC
, /* ALIAS Lower */
225 COND_MI
= 0x4, /* Negative */
226 COND_PL
= 0x5, /* Zero or greater */
227 COND_VS
= 0x6, /* Overflow */
228 COND_VC
= 0x7, /* No overflow */
229 COND_HI
= 0x8, /* Unsigned greater than */
230 COND_LS
= 0x9, /* Unsigned less or equal */
236 COND_NV
= 0xf, /* behaves like COND_AL here */
239 static const enum aarch64_cond_code tcg_cond_to_aarch64
[] = {
240 [TCG_COND_EQ
] = COND_EQ
,
241 [TCG_COND_NE
] = COND_NE
,
242 [TCG_COND_LT
] = COND_LT
,
243 [TCG_COND_GE
] = COND_GE
,
244 [TCG_COND_LE
] = COND_LE
,
245 [TCG_COND_GT
] = COND_GT
,
247 [TCG_COND_LTU
] = COND_LO
,
248 [TCG_COND_GTU
] = COND_HI
,
249 [TCG_COND_GEU
] = COND_HS
,
250 [TCG_COND_LEU
] = COND_LS
,
253 /* opcodes for LDR / STR instructions with base + simm9 addressing */
254 enum aarch64_ldst_op_data
{ /* size of the data moved */
260 enum aarch64_ldst_op_type
{ /* type of operation */
261 LDST_ST
= 0x0, /* store */
262 LDST_LD
= 0x4, /* load */
263 LDST_LD_S_X
= 0x8, /* load and sign-extend into Xt */
264 LDST_LD_S_W
= 0xc, /* load and sign-extend into Wt */
267 /* We encode the format of the insn into the beginning of the name, so that
268 we can have the preprocessor help "typecheck" the insn vs the output
269 function. Arm didn't provide us with nice names for the formats, so we
270 use the section number of the architecture reference manual in which the
271 instruction group is described. */
273 /* Add/subtract immediate instructions. */
274 I3401_ADDI
= 0x11000000,
275 I3401_ADDSI
= 0x31000000,
276 I3401_SUBI
= 0x51000000,
277 I3401_SUBSI
= 0x71000000,
279 /* Bitfield instructions. */
280 I3402_BFM
= 0x33000000,
281 I3402_SBFM
= 0x13000000,
282 I3402_UBFM
= 0x53000000,
284 /* Extract instruction. */
285 I3403_EXTR
= 0x13800000,
287 /* Logical immediate instructions. */
288 I3404_ANDI
= 0x12000000,
289 I3404_ORRI
= 0x32000000,
290 I3404_EORI
= 0x52000000,
292 /* Move wide immediate instructions. */
293 I3405_MOVN
= 0x12800000,
294 I3405_MOVZ
= 0x52800000,
295 I3405_MOVK
= 0x72800000,
297 /* Add/subtract shifted register instructions (without a shift). */
298 I3502_ADD
= 0x0b000000,
299 I3502_ADDS
= 0x2b000000,
300 I3502_SUB
= 0x4b000000,
301 I3502_SUBS
= 0x6b000000,
303 /* Add/subtract shifted register instructions (with a shift). */
304 I3502S_ADD_LSL
= I3502_ADD
,
306 /* Add/subtract with carry instructions. */
307 I3503_ADC
= 0x1a000000,
308 I3503_SBC
= 0x5a000000,
310 /* Conditional select instructions. */
311 I3506_CSEL
= 0x1a800000,
312 I3506_CSINC
= 0x1a800400,
314 /* Data-processing (2 source) instructions. */
315 I3508_LSLV
= 0x1ac02000,
316 I3508_LSRV
= 0x1ac02400,
317 I3508_ASRV
= 0x1ac02800,
318 I3508_RORV
= 0x1ac02c00,
319 I3508_SMULH
= 0x9b407c00,
320 I3508_UMULH
= 0x9bc07c00,
321 I3508_UDIV
= 0x1ac00800,
322 I3508_SDIV
= 0x1ac00c00,
324 /* Data-processing (3 source) instructions. */
325 I3509_MADD
= 0x1b000000,
326 I3509_MSUB
= 0x1b008000,
328 /* Logical shifted register instructions (without a shift). */
329 I3510_AND
= 0x0a000000,
330 I3510_BIC
= 0x0a200000,
331 I3510_ORR
= 0x2a000000,
332 I3510_ORN
= 0x2a200000,
333 I3510_EOR
= 0x4a000000,
334 I3510_EON
= 0x4a200000,
335 I3510_ANDS
= 0x6a000000,
338 static inline enum aarch64_ldst_op_data
339 aarch64_ldst_get_data(TCGOpcode tcg_op
)
342 case INDEX_op_ld8u_i32
:
343 case INDEX_op_ld8s_i32
:
344 case INDEX_op_ld8u_i64
:
345 case INDEX_op_ld8s_i64
:
346 case INDEX_op_st8_i32
:
347 case INDEX_op_st8_i64
:
350 case INDEX_op_ld16u_i32
:
351 case INDEX_op_ld16s_i32
:
352 case INDEX_op_ld16u_i64
:
353 case INDEX_op_ld16s_i64
:
354 case INDEX_op_st16_i32
:
355 case INDEX_op_st16_i64
:
358 case INDEX_op_ld_i32
:
359 case INDEX_op_st_i32
:
360 case INDEX_op_ld32u_i64
:
361 case INDEX_op_ld32s_i64
:
362 case INDEX_op_st32_i64
:
365 case INDEX_op_ld_i64
:
366 case INDEX_op_st_i64
:
374 static inline enum aarch64_ldst_op_type
375 aarch64_ldst_get_type(TCGOpcode tcg_op
)
378 case INDEX_op_st8_i32
:
379 case INDEX_op_st16_i32
:
380 case INDEX_op_st8_i64
:
381 case INDEX_op_st16_i64
:
382 case INDEX_op_st_i32
:
383 case INDEX_op_st32_i64
:
384 case INDEX_op_st_i64
:
387 case INDEX_op_ld8u_i32
:
388 case INDEX_op_ld16u_i32
:
389 case INDEX_op_ld8u_i64
:
390 case INDEX_op_ld16u_i64
:
391 case INDEX_op_ld_i32
:
392 case INDEX_op_ld32u_i64
:
393 case INDEX_op_ld_i64
:
396 case INDEX_op_ld8s_i32
:
397 case INDEX_op_ld16s_i32
:
400 case INDEX_op_ld8s_i64
:
401 case INDEX_op_ld16s_i64
:
402 case INDEX_op_ld32s_i64
:
410 static inline uint32_t tcg_in32(TCGContext
*s
)
412 uint32_t v
= *(uint32_t *)s
->code_ptr
;
416 /* Emit an opcode with "type-checking" of the format. */
417 #define tcg_out_insn(S, FMT, OP, ...) \
418 glue(tcg_out_insn_,FMT)(S, glue(glue(glue(I,FMT),_),OP), ## __VA_ARGS__)
420 static void tcg_out_insn_3401(TCGContext
*s
, AArch64Insn insn
, TCGType ext
,
421 TCGReg rd
, TCGReg rn
, uint64_t aimm
)
424 assert((aimm
& 0xfff) == 0);
426 assert(aimm
<= 0xfff);
427 aimm
|= 1 << 12; /* apply LSL 12 */
429 tcg_out32(s
, insn
| ext
<< 31 | aimm
<< 10 | rn
<< 5 | rd
);
432 /* This function can be used for both 3.4.2 (Bitfield) and 3.4.4
433 (Logical immediate). Both insn groups have N, IMMR and IMMS fields
434 that feed the DecodeBitMasks pseudo function. */
435 static void tcg_out_insn_3402(TCGContext
*s
, AArch64Insn insn
, TCGType ext
,
436 TCGReg rd
, TCGReg rn
, int n
, int immr
, int imms
)
438 tcg_out32(s
, insn
| ext
<< 31 | n
<< 22 | immr
<< 16 | imms
<< 10
442 #define tcg_out_insn_3404 tcg_out_insn_3402
444 static void tcg_out_insn_3403(TCGContext
*s
, AArch64Insn insn
, TCGType ext
,
445 TCGReg rd
, TCGReg rn
, TCGReg rm
, int imms
)
447 tcg_out32(s
, insn
| ext
<< 31 | ext
<< 22 | rm
<< 16 | imms
<< 10
451 /* This function is used for the Move (wide immediate) instruction group.
452 Note that SHIFT is a full shift count, not the 2 bit HW field. */
453 static void tcg_out_insn_3405(TCGContext
*s
, AArch64Insn insn
, TCGType ext
,
454 TCGReg rd
, uint16_t half
, unsigned shift
)
456 assert((shift
& ~0x30) == 0);
457 tcg_out32(s
, insn
| ext
<< 31 | shift
<< (21 - 4) | half
<< 5 | rd
);
460 /* This function is for both 3.5.2 (Add/Subtract shifted register), for
461 the rare occasion when we actually want to supply a shift amount. */
462 static inline void tcg_out_insn_3502S(TCGContext
*s
, AArch64Insn insn
,
463 TCGType ext
, TCGReg rd
, TCGReg rn
,
466 tcg_out32(s
, insn
| ext
<< 31 | rm
<< 16 | imm6
<< 10 | rn
<< 5 | rd
);
469 /* This function is for 3.5.2 (Add/subtract shifted register),
470 and 3.5.10 (Logical shifted register), for the vast majorty of cases
471 when we don't want to apply a shift. Thus it can also be used for
472 3.5.3 (Add/subtract with carry) and 3.5.8 (Data processing 2 source). */
473 static void tcg_out_insn_3502(TCGContext
*s
, AArch64Insn insn
, TCGType ext
,
474 TCGReg rd
, TCGReg rn
, TCGReg rm
)
476 tcg_out32(s
, insn
| ext
<< 31 | rm
<< 16 | rn
<< 5 | rd
);
479 #define tcg_out_insn_3503 tcg_out_insn_3502
480 #define tcg_out_insn_3508 tcg_out_insn_3502
481 #define tcg_out_insn_3510 tcg_out_insn_3502
483 static void tcg_out_insn_3506(TCGContext
*s
, AArch64Insn insn
, TCGType ext
,
484 TCGReg rd
, TCGReg rn
, TCGReg rm
, TCGCond c
)
486 tcg_out32(s
, insn
| ext
<< 31 | rm
<< 16 | rn
<< 5 | rd
487 | tcg_cond_to_aarch64
[c
] << 12);
490 static void tcg_out_insn_3509(TCGContext
*s
, AArch64Insn insn
, TCGType ext
,
491 TCGReg rd
, TCGReg rn
, TCGReg rm
, TCGReg ra
)
493 tcg_out32(s
, insn
| ext
<< 31 | rm
<< 16 | ra
<< 10 | rn
<< 5 | rd
);
497 static inline void tcg_out_ldst_9(TCGContext
*s
,
498 enum aarch64_ldst_op_data op_data
,
499 enum aarch64_ldst_op_type op_type
,
500 TCGReg rd
, TCGReg rn
, intptr_t offset
)
502 /* use LDUR with BASE register with 9bit signed unscaled offset */
503 tcg_out32(s
, op_data
<< 24 | op_type
<< 20
504 | (offset
& 0x1ff) << 12 | rn
<< 5 | rd
);
507 /* tcg_out_ldst_12 expects a scaled unsigned immediate offset */
508 static inline void tcg_out_ldst_12(TCGContext
*s
,
509 enum aarch64_ldst_op_data op_data
,
510 enum aarch64_ldst_op_type op_type
,
511 TCGReg rd
, TCGReg rn
,
512 tcg_target_ulong scaled_uimm
)
514 tcg_out32(s
, (op_data
| 1) << 24
515 | op_type
<< 20 | scaled_uimm
<< 10 | rn
<< 5 | rd
);
518 /* Register to register move using ORR (shifted register with no shift). */
519 static void tcg_out_movr(TCGContext
*s
, TCGType ext
, TCGReg rd
, TCGReg rm
)
521 tcg_out_insn(s
, 3510, ORR
, ext
, rd
, TCG_REG_XZR
, rm
);
524 /* Register to register move using ADDI (move to/from SP). */
525 static void tcg_out_movr_sp(TCGContext
*s
, TCGType ext
, TCGReg rd
, TCGReg rn
)
527 tcg_out_insn(s
, 3401, ADDI
, ext
, rd
, rn
, 0);
530 static void tcg_out_movi(TCGContext
*s
, TCGType type
, TCGReg rd
,
531 tcg_target_long value
)
534 int i
, wantinv
, shift
;
535 tcg_target_long svalue
= value
;
536 tcg_target_long ivalue
= ~value
;
537 tcg_target_long imask
;
539 /* For 32-bit values, discard potential garbage in value. For 64-bit
540 values within [2**31, 2**32-1], we can create smaller sequences by
541 interpreting this as a negative 32-bit number, while ensuring that
542 the high 32 bits are cleared by setting SF=0. */
543 if (type
== TCG_TYPE_I32
|| (value
& ~0xffffffffull
) == 0) {
544 svalue
= (int32_t)value
;
545 value
= (uint32_t)value
;
546 ivalue
= (uint32_t)ivalue
;
550 /* Would it take fewer insns to begin with MOVN? For the value and its
551 inverse, count the number of 16-bit lanes that are 0. */
552 for (i
= wantinv
= imask
= 0; i
< 64; i
+= 16) {
553 tcg_target_long mask
= 0xffffull
<< i
;
554 if ((value
& mask
) == 0) {
557 if ((ivalue
& mask
) == 0) {
563 /* If we had more 0xffff than 0x0000, invert VALUE and use MOVN. */
570 /* Find the lowest lane that is not 0x0000. */
571 shift
= ctz64(value
) & (63 & -16);
572 tcg_out_insn_3405(s
, insn
, type
, rd
, value
>> shift
, shift
);
575 /* Re-invert the value, so MOVK sees non-inverted bits. */
577 /* Clear out all the 0xffff lanes. */
580 /* Clear out the lane that we just set. */
581 value
&= ~(0xffffUL
<< shift
);
583 /* Iterate until all lanes have been set, and thus cleared from VALUE. */
585 shift
= ctz64(value
) & (63 & -16);
586 tcg_out_insn(s
, 3405, MOVK
, type
, rd
, value
>> shift
, shift
);
587 value
&= ~(0xffffUL
<< shift
);
591 static inline void tcg_out_ldst_r(TCGContext
*s
,
592 enum aarch64_ldst_op_data op_data
,
593 enum aarch64_ldst_op_type op_type
,
594 TCGReg rd
, TCGReg base
, TCGReg regoff
)
596 /* load from memory to register using base + 64bit register offset */
597 /* using f.e. STR Wt, [Xn, Xm] 0xb8600800|(regoff << 16)|(base << 5)|rd */
598 /* the 0x6000 is for the "no extend field" */
599 tcg_out32(s
, 0x00206800
600 | op_data
<< 24 | op_type
<< 20 | regoff
<< 16 | base
<< 5 | rd
);
603 /* solve the whole ldst problem */
604 static inline void tcg_out_ldst(TCGContext
*s
, enum aarch64_ldst_op_data data
,
605 enum aarch64_ldst_op_type type
,
606 TCGReg rd
, TCGReg rn
, intptr_t offset
)
608 if (offset
>= -256 && offset
< 256) {
609 tcg_out_ldst_9(s
, data
, type
, rd
, rn
, offset
);
614 /* if the offset is naturally aligned and in range,
615 then we can use the scaled uimm12 encoding */
616 unsigned int s_bits
= data
>> 6;
617 if (!(offset
& ((1 << s_bits
) - 1))) {
618 tcg_target_ulong scaled_uimm
= offset
>> s_bits
;
619 if (scaled_uimm
<= 0xfff) {
620 tcg_out_ldst_12(s
, data
, type
, rd
, rn
, scaled_uimm
);
626 /* worst-case scenario, move offset to temp register, use reg offset */
627 tcg_out_movi(s
, TCG_TYPE_I64
, TCG_REG_TMP
, offset
);
628 tcg_out_ldst_r(s
, data
, type
, rd
, rn
, TCG_REG_TMP
);
631 static inline void tcg_out_mov(TCGContext
*s
,
632 TCGType type
, TCGReg ret
, TCGReg arg
)
635 tcg_out_movr(s
, type
, ret
, arg
);
639 static inline void tcg_out_ld(TCGContext
*s
, TCGType type
, TCGReg arg
,
640 TCGReg arg1
, intptr_t arg2
)
642 tcg_out_ldst(s
, (type
== TCG_TYPE_I64
) ? LDST_64
: LDST_32
, LDST_LD
,
646 static inline void tcg_out_st(TCGContext
*s
, TCGType type
, TCGReg arg
,
647 TCGReg arg1
, intptr_t arg2
)
649 tcg_out_ldst(s
, (type
== TCG_TYPE_I64
) ? LDST_64
: LDST_32
, LDST_ST
,
653 static inline void tcg_out_bfm(TCGContext
*s
, TCGType ext
, TCGReg rd
,
654 TCGReg rn
, unsigned int a
, unsigned int b
)
656 tcg_out_insn(s
, 3402, BFM
, ext
, rd
, rn
, ext
, a
, b
);
659 static inline void tcg_out_ubfm(TCGContext
*s
, TCGType ext
, TCGReg rd
,
660 TCGReg rn
, unsigned int a
, unsigned int b
)
662 tcg_out_insn(s
, 3402, UBFM
, ext
, rd
, rn
, ext
, a
, b
);
665 static inline void tcg_out_sbfm(TCGContext
*s
, TCGType ext
, TCGReg rd
,
666 TCGReg rn
, unsigned int a
, unsigned int b
)
668 tcg_out_insn(s
, 3402, SBFM
, ext
, rd
, rn
, ext
, a
, b
);
671 static inline void tcg_out_extr(TCGContext
*s
, TCGType ext
, TCGReg rd
,
672 TCGReg rn
, TCGReg rm
, unsigned int a
)
674 tcg_out_insn(s
, 3403, EXTR
, ext
, rd
, rn
, rm
, a
);
677 static inline void tcg_out_shl(TCGContext
*s
, TCGType ext
,
678 TCGReg rd
, TCGReg rn
, unsigned int m
)
680 int bits
= ext
? 64 : 32;
682 tcg_out_ubfm(s
, ext
, rd
, rn
, bits
- (m
& max
), max
- (m
& max
));
685 static inline void tcg_out_shr(TCGContext
*s
, TCGType ext
,
686 TCGReg rd
, TCGReg rn
, unsigned int m
)
688 int max
= ext
? 63 : 31;
689 tcg_out_ubfm(s
, ext
, rd
, rn
, m
& max
, max
);
692 static inline void tcg_out_sar(TCGContext
*s
, TCGType ext
,
693 TCGReg rd
, TCGReg rn
, unsigned int m
)
695 int max
= ext
? 63 : 31;
696 tcg_out_sbfm(s
, ext
, rd
, rn
, m
& max
, max
);
699 static inline void tcg_out_rotr(TCGContext
*s
, TCGType ext
,
700 TCGReg rd
, TCGReg rn
, unsigned int m
)
702 int max
= ext
? 63 : 31;
703 tcg_out_extr(s
, ext
, rd
, rn
, rn
, m
& max
);
706 static inline void tcg_out_rotl(TCGContext
*s
, TCGType ext
,
707 TCGReg rd
, TCGReg rn
, unsigned int m
)
709 int bits
= ext
? 64 : 32;
711 tcg_out_extr(s
, ext
, rd
, rn
, rn
, bits
- (m
& max
));
714 static inline void tcg_out_dep(TCGContext
*s
, TCGType ext
, TCGReg rd
,
715 TCGReg rn
, unsigned lsb
, unsigned width
)
717 unsigned size
= ext
? 64 : 32;
718 unsigned a
= (size
- lsb
) & (size
- 1);
719 unsigned b
= width
- 1;
720 tcg_out_bfm(s
, ext
, rd
, rn
, a
, b
);
723 static void tcg_out_cmp(TCGContext
*s
, TCGType ext
, TCGReg a
,
724 tcg_target_long b
, bool const_b
)
727 /* Using CMP or CMN aliases. */
729 tcg_out_insn(s
, 3401, SUBSI
, ext
, TCG_REG_XZR
, a
, b
);
731 tcg_out_insn(s
, 3401, ADDSI
, ext
, TCG_REG_XZR
, a
, -b
);
734 /* Using CMP alias SUBS wzr, Wn, Wm */
735 tcg_out_insn(s
, 3502, SUBS
, ext
, TCG_REG_XZR
, a
, b
);
739 static inline void tcg_out_goto(TCGContext
*s
, intptr_t target
)
741 intptr_t offset
= (target
- (intptr_t)s
->code_ptr
) / 4;
743 if (offset
< -0x02000000 || offset
>= 0x02000000) {
744 /* out of 26bit range */
748 tcg_out32(s
, 0x14000000 | (offset
& 0x03ffffff));
751 static inline void tcg_out_goto_noaddr(TCGContext
*s
)
753 /* We pay attention here to not modify the branch target by
754 reading from the buffer. This ensure that caches and memory are
755 kept coherent during retranslation.
756 Mask away possible garbage in the high bits for the first translation,
757 while keeping the offset bits for retranslation. */
759 insn
= (tcg_in32(s
) & 0x03ffffff) | 0x14000000;
763 static inline void tcg_out_goto_cond_noaddr(TCGContext
*s
, TCGCond c
)
765 /* see comments in tcg_out_goto_noaddr */
767 insn
= tcg_in32(s
) & (0x07ffff << 5);
768 insn
|= 0x54000000 | tcg_cond_to_aarch64
[c
];
772 static inline void tcg_out_goto_cond(TCGContext
*s
, TCGCond c
, intptr_t target
)
774 intptr_t offset
= (target
- (intptr_t)s
->code_ptr
) / 4;
776 if (offset
< -0x40000 || offset
>= 0x40000) {
777 /* out of 19bit range */
782 tcg_out32(s
, 0x54000000 | tcg_cond_to_aarch64
[c
] | offset
<< 5);
785 static inline void tcg_out_callr(TCGContext
*s
, TCGReg reg
)
787 tcg_out32(s
, 0xd63f0000 | reg
<< 5);
790 static inline void tcg_out_gotor(TCGContext
*s
, TCGReg reg
)
792 tcg_out32(s
, 0xd61f0000 | reg
<< 5);
795 static inline void tcg_out_call(TCGContext
*s
, intptr_t target
)
797 intptr_t offset
= (target
- (intptr_t)s
->code_ptr
) / 4;
799 if (offset
< -0x02000000 || offset
>= 0x02000000) { /* out of 26bit rng */
800 tcg_out_movi(s
, TCG_TYPE_I64
, TCG_REG_TMP
, target
);
801 tcg_out_callr(s
, TCG_REG_TMP
);
803 tcg_out32(s
, 0x94000000 | (offset
& 0x03ffffff));
807 static inline void tcg_out_ret(TCGContext
*s
)
809 /* emit RET { LR } */
810 tcg_out32(s
, 0xd65f03c0);
813 void aarch64_tb_set_jmp_target(uintptr_t jmp_addr
, uintptr_t addr
)
815 intptr_t target
= addr
;
816 intptr_t offset
= (target
- (intptr_t)jmp_addr
) / 4;
818 if (offset
< -0x02000000 || offset
>= 0x02000000) {
819 /* out of 26bit range */
823 patch_reloc((uint8_t *)jmp_addr
, R_AARCH64_JUMP26
, target
, 0);
824 flush_icache_range(jmp_addr
, jmp_addr
+ 4);
827 static inline void tcg_out_goto_label(TCGContext
*s
, int label_index
)
829 TCGLabel
*l
= &s
->labels
[label_index
];
832 tcg_out_reloc(s
, s
->code_ptr
, R_AARCH64_JUMP26
, label_index
, 0);
833 tcg_out_goto_noaddr(s
);
835 tcg_out_goto(s
, l
->u
.value
);
839 static inline void tcg_out_goto_label_cond(TCGContext
*s
,
840 TCGCond c
, int label_index
)
842 TCGLabel
*l
= &s
->labels
[label_index
];
845 tcg_out_reloc(s
, s
->code_ptr
, R_AARCH64_CONDBR19
, label_index
, 0);
846 tcg_out_goto_cond_noaddr(s
, c
);
848 tcg_out_goto_cond(s
, c
, l
->u
.value
);
852 static inline void tcg_out_rev(TCGContext
*s
, TCGType ext
,
853 TCGReg rd
, TCGReg rm
)
855 /* using REV 0x5ac00800 */
856 unsigned int base
= ext
? 0xdac00c00 : 0x5ac00800;
857 tcg_out32(s
, base
| rm
<< 5 | rd
);
860 static inline void tcg_out_rev16(TCGContext
*s
, TCGType ext
,
861 TCGReg rd
, TCGReg rm
)
863 /* using REV16 0x5ac00400 */
864 unsigned int base
= ext
? 0xdac00400 : 0x5ac00400;
865 tcg_out32(s
, base
| rm
<< 5 | rd
);
868 static inline void tcg_out_sxt(TCGContext
*s
, TCGType ext
, TCGMemOp s_bits
,
869 TCGReg rd
, TCGReg rn
)
871 /* Using ALIASes SXTB, SXTH, SXTW, of SBFM Xd, Xn, #0, #7|15|31 */
872 int bits
= (8 << s_bits
) - 1;
873 tcg_out_sbfm(s
, ext
, rd
, rn
, 0, bits
);
876 static inline void tcg_out_uxt(TCGContext
*s
, TCGMemOp s_bits
,
877 TCGReg rd
, TCGReg rn
)
879 /* Using ALIASes UXTB, UXTH of UBFM Wd, Wn, #0, #7|15 */
880 int bits
= (8 << s_bits
) - 1;
881 tcg_out_ubfm(s
, 0, rd
, rn
, 0, bits
);
884 static void tcg_out_addsubi(TCGContext
*s
, int ext
, TCGReg rd
,
885 TCGReg rn
, int64_t aimm
)
888 tcg_out_insn(s
, 3401, ADDI
, ext
, rd
, rn
, aimm
);
890 tcg_out_insn(s
, 3401, SUBI
, ext
, rd
, rn
, -aimm
);
894 /* This function is used for the Logical (immediate) instruction group.
895 The value of LIMM must satisfy IS_LIMM. See the comment above about
896 only supporting simplified logical immediates. */
897 static void tcg_out_logicali(TCGContext
*s
, AArch64Insn insn
, TCGType ext
,
898 TCGReg rd
, TCGReg rn
, uint64_t limm
)
902 assert(is_limm(limm
));
907 r
= 0; /* form 0....01....1 */
908 c
= ctz64(~limm
) - 1;
910 r
= clz64(~limm
); /* form 1..10..01..1 */
914 r
= 64 - l
; /* form 1....10....0 or 0..01..10..0 */
917 if (ext
== TCG_TYPE_I32
) {
922 tcg_out_insn_3404(s
, insn
, ext
, rd
, rn
, ext
, r
, c
);
925 static inline void tcg_out_addsub2(TCGContext
*s
, int ext
, TCGReg rl
,
926 TCGReg rh
, TCGReg al
, TCGReg ah
,
927 tcg_target_long bl
, tcg_target_long bh
,
928 bool const_bl
, bool const_bh
, bool sub
)
933 if (rl
== ah
|| (!const_bh
&& rl
== bh
)) {
939 if ((bl
< 0) ^ sub
) {
943 tcg_out_insn_3401(s
, insn
, ext
, rl
, al
, bl
);
945 tcg_out_insn_3502(s
, sub
? I3502_SUBS
: I3502_ADDS
, ext
, rl
, al
, bl
);
950 /* Note that the only two constants we support are 0 and -1, and
951 that SBC = rn + ~rm + c, so adc -1 is sbc 0, and vice-versa. */
952 if ((bh
!= 0) ^ sub
) {
959 tcg_out_insn_3503(s
, insn
, ext
, rh
, ah
, bh
);
962 tcg_out_movr(s
, ext
, orig_rl
, rl
);
966 #ifdef CONFIG_SOFTMMU
967 /* helper signature: helper_ret_ld_mmu(CPUState *env, target_ulong addr,
968 * int mmu_idx, uintptr_t ra)
970 static const void * const qemu_ld_helpers
[4] = {
977 /* helper signature: helper_ret_st_mmu(CPUState *env, target_ulong addr,
978 * uintxx_t val, int mmu_idx, uintptr_t ra)
980 static const void * const qemu_st_helpers
[4] = {
987 static void tcg_out_qemu_ld_slow_path(TCGContext
*s
, TCGLabelQemuLdst
*lb
)
989 TCGMemOp opc
= lb
->opc
;
990 TCGMemOp size
= opc
& MO_SIZE
;
992 reloc_pc19(lb
->label_ptr
[0], (intptr_t)s
->code_ptr
);
994 tcg_out_movr(s
, TCG_TYPE_I64
, TCG_REG_X0
, TCG_AREG0
);
995 tcg_out_movr(s
, TARGET_LONG_BITS
== 64, TCG_REG_X1
, lb
->addrlo_reg
);
996 tcg_out_movi(s
, TCG_TYPE_I32
, TCG_REG_X2
, lb
->mem_index
);
997 tcg_out_movi(s
, TCG_TYPE_PTR
, TCG_REG_X3
, (intptr_t)lb
->raddr
);
998 tcg_out_movi(s
, TCG_TYPE_I64
, TCG_REG_TMP
, (intptr_t)qemu_ld_helpers
[size
]);
999 tcg_out_callr(s
, TCG_REG_TMP
);
1000 if (opc
& MO_SIGN
) {
1001 tcg_out_sxt(s
, TCG_TYPE_I64
, size
, lb
->datalo_reg
, TCG_REG_X0
);
1003 tcg_out_movr(s
, TCG_TYPE_I64
, lb
->datalo_reg
, TCG_REG_X0
);
1006 tcg_out_goto(s
, (intptr_t)lb
->raddr
);
1009 static void tcg_out_qemu_st_slow_path(TCGContext
*s
, TCGLabelQemuLdst
*lb
)
1011 TCGMemOp size
= lb
->opc
;
1013 reloc_pc19(lb
->label_ptr
[0], (intptr_t)s
->code_ptr
);
1015 tcg_out_movr(s
, TCG_TYPE_I64
, TCG_REG_X0
, TCG_AREG0
);
1016 tcg_out_movr(s
, TARGET_LONG_BITS
== 64, TCG_REG_X1
, lb
->addrlo_reg
);
1017 tcg_out_movr(s
, size
== MO_64
, TCG_REG_X2
, lb
->datalo_reg
);
1018 tcg_out_movi(s
, TCG_TYPE_I32
, TCG_REG_X3
, lb
->mem_index
);
1019 tcg_out_movi(s
, TCG_TYPE_PTR
, TCG_REG_X4
, (intptr_t)lb
->raddr
);
1020 tcg_out_movi(s
, TCG_TYPE_I64
, TCG_REG_TMP
, (intptr_t)qemu_st_helpers
[size
]);
1021 tcg_out_callr(s
, TCG_REG_TMP
);
1022 tcg_out_goto(s
, (intptr_t)lb
->raddr
);
1025 static void add_qemu_ldst_label(TCGContext
*s
, int is_ld
, int opc
,
1026 TCGReg data_reg
, TCGReg addr_reg
,
1028 uint8_t *raddr
, uint8_t *label_ptr
)
1030 TCGLabelQemuLdst
*label
= new_ldst_label(s
);
1032 label
->is_ld
= is_ld
;
1034 label
->datalo_reg
= data_reg
;
1035 label
->addrlo_reg
= addr_reg
;
1036 label
->mem_index
= mem_index
;
1037 label
->raddr
= raddr
;
1038 label
->label_ptr
[0] = label_ptr
;
1041 /* Load and compare a TLB entry, emitting the conditional jump to the
1042 slow path for the failure case, which will be patched later when finalizing
1043 the slow path. Generated code returns the host addend in X1,
1044 clobbers X0,X2,X3,TMP. */
1045 static void tcg_out_tlb_read(TCGContext
*s
, TCGReg addr_reg
,
1046 int s_bits
, uint8_t **label_ptr
, int mem_index
, int is_read
)
1048 TCGReg base
= TCG_AREG0
;
1049 int tlb_offset
= is_read
?
1050 offsetof(CPUArchState
, tlb_table
[mem_index
][0].addr_read
)
1051 : offsetof(CPUArchState
, tlb_table
[mem_index
][0].addr_write
);
1052 /* Extract the TLB index from the address into X0.
1053 X0<CPU_TLB_BITS:0> =
1054 addr_reg<TARGET_PAGE_BITS+CPU_TLB_BITS:TARGET_PAGE_BITS> */
1055 tcg_out_ubfm(s
, (TARGET_LONG_BITS
== 64), TCG_REG_X0
, addr_reg
,
1056 TARGET_PAGE_BITS
, TARGET_PAGE_BITS
+ CPU_TLB_BITS
);
1057 /* Store the page mask part of the address and the low s_bits into X3.
1058 Later this allows checking for equality and alignment at the same time.
1059 X3 = addr_reg & (PAGE_MASK | ((1 << s_bits) - 1)) */
1060 tcg_out_logicali(s
, I3404_ANDI
, TARGET_LONG_BITS
== 64, TCG_REG_X3
,
1061 addr_reg
, TARGET_PAGE_MASK
| ((1 << s_bits
) - 1));
1062 /* Add any "high bits" from the tlb offset to the env address into X2,
1063 to take advantage of the LSL12 form of the ADDI instruction.
1064 X2 = env + (tlb_offset & 0xfff000) */
1065 tcg_out_insn(s
, 3401, ADDI
, TCG_TYPE_I64
, TCG_REG_X2
, base
,
1066 tlb_offset
& 0xfff000);
1067 /* Merge the tlb index contribution into X2.
1068 X2 = X2 + (X0 << CPU_TLB_ENTRY_BITS) */
1069 tcg_out_insn(s
, 3502S
, ADD_LSL
, 1, TCG_REG_X2
, TCG_REG_X2
,
1070 TCG_REG_X0
, CPU_TLB_ENTRY_BITS
);
1071 /* Merge "low bits" from tlb offset, load the tlb comparator into X0.
1072 X0 = load [X2 + (tlb_offset & 0x000fff)] */
1073 tcg_out_ldst(s
, TARGET_LONG_BITS
== 64 ? LDST_64
: LDST_32
,
1074 LDST_LD
, TCG_REG_X0
, TCG_REG_X2
,
1075 (tlb_offset
& 0xfff));
1076 /* Load the tlb addend. Do that early to avoid stalling.
1077 X1 = load [X2 + (tlb_offset & 0xfff) + offsetof(addend)] */
1078 tcg_out_ldst(s
, LDST_64
, LDST_LD
, TCG_REG_X1
, TCG_REG_X2
,
1079 (tlb_offset
& 0xfff) + (offsetof(CPUTLBEntry
, addend
)) -
1080 (is_read
? offsetof(CPUTLBEntry
, addr_read
)
1081 : offsetof(CPUTLBEntry
, addr_write
)));
1082 /* Perform the address comparison. */
1083 tcg_out_cmp(s
, (TARGET_LONG_BITS
== 64), TCG_REG_X0
, TCG_REG_X3
, 0);
1084 *label_ptr
= s
->code_ptr
;
1085 /* If not equal, we jump to the slow path. */
1086 tcg_out_goto_cond_noaddr(s
, TCG_COND_NE
);
1089 #endif /* CONFIG_SOFTMMU */
1091 static void tcg_out_qemu_ld_direct(TCGContext
*s
, int opc
, TCGReg data_r
,
1092 TCGReg addr_r
, TCGReg off_r
)
1096 tcg_out_ldst_r(s
, LDST_8
, LDST_LD
, data_r
, addr_r
, off_r
);
1099 tcg_out_ldst_r(s
, LDST_8
, LDST_LD_S_X
, data_r
, addr_r
, off_r
);
1102 tcg_out_ldst_r(s
, LDST_16
, LDST_LD
, data_r
, addr_r
, off_r
);
1103 if (TCG_LDST_BSWAP
) {
1104 tcg_out_rev16(s
, TCG_TYPE_I32
, data_r
, data_r
);
1108 if (TCG_LDST_BSWAP
) {
1109 tcg_out_ldst_r(s
, LDST_16
, LDST_LD
, data_r
, addr_r
, off_r
);
1110 tcg_out_rev16(s
, TCG_TYPE_I32
, data_r
, data_r
);
1111 tcg_out_sxt(s
, TCG_TYPE_I64
, MO_16
, data_r
, data_r
);
1113 tcg_out_ldst_r(s
, LDST_16
, LDST_LD_S_X
, data_r
, addr_r
, off_r
);
1117 tcg_out_ldst_r(s
, LDST_32
, LDST_LD
, data_r
, addr_r
, off_r
);
1118 if (TCG_LDST_BSWAP
) {
1119 tcg_out_rev(s
, TCG_TYPE_I32
, data_r
, data_r
);
1123 if (TCG_LDST_BSWAP
) {
1124 tcg_out_ldst_r(s
, LDST_32
, LDST_LD
, data_r
, addr_r
, off_r
);
1125 tcg_out_rev(s
, TCG_TYPE_I32
, data_r
, data_r
);
1126 tcg_out_sxt(s
, TCG_TYPE_I64
, MO_32
, data_r
, data_r
);
1128 tcg_out_ldst_r(s
, LDST_32
, LDST_LD_S_X
, data_r
, addr_r
, off_r
);
1132 tcg_out_ldst_r(s
, LDST_64
, LDST_LD
, data_r
, addr_r
, off_r
);
1133 if (TCG_LDST_BSWAP
) {
1134 tcg_out_rev(s
, TCG_TYPE_I64
, data_r
, data_r
);
1142 static void tcg_out_qemu_st_direct(TCGContext
*s
, int opc
, TCGReg data_r
,
1143 TCGReg addr_r
, TCGReg off_r
)
1147 tcg_out_ldst_r(s
, LDST_8
, LDST_ST
, data_r
, addr_r
, off_r
);
1150 if (TCG_LDST_BSWAP
) {
1151 tcg_out_rev16(s
, TCG_TYPE_I32
, TCG_REG_TMP
, data_r
);
1152 tcg_out_ldst_r(s
, LDST_16
, LDST_ST
, TCG_REG_TMP
, addr_r
, off_r
);
1154 tcg_out_ldst_r(s
, LDST_16
, LDST_ST
, data_r
, addr_r
, off_r
);
1158 if (TCG_LDST_BSWAP
) {
1159 tcg_out_rev(s
, TCG_TYPE_I32
, TCG_REG_TMP
, data_r
);
1160 tcg_out_ldst_r(s
, LDST_32
, LDST_ST
, TCG_REG_TMP
, addr_r
, off_r
);
1162 tcg_out_ldst_r(s
, LDST_32
, LDST_ST
, data_r
, addr_r
, off_r
);
1166 if (TCG_LDST_BSWAP
) {
1167 tcg_out_rev(s
, TCG_TYPE_I64
, TCG_REG_TMP
, data_r
);
1168 tcg_out_ldst_r(s
, LDST_64
, LDST_ST
, TCG_REG_TMP
, addr_r
, off_r
);
1170 tcg_out_ldst_r(s
, LDST_64
, LDST_ST
, data_r
, addr_r
, off_r
);
1178 static void tcg_out_qemu_ld(TCGContext
*s
, const TCGArg
*args
, int opc
)
1180 TCGReg addr_reg
, data_reg
;
1181 #ifdef CONFIG_SOFTMMU
1182 int mem_index
, s_bits
;
1188 #ifdef CONFIG_SOFTMMU
1189 mem_index
= args
[2];
1191 tcg_out_tlb_read(s
, addr_reg
, s_bits
, &label_ptr
, mem_index
, 1);
1192 tcg_out_qemu_ld_direct(s
, opc
, data_reg
, addr_reg
, TCG_REG_X1
);
1193 add_qemu_ldst_label(s
, 1, opc
, data_reg
, addr_reg
,
1194 mem_index
, s
->code_ptr
, label_ptr
);
1195 #else /* !CONFIG_SOFTMMU */
1196 tcg_out_qemu_ld_direct(s
, opc
, data_reg
, addr_reg
,
1197 GUEST_BASE
? TCG_REG_GUEST_BASE
: TCG_REG_XZR
);
1198 #endif /* CONFIG_SOFTMMU */
1201 static void tcg_out_qemu_st(TCGContext
*s
, const TCGArg
*args
, int opc
)
1203 TCGReg addr_reg
, data_reg
;
1204 #ifdef CONFIG_SOFTMMU
1205 int mem_index
, s_bits
;
1211 #ifdef CONFIG_SOFTMMU
1212 mem_index
= args
[2];
1215 tcg_out_tlb_read(s
, addr_reg
, s_bits
, &label_ptr
, mem_index
, 0);
1216 tcg_out_qemu_st_direct(s
, opc
, data_reg
, addr_reg
, TCG_REG_X1
);
1217 add_qemu_ldst_label(s
, 0, opc
, data_reg
, addr_reg
,
1218 mem_index
, s
->code_ptr
, label_ptr
);
1219 #else /* !CONFIG_SOFTMMU */
1220 tcg_out_qemu_st_direct(s
, opc
, data_reg
, addr_reg
,
1221 GUEST_BASE
? TCG_REG_GUEST_BASE
: TCG_REG_XZR
);
1222 #endif /* CONFIG_SOFTMMU */
1225 static uint8_t *tb_ret_addr
;
1227 /* callee stack use example:
1228 stp x29, x30, [sp,#-32]!
1230 stp x1, x2, [sp,#16]
1232 ldp x1, x2, [sp,#16]
1233 ldp x29, x30, [sp],#32
1237 /* push r1 and r2, and alloc stack space for a total of
1238 alloc_n elements (1 element=16 bytes, must be between 1 and 31. */
1239 static inline void tcg_out_push_pair(TCGContext
*s
, TCGReg addr
,
1240 TCGReg r1
, TCGReg r2
, int alloc_n
)
1242 /* using indexed scaled simm7 STP 0x28800000 | (ext) | 0x01000000 (pre-idx)
1243 | alloc_n * (-1) << 16 | r2 << 10 | addr << 5 | r1 */
1244 assert(alloc_n
> 0 && alloc_n
< 0x20);
1245 alloc_n
= (-alloc_n
) & 0x3f;
1246 tcg_out32(s
, 0xa9800000 | alloc_n
<< 16 | r2
<< 10 | addr
<< 5 | r1
);
1249 /* dealloc stack space for a total of alloc_n elements and pop r1, r2. */
1250 static inline void tcg_out_pop_pair(TCGContext
*s
, TCGReg addr
,
1251 TCGReg r1
, TCGReg r2
, int alloc_n
)
1253 /* using indexed scaled simm7 LDP 0x28c00000 | (ext) | nothing (post-idx)
1254 | alloc_n << 16 | r2 << 10 | addr << 5 | r1 */
1255 assert(alloc_n
> 0 && alloc_n
< 0x20);
1256 tcg_out32(s
, 0xa8c00000 | alloc_n
<< 16 | r2
<< 10 | addr
<< 5 | r1
);
1259 static inline void tcg_out_store_pair(TCGContext
*s
, TCGReg addr
,
1260 TCGReg r1
, TCGReg r2
, int idx
)
1262 /* using register pair offset simm7 STP 0x29000000 | (ext)
1263 | idx << 16 | r2 << 10 | addr << 5 | r1 */
1264 assert(idx
> 0 && idx
< 0x20);
1265 tcg_out32(s
, 0xa9000000 | idx
<< 16 | r2
<< 10 | addr
<< 5 | r1
);
1268 static inline void tcg_out_load_pair(TCGContext
*s
, TCGReg addr
,
1269 TCGReg r1
, TCGReg r2
, int idx
)
1271 /* using register pair offset simm7 LDP 0x29400000 | (ext)
1272 | idx << 16 | r2 << 10 | addr << 5 | r1 */
1273 assert(idx
> 0 && idx
< 0x20);
1274 tcg_out32(s
, 0xa9400000 | idx
<< 16 | r2
<< 10 | addr
<< 5 | r1
);
1277 static void tcg_out_op(TCGContext
*s
, TCGOpcode opc
,
1278 const TCGArg args
[TCG_MAX_OP_ARGS
],
1279 const int const_args
[TCG_MAX_OP_ARGS
])
1281 /* 99% of the time, we can signal the use of extension registers
1282 by looking to see if the opcode handles 64-bit data. */
1283 TCGType ext
= (tcg_op_defs
[opc
].flags
& TCG_OPF_64BIT
) != 0;
1285 /* Hoist the loads of the most common arguments. */
1286 TCGArg a0
= args
[0];
1287 TCGArg a1
= args
[1];
1288 TCGArg a2
= args
[2];
1289 int c2
= const_args
[2];
1291 /* Some operands are defined with "rZ" constraint, a register or
1292 the zero register. These need not actually test args[I] == 0. */
1293 #define REG0(I) (const_args[I] ? TCG_REG_XZR : (TCGReg)args[I])
1296 case INDEX_op_exit_tb
:
1297 tcg_out_movi(s
, TCG_TYPE_I64
, TCG_REG_X0
, a0
);
1298 tcg_out_goto(s
, (intptr_t)tb_ret_addr
);
1301 case INDEX_op_goto_tb
:
1302 #ifndef USE_DIRECT_JUMP
1303 #error "USE_DIRECT_JUMP required for aarch64"
1305 assert(s
->tb_jmp_offset
!= NULL
); /* consistency for USE_DIRECT_JUMP */
1306 s
->tb_jmp_offset
[a0
] = s
->code_ptr
- s
->code_buf
;
1307 /* actual branch destination will be patched by
1308 aarch64_tb_set_jmp_target later, beware retranslation. */
1309 tcg_out_goto_noaddr(s
);
1310 s
->tb_next_offset
[a0
] = s
->code_ptr
- s
->code_buf
;
1314 if (const_args
[0]) {
1315 tcg_out_call(s
, a0
);
1317 tcg_out_callr(s
, a0
);
1322 tcg_out_goto_label(s
, a0
);
1325 case INDEX_op_ld_i32
:
1326 case INDEX_op_ld_i64
:
1327 case INDEX_op_st_i32
:
1328 case INDEX_op_st_i64
:
1329 case INDEX_op_ld8u_i32
:
1330 case INDEX_op_ld8s_i32
:
1331 case INDEX_op_ld16u_i32
:
1332 case INDEX_op_ld16s_i32
:
1333 case INDEX_op_ld8u_i64
:
1334 case INDEX_op_ld8s_i64
:
1335 case INDEX_op_ld16u_i64
:
1336 case INDEX_op_ld16s_i64
:
1337 case INDEX_op_ld32u_i64
:
1338 case INDEX_op_ld32s_i64
:
1339 case INDEX_op_st8_i32
:
1340 case INDEX_op_st8_i64
:
1341 case INDEX_op_st16_i32
:
1342 case INDEX_op_st16_i64
:
1343 case INDEX_op_st32_i64
:
1344 tcg_out_ldst(s
, aarch64_ldst_get_data(opc
), aarch64_ldst_get_type(opc
),
1348 case INDEX_op_add_i32
:
1351 case INDEX_op_add_i64
:
1353 tcg_out_addsubi(s
, ext
, a0
, a1
, a2
);
1355 tcg_out_insn(s
, 3502, ADD
, ext
, a0
, a1
, a2
);
1359 case INDEX_op_sub_i32
:
1362 case INDEX_op_sub_i64
:
1364 tcg_out_addsubi(s
, ext
, a0
, a1
, -a2
);
1366 tcg_out_insn(s
, 3502, SUB
, ext
, a0
, a1
, a2
);
1370 case INDEX_op_neg_i64
:
1371 case INDEX_op_neg_i32
:
1372 tcg_out_insn(s
, 3502, SUB
, ext
, a0
, TCG_REG_XZR
, a1
);
1375 case INDEX_op_and_i32
:
1378 case INDEX_op_and_i64
:
1380 tcg_out_logicali(s
, I3404_ANDI
, ext
, a0
, a1
, a2
);
1382 tcg_out_insn(s
, 3510, AND
, ext
, a0
, a1
, a2
);
1386 case INDEX_op_andc_i32
:
1389 case INDEX_op_andc_i64
:
1391 tcg_out_logicali(s
, I3404_ANDI
, ext
, a0
, a1
, ~a2
);
1393 tcg_out_insn(s
, 3510, BIC
, ext
, a0
, a1
, a2
);
1397 case INDEX_op_or_i32
:
1400 case INDEX_op_or_i64
:
1402 tcg_out_logicali(s
, I3404_ORRI
, ext
, a0
, a1
, a2
);
1404 tcg_out_insn(s
, 3510, ORR
, ext
, a0
, a1
, a2
);
1408 case INDEX_op_orc_i32
:
1411 case INDEX_op_orc_i64
:
1413 tcg_out_logicali(s
, I3404_ORRI
, ext
, a0
, a1
, ~a2
);
1415 tcg_out_insn(s
, 3510, ORN
, ext
, a0
, a1
, a2
);
1419 case INDEX_op_xor_i32
:
1422 case INDEX_op_xor_i64
:
1424 tcg_out_logicali(s
, I3404_EORI
, ext
, a0
, a1
, a2
);
1426 tcg_out_insn(s
, 3510, EOR
, ext
, a0
, a1
, a2
);
1430 case INDEX_op_eqv_i32
:
1433 case INDEX_op_eqv_i64
:
1435 tcg_out_logicali(s
, I3404_EORI
, ext
, a0
, a1
, ~a2
);
1437 tcg_out_insn(s
, 3510, EON
, ext
, a0
, a1
, a2
);
1441 case INDEX_op_not_i64
:
1442 case INDEX_op_not_i32
:
1443 tcg_out_insn(s
, 3510, ORN
, ext
, a0
, TCG_REG_XZR
, a1
);
1446 case INDEX_op_mul_i64
:
1447 case INDEX_op_mul_i32
:
1448 tcg_out_insn(s
, 3509, MADD
, ext
, a0
, a1
, a2
, TCG_REG_XZR
);
1451 case INDEX_op_div_i64
:
1452 case INDEX_op_div_i32
:
1453 tcg_out_insn(s
, 3508, SDIV
, ext
, a0
, a1
, a2
);
1455 case INDEX_op_divu_i64
:
1456 case INDEX_op_divu_i32
:
1457 tcg_out_insn(s
, 3508, UDIV
, ext
, a0
, a1
, a2
);
1460 case INDEX_op_rem_i64
:
1461 case INDEX_op_rem_i32
:
1462 tcg_out_insn(s
, 3508, SDIV
, ext
, TCG_REG_TMP
, a1
, a2
);
1463 tcg_out_insn(s
, 3509, MSUB
, ext
, a0
, TCG_REG_TMP
, a2
, a1
);
1465 case INDEX_op_remu_i64
:
1466 case INDEX_op_remu_i32
:
1467 tcg_out_insn(s
, 3508, UDIV
, ext
, TCG_REG_TMP
, a1
, a2
);
1468 tcg_out_insn(s
, 3509, MSUB
, ext
, a0
, TCG_REG_TMP
, a2
, a1
);
1471 case INDEX_op_shl_i64
:
1472 case INDEX_op_shl_i32
:
1474 tcg_out_shl(s
, ext
, a0
, a1
, a2
);
1476 tcg_out_insn(s
, 3508, LSLV
, ext
, a0
, a1
, a2
);
1480 case INDEX_op_shr_i64
:
1481 case INDEX_op_shr_i32
:
1483 tcg_out_shr(s
, ext
, a0
, a1
, a2
);
1485 tcg_out_insn(s
, 3508, LSRV
, ext
, a0
, a1
, a2
);
1489 case INDEX_op_sar_i64
:
1490 case INDEX_op_sar_i32
:
1492 tcg_out_sar(s
, ext
, a0
, a1
, a2
);
1494 tcg_out_insn(s
, 3508, ASRV
, ext
, a0
, a1
, a2
);
1498 case INDEX_op_rotr_i64
:
1499 case INDEX_op_rotr_i32
:
1501 tcg_out_rotr(s
, ext
, a0
, a1
, a2
);
1503 tcg_out_insn(s
, 3508, RORV
, ext
, a0
, a1
, a2
);
1507 case INDEX_op_rotl_i64
:
1508 case INDEX_op_rotl_i32
:
1510 tcg_out_rotl(s
, ext
, a0
, a1
, a2
);
1512 tcg_out_insn(s
, 3502, SUB
, 0, TCG_REG_TMP
, TCG_REG_XZR
, a2
);
1513 tcg_out_insn(s
, 3508, RORV
, ext
, a0
, a1
, TCG_REG_TMP
);
1517 case INDEX_op_brcond_i32
:
1520 case INDEX_op_brcond_i64
:
1521 tcg_out_cmp(s
, ext
, a0
, a1
, const_args
[1]);
1522 tcg_out_goto_label_cond(s
, a2
, args
[3]);
1525 case INDEX_op_setcond_i32
:
1528 case INDEX_op_setcond_i64
:
1529 tcg_out_cmp(s
, ext
, a1
, a2
, c2
);
1530 /* Use CSET alias of CSINC Wd, WZR, WZR, invert(cond). */
1531 tcg_out_insn(s
, 3506, CSINC
, TCG_TYPE_I32
, a0
, TCG_REG_XZR
,
1532 TCG_REG_XZR
, tcg_invert_cond(args
[3]));
1535 case INDEX_op_movcond_i32
:
1538 case INDEX_op_movcond_i64
:
1539 tcg_out_cmp(s
, ext
, a1
, a2
, c2
);
1540 tcg_out_insn(s
, 3506, CSEL
, ext
, a0
, REG0(3), REG0(4), args
[5]);
1543 case INDEX_op_qemu_ld8u
:
1544 tcg_out_qemu_ld(s
, args
, 0 | 0);
1546 case INDEX_op_qemu_ld8s
:
1547 tcg_out_qemu_ld(s
, args
, 4 | 0);
1549 case INDEX_op_qemu_ld16u
:
1550 tcg_out_qemu_ld(s
, args
, 0 | 1);
1552 case INDEX_op_qemu_ld16s
:
1553 tcg_out_qemu_ld(s
, args
, 4 | 1);
1555 case INDEX_op_qemu_ld32u
:
1556 tcg_out_qemu_ld(s
, args
, 0 | 2);
1558 case INDEX_op_qemu_ld32s
:
1559 tcg_out_qemu_ld(s
, args
, 4 | 2);
1561 case INDEX_op_qemu_ld32
:
1562 tcg_out_qemu_ld(s
, args
, 0 | 2);
1564 case INDEX_op_qemu_ld64
:
1565 tcg_out_qemu_ld(s
, args
, 0 | 3);
1567 case INDEX_op_qemu_st8
:
1568 tcg_out_qemu_st(s
, args
, 0);
1570 case INDEX_op_qemu_st16
:
1571 tcg_out_qemu_st(s
, args
, 1);
1573 case INDEX_op_qemu_st32
:
1574 tcg_out_qemu_st(s
, args
, 2);
1576 case INDEX_op_qemu_st64
:
1577 tcg_out_qemu_st(s
, args
, 3);
1580 case INDEX_op_bswap32_i64
:
1581 /* Despite the _i64, this is a 32-bit bswap. */
1584 case INDEX_op_bswap64_i64
:
1585 case INDEX_op_bswap32_i32
:
1586 tcg_out_rev(s
, ext
, a0
, a1
);
1588 case INDEX_op_bswap16_i64
:
1589 case INDEX_op_bswap16_i32
:
1590 tcg_out_rev16(s
, TCG_TYPE_I32
, a0
, a1
);
1593 case INDEX_op_ext8s_i64
:
1594 case INDEX_op_ext8s_i32
:
1595 tcg_out_sxt(s
, ext
, MO_8
, a0
, a1
);
1597 case INDEX_op_ext16s_i64
:
1598 case INDEX_op_ext16s_i32
:
1599 tcg_out_sxt(s
, ext
, MO_16
, a0
, a1
);
1601 case INDEX_op_ext32s_i64
:
1602 tcg_out_sxt(s
, TCG_TYPE_I64
, MO_32
, a0
, a1
);
1604 case INDEX_op_ext8u_i64
:
1605 case INDEX_op_ext8u_i32
:
1606 tcg_out_uxt(s
, MO_8
, a0
, a1
);
1608 case INDEX_op_ext16u_i64
:
1609 case INDEX_op_ext16u_i32
:
1610 tcg_out_uxt(s
, MO_16
, a0
, a1
);
1612 case INDEX_op_ext32u_i64
:
1613 tcg_out_movr(s
, TCG_TYPE_I32
, a0
, a1
);
1616 case INDEX_op_deposit_i64
:
1617 case INDEX_op_deposit_i32
:
1618 tcg_out_dep(s
, ext
, a0
, REG0(2), args
[3], args
[4]);
1621 case INDEX_op_add2_i32
:
1622 tcg_out_addsub2(s
, TCG_TYPE_I32
, a0
, a1
, REG0(2), REG0(3),
1623 (int32_t)args
[4], args
[5], const_args
[4],
1624 const_args
[5], false);
1626 case INDEX_op_add2_i64
:
1627 tcg_out_addsub2(s
, TCG_TYPE_I64
, a0
, a1
, REG0(2), REG0(3), args
[4],
1628 args
[5], const_args
[4], const_args
[5], false);
1630 case INDEX_op_sub2_i32
:
1631 tcg_out_addsub2(s
, TCG_TYPE_I32
, a0
, a1
, REG0(2), REG0(3),
1632 (int32_t)args
[4], args
[5], const_args
[4],
1633 const_args
[5], true);
1635 case INDEX_op_sub2_i64
:
1636 tcg_out_addsub2(s
, TCG_TYPE_I64
, a0
, a1
, REG0(2), REG0(3), args
[4],
1637 args
[5], const_args
[4], const_args
[5], true);
1640 case INDEX_op_muluh_i64
:
1641 tcg_out_insn(s
, 3508, UMULH
, TCG_TYPE_I64
, a0
, a1
, a2
);
1643 case INDEX_op_mulsh_i64
:
1644 tcg_out_insn(s
, 3508, SMULH
, TCG_TYPE_I64
, a0
, a1
, a2
);
1647 case INDEX_op_mov_i64
:
1648 case INDEX_op_mov_i32
:
1649 case INDEX_op_movi_i64
:
1650 case INDEX_op_movi_i32
:
1651 /* Always implemented with tcg_out_mov/i, never with tcg_out_op. */
1653 /* Opcode not implemented. */
1660 static const TCGTargetOpDef aarch64_op_defs
[] = {
1661 { INDEX_op_exit_tb
, { } },
1662 { INDEX_op_goto_tb
, { } },
1663 { INDEX_op_call
, { "ri" } },
1664 { INDEX_op_br
, { } },
1666 { INDEX_op_mov_i32
, { "r", "r" } },
1667 { INDEX_op_mov_i64
, { "r", "r" } },
1669 { INDEX_op_movi_i32
, { "r" } },
1670 { INDEX_op_movi_i64
, { "r" } },
1672 { INDEX_op_ld8u_i32
, { "r", "r" } },
1673 { INDEX_op_ld8s_i32
, { "r", "r" } },
1674 { INDEX_op_ld16u_i32
, { "r", "r" } },
1675 { INDEX_op_ld16s_i32
, { "r", "r" } },
1676 { INDEX_op_ld_i32
, { "r", "r" } },
1677 { INDEX_op_ld8u_i64
, { "r", "r" } },
1678 { INDEX_op_ld8s_i64
, { "r", "r" } },
1679 { INDEX_op_ld16u_i64
, { "r", "r" } },
1680 { INDEX_op_ld16s_i64
, { "r", "r" } },
1681 { INDEX_op_ld32u_i64
, { "r", "r" } },
1682 { INDEX_op_ld32s_i64
, { "r", "r" } },
1683 { INDEX_op_ld_i64
, { "r", "r" } },
1685 { INDEX_op_st8_i32
, { "r", "r" } },
1686 { INDEX_op_st16_i32
, { "r", "r" } },
1687 { INDEX_op_st_i32
, { "r", "r" } },
1688 { INDEX_op_st8_i64
, { "r", "r" } },
1689 { INDEX_op_st16_i64
, { "r", "r" } },
1690 { INDEX_op_st32_i64
, { "r", "r" } },
1691 { INDEX_op_st_i64
, { "r", "r" } },
1693 { INDEX_op_add_i32
, { "r", "r", "rwA" } },
1694 { INDEX_op_add_i64
, { "r", "r", "rA" } },
1695 { INDEX_op_sub_i32
, { "r", "r", "rwA" } },
1696 { INDEX_op_sub_i64
, { "r", "r", "rA" } },
1697 { INDEX_op_mul_i32
, { "r", "r", "r" } },
1698 { INDEX_op_mul_i64
, { "r", "r", "r" } },
1699 { INDEX_op_div_i32
, { "r", "r", "r" } },
1700 { INDEX_op_div_i64
, { "r", "r", "r" } },
1701 { INDEX_op_divu_i32
, { "r", "r", "r" } },
1702 { INDEX_op_divu_i64
, { "r", "r", "r" } },
1703 { INDEX_op_rem_i32
, { "r", "r", "r" } },
1704 { INDEX_op_rem_i64
, { "r", "r", "r" } },
1705 { INDEX_op_remu_i32
, { "r", "r", "r" } },
1706 { INDEX_op_remu_i64
, { "r", "r", "r" } },
1707 { INDEX_op_and_i32
, { "r", "r", "rwL" } },
1708 { INDEX_op_and_i64
, { "r", "r", "rL" } },
1709 { INDEX_op_or_i32
, { "r", "r", "rwL" } },
1710 { INDEX_op_or_i64
, { "r", "r", "rL" } },
1711 { INDEX_op_xor_i32
, { "r", "r", "rwL" } },
1712 { INDEX_op_xor_i64
, { "r", "r", "rL" } },
1713 { INDEX_op_andc_i32
, { "r", "r", "rwL" } },
1714 { INDEX_op_andc_i64
, { "r", "r", "rL" } },
1715 { INDEX_op_orc_i32
, { "r", "r", "rwL" } },
1716 { INDEX_op_orc_i64
, { "r", "r", "rL" } },
1717 { INDEX_op_eqv_i32
, { "r", "r", "rwL" } },
1718 { INDEX_op_eqv_i64
, { "r", "r", "rL" } },
1720 { INDEX_op_neg_i32
, { "r", "r" } },
1721 { INDEX_op_neg_i64
, { "r", "r" } },
1722 { INDEX_op_not_i32
, { "r", "r" } },
1723 { INDEX_op_not_i64
, { "r", "r" } },
1725 { INDEX_op_shl_i32
, { "r", "r", "ri" } },
1726 { INDEX_op_shr_i32
, { "r", "r", "ri" } },
1727 { INDEX_op_sar_i32
, { "r", "r", "ri" } },
1728 { INDEX_op_rotl_i32
, { "r", "r", "ri" } },
1729 { INDEX_op_rotr_i32
, { "r", "r", "ri" } },
1730 { INDEX_op_shl_i64
, { "r", "r", "ri" } },
1731 { INDEX_op_shr_i64
, { "r", "r", "ri" } },
1732 { INDEX_op_sar_i64
, { "r", "r", "ri" } },
1733 { INDEX_op_rotl_i64
, { "r", "r", "ri" } },
1734 { INDEX_op_rotr_i64
, { "r", "r", "ri" } },
1736 { INDEX_op_brcond_i32
, { "r", "rwA" } },
1737 { INDEX_op_brcond_i64
, { "r", "rA" } },
1738 { INDEX_op_setcond_i32
, { "r", "r", "rwA" } },
1739 { INDEX_op_setcond_i64
, { "r", "r", "rA" } },
1740 { INDEX_op_movcond_i32
, { "r", "r", "rwA", "rZ", "rZ" } },
1741 { INDEX_op_movcond_i64
, { "r", "r", "rA", "rZ", "rZ" } },
1743 { INDEX_op_qemu_ld8u
, { "r", "l" } },
1744 { INDEX_op_qemu_ld8s
, { "r", "l" } },
1745 { INDEX_op_qemu_ld16u
, { "r", "l" } },
1746 { INDEX_op_qemu_ld16s
, { "r", "l" } },
1747 { INDEX_op_qemu_ld32u
, { "r", "l" } },
1748 { INDEX_op_qemu_ld32s
, { "r", "l" } },
1750 { INDEX_op_qemu_ld32
, { "r", "l" } },
1751 { INDEX_op_qemu_ld64
, { "r", "l" } },
1753 { INDEX_op_qemu_st8
, { "l", "l" } },
1754 { INDEX_op_qemu_st16
, { "l", "l" } },
1755 { INDEX_op_qemu_st32
, { "l", "l" } },
1756 { INDEX_op_qemu_st64
, { "l", "l" } },
1758 { INDEX_op_bswap16_i32
, { "r", "r" } },
1759 { INDEX_op_bswap32_i32
, { "r", "r" } },
1760 { INDEX_op_bswap16_i64
, { "r", "r" } },
1761 { INDEX_op_bswap32_i64
, { "r", "r" } },
1762 { INDEX_op_bswap64_i64
, { "r", "r" } },
1764 { INDEX_op_ext8s_i32
, { "r", "r" } },
1765 { INDEX_op_ext16s_i32
, { "r", "r" } },
1766 { INDEX_op_ext8u_i32
, { "r", "r" } },
1767 { INDEX_op_ext16u_i32
, { "r", "r" } },
1769 { INDEX_op_ext8s_i64
, { "r", "r" } },
1770 { INDEX_op_ext16s_i64
, { "r", "r" } },
1771 { INDEX_op_ext32s_i64
, { "r", "r" } },
1772 { INDEX_op_ext8u_i64
, { "r", "r" } },
1773 { INDEX_op_ext16u_i64
, { "r", "r" } },
1774 { INDEX_op_ext32u_i64
, { "r", "r" } },
1776 { INDEX_op_deposit_i32
, { "r", "0", "rZ" } },
1777 { INDEX_op_deposit_i64
, { "r", "0", "rZ" } },
1779 { INDEX_op_add2_i32
, { "r", "r", "rZ", "rZ", "rwA", "rwMZ" } },
1780 { INDEX_op_add2_i64
, { "r", "r", "rZ", "rZ", "rA", "rMZ" } },
1781 { INDEX_op_sub2_i32
, { "r", "r", "rZ", "rZ", "rwA", "rwMZ" } },
1782 { INDEX_op_sub2_i64
, { "r", "r", "rZ", "rZ", "rA", "rMZ" } },
1784 { INDEX_op_muluh_i64
, { "r", "r", "r" } },
1785 { INDEX_op_mulsh_i64
, { "r", "r", "r" } },
1790 static void tcg_target_init(TCGContext
*s
)
1792 tcg_regset_set32(tcg_target_available_regs
[TCG_TYPE_I32
], 0, 0xffffffff);
1793 tcg_regset_set32(tcg_target_available_regs
[TCG_TYPE_I64
], 0, 0xffffffff);
1795 tcg_regset_set32(tcg_target_call_clobber_regs
, 0,
1796 (1 << TCG_REG_X0
) | (1 << TCG_REG_X1
) |
1797 (1 << TCG_REG_X2
) | (1 << TCG_REG_X3
) |
1798 (1 << TCG_REG_X4
) | (1 << TCG_REG_X5
) |
1799 (1 << TCG_REG_X6
) | (1 << TCG_REG_X7
) |
1800 (1 << TCG_REG_X8
) | (1 << TCG_REG_X9
) |
1801 (1 << TCG_REG_X10
) | (1 << TCG_REG_X11
) |
1802 (1 << TCG_REG_X12
) | (1 << TCG_REG_X13
) |
1803 (1 << TCG_REG_X14
) | (1 << TCG_REG_X15
) |
1804 (1 << TCG_REG_X16
) | (1 << TCG_REG_X17
) |
1805 (1 << TCG_REG_X18
));
1807 tcg_regset_clear(s
->reserved_regs
);
1808 tcg_regset_set_reg(s
->reserved_regs
, TCG_REG_SP
);
1809 tcg_regset_set_reg(s
->reserved_regs
, TCG_REG_FP
);
1810 tcg_regset_set_reg(s
->reserved_regs
, TCG_REG_TMP
);
1811 tcg_regset_set_reg(s
->reserved_regs
, TCG_REG_X18
); /* platform register */
1813 tcg_add_target_add_op_defs(aarch64_op_defs
);
1816 static void tcg_target_qemu_prologue(TCGContext
*s
)
1818 /* NB: frame sizes are in 16 byte stack units! */
1819 int frame_size_callee_saved
, frame_size_tcg_locals
;
1822 /* save pairs (FP, LR) and (X19, X20) .. (X27, X28) */
1823 frame_size_callee_saved
= (1) + (TCG_REG_X28
- TCG_REG_X19
) / 2 + 1;
1825 /* frame size requirement for TCG local variables */
1826 frame_size_tcg_locals
= TCG_STATIC_CALL_ARGS_SIZE
1827 + CPU_TEMP_BUF_NLONGS
* sizeof(long)
1828 + (TCG_TARGET_STACK_ALIGN
- 1);
1829 frame_size_tcg_locals
&= ~(TCG_TARGET_STACK_ALIGN
- 1);
1830 frame_size_tcg_locals
/= TCG_TARGET_STACK_ALIGN
;
1832 /* push (FP, LR) and update sp */
1833 tcg_out_push_pair(s
, TCG_REG_SP
,
1834 TCG_REG_FP
, TCG_REG_LR
, frame_size_callee_saved
);
1836 /* FP -> callee_saved */
1837 tcg_out_movr_sp(s
, TCG_TYPE_I64
, TCG_REG_FP
, TCG_REG_SP
);
1839 /* store callee-preserved regs x19..x28 using FP -> callee_saved */
1840 for (r
= TCG_REG_X19
; r
<= TCG_REG_X27
; r
+= 2) {
1841 int idx
= (r
- TCG_REG_X19
) / 2 + 1;
1842 tcg_out_store_pair(s
, TCG_REG_FP
, r
, r
+ 1, idx
);
1845 /* Make stack space for TCG locals. */
1846 tcg_out_insn(s
, 3401, SUBI
, TCG_TYPE_I64
, TCG_REG_SP
, TCG_REG_SP
,
1847 frame_size_tcg_locals
* TCG_TARGET_STACK_ALIGN
);
1849 /* inform TCG about how to find TCG locals with register, offset, size */
1850 tcg_set_frame(s
, TCG_REG_SP
, TCG_STATIC_CALL_ARGS_SIZE
,
1851 CPU_TEMP_BUF_NLONGS
* sizeof(long));
1853 #if defined(CONFIG_USE_GUEST_BASE)
1855 tcg_out_movi(s
, TCG_TYPE_PTR
, TCG_REG_GUEST_BASE
, GUEST_BASE
);
1856 tcg_regset_set_reg(s
->reserved_regs
, TCG_REG_GUEST_BASE
);
1860 tcg_out_mov(s
, TCG_TYPE_PTR
, TCG_AREG0
, tcg_target_call_iarg_regs
[0]);
1861 tcg_out_gotor(s
, tcg_target_call_iarg_regs
[1]);
1863 tb_ret_addr
= s
->code_ptr
;
1865 /* Remove TCG locals stack space. */
1866 tcg_out_insn(s
, 3401, ADDI
, TCG_TYPE_I64
, TCG_REG_SP
, TCG_REG_SP
,
1867 frame_size_tcg_locals
* TCG_TARGET_STACK_ALIGN
);
1869 /* restore registers x19..x28.
1870 FP must be preserved, so it still points to callee_saved area */
1871 for (r
= TCG_REG_X19
; r
<= TCG_REG_X27
; r
+= 2) {
1872 int idx
= (r
- TCG_REG_X19
) / 2 + 1;
1873 tcg_out_load_pair(s
, TCG_REG_FP
, r
, r
+ 1, idx
);
1876 /* pop (FP, LR), restore SP to previous frame, return */
1877 tcg_out_pop_pair(s
, TCG_REG_SP
,
1878 TCG_REG_FP
, TCG_REG_LR
, frame_size_callee_saved
);