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