]> git.proxmox.com Git - mirror_qemu.git/blame - tcg/aarch64/tcg-target.inc.c
tcg/tci: Add TCG_TARGET_DEFAULT_MO
[mirror_qemu.git] / tcg / aarch64 / tcg-target.inc.c
CommitLineData
4a136e0a
CF
1/*
2 * Initial TCG Implementation for aarch64
3 *
4 * Copyright (c) 2013 Huawei Technologies Duesseldorf GmbH
5 * Written by Claudio Fontana
6 *
7 * This work is licensed under the terms of the GNU GPL, version 2 or
8 * (at your option) any later version.
9 *
10 * See the COPYING file in the top-level directory for details.
11 */
12
9ecefc84 13#include "tcg-be-ldst.h"
4a136e0a
CF
14#include "qemu/bitops.h"
15
7763ffa0
RH
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. */
19QEMU_BUILD_BUG_ON(TCG_TYPE_I32 != 0 || TCG_TYPE_I64 != 1);
20
8d8fdbae 21#ifdef CONFIG_DEBUG_TCG
4a136e0a
CF
22static 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",
d82b78e4 26 "%x24", "%x25", "%x26", "%x27", "%x28", "%fp", "%x30", "%sp",
4a136e0a 27};
8d8fdbae 28#endif /* CONFIG_DEBUG_TCG */
4a136e0a
CF
29
30static const int tcg_target_reg_alloc_order[] = {
31 TCG_REG_X20, TCG_REG_X21, TCG_REG_X22, TCG_REG_X23,
32 TCG_REG_X24, TCG_REG_X25, TCG_REG_X26, TCG_REG_X27,
b76f21a7 33 TCG_REG_X28, /* we will reserve this for guest_base if configured */
4a136e0a 34
d82b78e4
RH
35 TCG_REG_X8, TCG_REG_X9, TCG_REG_X10, TCG_REG_X11,
36 TCG_REG_X12, TCG_REG_X13, TCG_REG_X14, TCG_REG_X15,
4a136e0a
CF
37 TCG_REG_X16, TCG_REG_X17,
38
4a136e0a
CF
39 TCG_REG_X0, TCG_REG_X1, TCG_REG_X2, TCG_REG_X3,
40 TCG_REG_X4, TCG_REG_X5, TCG_REG_X6, TCG_REG_X7,
41
d82b78e4
RH
42 /* X18 reserved by system */
43 /* X19 reserved for AREG0 */
44 /* X29 reserved as fp */
45 /* X30 reserved as temporary */
4a136e0a
CF
46};
47
48static const int tcg_target_call_iarg_regs[8] = {
49 TCG_REG_X0, TCG_REG_X1, TCG_REG_X2, TCG_REG_X3,
50 TCG_REG_X4, TCG_REG_X5, TCG_REG_X6, TCG_REG_X7
51};
52static const int tcg_target_call_oarg_regs[1] = {
53 TCG_REG_X0
54};
55
d82b78e4 56#define TCG_REG_TMP TCG_REG_X30
4a136e0a 57
6a91c7c9 58#ifndef CONFIG_SOFTMMU
352bcb0a
RH
59/* Note that XZR cannot be encoded in the address base register slot,
60 as that actaully encodes SP. So if we need to zero-extend the guest
61 address, via the address index register slot, we need to load even
62 a zero guest base into a register. */
63#define USE_GUEST_BASE (guest_base != 0 || TARGET_LONG_BITS == 32)
4cbea598 64#define TCG_REG_GUEST_BASE TCG_REG_X28
6a91c7c9
JK
65#endif
66
8587c30c 67static inline void reloc_pc26(tcg_insn_unit *code_ptr, tcg_insn_unit *target)
4a136e0a 68{
8587c30c 69 ptrdiff_t offset = target - code_ptr;
eabb7b91 70 tcg_debug_assert(offset == sextract64(offset, 0, 26));
4a136e0a
CF
71 /* read instruction, mask away previous PC_REL26 parameter contents,
72 set the proper offset, then write back the instruction. */
8587c30c 73 *code_ptr = deposit32(*code_ptr, 0, 26, offset);
4a136e0a
CF
74}
75
9e269112
SF
76static inline void reloc_pc26_atomic(tcg_insn_unit *code_ptr,
77 tcg_insn_unit *target)
78{
79 ptrdiff_t offset = target - code_ptr;
80 tcg_insn_unit insn;
81 tcg_debug_assert(offset == sextract64(offset, 0, 26));
82 /* read instruction, mask away previous PC_REL26 parameter contents,
83 set the proper offset, then write back the instruction. */
84 insn = atomic_read(code_ptr);
85 atomic_set(code_ptr, deposit32(insn, 0, 26, offset));
86}
87
8587c30c 88static inline void reloc_pc19(tcg_insn_unit *code_ptr, tcg_insn_unit *target)
4a136e0a 89{
8587c30c 90 ptrdiff_t offset = target - code_ptr;
eabb7b91 91 tcg_debug_assert(offset == sextract64(offset, 0, 19));
8587c30c 92 *code_ptr = deposit32(*code_ptr, 5, 19, offset);
4a136e0a
CF
93}
94
8587c30c 95static inline void patch_reloc(tcg_insn_unit *code_ptr, int type,
2ba7fae2 96 intptr_t value, intptr_t addend)
4a136e0a 97{
eabb7b91 98 tcg_debug_assert(addend == 0);
4a136e0a
CF
99 switch (type) {
100 case R_AARCH64_JUMP26:
101 case R_AARCH64_CALL26:
8587c30c 102 reloc_pc26(code_ptr, (tcg_insn_unit *)value);
4a136e0a
CF
103 break;
104 case R_AARCH64_CONDBR19:
8587c30c 105 reloc_pc19(code_ptr, (tcg_insn_unit *)value);
4a136e0a 106 break;
4a136e0a
CF
107 default:
108 tcg_abort();
109 }
110}
111
170bf931
RH
112#define TCG_CT_CONST_AIMM 0x100
113#define TCG_CT_CONST_LIMM 0x200
114#define TCG_CT_CONST_ZERO 0x400
115#define TCG_CT_CONST_MONE 0x800
90f1cd91 116
4a136e0a 117/* parse target specific constraints */
069ea736
RH
118static const char *target_parse_constraint(TCGArgConstraint *ct,
119 const char *ct_str, TCGType type)
4a136e0a 120{
069ea736 121 switch (*ct_str++) {
4a136e0a
CF
122 case 'r':
123 ct->ct |= TCG_CT_REG;
124 tcg_regset_set32(ct->u.regs, 0, (1ULL << TCG_TARGET_NB_REGS) - 1);
125 break;
126 case 'l': /* qemu_ld / qemu_st address, data_reg */
127 ct->ct |= TCG_CT_REG;
128 tcg_regset_set32(ct->u.regs, 0, (1ULL << TCG_TARGET_NB_REGS) - 1);
129#ifdef CONFIG_SOFTMMU
130 /* x0 and x1 will be overwritten when reading the tlb entry,
131 and x2, and x3 for helper args, better to avoid using them. */
132 tcg_regset_reset_reg(ct->u.regs, TCG_REG_X0);
133 tcg_regset_reset_reg(ct->u.regs, TCG_REG_X1);
134 tcg_regset_reset_reg(ct->u.regs, TCG_REG_X2);
135 tcg_regset_reset_reg(ct->u.regs, TCG_REG_X3);
136#endif
137 break;
90f1cd91
RH
138 case 'A': /* Valid for arithmetic immediate (positive or negative). */
139 ct->ct |= TCG_CT_CONST_AIMM;
140 break;
e029f293
RH
141 case 'L': /* Valid for logical immediate. */
142 ct->ct |= TCG_CT_CONST_LIMM;
143 break;
c6e929e7
RH
144 case 'M': /* minus one */
145 ct->ct |= TCG_CT_CONST_MONE;
146 break;
04ce397b
RH
147 case 'Z': /* zero */
148 ct->ct |= TCG_CT_CONST_ZERO;
149 break;
4a136e0a 150 default:
069ea736 151 return NULL;
4a136e0a 152 }
069ea736 153 return ct_str;
4a136e0a
CF
154}
155
90f1cd91
RH
156static inline bool is_aimm(uint64_t val)
157{
158 return (val & ~0xfff) == 0 || (val & ~0xfff000) == 0;
159}
160
e029f293
RH
161static inline bool is_limm(uint64_t val)
162{
163 /* Taking a simplified view of the logical immediates for now, ignoring
164 the replication that can happen across the field. Match bit patterns
165 of the forms
166 0....01....1
167 0..01..10..0
168 and their inverses. */
169
170 /* Make things easier below, by testing the form with msb clear. */
171 if ((int64_t)val < 0) {
172 val = ~val;
173 }
174 if (val == 0) {
175 return false;
176 }
177 val += val & -val;
178 return (val & (val - 1)) == 0;
179}
180
f6c6afc1 181static int tcg_target_const_match(tcg_target_long val, TCGType type,
90f1cd91 182 const TCGArgConstraint *arg_ct)
4a136e0a
CF
183{
184 int ct = arg_ct->ct;
185
186 if (ct & TCG_CT_CONST) {
187 return 1;
188 }
170bf931 189 if (type == TCG_TYPE_I32) {
90f1cd91
RH
190 val = (int32_t)val;
191 }
192 if ((ct & TCG_CT_CONST_AIMM) && (is_aimm(val) || is_aimm(-val))) {
193 return 1;
194 }
e029f293
RH
195 if ((ct & TCG_CT_CONST_LIMM) && is_limm(val)) {
196 return 1;
197 }
04ce397b
RH
198 if ((ct & TCG_CT_CONST_ZERO) && val == 0) {
199 return 1;
200 }
c6e929e7
RH
201 if ((ct & TCG_CT_CONST_MONE) && val == -1) {
202 return 1;
203 }
4a136e0a
CF
204
205 return 0;
206}
207
208enum aarch64_cond_code {
209 COND_EQ = 0x0,
210 COND_NE = 0x1,
211 COND_CS = 0x2, /* Unsigned greater or equal */
212 COND_HS = COND_CS, /* ALIAS greater or equal */
213 COND_CC = 0x3, /* Unsigned less than */
214 COND_LO = COND_CC, /* ALIAS Lower */
215 COND_MI = 0x4, /* Negative */
216 COND_PL = 0x5, /* Zero or greater */
217 COND_VS = 0x6, /* Overflow */
218 COND_VC = 0x7, /* No overflow */
219 COND_HI = 0x8, /* Unsigned greater than */
220 COND_LS = 0x9, /* Unsigned less or equal */
221 COND_GE = 0xa,
222 COND_LT = 0xb,
223 COND_GT = 0xc,
224 COND_LE = 0xd,
225 COND_AL = 0xe,
226 COND_NV = 0xf, /* behaves like COND_AL here */
227};
228
229static const enum aarch64_cond_code tcg_cond_to_aarch64[] = {
230 [TCG_COND_EQ] = COND_EQ,
231 [TCG_COND_NE] = COND_NE,
232 [TCG_COND_LT] = COND_LT,
233 [TCG_COND_GE] = COND_GE,
234 [TCG_COND_LE] = COND_LE,
235 [TCG_COND_GT] = COND_GT,
236 /* unsigned */
237 [TCG_COND_LTU] = COND_LO,
238 [TCG_COND_GTU] = COND_HI,
239 [TCG_COND_GEU] = COND_HS,
240 [TCG_COND_LEU] = COND_LS,
241};
242
3d4299f4
RH
243typedef enum {
244 LDST_ST = 0, /* store */
245 LDST_LD = 1, /* load */
246 LDST_LD_S_X = 2, /* load and sign-extend into Xt */
247 LDST_LD_S_W = 3, /* load and sign-extend into Wt */
248} AArch64LdstType;
4a136e0a 249
50573c66
RH
250/* We encode the format of the insn into the beginning of the name, so that
251 we can have the preprocessor help "typecheck" the insn vs the output
252 function. Arm didn't provide us with nice names for the formats, so we
253 use the section number of the architecture reference manual in which the
254 instruction group is described. */
255typedef enum {
3d9e69a2
RH
256 /* Compare and branch (immediate). */
257 I3201_CBZ = 0x34000000,
258 I3201_CBNZ = 0x35000000,
259
81d8a5ee
RH
260 /* Conditional branch (immediate). */
261 I3202_B_C = 0x54000000,
262
263 /* Unconditional branch (immediate). */
264 I3206_B = 0x14000000,
265 I3206_BL = 0x94000000,
266
267 /* Unconditional branch (register). */
268 I3207_BR = 0xd61f0000,
269 I3207_BLR = 0xd63f0000,
270 I3207_RET = 0xd65f0000,
271
2acee8b2
PK
272 /* Load literal for loading the address at pc-relative offset */
273 I3305_LDR = 0x58000000,
3d4299f4
RH
274 /* Load/store register. Described here as 3.3.12, but the helper
275 that emits them can transform to 3.3.10 or 3.3.13. */
276 I3312_STRB = 0x38000000 | LDST_ST << 22 | MO_8 << 30,
277 I3312_STRH = 0x38000000 | LDST_ST << 22 | MO_16 << 30,
278 I3312_STRW = 0x38000000 | LDST_ST << 22 | MO_32 << 30,
279 I3312_STRX = 0x38000000 | LDST_ST << 22 | MO_64 << 30,
280
281 I3312_LDRB = 0x38000000 | LDST_LD << 22 | MO_8 << 30,
282 I3312_LDRH = 0x38000000 | LDST_LD << 22 | MO_16 << 30,
283 I3312_LDRW = 0x38000000 | LDST_LD << 22 | MO_32 << 30,
284 I3312_LDRX = 0x38000000 | LDST_LD << 22 | MO_64 << 30,
285
286 I3312_LDRSBW = 0x38000000 | LDST_LD_S_W << 22 | MO_8 << 30,
287 I3312_LDRSHW = 0x38000000 | LDST_LD_S_W << 22 | MO_16 << 30,
288
289 I3312_LDRSBX = 0x38000000 | LDST_LD_S_X << 22 | MO_8 << 30,
290 I3312_LDRSHX = 0x38000000 | LDST_LD_S_X << 22 | MO_16 << 30,
291 I3312_LDRSWX = 0x38000000 | LDST_LD_S_X << 22 | MO_32 << 30,
292
6c0f0c0f 293 I3312_TO_I3310 = 0x00200800,
3d4299f4
RH
294 I3312_TO_I3313 = 0x01000000,
295
95f72aa9
RH
296 /* Load/store register pair instructions. */
297 I3314_LDP = 0x28400000,
298 I3314_STP = 0x28000000,
299
096c46c0
RH
300 /* Add/subtract immediate instructions. */
301 I3401_ADDI = 0x11000000,
302 I3401_ADDSI = 0x31000000,
303 I3401_SUBI = 0x51000000,
304 I3401_SUBSI = 0x71000000,
305
b3c56df7
RH
306 /* Bitfield instructions. */
307 I3402_BFM = 0x33000000,
308 I3402_SBFM = 0x13000000,
309 I3402_UBFM = 0x53000000,
310
311 /* Extract instruction. */
312 I3403_EXTR = 0x13800000,
313
e029f293
RH
314 /* Logical immediate instructions. */
315 I3404_ANDI = 0x12000000,
316 I3404_ORRI = 0x32000000,
317 I3404_EORI = 0x52000000,
318
582ab779
RH
319 /* Move wide immediate instructions. */
320 I3405_MOVN = 0x12800000,
321 I3405_MOVZ = 0x52800000,
322 I3405_MOVK = 0x72800000,
323
c6e310d9
RH
324 /* PC relative addressing instructions. */
325 I3406_ADR = 0x10000000,
326 I3406_ADRP = 0x90000000,
327
50573c66
RH
328 /* Add/subtract shifted register instructions (without a shift). */
329 I3502_ADD = 0x0b000000,
330 I3502_ADDS = 0x2b000000,
331 I3502_SUB = 0x4b000000,
332 I3502_SUBS = 0x6b000000,
333
334 /* Add/subtract shifted register instructions (with a shift). */
335 I3502S_ADD_LSL = I3502_ADD,
336
c6e929e7
RH
337 /* Add/subtract with carry instructions. */
338 I3503_ADC = 0x1a000000,
339 I3503_SBC = 0x5a000000,
340
04ce397b
RH
341 /* Conditional select instructions. */
342 I3506_CSEL = 0x1a800000,
343 I3506_CSINC = 0x1a800400,
53c76c19
RH
344 I3506_CSINV = 0x5a800000,
345 I3506_CSNEG = 0x5a800400,
04ce397b 346
edd8824c 347 /* Data-processing (1 source) instructions. */
53c76c19
RH
348 I3507_CLZ = 0x5ac01000,
349 I3507_RBIT = 0x5ac00000,
edd8824c
RH
350 I3507_REV16 = 0x5ac00400,
351 I3507_REV32 = 0x5ac00800,
352 I3507_REV64 = 0x5ac00c00,
353
df9351e3
RH
354 /* Data-processing (2 source) instructions. */
355 I3508_LSLV = 0x1ac02000,
356 I3508_LSRV = 0x1ac02400,
357 I3508_ASRV = 0x1ac02800,
358 I3508_RORV = 0x1ac02c00,
1fcc9ddf
RH
359 I3508_SMULH = 0x9b407c00,
360 I3508_UMULH = 0x9bc07c00,
8678b71c
RH
361 I3508_UDIV = 0x1ac00800,
362 I3508_SDIV = 0x1ac00c00,
363
364 /* Data-processing (3 source) instructions. */
365 I3509_MADD = 0x1b000000,
366 I3509_MSUB = 0x1b008000,
df9351e3 367
50573c66
RH
368 /* Logical shifted register instructions (without a shift). */
369 I3510_AND = 0x0a000000,
14b155dd 370 I3510_BIC = 0x0a200000,
50573c66 371 I3510_ORR = 0x2a000000,
14b155dd 372 I3510_ORN = 0x2a200000,
50573c66 373 I3510_EOR = 0x4a000000,
14b155dd 374 I3510_EON = 0x4a200000,
50573c66 375 I3510_ANDS = 0x6a000000,
c7a59c2a 376
b68686bd 377 NOP = 0xd503201f,
c7a59c2a
PK
378 /* System instructions. */
379 DMB_ISH = 0xd50338bf,
380 DMB_LD = 0x00000100,
381 DMB_ST = 0x00000200,
50573c66 382} AArch64Insn;
4a136e0a 383
4a136e0a
CF
384static inline uint32_t tcg_in32(TCGContext *s)
385{
386 uint32_t v = *(uint32_t *)s->code_ptr;
387 return v;
388}
389
50573c66
RH
390/* Emit an opcode with "type-checking" of the format. */
391#define tcg_out_insn(S, FMT, OP, ...) \
392 glue(tcg_out_insn_,FMT)(S, glue(glue(glue(I,FMT),_),OP), ## __VA_ARGS__)
393
2acee8b2
PK
394static void tcg_out_insn_3305(TCGContext *s, AArch64Insn insn, int imm19, TCGReg rt)
395{
396 tcg_out32(s, insn | (imm19 & 0x7ffff) << 5 | rt);
397}
398
3d9e69a2
RH
399static void tcg_out_insn_3201(TCGContext *s, AArch64Insn insn, TCGType ext,
400 TCGReg rt, int imm19)
401{
402 tcg_out32(s, insn | ext << 31 | (imm19 & 0x7ffff) << 5 | rt);
403}
404
81d8a5ee
RH
405static void tcg_out_insn_3202(TCGContext *s, AArch64Insn insn,
406 TCGCond c, int imm19)
407{
408 tcg_out32(s, insn | tcg_cond_to_aarch64[c] | (imm19 & 0x7ffff) << 5);
409}
410
411static void tcg_out_insn_3206(TCGContext *s, AArch64Insn insn, int imm26)
412{
413 tcg_out32(s, insn | (imm26 & 0x03ffffff));
414}
415
416static void tcg_out_insn_3207(TCGContext *s, AArch64Insn insn, TCGReg rn)
417{
418 tcg_out32(s, insn | rn << 5);
419}
420
95f72aa9
RH
421static void tcg_out_insn_3314(TCGContext *s, AArch64Insn insn,
422 TCGReg r1, TCGReg r2, TCGReg rn,
423 tcg_target_long ofs, bool pre, bool w)
424{
425 insn |= 1u << 31; /* ext */
426 insn |= pre << 24;
427 insn |= w << 23;
428
eabb7b91 429 tcg_debug_assert(ofs >= -0x200 && ofs < 0x200 && (ofs & 7) == 0);
95f72aa9
RH
430 insn |= (ofs & (0x7f << 3)) << (15 - 3);
431
432 tcg_out32(s, insn | r2 << 10 | rn << 5 | r1);
433}
434
096c46c0
RH
435static void tcg_out_insn_3401(TCGContext *s, AArch64Insn insn, TCGType ext,
436 TCGReg rd, TCGReg rn, uint64_t aimm)
437{
438 if (aimm > 0xfff) {
eabb7b91 439 tcg_debug_assert((aimm & 0xfff) == 0);
096c46c0 440 aimm >>= 12;
eabb7b91 441 tcg_debug_assert(aimm <= 0xfff);
096c46c0
RH
442 aimm |= 1 << 12; /* apply LSL 12 */
443 }
444 tcg_out32(s, insn | ext << 31 | aimm << 10 | rn << 5 | rd);
445}
446
e029f293
RH
447/* This function can be used for both 3.4.2 (Bitfield) and 3.4.4
448 (Logical immediate). Both insn groups have N, IMMR and IMMS fields
449 that feed the DecodeBitMasks pseudo function. */
450static void tcg_out_insn_3402(TCGContext *s, AArch64Insn insn, TCGType ext,
451 TCGReg rd, TCGReg rn, int n, int immr, int imms)
452{
453 tcg_out32(s, insn | ext << 31 | n << 22 | immr << 16 | imms << 10
454 | rn << 5 | rd);
455}
456
457#define tcg_out_insn_3404 tcg_out_insn_3402
458
b3c56df7
RH
459static void tcg_out_insn_3403(TCGContext *s, AArch64Insn insn, TCGType ext,
460 TCGReg rd, TCGReg rn, TCGReg rm, int imms)
461{
462 tcg_out32(s, insn | ext << 31 | ext << 22 | rm << 16 | imms << 10
463 | rn << 5 | rd);
464}
465
582ab779
RH
466/* This function is used for the Move (wide immediate) instruction group.
467 Note that SHIFT is a full shift count, not the 2 bit HW field. */
468static void tcg_out_insn_3405(TCGContext *s, AArch64Insn insn, TCGType ext,
469 TCGReg rd, uint16_t half, unsigned shift)
470{
eabb7b91 471 tcg_debug_assert((shift & ~0x30) == 0);
582ab779
RH
472 tcg_out32(s, insn | ext << 31 | shift << (21 - 4) | half << 5 | rd);
473}
474
c6e310d9
RH
475static void tcg_out_insn_3406(TCGContext *s, AArch64Insn insn,
476 TCGReg rd, int64_t disp)
477{
478 tcg_out32(s, insn | (disp & 3) << 29 | (disp & 0x1ffffc) << (5 - 2) | rd);
479}
480
50573c66
RH
481/* This function is for both 3.5.2 (Add/Subtract shifted register), for
482 the rare occasion when we actually want to supply a shift amount. */
483static inline void tcg_out_insn_3502S(TCGContext *s, AArch64Insn insn,
484 TCGType ext, TCGReg rd, TCGReg rn,
485 TCGReg rm, int imm6)
486{
487 tcg_out32(s, insn | ext << 31 | rm << 16 | imm6 << 10 | rn << 5 | rd);
488}
489
490/* This function is for 3.5.2 (Add/subtract shifted register),
491 and 3.5.10 (Logical shifted register), for the vast majorty of cases
492 when we don't want to apply a shift. Thus it can also be used for
493 3.5.3 (Add/subtract with carry) and 3.5.8 (Data processing 2 source). */
494static void tcg_out_insn_3502(TCGContext *s, AArch64Insn insn, TCGType ext,
495 TCGReg rd, TCGReg rn, TCGReg rm)
496{
497 tcg_out32(s, insn | ext << 31 | rm << 16 | rn << 5 | rd);
498}
499
500#define tcg_out_insn_3503 tcg_out_insn_3502
501#define tcg_out_insn_3508 tcg_out_insn_3502
502#define tcg_out_insn_3510 tcg_out_insn_3502
503
04ce397b
RH
504static void tcg_out_insn_3506(TCGContext *s, AArch64Insn insn, TCGType ext,
505 TCGReg rd, TCGReg rn, TCGReg rm, TCGCond c)
506{
507 tcg_out32(s, insn | ext << 31 | rm << 16 | rn << 5 | rd
508 | tcg_cond_to_aarch64[c] << 12);
509}
510
edd8824c
RH
511static void tcg_out_insn_3507(TCGContext *s, AArch64Insn insn, TCGType ext,
512 TCGReg rd, TCGReg rn)
513{
514 tcg_out32(s, insn | ext << 31 | rn << 5 | rd);
515}
516
8678b71c
RH
517static void tcg_out_insn_3509(TCGContext *s, AArch64Insn insn, TCGType ext,
518 TCGReg rd, TCGReg rn, TCGReg rm, TCGReg ra)
519{
520 tcg_out32(s, insn | ext << 31 | rm << 16 | ra << 10 | rn << 5 | rd);
521}
522
3d4299f4 523static void tcg_out_insn_3310(TCGContext *s, AArch64Insn insn,
6c0f0c0f
PB
524 TCGReg rd, TCGReg base, TCGType ext,
525 TCGReg regoff)
3d4299f4
RH
526{
527 /* Note the AArch64Insn constants above are for C3.3.12. Adjust. */
6c0f0c0f
PB
528 tcg_out32(s, insn | I3312_TO_I3310 | regoff << 16 |
529 0x4000 | ext << 13 | base << 5 | rd);
3d4299f4 530}
50573c66 531
3d4299f4
RH
532static void tcg_out_insn_3312(TCGContext *s, AArch64Insn insn,
533 TCGReg rd, TCGReg rn, intptr_t offset)
4a136e0a 534{
3d4299f4 535 tcg_out32(s, insn | (offset & 0x1ff) << 12 | rn << 5 | rd);
4a136e0a
CF
536}
537
3d4299f4
RH
538static void tcg_out_insn_3313(TCGContext *s, AArch64Insn insn,
539 TCGReg rd, TCGReg rn, uintptr_t scaled_uimm)
b1f6dc0d 540{
3d4299f4
RH
541 /* Note the AArch64Insn constants above are for C3.3.12. Adjust. */
542 tcg_out32(s, insn | I3312_TO_I3313 | scaled_uimm << 10 | rn << 5 | rd);
b1f6dc0d
CF
543}
544
7d11fc7c
RH
545/* Register to register move using ORR (shifted register with no shift). */
546static void tcg_out_movr(TCGContext *s, TCGType ext, TCGReg rd, TCGReg rm)
4a136e0a 547{
7d11fc7c
RH
548 tcg_out_insn(s, 3510, ORR, ext, rd, TCG_REG_XZR, rm);
549}
550
551/* Register to register move using ADDI (move to/from SP). */
552static void tcg_out_movr_sp(TCGContext *s, TCGType ext, TCGReg rd, TCGReg rn)
553{
554 tcg_out_insn(s, 3401, ADDI, ext, rd, rn, 0);
4a136e0a
CF
555}
556
4ec4f0bd
RH
557/* This function is used for the Logical (immediate) instruction group.
558 The value of LIMM must satisfy IS_LIMM. See the comment above about
559 only supporting simplified logical immediates. */
560static void tcg_out_logicali(TCGContext *s, AArch64Insn insn, TCGType ext,
561 TCGReg rd, TCGReg rn, uint64_t limm)
562{
563 unsigned h, l, r, c;
564
eabb7b91 565 tcg_debug_assert(is_limm(limm));
4ec4f0bd
RH
566
567 h = clz64(limm);
568 l = ctz64(limm);
569 if (l == 0) {
570 r = 0; /* form 0....01....1 */
571 c = ctz64(~limm) - 1;
572 if (h == 0) {
573 r = clz64(~limm); /* form 1..10..01..1 */
574 c += r;
575 }
576 } else {
577 r = 64 - l; /* form 1....10....0 or 0..01..10..0 */
578 c = r - h - 1;
579 }
580 if (ext == TCG_TYPE_I32) {
581 r &= 31;
582 c &= 31;
583 }
584
585 tcg_out_insn_3404(s, insn, ext, rd, rn, ext, r, c);
586}
587
582ab779
RH
588static void tcg_out_movi(TCGContext *s, TCGType type, TCGReg rd,
589 tcg_target_long value)
4a136e0a 590{
dfeb5fe7
RH
591 int i, wantinv, shift;
592 tcg_target_long svalue = value;
593 tcg_target_long ivalue = ~value;
dfeb5fe7
RH
594
595 /* For 32-bit values, discard potential garbage in value. For 64-bit
596 values within [2**31, 2**32-1], we can create smaller sequences by
597 interpreting this as a negative 32-bit number, while ensuring that
598 the high 32 bits are cleared by setting SF=0. */
599 if (type == TCG_TYPE_I32 || (value & ~0xffffffffull) == 0) {
600 svalue = (int32_t)value;
582ab779 601 value = (uint32_t)value;
dfeb5fe7
RH
602 ivalue = (uint32_t)ivalue;
603 type = TCG_TYPE_I32;
604 }
605
d8918df5
RH
606 /* Speed things up by handling the common case of small positive
607 and negative values specially. */
608 if ((value & ~0xffffull) == 0) {
609 tcg_out_insn(s, 3405, MOVZ, type, rd, value, 0);
610 return;
611 } else if ((ivalue & ~0xffffull) == 0) {
612 tcg_out_insn(s, 3405, MOVN, type, rd, ivalue, 0);
613 return;
614 }
615
4ec4f0bd
RH
616 /* Check for bitfield immediates. For the benefit of 32-bit quantities,
617 use the sign-extended value. That lets us match rotated values such
618 as 0xff0000ff with the same 64-bit logic matching 0xffffffffff0000ff. */
619 if (is_limm(svalue)) {
620 tcg_out_logicali(s, I3404_ORRI, type, rd, TCG_REG_XZR, svalue);
621 return;
622 }
623
c6e310d9
RH
624 /* Look for host pointer values within 4G of the PC. This happens
625 often when loading pointers to QEMU's own data structures. */
626 if (type == TCG_TYPE_I64) {
cc74d332
RH
627 tcg_target_long disp = value - (intptr_t)s->code_ptr;
628 if (disp == sextract64(disp, 0, 21)) {
629 tcg_out_insn(s, 3406, ADR, rd, disp);
630 return;
631 }
632 disp = (value >> 12) - ((intptr_t)s->code_ptr >> 12);
c6e310d9
RH
633 if (disp == sextract64(disp, 0, 21)) {
634 tcg_out_insn(s, 3406, ADRP, rd, disp);
635 if (value & 0xfff) {
636 tcg_out_insn(s, 3401, ADDI, type, rd, rd, value & 0xfff);
637 }
638 return;
639 }
640 }
641
dfeb5fe7
RH
642 /* Would it take fewer insns to begin with MOVN? For the value and its
643 inverse, count the number of 16-bit lanes that are 0. */
8cf9a3d3 644 for (i = wantinv = 0; i < 64; i += 16) {
dfeb5fe7 645 tcg_target_long mask = 0xffffull << i;
8cf9a3d3
RH
646 wantinv -= ((value & mask) == 0);
647 wantinv += ((ivalue & mask) == 0);
dfeb5fe7 648 }
dfeb5fe7 649
8cf9a3d3
RH
650 if (wantinv <= 0) {
651 /* Find the lowest lane that is not 0x0000. */
dfeb5fe7 652 shift = ctz64(value) & (63 & -16);
8cf9a3d3
RH
653 tcg_out_insn(s, 3405, MOVZ, type, rd, value >> shift, shift);
654 /* Clear out the lane that we just set. */
4a136e0a 655 value &= ~(0xffffUL << shift);
8cf9a3d3
RH
656 /* Iterate until all non-zero lanes have been processed. */
657 while (value) {
658 shift = ctz64(value) & (63 & -16);
659 tcg_out_insn(s, 3405, MOVK, type, rd, value >> shift, shift);
660 value &= ~(0xffffUL << shift);
661 }
662 } else {
663 /* Like above, but with the inverted value and MOVN to start. */
664 shift = ctz64(ivalue) & (63 & -16);
665 tcg_out_insn(s, 3405, MOVN, type, rd, ivalue >> shift, shift);
666 ivalue &= ~(0xffffUL << shift);
667 while (ivalue) {
668 shift = ctz64(ivalue) & (63 & -16);
669 /* Provide MOVK with the non-inverted value. */
670 tcg_out_insn(s, 3405, MOVK, type, rd, ~(ivalue >> shift), shift);
671 ivalue &= ~(0xffffUL << shift);
672 }
dfeb5fe7 673 }
4a136e0a
CF
674}
675
3d4299f4
RH
676/* Define something more legible for general use. */
677#define tcg_out_ldst_r tcg_out_insn_3310
4a136e0a 678
3d4299f4
RH
679static void tcg_out_ldst(TCGContext *s, AArch64Insn insn,
680 TCGReg rd, TCGReg rn, intptr_t offset)
4a136e0a 681{
3d4299f4
RH
682 TCGMemOp size = (uint32_t)insn >> 30;
683
3d4299f4
RH
684 /* If the offset is naturally aligned and in range, then we can
685 use the scaled uimm12 encoding */
686 if (offset >= 0 && !(offset & ((1 << size) - 1))) {
687 uintptr_t scaled_uimm = offset >> size;
688 if (scaled_uimm <= 0xfff) {
689 tcg_out_insn_3313(s, insn, rd, rn, scaled_uimm);
690 return;
b1f6dc0d
CF
691 }
692 }
693
a056c9fa
RH
694 /* Small signed offsets can use the unscaled encoding. */
695 if (offset >= -256 && offset < 256) {
696 tcg_out_insn_3312(s, insn, rd, rn, offset);
697 return;
698 }
699
3d4299f4 700 /* Worst-case scenario, move offset to temp register, use reg offset. */
b1f6dc0d 701 tcg_out_movi(s, TCG_TYPE_I64, TCG_REG_TMP, offset);
6c0f0c0f 702 tcg_out_ldst_r(s, insn, rd, rn, TCG_TYPE_I64, TCG_REG_TMP);
4a136e0a
CF
703}
704
4a136e0a
CF
705static inline void tcg_out_mov(TCGContext *s,
706 TCGType type, TCGReg ret, TCGReg arg)
707{
708 if (ret != arg) {
929f8b55 709 tcg_out_movr(s, type, ret, arg);
4a136e0a
CF
710 }
711}
712
713static inline void tcg_out_ld(TCGContext *s, TCGType type, TCGReg arg,
a05b5b9b 714 TCGReg arg1, intptr_t arg2)
4a136e0a 715{
3d4299f4 716 tcg_out_ldst(s, type == TCG_TYPE_I32 ? I3312_LDRW : I3312_LDRX,
4a136e0a
CF
717 arg, arg1, arg2);
718}
719
720static inline void tcg_out_st(TCGContext *s, TCGType type, TCGReg arg,
a05b5b9b 721 TCGReg arg1, intptr_t arg2)
4a136e0a 722{
3d4299f4 723 tcg_out_ldst(s, type == TCG_TYPE_I32 ? I3312_STRW : I3312_STRX,
4a136e0a
CF
724 arg, arg1, arg2);
725}
726
59d7c14e
RH
727static inline bool tcg_out_sti(TCGContext *s, TCGType type, TCGArg val,
728 TCGReg base, intptr_t ofs)
729{
730 if (val == 0) {
731 tcg_out_st(s, type, TCG_REG_XZR, base, ofs);
732 return true;
733 }
734 return false;
735}
736
b3c56df7
RH
737static inline void tcg_out_bfm(TCGContext *s, TCGType ext, TCGReg rd,
738 TCGReg rn, unsigned int a, unsigned int b)
739{
740 tcg_out_insn(s, 3402, BFM, ext, rd, rn, ext, a, b);
741}
742
7763ffa0
RH
743static inline void tcg_out_ubfm(TCGContext *s, TCGType ext, TCGReg rd,
744 TCGReg rn, unsigned int a, unsigned int b)
4a136e0a 745{
b3c56df7 746 tcg_out_insn(s, 3402, UBFM, ext, rd, rn, ext, a, b);
4a136e0a
CF
747}
748
7763ffa0
RH
749static inline void tcg_out_sbfm(TCGContext *s, TCGType ext, TCGReg rd,
750 TCGReg rn, unsigned int a, unsigned int b)
4a136e0a 751{
b3c56df7 752 tcg_out_insn(s, 3402, SBFM, ext, rd, rn, ext, a, b);
4a136e0a
CF
753}
754
7763ffa0 755static inline void tcg_out_extr(TCGContext *s, TCGType ext, TCGReg rd,
4a136e0a
CF
756 TCGReg rn, TCGReg rm, unsigned int a)
757{
b3c56df7 758 tcg_out_insn(s, 3403, EXTR, ext, rd, rn, rm, a);
4a136e0a
CF
759}
760
7763ffa0 761static inline void tcg_out_shl(TCGContext *s, TCGType ext,
4a136e0a
CF
762 TCGReg rd, TCGReg rn, unsigned int m)
763{
b3c56df7
RH
764 int bits = ext ? 64 : 32;
765 int max = bits - 1;
4a136e0a
CF
766 tcg_out_ubfm(s, ext, rd, rn, bits - (m & max), max - (m & max));
767}
768
7763ffa0 769static inline void tcg_out_shr(TCGContext *s, TCGType ext,
4a136e0a
CF
770 TCGReg rd, TCGReg rn, unsigned int m)
771{
772 int max = ext ? 63 : 31;
773 tcg_out_ubfm(s, ext, rd, rn, m & max, max);
774}
775
7763ffa0 776static inline void tcg_out_sar(TCGContext *s, TCGType ext,
4a136e0a
CF
777 TCGReg rd, TCGReg rn, unsigned int m)
778{
779 int max = ext ? 63 : 31;
780 tcg_out_sbfm(s, ext, rd, rn, m & max, max);
781}
782
7763ffa0 783static inline void tcg_out_rotr(TCGContext *s, TCGType ext,
4a136e0a
CF
784 TCGReg rd, TCGReg rn, unsigned int m)
785{
786 int max = ext ? 63 : 31;
787 tcg_out_extr(s, ext, rd, rn, rn, m & max);
788}
789
7763ffa0 790static inline void tcg_out_rotl(TCGContext *s, TCGType ext,
4a136e0a
CF
791 TCGReg rd, TCGReg rn, unsigned int m)
792{
b3c56df7
RH
793 int bits = ext ? 64 : 32;
794 int max = bits - 1;
4a136e0a
CF
795 tcg_out_extr(s, ext, rd, rn, rn, bits - (m & max));
796}
797
b3c56df7
RH
798static inline void tcg_out_dep(TCGContext *s, TCGType ext, TCGReg rd,
799 TCGReg rn, unsigned lsb, unsigned width)
800{
801 unsigned size = ext ? 64 : 32;
802 unsigned a = (size - lsb) & (size - 1);
803 unsigned b = width - 1;
804 tcg_out_bfm(s, ext, rd, rn, a, b);
805}
806
90f1cd91
RH
807static void tcg_out_cmp(TCGContext *s, TCGType ext, TCGReg a,
808 tcg_target_long b, bool const_b)
4a136e0a 809{
90f1cd91
RH
810 if (const_b) {
811 /* Using CMP or CMN aliases. */
812 if (b >= 0) {
813 tcg_out_insn(s, 3401, SUBSI, ext, TCG_REG_XZR, a, b);
814 } else {
815 tcg_out_insn(s, 3401, ADDSI, ext, TCG_REG_XZR, a, -b);
816 }
817 } else {
818 /* Using CMP alias SUBS wzr, Wn, Wm */
819 tcg_out_insn(s, 3502, SUBS, ext, TCG_REG_XZR, a, b);
820 }
4a136e0a
CF
821}
822
8587c30c 823static inline void tcg_out_goto(TCGContext *s, tcg_insn_unit *target)
4a136e0a 824{
8587c30c 825 ptrdiff_t offset = target - s->code_ptr;
eabb7b91 826 tcg_debug_assert(offset == sextract64(offset, 0, 26));
81d8a5ee 827 tcg_out_insn(s, 3206, B, offset);
4a136e0a
CF
828}
829
23b7aa1d
PK
830static inline void tcg_out_goto_long(TCGContext *s, tcg_insn_unit *target)
831{
832 ptrdiff_t offset = target - s->code_ptr;
833 if (offset == sextract64(offset, 0, 26)) {
834 tcg_out_insn(s, 3206, BL, offset);
835 } else {
836 tcg_out_movi(s, TCG_TYPE_I64, TCG_REG_TMP, (intptr_t)target);
837 tcg_out_insn(s, 3207, BR, TCG_REG_TMP);
838 }
839}
840
4a136e0a
CF
841static inline void tcg_out_goto_noaddr(TCGContext *s)
842{
81d8a5ee
RH
843 /* We pay attention here to not modify the branch target by reading from
844 the buffer. This ensure that caches and memory are kept coherent during
845 retranslation. Mask away possible garbage in the high bits for the
846 first translation, while keeping the offset bits for retranslation. */
847 uint32_t old = tcg_in32(s);
848 tcg_out_insn(s, 3206, B, old);
4a136e0a
CF
849}
850
851static inline void tcg_out_goto_cond_noaddr(TCGContext *s, TCGCond c)
852{
81d8a5ee
RH
853 /* See comments in tcg_out_goto_noaddr. */
854 uint32_t old = tcg_in32(s) >> 5;
855 tcg_out_insn(s, 3202, B_C, c, old);
4a136e0a
CF
856}
857
4a136e0a
CF
858static inline void tcg_out_callr(TCGContext *s, TCGReg reg)
859{
81d8a5ee 860 tcg_out_insn(s, 3207, BLR, reg);
4a136e0a
CF
861}
862
8587c30c 863static inline void tcg_out_call(TCGContext *s, tcg_insn_unit *target)
4a136e0a 864{
8587c30c
RH
865 ptrdiff_t offset = target - s->code_ptr;
866 if (offset == sextract64(offset, 0, 26)) {
81d8a5ee 867 tcg_out_insn(s, 3206, BL, offset);
8587c30c
RH
868 } else {
869 tcg_out_movi(s, TCG_TYPE_I64, TCG_REG_TMP, (intptr_t)target);
870 tcg_out_callr(s, TCG_REG_TMP);
4a136e0a
CF
871 }
872}
873
2acee8b2
PK
874#ifdef USE_DIRECT_JUMP
875
4a136e0a
CF
876void aarch64_tb_set_jmp_target(uintptr_t jmp_addr, uintptr_t addr)
877{
b68686bd
PK
878 tcg_insn_unit i1, i2;
879 TCGType rt = TCG_TYPE_I64;
880 TCGReg rd = TCG_REG_TMP;
881 uint64_t pair;
4a136e0a 882
b68686bd
PK
883 ptrdiff_t offset = addr - jmp_addr;
884
885 if (offset == sextract64(offset, 0, 26)) {
886 i1 = I3206_B | ((offset >> 2) & 0x3ffffff);
887 i2 = NOP;
888 } else {
889 offset = (addr >> 12) - (jmp_addr >> 12);
890
891 /* patch ADRP */
892 i1 = I3406_ADRP | (offset & 3) << 29 | (offset & 0x1ffffc) << (5 - 2) | rd;
893 /* patch ADDI */
894 i2 = I3401_ADDI | rt << 31 | (addr & 0xfff) << 10 | rd << 5 | rd;
895 }
896 pair = (uint64_t)i2 << 32 | i1;
897 atomic_set((uint64_t *)jmp_addr, pair);
898 flush_icache_range(jmp_addr, jmp_addr + 8);
4a136e0a
CF
899}
900
2acee8b2
PK
901#endif
902
bec16311 903static inline void tcg_out_goto_label(TCGContext *s, TCGLabel *l)
4a136e0a 904{
4a136e0a 905 if (!l->has_value) {
bec16311 906 tcg_out_reloc(s, s->code_ptr, R_AARCH64_JUMP26, l, 0);
4a136e0a
CF
907 tcg_out_goto_noaddr(s);
908 } else {
8587c30c 909 tcg_out_goto(s, l->u.value_ptr);
4a136e0a
CF
910 }
911}
912
dc1eccd6 913static void tcg_out_brcond(TCGContext *s, TCGType ext, TCGCond c, TCGArg a,
bec16311 914 TCGArg b, bool b_const, TCGLabel *l)
4a136e0a 915{
cae1f6f3 916 intptr_t offset;
3d9e69a2 917 bool need_cmp;
cae1f6f3 918
3d9e69a2
RH
919 if (b_const && b == 0 && (c == TCG_COND_EQ || c == TCG_COND_NE)) {
920 need_cmp = false;
921 } else {
922 need_cmp = true;
923 tcg_out_cmp(s, ext, a, b, b_const);
924 }
4a136e0a
CF
925
926 if (!l->has_value) {
bec16311 927 tcg_out_reloc(s, s->code_ptr, R_AARCH64_CONDBR19, l, 0);
cae1f6f3 928 offset = tcg_in32(s) >> 5;
4a136e0a 929 } else {
8587c30c 930 offset = l->u.value_ptr - s->code_ptr;
eabb7b91 931 tcg_debug_assert(offset == sextract64(offset, 0, 19));
4a136e0a 932 }
cae1f6f3 933
3d9e69a2
RH
934 if (need_cmp) {
935 tcg_out_insn(s, 3202, B_C, c, offset);
936 } else if (c == TCG_COND_EQ) {
937 tcg_out_insn(s, 3201, CBZ, ext, a, offset);
938 } else {
939 tcg_out_insn(s, 3201, CBNZ, ext, a, offset);
940 }
4a136e0a
CF
941}
942
edd8824c 943static inline void tcg_out_rev64(TCGContext *s, TCGReg rd, TCGReg rn)
9c4a059d 944{
edd8824c 945 tcg_out_insn(s, 3507, REV64, TCG_TYPE_I64, rd, rn);
9c4a059d
CF
946}
947
edd8824c 948static inline void tcg_out_rev32(TCGContext *s, TCGReg rd, TCGReg rn)
9c4a059d 949{
edd8824c
RH
950 tcg_out_insn(s, 3507, REV32, TCG_TYPE_I32, rd, rn);
951}
952
953static inline void tcg_out_rev16(TCGContext *s, TCGReg rd, TCGReg rn)
954{
955 tcg_out_insn(s, 3507, REV16, TCG_TYPE_I32, rd, rn);
9c4a059d
CF
956}
957
929f8b55 958static inline void tcg_out_sxt(TCGContext *s, TCGType ext, TCGMemOp s_bits,
31f1275b
CF
959 TCGReg rd, TCGReg rn)
960{
b3c56df7 961 /* Using ALIASes SXTB, SXTH, SXTW, of SBFM Xd, Xn, #0, #7|15|31 */
929f8b55 962 int bits = (8 << s_bits) - 1;
31f1275b
CF
963 tcg_out_sbfm(s, ext, rd, rn, 0, bits);
964}
965
929f8b55 966static inline void tcg_out_uxt(TCGContext *s, TCGMemOp s_bits,
31f1275b
CF
967 TCGReg rd, TCGReg rn)
968{
b3c56df7 969 /* Using ALIASes UXTB, UXTH of UBFM Wd, Wn, #0, #7|15 */
929f8b55 970 int bits = (8 << s_bits) - 1;
31f1275b
CF
971 tcg_out_ubfm(s, 0, rd, rn, 0, bits);
972}
973
90f1cd91
RH
974static void tcg_out_addsubi(TCGContext *s, int ext, TCGReg rd,
975 TCGReg rn, int64_t aimm)
976{
977 if (aimm >= 0) {
978 tcg_out_insn(s, 3401, ADDI, ext, rd, rn, aimm);
979 } else {
980 tcg_out_insn(s, 3401, SUBI, ext, rd, rn, -aimm);
981 }
982}
983
dc1eccd6 984static inline void tcg_out_addsub2(TCGContext *s, TCGType ext, TCGReg rl,
c6e929e7
RH
985 TCGReg rh, TCGReg al, TCGReg ah,
986 tcg_target_long bl, tcg_target_long bh,
987 bool const_bl, bool const_bh, bool sub)
988{
989 TCGReg orig_rl = rl;
990 AArch64Insn insn;
991
992 if (rl == ah || (!const_bh && rl == bh)) {
993 rl = TCG_REG_TMP;
994 }
995
996 if (const_bl) {
997 insn = I3401_ADDSI;
998 if ((bl < 0) ^ sub) {
999 insn = I3401_SUBSI;
1000 bl = -bl;
1001 }
b1eb20da
RH
1002 if (unlikely(al == TCG_REG_XZR)) {
1003 /* ??? We want to allow al to be zero for the benefit of
1004 negation via subtraction. However, that leaves open the
1005 possibility of adding 0+const in the low part, and the
1006 immediate add instructions encode XSP not XZR. Don't try
1007 anything more elaborate here than loading another zero. */
1008 al = TCG_REG_TMP;
1009 tcg_out_movi(s, ext, al, 0);
1010 }
c6e929e7
RH
1011 tcg_out_insn_3401(s, insn, ext, rl, al, bl);
1012 } else {
1013 tcg_out_insn_3502(s, sub ? I3502_SUBS : I3502_ADDS, ext, rl, al, bl);
1014 }
1015
1016 insn = I3503_ADC;
1017 if (const_bh) {
1018 /* Note that the only two constants we support are 0 and -1, and
1019 that SBC = rn + ~rm + c, so adc -1 is sbc 0, and vice-versa. */
1020 if ((bh != 0) ^ sub) {
1021 insn = I3503_SBC;
1022 }
1023 bh = TCG_REG_XZR;
1024 } else if (sub) {
1025 insn = I3503_SBC;
1026 }
1027 tcg_out_insn_3503(s, insn, ext, rh, ah, bh);
1028
b825025f 1029 tcg_out_mov(s, ext, orig_rl, rl);
c6e929e7
RH
1030}
1031
c7a59c2a
PK
1032static inline void tcg_out_mb(TCGContext *s, TCGArg a0)
1033{
1034 static const uint32_t sync[] = {
1035 [0 ... TCG_MO_ALL] = DMB_ISH | DMB_LD | DMB_ST,
1036 [TCG_MO_ST_ST] = DMB_ISH | DMB_ST,
1037 [TCG_MO_LD_LD] = DMB_ISH | DMB_LD,
1038 [TCG_MO_LD_ST] = DMB_ISH | DMB_LD,
1039 [TCG_MO_LD_ST | TCG_MO_LD_LD] = DMB_ISH | DMB_LD,
1040 };
1041 tcg_out32(s, sync[a0 & TCG_MO_ALL]);
1042}
1043
53c76c19
RH
1044static void tcg_out_cltz(TCGContext *s, TCGType ext, TCGReg d,
1045 TCGReg a0, TCGArg b, bool const_b, bool is_ctz)
1046{
1047 TCGReg a1 = a0;
1048 if (is_ctz) {
1049 a1 = TCG_REG_TMP;
1050 tcg_out_insn(s, 3507, RBIT, ext, a1, a0);
1051 }
1052 if (const_b && b == (ext ? 64 : 32)) {
1053 tcg_out_insn(s, 3507, CLZ, ext, d, a1);
1054 } else {
1055 AArch64Insn sel = I3506_CSEL;
1056
1057 tcg_out_cmp(s, ext, a0, 0, 1);
1058 tcg_out_insn(s, 3507, CLZ, ext, TCG_REG_TMP, a1);
1059
1060 if (const_b) {
1061 if (b == -1) {
1062 b = TCG_REG_XZR;
1063 sel = I3506_CSINV;
1064 } else if (b == 0) {
1065 b = TCG_REG_XZR;
1066 } else {
1067 tcg_out_movi(s, ext, d, b);
1068 b = d;
1069 }
1070 }
1071 tcg_out_insn_3506(s, sel, ext, d, TCG_REG_TMP, b, TCG_COND_NE);
1072 }
1073}
1074
4a136e0a 1075#ifdef CONFIG_SOFTMMU
023261ef 1076/* helper signature: helper_ret_ld_mmu(CPUState *env, target_ulong addr,
3972ef6f 1077 * TCGMemOpIdx oi, uintptr_t ra)
023261ef 1078 */
8587c30c 1079static void * const qemu_ld_helpers[16] = {
de61d14f
RH
1080 [MO_UB] = helper_ret_ldub_mmu,
1081 [MO_LEUW] = helper_le_lduw_mmu,
1082 [MO_LEUL] = helper_le_ldul_mmu,
1083 [MO_LEQ] = helper_le_ldq_mmu,
1084 [MO_BEUW] = helper_be_lduw_mmu,
1085 [MO_BEUL] = helper_be_ldul_mmu,
1086 [MO_BEQ] = helper_be_ldq_mmu,
4a136e0a
CF
1087};
1088
023261ef 1089/* helper signature: helper_ret_st_mmu(CPUState *env, target_ulong addr,
3972ef6f
RH
1090 * uintxx_t val, TCGMemOpIdx oi,
1091 * uintptr_t ra)
023261ef 1092 */
8587c30c 1093static void * const qemu_st_helpers[16] = {
de61d14f
RH
1094 [MO_UB] = helper_ret_stb_mmu,
1095 [MO_LEUW] = helper_le_stw_mmu,
1096 [MO_LEUL] = helper_le_stl_mmu,
1097 [MO_LEQ] = helper_le_stq_mmu,
1098 [MO_BEUW] = helper_be_stw_mmu,
1099 [MO_BEUL] = helper_be_stl_mmu,
1100 [MO_BEQ] = helper_be_stq_mmu,
4a136e0a
CF
1101};
1102
8587c30c 1103static inline void tcg_out_adr(TCGContext *s, TCGReg rd, void *target)
dc0c8aaf 1104{
8587c30c 1105 ptrdiff_t offset = tcg_pcrel_diff(s, target);
eabb7b91 1106 tcg_debug_assert(offset == sextract64(offset, 0, 21));
8587c30c 1107 tcg_out_insn(s, 3406, ADR, rd, offset);
dc0c8aaf
RH
1108}
1109
c6d8ed24
JK
1110static void tcg_out_qemu_ld_slow_path(TCGContext *s, TCGLabelQemuLdst *lb)
1111{
3972ef6f
RH
1112 TCGMemOpIdx oi = lb->oi;
1113 TCGMemOp opc = get_memop(oi);
929f8b55
RH
1114 TCGMemOp size = opc & MO_SIZE;
1115
8587c30c 1116 reloc_pc19(lb->label_ptr[0], s->code_ptr);
017a86f7 1117
3972ef6f 1118 tcg_out_mov(s, TCG_TYPE_PTR, TCG_REG_X0, TCG_AREG0);
b825025f 1119 tcg_out_mov(s, TARGET_LONG_BITS == 64, TCG_REG_X1, lb->addrlo_reg);
3972ef6f 1120 tcg_out_movi(s, TCG_TYPE_I32, TCG_REG_X2, oi);
8587c30c 1121 tcg_out_adr(s, TCG_REG_X3, lb->raddr);
2b7ec66f 1122 tcg_out_call(s, qemu_ld_helpers[opc & (MO_BSWAP | MO_SIZE)]);
929f8b55 1123 if (opc & MO_SIGN) {
9c53889b 1124 tcg_out_sxt(s, lb->type, size, lb->datalo_reg, TCG_REG_X0);
c6d8ed24 1125 } else {
b825025f 1126 tcg_out_mov(s, size == MO_64, lb->datalo_reg, TCG_REG_X0);
c6d8ed24
JK
1127 }
1128
8587c30c 1129 tcg_out_goto(s, lb->raddr);
c6d8ed24
JK
1130}
1131
1132static void tcg_out_qemu_st_slow_path(TCGContext *s, TCGLabelQemuLdst *lb)
1133{
3972ef6f
RH
1134 TCGMemOpIdx oi = lb->oi;
1135 TCGMemOp opc = get_memop(oi);
de61d14f 1136 TCGMemOp size = opc & MO_SIZE;
929f8b55 1137
8587c30c 1138 reloc_pc19(lb->label_ptr[0], s->code_ptr);
c6d8ed24 1139
3972ef6f 1140 tcg_out_mov(s, TCG_TYPE_PTR, TCG_REG_X0, TCG_AREG0);
b825025f
RH
1141 tcg_out_mov(s, TARGET_LONG_BITS == 64, TCG_REG_X1, lb->addrlo_reg);
1142 tcg_out_mov(s, size == MO_64, TCG_REG_X2, lb->datalo_reg);
3972ef6f 1143 tcg_out_movi(s, TCG_TYPE_I32, TCG_REG_X3, oi);
8587c30c 1144 tcg_out_adr(s, TCG_REG_X4, lb->raddr);
2b7ec66f 1145 tcg_out_call(s, qemu_st_helpers[opc & (MO_BSWAP | MO_SIZE)]);
8587c30c 1146 tcg_out_goto(s, lb->raddr);
c6d8ed24
JK
1147}
1148
3972ef6f 1149static void add_qemu_ldst_label(TCGContext *s, bool is_ld, TCGMemOpIdx oi,
9c53889b 1150 TCGType ext, TCGReg data_reg, TCGReg addr_reg,
3972ef6f 1151 tcg_insn_unit *raddr, tcg_insn_unit *label_ptr)
c6d8ed24 1152{
9ecefc84 1153 TCGLabelQemuLdst *label = new_ldst_label(s);
c6d8ed24 1154
c6d8ed24 1155 label->is_ld = is_ld;
3972ef6f 1156 label->oi = oi;
9c53889b 1157 label->type = ext;
c6d8ed24
JK
1158 label->datalo_reg = data_reg;
1159 label->addrlo_reg = addr_reg;
c6d8ed24
JK
1160 label->raddr = raddr;
1161 label->label_ptr[0] = label_ptr;
1162}
1163
1164/* Load and compare a TLB entry, emitting the conditional jump to the
1165 slow path for the failure case, which will be patched later when finalizing
1166 the slow path. Generated code returns the host addend in X1,
1167 clobbers X0,X2,X3,TMP. */
9ee14902 1168static void tcg_out_tlb_read(TCGContext *s, TCGReg addr_reg, TCGMemOp opc,
8587c30c
RH
1169 tcg_insn_unit **label_ptr, int mem_index,
1170 bool is_read)
c6d8ed24 1171{
c6d8ed24
JK
1172 int tlb_offset = is_read ?
1173 offsetof(CPUArchState, tlb_table[mem_index][0].addr_read)
1174 : offsetof(CPUArchState, tlb_table[mem_index][0].addr_write);
85aa8081
RH
1175 unsigned a_bits = get_alignment_bits(opc);
1176 unsigned s_bits = opc & MO_SIZE;
1177 unsigned a_mask = (1u << a_bits) - 1;
1178 unsigned s_mask = (1u << s_bits) - 1;
9ee14902
RH
1179 TCGReg base = TCG_AREG0, x3;
1180 uint64_t tlb_mask;
1181
1182 /* For aligned accesses, we check the first byte and include the alignment
1183 bits within the address. For unaligned access, we check that we don't
1184 cross pages using the address of the last byte of the access. */
85aa8081 1185 if (a_bits >= s_bits) {
9ee14902
RH
1186 x3 = addr_reg;
1187 } else {
1188 tcg_out_insn(s, 3401, ADDI, TARGET_LONG_BITS == 64,
85aa8081 1189 TCG_REG_X3, addr_reg, s_mask - a_mask);
9ee14902
RH
1190 x3 = TCG_REG_X3;
1191 }
85aa8081 1192 tlb_mask = (uint64_t)TARGET_PAGE_MASK | a_mask;
6f472467 1193
c6d8ed24
JK
1194 /* Extract the TLB index from the address into X0.
1195 X0<CPU_TLB_BITS:0> =
1196 addr_reg<TARGET_PAGE_BITS+CPU_TLB_BITS:TARGET_PAGE_BITS> */
6f472467 1197 tcg_out_ubfm(s, TARGET_LONG_BITS == 64, TCG_REG_X0, addr_reg,
c6d8ed24 1198 TARGET_PAGE_BITS, TARGET_PAGE_BITS + CPU_TLB_BITS);
6f472467 1199
9ee14902
RH
1200 /* Store the page mask part of the address into X3. */
1201 tcg_out_logicali(s, I3404_ANDI, TARGET_LONG_BITS == 64,
1202 TCG_REG_X3, x3, tlb_mask);
6f472467 1203
c6d8ed24 1204 /* Add any "high bits" from the tlb offset to the env address into X2,
096c46c0 1205 to take advantage of the LSL12 form of the ADDI instruction.
c6d8ed24 1206 X2 = env + (tlb_offset & 0xfff000) */
6f472467
RH
1207 if (tlb_offset & 0xfff000) {
1208 tcg_out_insn(s, 3401, ADDI, TCG_TYPE_I64, TCG_REG_X2, base,
1209 tlb_offset & 0xfff000);
1210 base = TCG_REG_X2;
1211 }
1212
c6d8ed24
JK
1213 /* Merge the tlb index contribution into X2.
1214 X2 = X2 + (X0 << CPU_TLB_ENTRY_BITS) */
6f472467 1215 tcg_out_insn(s, 3502S, ADD_LSL, TCG_TYPE_I64, TCG_REG_X2, base,
50573c66 1216 TCG_REG_X0, CPU_TLB_ENTRY_BITS);
6f472467 1217
c6d8ed24
JK
1218 /* Merge "low bits" from tlb offset, load the tlb comparator into X0.
1219 X0 = load [X2 + (tlb_offset & 0x000fff)] */
3d4299f4
RH
1220 tcg_out_ldst(s, TARGET_LONG_BITS == 32 ? I3312_LDRW : I3312_LDRX,
1221 TCG_REG_X0, TCG_REG_X2, tlb_offset & 0xfff);
6f472467 1222
c6d8ed24
JK
1223 /* Load the tlb addend. Do that early to avoid stalling.
1224 X1 = load [X2 + (tlb_offset & 0xfff) + offsetof(addend)] */
3d4299f4 1225 tcg_out_ldst(s, I3312_LDRX, TCG_REG_X1, TCG_REG_X2,
c6d8ed24
JK
1226 (tlb_offset & 0xfff) + (offsetof(CPUTLBEntry, addend)) -
1227 (is_read ? offsetof(CPUTLBEntry, addr_read)
1228 : offsetof(CPUTLBEntry, addr_write)));
6f472467 1229
c6d8ed24 1230 /* Perform the address comparison. */
90f1cd91 1231 tcg_out_cmp(s, (TARGET_LONG_BITS == 64), TCG_REG_X0, TCG_REG_X3, 0);
6f472467 1232
c6d8ed24 1233 /* If not equal, we jump to the slow path. */
6f472467 1234 *label_ptr = s->code_ptr;
c6d8ed24
JK
1235 tcg_out_goto_cond_noaddr(s, TCG_COND_NE);
1236}
1237
1238#endif /* CONFIG_SOFTMMU */
6a91c7c9 1239
9c53889b 1240static void tcg_out_qemu_ld_direct(TCGContext *s, TCGMemOp memop, TCGType ext,
ffc63728
PB
1241 TCGReg data_r, TCGReg addr_r,
1242 TCGType otype, TCGReg off_r)
6a91c7c9 1243{
9e4177ad
RH
1244 const TCGMemOp bswap = memop & MO_BSWAP;
1245
1246 switch (memop & MO_SSIZE) {
1247 case MO_UB:
6c0f0c0f 1248 tcg_out_ldst_r(s, I3312_LDRB, data_r, addr_r, otype, off_r);
6a91c7c9 1249 break;
9e4177ad 1250 case MO_SB:
9c53889b 1251 tcg_out_ldst_r(s, ext ? I3312_LDRSBX : I3312_LDRSBW,
6c0f0c0f 1252 data_r, addr_r, otype, off_r);
6a91c7c9 1253 break;
9e4177ad 1254 case MO_UW:
6c0f0c0f 1255 tcg_out_ldst_r(s, I3312_LDRH, data_r, addr_r, otype, off_r);
9e4177ad 1256 if (bswap) {
edd8824c 1257 tcg_out_rev16(s, data_r, data_r);
6a91c7c9
JK
1258 }
1259 break;
9e4177ad
RH
1260 case MO_SW:
1261 if (bswap) {
6c0f0c0f 1262 tcg_out_ldst_r(s, I3312_LDRH, data_r, addr_r, otype, off_r);
edd8824c 1263 tcg_out_rev16(s, data_r, data_r);
9c53889b 1264 tcg_out_sxt(s, ext, MO_16, data_r, data_r);
6a91c7c9 1265 } else {
6c0f0c0f
PB
1266 tcg_out_ldst_r(s, (ext ? I3312_LDRSHX : I3312_LDRSHW),
1267 data_r, addr_r, otype, off_r);
6a91c7c9
JK
1268 }
1269 break;
9e4177ad 1270 case MO_UL:
6c0f0c0f 1271 tcg_out_ldst_r(s, I3312_LDRW, data_r, addr_r, otype, off_r);
9e4177ad 1272 if (bswap) {
edd8824c 1273 tcg_out_rev32(s, data_r, data_r);
6a91c7c9
JK
1274 }
1275 break;
9e4177ad
RH
1276 case MO_SL:
1277 if (bswap) {
6c0f0c0f 1278 tcg_out_ldst_r(s, I3312_LDRW, data_r, addr_r, otype, off_r);
edd8824c 1279 tcg_out_rev32(s, data_r, data_r);
929f8b55 1280 tcg_out_sxt(s, TCG_TYPE_I64, MO_32, data_r, data_r);
6a91c7c9 1281 } else {
6c0f0c0f 1282 tcg_out_ldst_r(s, I3312_LDRSWX, data_r, addr_r, otype, off_r);
6a91c7c9
JK
1283 }
1284 break;
9e4177ad 1285 case MO_Q:
6c0f0c0f 1286 tcg_out_ldst_r(s, I3312_LDRX, data_r, addr_r, otype, off_r);
9e4177ad 1287 if (bswap) {
edd8824c 1288 tcg_out_rev64(s, data_r, data_r);
6a91c7c9
JK
1289 }
1290 break;
1291 default:
1292 tcg_abort();
1293 }
1294}
1295
9e4177ad 1296static void tcg_out_qemu_st_direct(TCGContext *s, TCGMemOp memop,
ffc63728
PB
1297 TCGReg data_r, TCGReg addr_r,
1298 TCGType otype, TCGReg off_r)
6a91c7c9 1299{
9e4177ad
RH
1300 const TCGMemOp bswap = memop & MO_BSWAP;
1301
1302 switch (memop & MO_SIZE) {
1303 case MO_8:
6c0f0c0f 1304 tcg_out_ldst_r(s, I3312_STRB, data_r, addr_r, otype, off_r);
6a91c7c9 1305 break;
9e4177ad 1306 case MO_16:
e81864a1 1307 if (bswap && data_r != TCG_REG_XZR) {
edd8824c 1308 tcg_out_rev16(s, TCG_REG_TMP, data_r);
9e4177ad 1309 data_r = TCG_REG_TMP;
6a91c7c9 1310 }
6c0f0c0f 1311 tcg_out_ldst_r(s, I3312_STRH, data_r, addr_r, otype, off_r);
6a91c7c9 1312 break;
9e4177ad 1313 case MO_32:
e81864a1 1314 if (bswap && data_r != TCG_REG_XZR) {
edd8824c 1315 tcg_out_rev32(s, TCG_REG_TMP, data_r);
9e4177ad 1316 data_r = TCG_REG_TMP;
6a91c7c9 1317 }
6c0f0c0f 1318 tcg_out_ldst_r(s, I3312_STRW, data_r, addr_r, otype, off_r);
6a91c7c9 1319 break;
9e4177ad 1320 case MO_64:
e81864a1 1321 if (bswap && data_r != TCG_REG_XZR) {
edd8824c 1322 tcg_out_rev64(s, TCG_REG_TMP, data_r);
9e4177ad 1323 data_r = TCG_REG_TMP;
6a91c7c9 1324 }
6c0f0c0f 1325 tcg_out_ldst_r(s, I3312_STRX, data_r, addr_r, otype, off_r);
6a91c7c9
JK
1326 break;
1327 default:
1328 tcg_abort();
1329 }
1330}
4a136e0a 1331
667b1cdd 1332static void tcg_out_qemu_ld(TCGContext *s, TCGReg data_reg, TCGReg addr_reg,
59227d5d 1333 TCGMemOpIdx oi, TCGType ext)
4a136e0a 1334{
59227d5d 1335 TCGMemOp memop = get_memop(oi);
80adb8fc 1336 const TCGType otype = TARGET_LONG_BITS == 64 ? TCG_TYPE_I64 : TCG_TYPE_I32;
4a136e0a 1337#ifdef CONFIG_SOFTMMU
59227d5d 1338 unsigned mem_index = get_mmuidx(oi);
8587c30c 1339 tcg_insn_unit *label_ptr;
4a136e0a 1340
9ee14902 1341 tcg_out_tlb_read(s, addr_reg, memop, &label_ptr, mem_index, 1);
80adb8fc
RH
1342 tcg_out_qemu_ld_direct(s, memop, ext, data_reg,
1343 TCG_REG_X1, otype, addr_reg);
3972ef6f
RH
1344 add_qemu_ldst_label(s, true, oi, ext, data_reg, addr_reg,
1345 s->code_ptr, label_ptr);
4a136e0a 1346#else /* !CONFIG_SOFTMMU */
352bcb0a
RH
1347 if (USE_GUEST_BASE) {
1348 tcg_out_qemu_ld_direct(s, memop, ext, data_reg,
1349 TCG_REG_GUEST_BASE, otype, addr_reg);
1350 } else {
1351 tcg_out_qemu_ld_direct(s, memop, ext, data_reg,
1352 addr_reg, TCG_TYPE_I64, TCG_REG_XZR);
1353 }
6a91c7c9 1354#endif /* CONFIG_SOFTMMU */
4a136e0a
CF
1355}
1356
667b1cdd 1357static void tcg_out_qemu_st(TCGContext *s, TCGReg data_reg, TCGReg addr_reg,
59227d5d 1358 TCGMemOpIdx oi)
4a136e0a 1359{
59227d5d 1360 TCGMemOp memop = get_memop(oi);
80adb8fc 1361 const TCGType otype = TARGET_LONG_BITS == 64 ? TCG_TYPE_I64 : TCG_TYPE_I32;
4a136e0a 1362#ifdef CONFIG_SOFTMMU
59227d5d 1363 unsigned mem_index = get_mmuidx(oi);
8587c30c 1364 tcg_insn_unit *label_ptr;
4a136e0a 1365
9ee14902 1366 tcg_out_tlb_read(s, addr_reg, memop, &label_ptr, mem_index, 0);
80adb8fc
RH
1367 tcg_out_qemu_st_direct(s, memop, data_reg,
1368 TCG_REG_X1, otype, addr_reg);
9ee14902
RH
1369 add_qemu_ldst_label(s, false, oi, (memop & MO_SIZE)== MO_64,
1370 data_reg, addr_reg, s->code_ptr, label_ptr);
4a136e0a 1371#else /* !CONFIG_SOFTMMU */
352bcb0a
RH
1372 if (USE_GUEST_BASE) {
1373 tcg_out_qemu_st_direct(s, memop, data_reg,
1374 TCG_REG_GUEST_BASE, otype, addr_reg);
1375 } else {
1376 tcg_out_qemu_st_direct(s, memop, data_reg,
1377 addr_reg, TCG_TYPE_I64, TCG_REG_XZR);
1378 }
6a91c7c9 1379#endif /* CONFIG_SOFTMMU */
4a136e0a
CF
1380}
1381
8587c30c 1382static tcg_insn_unit *tb_ret_addr;
4a136e0a 1383
4a136e0a 1384static void tcg_out_op(TCGContext *s, TCGOpcode opc,
8d8db193
RH
1385 const TCGArg args[TCG_MAX_OP_ARGS],
1386 const int const_args[TCG_MAX_OP_ARGS])
4a136e0a 1387{
f0293414
RH
1388 /* 99% of the time, we can signal the use of extension registers
1389 by looking to see if the opcode handles 64-bit data. */
1390 TCGType ext = (tcg_op_defs[opc].flags & TCG_OPF_64BIT) != 0;
4a136e0a 1391
8d8db193
RH
1392 /* Hoist the loads of the most common arguments. */
1393 TCGArg a0 = args[0];
1394 TCGArg a1 = args[1];
1395 TCGArg a2 = args[2];
1396 int c2 = const_args[2];
1397
04ce397b
RH
1398 /* Some operands are defined with "rZ" constraint, a register or
1399 the zero register. These need not actually test args[I] == 0. */
1400#define REG0(I) (const_args[I] ? TCG_REG_XZR : (TCGReg)args[I])
1401
4a136e0a
CF
1402 switch (opc) {
1403 case INDEX_op_exit_tb:
b19f0c2e
RH
1404 /* Reuse the zeroing that exists for goto_ptr. */
1405 if (a0 == 0) {
23b7aa1d 1406 tcg_out_goto_long(s, s->code_gen_epilogue);
b19f0c2e
RH
1407 } else {
1408 tcg_out_movi(s, TCG_TYPE_I64, TCG_REG_X0, a0);
23b7aa1d 1409 tcg_out_goto_long(s, tb_ret_addr);
b19f0c2e 1410 }
4a136e0a
CF
1411 break;
1412
1413 case INDEX_op_goto_tb:
2acee8b2
PK
1414 if (s->tb_jmp_insn_offset != NULL) {
1415 /* USE_DIRECT_JUMP */
1416 /* Ensure that ADRP+ADD are 8-byte aligned so that an atomic
1417 write can be used to patch the target address. */
1418 if ((uintptr_t)s->code_ptr & 7) {
1419 tcg_out32(s, NOP);
1420 }
1421 s->tb_jmp_insn_offset[a0] = tcg_current_code_size(s);
1422 /* actual branch destination will be patched by
1423 aarch64_tb_set_jmp_target later. */
1424 tcg_out_insn(s, 3406, ADRP, TCG_REG_TMP, 0);
1425 tcg_out_insn(s, 3401, ADDI, TCG_TYPE_I64, TCG_REG_TMP, TCG_REG_TMP, 0);
1426 } else {
1427 /* !USE_DIRECT_JUMP */
1428 tcg_debug_assert(s->tb_jmp_target_addr != NULL);
1429 intptr_t offset = tcg_pcrel_diff(s, (s->tb_jmp_target_addr + a0)) >> 2;
1430 tcg_out_insn(s, 3305, LDR, offset, TCG_REG_TMP);
b68686bd 1431 }
b68686bd 1432 tcg_out_insn(s, 3207, BR, TCG_REG_TMP);
f309101c 1433 s->tb_jmp_reset_offset[a0] = tcg_current_code_size(s);
4a136e0a
CF
1434 break;
1435
b19f0c2e
RH
1436 case INDEX_op_goto_ptr:
1437 tcg_out_insn(s, 3207, BR, a0);
1438 break;
1439
4a136e0a 1440 case INDEX_op_br:
bec16311 1441 tcg_out_goto_label(s, arg_label(a0));
4a136e0a
CF
1442 break;
1443
4a136e0a 1444 case INDEX_op_ld8u_i32:
4a136e0a 1445 case INDEX_op_ld8u_i64:
3d4299f4 1446 tcg_out_ldst(s, I3312_LDRB, a0, a1, a2);
dc73dfd4
RH
1447 break;
1448 case INDEX_op_ld8s_i32:
3d4299f4 1449 tcg_out_ldst(s, I3312_LDRSBW, a0, a1, a2);
dc73dfd4 1450 break;
4a136e0a 1451 case INDEX_op_ld8s_i64:
3d4299f4 1452 tcg_out_ldst(s, I3312_LDRSBX, a0, a1, a2);
dc73dfd4
RH
1453 break;
1454 case INDEX_op_ld16u_i32:
4a136e0a 1455 case INDEX_op_ld16u_i64:
3d4299f4 1456 tcg_out_ldst(s, I3312_LDRH, a0, a1, a2);
dc73dfd4
RH
1457 break;
1458 case INDEX_op_ld16s_i32:
3d4299f4 1459 tcg_out_ldst(s, I3312_LDRSHW, a0, a1, a2);
dc73dfd4 1460 break;
4a136e0a 1461 case INDEX_op_ld16s_i64:
3d4299f4 1462 tcg_out_ldst(s, I3312_LDRSHX, a0, a1, a2);
dc73dfd4
RH
1463 break;
1464 case INDEX_op_ld_i32:
4a136e0a 1465 case INDEX_op_ld32u_i64:
3d4299f4 1466 tcg_out_ldst(s, I3312_LDRW, a0, a1, a2);
dc73dfd4 1467 break;
4a136e0a 1468 case INDEX_op_ld32s_i64:
3d4299f4 1469 tcg_out_ldst(s, I3312_LDRSWX, a0, a1, a2);
e81864a1 1470 break;
dc73dfd4 1471 case INDEX_op_ld_i64:
3d4299f4 1472 tcg_out_ldst(s, I3312_LDRX, a0, a1, a2);
dc73dfd4
RH
1473 break;
1474
4a136e0a
CF
1475 case INDEX_op_st8_i32:
1476 case INDEX_op_st8_i64:
3d4299f4 1477 tcg_out_ldst(s, I3312_STRB, REG0(0), a1, a2);
dc73dfd4 1478 break;
4a136e0a
CF
1479 case INDEX_op_st16_i32:
1480 case INDEX_op_st16_i64:
3d4299f4 1481 tcg_out_ldst(s, I3312_STRH, REG0(0), a1, a2);
dc73dfd4
RH
1482 break;
1483 case INDEX_op_st_i32:
4a136e0a 1484 case INDEX_op_st32_i64:
3d4299f4 1485 tcg_out_ldst(s, I3312_STRW, REG0(0), a1, a2);
dc73dfd4
RH
1486 break;
1487 case INDEX_op_st_i64:
3d4299f4 1488 tcg_out_ldst(s, I3312_STRX, REG0(0), a1, a2);
4a136e0a
CF
1489 break;
1490
4a136e0a 1491 case INDEX_op_add_i32:
90f1cd91
RH
1492 a2 = (int32_t)a2;
1493 /* FALLTHRU */
1494 case INDEX_op_add_i64:
1495 if (c2) {
1496 tcg_out_addsubi(s, ext, a0, a1, a2);
1497 } else {
1498 tcg_out_insn(s, 3502, ADD, ext, a0, a1, a2);
1499 }
4a136e0a
CF
1500 break;
1501
4a136e0a 1502 case INDEX_op_sub_i32:
90f1cd91
RH
1503 a2 = (int32_t)a2;
1504 /* FALLTHRU */
1505 case INDEX_op_sub_i64:
1506 if (c2) {
1507 tcg_out_addsubi(s, ext, a0, a1, -a2);
1508 } else {
1509 tcg_out_insn(s, 3502, SUB, ext, a0, a1, a2);
1510 }
4a136e0a
CF
1511 break;
1512
14b155dd
RH
1513 case INDEX_op_neg_i64:
1514 case INDEX_op_neg_i32:
1515 tcg_out_insn(s, 3502, SUB, ext, a0, TCG_REG_XZR, a1);
1516 break;
1517
4a136e0a 1518 case INDEX_op_and_i32:
e029f293
RH
1519 a2 = (int32_t)a2;
1520 /* FALLTHRU */
1521 case INDEX_op_and_i64:
1522 if (c2) {
1523 tcg_out_logicali(s, I3404_ANDI, ext, a0, a1, a2);
1524 } else {
1525 tcg_out_insn(s, 3510, AND, ext, a0, a1, a2);
1526 }
4a136e0a
CF
1527 break;
1528
14b155dd
RH
1529 case INDEX_op_andc_i32:
1530 a2 = (int32_t)a2;
1531 /* FALLTHRU */
1532 case INDEX_op_andc_i64:
1533 if (c2) {
1534 tcg_out_logicali(s, I3404_ANDI, ext, a0, a1, ~a2);
1535 } else {
1536 tcg_out_insn(s, 3510, BIC, ext, a0, a1, a2);
1537 }
1538 break;
1539
4a136e0a 1540 case INDEX_op_or_i32:
e029f293
RH
1541 a2 = (int32_t)a2;
1542 /* FALLTHRU */
1543 case INDEX_op_or_i64:
1544 if (c2) {
1545 tcg_out_logicali(s, I3404_ORRI, ext, a0, a1, a2);
1546 } else {
1547 tcg_out_insn(s, 3510, ORR, ext, a0, a1, a2);
1548 }
4a136e0a
CF
1549 break;
1550
14b155dd
RH
1551 case INDEX_op_orc_i32:
1552 a2 = (int32_t)a2;
1553 /* FALLTHRU */
1554 case INDEX_op_orc_i64:
1555 if (c2) {
1556 tcg_out_logicali(s, I3404_ORRI, ext, a0, a1, ~a2);
1557 } else {
1558 tcg_out_insn(s, 3510, ORN, ext, a0, a1, a2);
1559 }
1560 break;
1561
4a136e0a 1562 case INDEX_op_xor_i32:
e029f293
RH
1563 a2 = (int32_t)a2;
1564 /* FALLTHRU */
1565 case INDEX_op_xor_i64:
1566 if (c2) {
1567 tcg_out_logicali(s, I3404_EORI, ext, a0, a1, a2);
1568 } else {
1569 tcg_out_insn(s, 3510, EOR, ext, a0, a1, a2);
1570 }
4a136e0a
CF
1571 break;
1572
14b155dd
RH
1573 case INDEX_op_eqv_i32:
1574 a2 = (int32_t)a2;
1575 /* FALLTHRU */
1576 case INDEX_op_eqv_i64:
1577 if (c2) {
1578 tcg_out_logicali(s, I3404_EORI, ext, a0, a1, ~a2);
1579 } else {
1580 tcg_out_insn(s, 3510, EON, ext, a0, a1, a2);
1581 }
1582 break;
1583
1584 case INDEX_op_not_i64:
1585 case INDEX_op_not_i32:
1586 tcg_out_insn(s, 3510, ORN, ext, a0, TCG_REG_XZR, a1);
1587 break;
1588
4a136e0a 1589 case INDEX_op_mul_i64:
4a136e0a 1590 case INDEX_op_mul_i32:
8678b71c
RH
1591 tcg_out_insn(s, 3509, MADD, ext, a0, a1, a2, TCG_REG_XZR);
1592 break;
1593
1594 case INDEX_op_div_i64:
1595 case INDEX_op_div_i32:
1596 tcg_out_insn(s, 3508, SDIV, ext, a0, a1, a2);
1597 break;
1598 case INDEX_op_divu_i64:
1599 case INDEX_op_divu_i32:
1600 tcg_out_insn(s, 3508, UDIV, ext, a0, a1, a2);
1601 break;
1602
1603 case INDEX_op_rem_i64:
1604 case INDEX_op_rem_i32:
1605 tcg_out_insn(s, 3508, SDIV, ext, TCG_REG_TMP, a1, a2);
1606 tcg_out_insn(s, 3509, MSUB, ext, a0, TCG_REG_TMP, a2, a1);
1607 break;
1608 case INDEX_op_remu_i64:
1609 case INDEX_op_remu_i32:
1610 tcg_out_insn(s, 3508, UDIV, ext, TCG_REG_TMP, a1, a2);
1611 tcg_out_insn(s, 3509, MSUB, ext, a0, TCG_REG_TMP, a2, a1);
4a136e0a
CF
1612 break;
1613
1614 case INDEX_op_shl_i64:
4a136e0a 1615 case INDEX_op_shl_i32:
df9351e3 1616 if (c2) {
8d8db193 1617 tcg_out_shl(s, ext, a0, a1, a2);
df9351e3
RH
1618 } else {
1619 tcg_out_insn(s, 3508, LSLV, ext, a0, a1, a2);
4a136e0a
CF
1620 }
1621 break;
1622
1623 case INDEX_op_shr_i64:
4a136e0a 1624 case INDEX_op_shr_i32:
df9351e3 1625 if (c2) {
8d8db193 1626 tcg_out_shr(s, ext, a0, a1, a2);
df9351e3
RH
1627 } else {
1628 tcg_out_insn(s, 3508, LSRV, ext, a0, a1, a2);
4a136e0a
CF
1629 }
1630 break;
1631
1632 case INDEX_op_sar_i64:
4a136e0a 1633 case INDEX_op_sar_i32:
df9351e3 1634 if (c2) {
8d8db193 1635 tcg_out_sar(s, ext, a0, a1, a2);
df9351e3
RH
1636 } else {
1637 tcg_out_insn(s, 3508, ASRV, ext, a0, a1, a2);
4a136e0a
CF
1638 }
1639 break;
1640
1641 case INDEX_op_rotr_i64:
4a136e0a 1642 case INDEX_op_rotr_i32:
df9351e3 1643 if (c2) {
8d8db193 1644 tcg_out_rotr(s, ext, a0, a1, a2);
df9351e3
RH
1645 } else {
1646 tcg_out_insn(s, 3508, RORV, ext, a0, a1, a2);
4a136e0a
CF
1647 }
1648 break;
1649
1650 case INDEX_op_rotl_i64:
df9351e3
RH
1651 case INDEX_op_rotl_i32:
1652 if (c2) {
8d8db193 1653 tcg_out_rotl(s, ext, a0, a1, a2);
4a136e0a 1654 } else {
50573c66 1655 tcg_out_insn(s, 3502, SUB, 0, TCG_REG_TMP, TCG_REG_XZR, a2);
df9351e3 1656 tcg_out_insn(s, 3508, RORV, ext, a0, a1, TCG_REG_TMP);
4a136e0a
CF
1657 }
1658 break;
1659
53c76c19
RH
1660 case INDEX_op_clz_i64:
1661 case INDEX_op_clz_i32:
1662 tcg_out_cltz(s, ext, a0, a1, a2, c2, false);
1663 break;
1664 case INDEX_op_ctz_i64:
1665 case INDEX_op_ctz_i32:
1666 tcg_out_cltz(s, ext, a0, a1, a2, c2, true);
1667 break;
1668
8d8db193 1669 case INDEX_op_brcond_i32:
90f1cd91
RH
1670 a1 = (int32_t)a1;
1671 /* FALLTHRU */
1672 case INDEX_op_brcond_i64:
bec16311 1673 tcg_out_brcond(s, ext, a2, a0, a1, const_args[1], arg_label(args[3]));
4a136e0a
CF
1674 break;
1675
4a136e0a 1676 case INDEX_op_setcond_i32:
90f1cd91
RH
1677 a2 = (int32_t)a2;
1678 /* FALLTHRU */
1679 case INDEX_op_setcond_i64:
1680 tcg_out_cmp(s, ext, a1, a2, c2);
ed7a0aa8
RH
1681 /* Use CSET alias of CSINC Wd, WZR, WZR, invert(cond). */
1682 tcg_out_insn(s, 3506, CSINC, TCG_TYPE_I32, a0, TCG_REG_XZR,
1683 TCG_REG_XZR, tcg_invert_cond(args[3]));
4a136e0a
CF
1684 break;
1685
04ce397b
RH
1686 case INDEX_op_movcond_i32:
1687 a2 = (int32_t)a2;
1688 /* FALLTHRU */
1689 case INDEX_op_movcond_i64:
1690 tcg_out_cmp(s, ext, a1, a2, c2);
1691 tcg_out_insn(s, 3506, CSEL, ext, a0, REG0(3), REG0(4), args[5]);
1692 break;
1693
de61d14f
RH
1694 case INDEX_op_qemu_ld_i32:
1695 case INDEX_op_qemu_ld_i64:
59227d5d 1696 tcg_out_qemu_ld(s, a0, a1, a2, ext);
4a136e0a 1697 break;
de61d14f
RH
1698 case INDEX_op_qemu_st_i32:
1699 case INDEX_op_qemu_st_i64:
59227d5d 1700 tcg_out_qemu_st(s, REG0(0), a1, a2);
4a136e0a
CF
1701 break;
1702
f0293414 1703 case INDEX_op_bswap64_i64:
edd8824c
RH
1704 tcg_out_rev64(s, a0, a1);
1705 break;
1706 case INDEX_op_bswap32_i64:
9c4a059d 1707 case INDEX_op_bswap32_i32:
edd8824c 1708 tcg_out_rev32(s, a0, a1);
9c4a059d
CF
1709 break;
1710 case INDEX_op_bswap16_i64:
1711 case INDEX_op_bswap16_i32:
edd8824c 1712 tcg_out_rev16(s, a0, a1);
9c4a059d
CF
1713 break;
1714
31f1275b 1715 case INDEX_op_ext8s_i64:
31f1275b 1716 case INDEX_op_ext8s_i32:
929f8b55 1717 tcg_out_sxt(s, ext, MO_8, a0, a1);
31f1275b
CF
1718 break;
1719 case INDEX_op_ext16s_i64:
31f1275b 1720 case INDEX_op_ext16s_i32:
929f8b55 1721 tcg_out_sxt(s, ext, MO_16, a0, a1);
31f1275b 1722 break;
4f2331e5 1723 case INDEX_op_ext_i32_i64:
31f1275b 1724 case INDEX_op_ext32s_i64:
929f8b55 1725 tcg_out_sxt(s, TCG_TYPE_I64, MO_32, a0, a1);
31f1275b
CF
1726 break;
1727 case INDEX_op_ext8u_i64:
1728 case INDEX_op_ext8u_i32:
929f8b55 1729 tcg_out_uxt(s, MO_8, a0, a1);
31f1275b
CF
1730 break;
1731 case INDEX_op_ext16u_i64:
1732 case INDEX_op_ext16u_i32:
929f8b55 1733 tcg_out_uxt(s, MO_16, a0, a1);
31f1275b 1734 break;
4f2331e5 1735 case INDEX_op_extu_i32_i64:
31f1275b 1736 case INDEX_op_ext32u_i64:
929f8b55 1737 tcg_out_movr(s, TCG_TYPE_I32, a0, a1);
31f1275b
CF
1738 break;
1739
b3c56df7
RH
1740 case INDEX_op_deposit_i64:
1741 case INDEX_op_deposit_i32:
1742 tcg_out_dep(s, ext, a0, REG0(2), args[3], args[4]);
1743 break;
1744
e2179f94
RH
1745 case INDEX_op_extract_i64:
1746 case INDEX_op_extract_i32:
1747 tcg_out_ubfm(s, ext, a0, a1, a2, a2 + args[3] - 1);
1748 break;
1749
1750 case INDEX_op_sextract_i64:
1751 case INDEX_op_sextract_i32:
1752 tcg_out_sbfm(s, ext, a0, a1, a2, a2 + args[3] - 1);
1753 break;
1754
c6e929e7
RH
1755 case INDEX_op_add2_i32:
1756 tcg_out_addsub2(s, TCG_TYPE_I32, a0, a1, REG0(2), REG0(3),
1757 (int32_t)args[4], args[5], const_args[4],
1758 const_args[5], false);
1759 break;
1760 case INDEX_op_add2_i64:
1761 tcg_out_addsub2(s, TCG_TYPE_I64, a0, a1, REG0(2), REG0(3), args[4],
1762 args[5], const_args[4], const_args[5], false);
1763 break;
1764 case INDEX_op_sub2_i32:
1765 tcg_out_addsub2(s, TCG_TYPE_I32, a0, a1, REG0(2), REG0(3),
1766 (int32_t)args[4], args[5], const_args[4],
1767 const_args[5], true);
1768 break;
1769 case INDEX_op_sub2_i64:
1770 tcg_out_addsub2(s, TCG_TYPE_I64, a0, a1, REG0(2), REG0(3), args[4],
1771 args[5], const_args[4], const_args[5], true);
1772 break;
1773
1fcc9ddf
RH
1774 case INDEX_op_muluh_i64:
1775 tcg_out_insn(s, 3508, UMULH, TCG_TYPE_I64, a0, a1, a2);
1776 break;
1777 case INDEX_op_mulsh_i64:
1778 tcg_out_insn(s, 3508, SMULH, TCG_TYPE_I64, a0, a1, a2);
1779 break;
1780
c7a59c2a
PK
1781 case INDEX_op_mb:
1782 tcg_out_mb(s, a0);
1783 break;
1784
96d0ee7f 1785 case INDEX_op_mov_i32: /* Always emitted via tcg_out_mov. */
a51a6b6a 1786 case INDEX_op_mov_i64:
96d0ee7f 1787 case INDEX_op_movi_i32: /* Always emitted via tcg_out_movi. */
a51a6b6a 1788 case INDEX_op_movi_i64:
96d0ee7f 1789 case INDEX_op_call: /* Always emitted via tcg_out_call. */
4a136e0a 1790 default:
a51a6b6a 1791 tcg_abort();
4a136e0a 1792 }
04ce397b
RH
1793
1794#undef REG0
4a136e0a
CF
1795}
1796
1797static const TCGTargetOpDef aarch64_op_defs[] = {
1798 { INDEX_op_exit_tb, { } },
1799 { INDEX_op_goto_tb, { } },
4a136e0a 1800 { INDEX_op_br, { } },
b19f0c2e 1801 { INDEX_op_goto_ptr, { "r" } },
4a136e0a 1802
4a136e0a
CF
1803 { INDEX_op_ld8u_i32, { "r", "r" } },
1804 { INDEX_op_ld8s_i32, { "r", "r" } },
1805 { INDEX_op_ld16u_i32, { "r", "r" } },
1806 { INDEX_op_ld16s_i32, { "r", "r" } },
1807 { INDEX_op_ld_i32, { "r", "r" } },
1808 { INDEX_op_ld8u_i64, { "r", "r" } },
1809 { INDEX_op_ld8s_i64, { "r", "r" } },
1810 { INDEX_op_ld16u_i64, { "r", "r" } },
1811 { INDEX_op_ld16s_i64, { "r", "r" } },
1812 { INDEX_op_ld32u_i64, { "r", "r" } },
1813 { INDEX_op_ld32s_i64, { "r", "r" } },
1814 { INDEX_op_ld_i64, { "r", "r" } },
1815
e81864a1
RH
1816 { INDEX_op_st8_i32, { "rZ", "r" } },
1817 { INDEX_op_st16_i32, { "rZ", "r" } },
1818 { INDEX_op_st_i32, { "rZ", "r" } },
1819 { INDEX_op_st8_i64, { "rZ", "r" } },
1820 { INDEX_op_st16_i64, { "rZ", "r" } },
1821 { INDEX_op_st32_i64, { "rZ", "r" } },
1822 { INDEX_op_st_i64, { "rZ", "r" } },
4a136e0a 1823
170bf931 1824 { INDEX_op_add_i32, { "r", "r", "rA" } },
90f1cd91 1825 { INDEX_op_add_i64, { "r", "r", "rA" } },
170bf931 1826 { INDEX_op_sub_i32, { "r", "r", "rA" } },
90f1cd91 1827 { INDEX_op_sub_i64, { "r", "r", "rA" } },
4a136e0a
CF
1828 { INDEX_op_mul_i32, { "r", "r", "r" } },
1829 { INDEX_op_mul_i64, { "r", "r", "r" } },
8678b71c
RH
1830 { INDEX_op_div_i32, { "r", "r", "r" } },
1831 { INDEX_op_div_i64, { "r", "r", "r" } },
1832 { INDEX_op_divu_i32, { "r", "r", "r" } },
1833 { INDEX_op_divu_i64, { "r", "r", "r" } },
1834 { INDEX_op_rem_i32, { "r", "r", "r" } },
1835 { INDEX_op_rem_i64, { "r", "r", "r" } },
1836 { INDEX_op_remu_i32, { "r", "r", "r" } },
1837 { INDEX_op_remu_i64, { "r", "r", "r" } },
170bf931 1838 { INDEX_op_and_i32, { "r", "r", "rL" } },
e029f293 1839 { INDEX_op_and_i64, { "r", "r", "rL" } },
170bf931 1840 { INDEX_op_or_i32, { "r", "r", "rL" } },
e029f293 1841 { INDEX_op_or_i64, { "r", "r", "rL" } },
170bf931 1842 { INDEX_op_xor_i32, { "r", "r", "rL" } },
e029f293 1843 { INDEX_op_xor_i64, { "r", "r", "rL" } },
170bf931 1844 { INDEX_op_andc_i32, { "r", "r", "rL" } },
14b155dd 1845 { INDEX_op_andc_i64, { "r", "r", "rL" } },
170bf931 1846 { INDEX_op_orc_i32, { "r", "r", "rL" } },
14b155dd 1847 { INDEX_op_orc_i64, { "r", "r", "rL" } },
170bf931 1848 { INDEX_op_eqv_i32, { "r", "r", "rL" } },
14b155dd
RH
1849 { INDEX_op_eqv_i64, { "r", "r", "rL" } },
1850
1851 { INDEX_op_neg_i32, { "r", "r" } },
1852 { INDEX_op_neg_i64, { "r", "r" } },
1853 { INDEX_op_not_i32, { "r", "r" } },
1854 { INDEX_op_not_i64, { "r", "r" } },
4a136e0a
CF
1855
1856 { INDEX_op_shl_i32, { "r", "r", "ri" } },
1857 { INDEX_op_shr_i32, { "r", "r", "ri" } },
1858 { INDEX_op_sar_i32, { "r", "r", "ri" } },
1859 { INDEX_op_rotl_i32, { "r", "r", "ri" } },
1860 { INDEX_op_rotr_i32, { "r", "r", "ri" } },
53c76c19
RH
1861 { INDEX_op_clz_i32, { "r", "r", "rAL" } },
1862 { INDEX_op_ctz_i32, { "r", "r", "rAL" } },
4a136e0a
CF
1863 { INDEX_op_shl_i64, { "r", "r", "ri" } },
1864 { INDEX_op_shr_i64, { "r", "r", "ri" } },
1865 { INDEX_op_sar_i64, { "r", "r", "ri" } },
1866 { INDEX_op_rotl_i64, { "r", "r", "ri" } },
1867 { INDEX_op_rotr_i64, { "r", "r", "ri" } },
53c76c19
RH
1868 { INDEX_op_clz_i64, { "r", "r", "rAL" } },
1869 { INDEX_op_ctz_i64, { "r", "r", "rAL" } },
4a136e0a 1870
170bf931 1871 { INDEX_op_brcond_i32, { "r", "rA" } },
90f1cd91 1872 { INDEX_op_brcond_i64, { "r", "rA" } },
170bf931 1873 { INDEX_op_setcond_i32, { "r", "r", "rA" } },
90f1cd91 1874 { INDEX_op_setcond_i64, { "r", "r", "rA" } },
170bf931 1875 { INDEX_op_movcond_i32, { "r", "r", "rA", "rZ", "rZ" } },
04ce397b 1876 { INDEX_op_movcond_i64, { "r", "r", "rA", "rZ", "rZ" } },
4a136e0a 1877
de61d14f
RH
1878 { INDEX_op_qemu_ld_i32, { "r", "l" } },
1879 { INDEX_op_qemu_ld_i64, { "r", "l" } },
e81864a1
RH
1880 { INDEX_op_qemu_st_i32, { "lZ", "l" } },
1881 { INDEX_op_qemu_st_i64, { "lZ", "l" } },
9c4a059d
CF
1882
1883 { INDEX_op_bswap16_i32, { "r", "r" } },
1884 { INDEX_op_bswap32_i32, { "r", "r" } },
1885 { INDEX_op_bswap16_i64, { "r", "r" } },
1886 { INDEX_op_bswap32_i64, { "r", "r" } },
1887 { INDEX_op_bswap64_i64, { "r", "r" } },
1888
31f1275b
CF
1889 { INDEX_op_ext8s_i32, { "r", "r" } },
1890 { INDEX_op_ext16s_i32, { "r", "r" } },
1891 { INDEX_op_ext8u_i32, { "r", "r" } },
1892 { INDEX_op_ext16u_i32, { "r", "r" } },
1893
1894 { INDEX_op_ext8s_i64, { "r", "r" } },
1895 { INDEX_op_ext16s_i64, { "r", "r" } },
1896 { INDEX_op_ext32s_i64, { "r", "r" } },
1897 { INDEX_op_ext8u_i64, { "r", "r" } },
1898 { INDEX_op_ext16u_i64, { "r", "r" } },
1899 { INDEX_op_ext32u_i64, { "r", "r" } },
4f2331e5
AJ
1900 { INDEX_op_ext_i32_i64, { "r", "r" } },
1901 { INDEX_op_extu_i32_i64, { "r", "r" } },
31f1275b 1902
b3c56df7
RH
1903 { INDEX_op_deposit_i32, { "r", "0", "rZ" } },
1904 { INDEX_op_deposit_i64, { "r", "0", "rZ" } },
e2179f94
RH
1905 { INDEX_op_extract_i32, { "r", "r" } },
1906 { INDEX_op_extract_i64, { "r", "r" } },
1907 { INDEX_op_sextract_i32, { "r", "r" } },
1908 { INDEX_op_sextract_i64, { "r", "r" } },
b3c56df7 1909
170bf931 1910 { INDEX_op_add2_i32, { "r", "r", "rZ", "rZ", "rA", "rMZ" } },
c6e929e7 1911 { INDEX_op_add2_i64, { "r", "r", "rZ", "rZ", "rA", "rMZ" } },
170bf931 1912 { INDEX_op_sub2_i32, { "r", "r", "rZ", "rZ", "rA", "rMZ" } },
c6e929e7
RH
1913 { INDEX_op_sub2_i64, { "r", "r", "rZ", "rZ", "rA", "rMZ" } },
1914
1fcc9ddf
RH
1915 { INDEX_op_muluh_i64, { "r", "r", "r" } },
1916 { INDEX_op_mulsh_i64, { "r", "r", "r" } },
1917
c7a59c2a 1918 { INDEX_op_mb, { } },
4a136e0a
CF
1919 { -1 },
1920};
1921
f69d277e
RH
1922static const TCGTargetOpDef *tcg_target_op_def(TCGOpcode op)
1923{
1924 int i, n = ARRAY_SIZE(aarch64_op_defs);
1925
1926 for (i = 0; i < n; ++i) {
1927 if (aarch64_op_defs[i].op == op) {
1928 return &aarch64_op_defs[i];
1929 }
1930 }
1931 return NULL;
1932}
1933
4a136e0a
CF
1934static void tcg_target_init(TCGContext *s)
1935{
4a136e0a
CF
1936 tcg_regset_set32(tcg_target_available_regs[TCG_TYPE_I32], 0, 0xffffffff);
1937 tcg_regset_set32(tcg_target_available_regs[TCG_TYPE_I64], 0, 0xffffffff);
1938
1939 tcg_regset_set32(tcg_target_call_clobber_regs, 0,
1940 (1 << TCG_REG_X0) | (1 << TCG_REG_X1) |
1941 (1 << TCG_REG_X2) | (1 << TCG_REG_X3) |
1942 (1 << TCG_REG_X4) | (1 << TCG_REG_X5) |
1943 (1 << TCG_REG_X6) | (1 << TCG_REG_X7) |
1944 (1 << TCG_REG_X8) | (1 << TCG_REG_X9) |
1945 (1 << TCG_REG_X10) | (1 << TCG_REG_X11) |
1946 (1 << TCG_REG_X12) | (1 << TCG_REG_X13) |
1947 (1 << TCG_REG_X14) | (1 << TCG_REG_X15) |
1948 (1 << TCG_REG_X16) | (1 << TCG_REG_X17) |
d82b78e4 1949 (1 << TCG_REG_X18) | (1 << TCG_REG_X30));
4a136e0a
CF
1950
1951 tcg_regset_clear(s->reserved_regs);
1952 tcg_regset_set_reg(s->reserved_regs, TCG_REG_SP);
1953 tcg_regset_set_reg(s->reserved_regs, TCG_REG_FP);
1954 tcg_regset_set_reg(s->reserved_regs, TCG_REG_TMP);
1955 tcg_regset_set_reg(s->reserved_regs, TCG_REG_X18); /* platform register */
4a136e0a
CF
1956}
1957
38d195aa
RH
1958/* Saving pairs: (X19, X20) .. (X27, X28), (X29(fp), X30(lr)). */
1959#define PUSH_SIZE ((30 - 19 + 1) * 8)
1960
1961#define FRAME_SIZE \
1962 ((PUSH_SIZE \
1963 + TCG_STATIC_CALL_ARGS_SIZE \
1964 + CPU_TEMP_BUF_NLONGS * sizeof(long) \
1965 + TCG_TARGET_STACK_ALIGN - 1) \
1966 & ~(TCG_TARGET_STACK_ALIGN - 1))
1967
1968/* We're expecting a 2 byte uleb128 encoded value. */
1969QEMU_BUILD_BUG_ON(FRAME_SIZE >= (1 << 14));
1970
1971/* We're expecting to use a single ADDI insn. */
1972QEMU_BUILD_BUG_ON(FRAME_SIZE - PUSH_SIZE > 0xfff);
1973
4a136e0a
CF
1974static void tcg_target_qemu_prologue(TCGContext *s)
1975{
4a136e0a
CF
1976 TCGReg r;
1977
95f72aa9
RH
1978 /* Push (FP, LR) and allocate space for all saved registers. */
1979 tcg_out_insn(s, 3314, STP, TCG_REG_FP, TCG_REG_LR,
38d195aa 1980 TCG_REG_SP, -PUSH_SIZE, 1, 1);
4a136e0a 1981
d82b78e4 1982 /* Set up frame pointer for canonical unwinding. */
929f8b55 1983 tcg_out_movr_sp(s, TCG_TYPE_I64, TCG_REG_FP, TCG_REG_SP);
4a136e0a 1984
d82b78e4 1985 /* Store callee-preserved regs x19..x28. */
4a136e0a 1986 for (r = TCG_REG_X19; r <= TCG_REG_X27; r += 2) {
95f72aa9
RH
1987 int ofs = (r - TCG_REG_X19 + 2) * 8;
1988 tcg_out_insn(s, 3314, STP, r, r + 1, TCG_REG_SP, ofs, 1, 0);
4a136e0a
CF
1989 }
1990
096c46c0
RH
1991 /* Make stack space for TCG locals. */
1992 tcg_out_insn(s, 3401, SUBI, TCG_TYPE_I64, TCG_REG_SP, TCG_REG_SP,
38d195aa 1993 FRAME_SIZE - PUSH_SIZE);
096c46c0 1994
95f72aa9 1995 /* Inform TCG about how to find TCG locals with register, offset, size. */
4a136e0a
CF
1996 tcg_set_frame(s, TCG_REG_SP, TCG_STATIC_CALL_ARGS_SIZE,
1997 CPU_TEMP_BUF_NLONGS * sizeof(long));
1998
4cbea598 1999#if !defined(CONFIG_SOFTMMU)
352bcb0a 2000 if (USE_GUEST_BASE) {
b76f21a7 2001 tcg_out_movi(s, TCG_TYPE_PTR, TCG_REG_GUEST_BASE, guest_base);
6a91c7c9
JK
2002 tcg_regset_set_reg(s->reserved_regs, TCG_REG_GUEST_BASE);
2003 }
2004#endif
2005
4a136e0a 2006 tcg_out_mov(s, TCG_TYPE_PTR, TCG_AREG0, tcg_target_call_iarg_regs[0]);
81d8a5ee 2007 tcg_out_insn(s, 3207, BR, tcg_target_call_iarg_regs[1]);
4a136e0a 2008
b19f0c2e
RH
2009 /*
2010 * Return path for goto_ptr. Set return value to 0, a-la exit_tb,
2011 * and fall through to the rest of the epilogue.
2012 */
2013 s->code_gen_epilogue = s->code_ptr;
2014 tcg_out_movi(s, TCG_TYPE_REG, TCG_REG_X0, 0);
2015
2016 /* TB epilogue */
4a136e0a
CF
2017 tb_ret_addr = s->code_ptr;
2018
096c46c0
RH
2019 /* Remove TCG locals stack space. */
2020 tcg_out_insn(s, 3401, ADDI, TCG_TYPE_I64, TCG_REG_SP, TCG_REG_SP,
38d195aa 2021 FRAME_SIZE - PUSH_SIZE);
4a136e0a 2022
95f72aa9 2023 /* Restore registers x19..x28. */
4a136e0a 2024 for (r = TCG_REG_X19; r <= TCG_REG_X27; r += 2) {
95f72aa9
RH
2025 int ofs = (r - TCG_REG_X19 + 2) * 8;
2026 tcg_out_insn(s, 3314, LDP, r, r + 1, TCG_REG_SP, ofs, 1, 0);
4a136e0a
CF
2027 }
2028
95f72aa9
RH
2029 /* Pop (FP, LR), restore SP to previous frame. */
2030 tcg_out_insn(s, 3314, LDP, TCG_REG_FP, TCG_REG_LR,
38d195aa 2031 TCG_REG_SP, PUSH_SIZE, 0, 1);
81d8a5ee 2032 tcg_out_insn(s, 3207, RET, TCG_REG_LR);
4a136e0a 2033}
38d195aa
RH
2034
2035typedef struct {
3d9bddb3 2036 DebugFrameHeader h;
38d195aa
RH
2037 uint8_t fde_def_cfa[4];
2038 uint8_t fde_reg_ofs[24];
2039} DebugFrame;
2040
2041#define ELF_HOST_MACHINE EM_AARCH64
2042
3d9bddb3
RH
2043static const DebugFrame debug_frame = {
2044 .h.cie.len = sizeof(DebugFrameCIE)-4, /* length after .len member */
2045 .h.cie.id = -1,
2046 .h.cie.version = 1,
2047 .h.cie.code_align = 1,
2048 .h.cie.data_align = 0x78, /* sleb128 -8 */
2049 .h.cie.return_column = TCG_REG_LR,
38d195aa
RH
2050
2051 /* Total FDE size does not include the "len" member. */
3d9bddb3 2052 .h.fde.len = sizeof(DebugFrame) - offsetof(DebugFrame, h.fde.cie_offset),
38d195aa
RH
2053
2054 .fde_def_cfa = {
2055 12, TCG_REG_SP, /* DW_CFA_def_cfa sp, ... */
2056 (FRAME_SIZE & 0x7f) | 0x80, /* ... uleb128 FRAME_SIZE */
2057 (FRAME_SIZE >> 7)
2058 },
2059 .fde_reg_ofs = {
2060 0x80 + 28, 1, /* DW_CFA_offset, x28, -8 */
2061 0x80 + 27, 2, /* DW_CFA_offset, x27, -16 */
2062 0x80 + 26, 3, /* DW_CFA_offset, x26, -24 */
2063 0x80 + 25, 4, /* DW_CFA_offset, x25, -32 */
2064 0x80 + 24, 5, /* DW_CFA_offset, x24, -40 */
2065 0x80 + 23, 6, /* DW_CFA_offset, x23, -48 */
2066 0x80 + 22, 7, /* DW_CFA_offset, x22, -56 */
2067 0x80 + 21, 8, /* DW_CFA_offset, x21, -64 */
2068 0x80 + 20, 9, /* DW_CFA_offset, x20, -72 */
2069 0x80 + 19, 10, /* DW_CFA_offset, x1p, -80 */
2070 0x80 + 30, 11, /* DW_CFA_offset, lr, -88 */
2071 0x80 + 29, 12, /* DW_CFA_offset, fp, -96 */
2072 }
2073};
2074
2075void tcg_register_jit(void *buf, size_t buf_size)
2076{
38d195aa
RH
2077 tcg_register_jit_int(buf, buf_size, &debug_frame, sizeof(debug_frame));
2078}