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