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