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