xref: /openbmc/qemu/tcg/aarch64/tcg-target.c.inc (revision 70581940cabcc51b329652becddfbc6a261b1b83)
1139c1837SPaolo Bonzini/*
2139c1837SPaolo Bonzini * Initial TCG Implementation for aarch64
3139c1837SPaolo Bonzini *
4139c1837SPaolo Bonzini * Copyright (c) 2013 Huawei Technologies Duesseldorf GmbH
5139c1837SPaolo Bonzini * Written by Claudio Fontana
6139c1837SPaolo Bonzini *
7139c1837SPaolo Bonzini * This work is licensed under the terms of the GNU GPL, version 2 or
8139c1837SPaolo Bonzini * (at your option) any later version.
9139c1837SPaolo Bonzini *
10139c1837SPaolo Bonzini * See the COPYING file in the top-level directory for details.
11139c1837SPaolo Bonzini */
12139c1837SPaolo Bonzini
13f85ab3d2SRichard Henderson#include "../tcg-ldst.c.inc"
14139c1837SPaolo Bonzini#include "../tcg-pool.c.inc"
15139c1837SPaolo Bonzini#include "qemu/bitops.h"
16139c1837SPaolo Bonzini
17139c1837SPaolo Bonzini/* We're going to re-use TCGType in setting of the SF bit, which controls
18139c1837SPaolo Bonzini   the size of the operation performed.  If we know the values match, it
19139c1837SPaolo Bonzini   makes things much cleaner.  */
20139c1837SPaolo BonziniQEMU_BUILD_BUG_ON(TCG_TYPE_I32 != 0 || TCG_TYPE_I64 != 1);
21139c1837SPaolo Bonzini
22139c1837SPaolo Bonzini#ifdef CONFIG_DEBUG_TCG
23139c1837SPaolo Bonzinistatic const char * const tcg_target_reg_names[TCG_TARGET_NB_REGS] = {
24139c1837SPaolo Bonzini    "x0", "x1", "x2", "x3", "x4", "x5", "x6", "x7",
25139c1837SPaolo Bonzini    "x8", "x9", "x10", "x11", "x12", "x13", "x14", "x15",
26139c1837SPaolo Bonzini    "x16", "x17", "x18", "x19", "x20", "x21", "x22", "x23",
27139c1837SPaolo Bonzini    "x24", "x25", "x26", "x27", "x28", "fp", "x30", "sp",
28139c1837SPaolo Bonzini
29139c1837SPaolo Bonzini    "v0", "v1", "v2", "v3", "v4", "v5", "v6", "v7",
30139c1837SPaolo Bonzini    "v8", "v9", "v10", "v11", "v12", "v13", "v14", "v15",
31139c1837SPaolo Bonzini    "v16", "v17", "v18", "v19", "v20", "v21", "v22", "v23",
32139c1837SPaolo Bonzini    "v24", "v25", "v26", "v27", "v28", "fp", "v30", "v31",
33139c1837SPaolo Bonzini};
34139c1837SPaolo Bonzini#endif /* CONFIG_DEBUG_TCG */
35139c1837SPaolo Bonzini
36139c1837SPaolo Bonzinistatic const int tcg_target_reg_alloc_order[] = {
37139c1837SPaolo Bonzini    TCG_REG_X20, TCG_REG_X21, TCG_REG_X22, TCG_REG_X23,
38139c1837SPaolo Bonzini    TCG_REG_X24, TCG_REG_X25, TCG_REG_X26, TCG_REG_X27,
39139c1837SPaolo Bonzini    TCG_REG_X28, /* we will reserve this for guest_base if configured */
40139c1837SPaolo Bonzini
41139c1837SPaolo Bonzini    TCG_REG_X8, TCG_REG_X9, TCG_REG_X10, TCG_REG_X11,
42139c1837SPaolo Bonzini    TCG_REG_X12, TCG_REG_X13, TCG_REG_X14, TCG_REG_X15,
43139c1837SPaolo Bonzini
44139c1837SPaolo Bonzini    TCG_REG_X0, TCG_REG_X1, TCG_REG_X2, TCG_REG_X3,
45139c1837SPaolo Bonzini    TCG_REG_X4, TCG_REG_X5, TCG_REG_X6, TCG_REG_X7,
46139c1837SPaolo Bonzini
47da4d0d95SRichard Henderson    /* X16 reserved as temporary */
48da4d0d95SRichard Henderson    /* X17 reserved as temporary */
49139c1837SPaolo Bonzini    /* X18 reserved by system */
50139c1837SPaolo Bonzini    /* X19 reserved for AREG0 */
51139c1837SPaolo Bonzini    /* X29 reserved as fp */
52139c1837SPaolo Bonzini    /* X30 reserved as temporary */
53139c1837SPaolo Bonzini
54139c1837SPaolo Bonzini    TCG_REG_V0, TCG_REG_V1, TCG_REG_V2, TCG_REG_V3,
55139c1837SPaolo Bonzini    TCG_REG_V4, TCG_REG_V5, TCG_REG_V6, TCG_REG_V7,
56139c1837SPaolo Bonzini    /* V8 - V15 are call-saved, and skipped.  */
57139c1837SPaolo Bonzini    TCG_REG_V16, TCG_REG_V17, TCG_REG_V18, TCG_REG_V19,
58139c1837SPaolo Bonzini    TCG_REG_V20, TCG_REG_V21, TCG_REG_V22, TCG_REG_V23,
59139c1837SPaolo Bonzini    TCG_REG_V24, TCG_REG_V25, TCG_REG_V26, TCG_REG_V27,
60139c1837SPaolo Bonzini    TCG_REG_V28, TCG_REG_V29, TCG_REG_V30, TCG_REG_V31,
61139c1837SPaolo Bonzini};
62139c1837SPaolo Bonzini
63139c1837SPaolo Bonzinistatic const int tcg_target_call_iarg_regs[8] = {
64139c1837SPaolo Bonzini    TCG_REG_X0, TCG_REG_X1, TCG_REG_X2, TCG_REG_X3,
65139c1837SPaolo Bonzini    TCG_REG_X4, TCG_REG_X5, TCG_REG_X6, TCG_REG_X7
66139c1837SPaolo Bonzini};
675e3d0c19SRichard Henderson
685e3d0c19SRichard Hendersonstatic TCGReg tcg_target_call_oarg_reg(TCGCallReturnKind kind, int slot)
695e3d0c19SRichard Henderson{
705e3d0c19SRichard Henderson    tcg_debug_assert(kind == TCG_CALL_RET_NORMAL);
715e3d0c19SRichard Henderson    tcg_debug_assert(slot >= 0 && slot <= 1);
725e3d0c19SRichard Henderson    return TCG_REG_X0 + slot;
735e3d0c19SRichard Henderson}
74139c1837SPaolo Bonzini
75da4d0d95SRichard Henderson#define TCG_REG_TMP0 TCG_REG_X16
76da4d0d95SRichard Henderson#define TCG_REG_TMP1 TCG_REG_X17
77da4d0d95SRichard Henderson#define TCG_REG_TMP2 TCG_REG_X30
78d67bcbddSRichard Henderson#define TCG_VEC_TMP0 TCG_REG_V31
79139c1837SPaolo Bonzini
80139c1837SPaolo Bonzini#define TCG_REG_GUEST_BASE TCG_REG_X28
81139c1837SPaolo Bonzini
82ffba3eb3SRichard Hendersonstatic bool reloc_pc26(tcg_insn_unit *src_rw, const tcg_insn_unit *target)
83139c1837SPaolo Bonzini{
84ffba3eb3SRichard Henderson    const tcg_insn_unit *src_rx = tcg_splitwx_to_rx(src_rw);
85ffba3eb3SRichard Henderson    ptrdiff_t offset = target - src_rx;
86ffba3eb3SRichard Henderson
87139c1837SPaolo Bonzini    if (offset == sextract64(offset, 0, 26)) {
88139c1837SPaolo Bonzini        /* read instruction, mask away previous PC_REL26 parameter contents,
89139c1837SPaolo Bonzini           set the proper offset, then write back the instruction. */
90ffba3eb3SRichard Henderson        *src_rw = deposit32(*src_rw, 0, 26, offset);
91139c1837SPaolo Bonzini        return true;
92139c1837SPaolo Bonzini    }
93139c1837SPaolo Bonzini    return false;
94139c1837SPaolo Bonzini}
95139c1837SPaolo Bonzini
96ffba3eb3SRichard Hendersonstatic bool reloc_pc19(tcg_insn_unit *src_rw, const tcg_insn_unit *target)
97139c1837SPaolo Bonzini{
98ffba3eb3SRichard Henderson    const tcg_insn_unit *src_rx = tcg_splitwx_to_rx(src_rw);
99ffba3eb3SRichard Henderson    ptrdiff_t offset = target - src_rx;
100ffba3eb3SRichard Henderson
101139c1837SPaolo Bonzini    if (offset == sextract64(offset, 0, 19)) {
102ffba3eb3SRichard Henderson        *src_rw = deposit32(*src_rw, 5, 19, offset);
103139c1837SPaolo Bonzini        return true;
104139c1837SPaolo Bonzini    }
105139c1837SPaolo Bonzini    return false;
106139c1837SPaolo Bonzini}
107139c1837SPaolo Bonzini
10892a11b93SRichard Hendersonstatic bool reloc_pc14(tcg_insn_unit *src_rw, const tcg_insn_unit *target)
10992a11b93SRichard Henderson{
11092a11b93SRichard Henderson    const tcg_insn_unit *src_rx = tcg_splitwx_to_rx(src_rw);
11192a11b93SRichard Henderson    ptrdiff_t offset = target - src_rx;
11292a11b93SRichard Henderson
11392a11b93SRichard Henderson    if (offset == sextract64(offset, 0, 14)) {
11492a11b93SRichard Henderson        *src_rw = deposit32(*src_rw, 5, 14, offset);
11592a11b93SRichard Henderson        return true;
11692a11b93SRichard Henderson    }
11792a11b93SRichard Henderson    return false;
11892a11b93SRichard Henderson}
11992a11b93SRichard Henderson
120ffba3eb3SRichard Hendersonstatic bool patch_reloc(tcg_insn_unit *code_ptr, int type,
121139c1837SPaolo Bonzini                        intptr_t value, intptr_t addend)
122139c1837SPaolo Bonzini{
123139c1837SPaolo Bonzini    tcg_debug_assert(addend == 0);
124139c1837SPaolo Bonzini    switch (type) {
125139c1837SPaolo Bonzini    case R_AARCH64_JUMP26:
126139c1837SPaolo Bonzini    case R_AARCH64_CALL26:
127ffba3eb3SRichard Henderson        return reloc_pc26(code_ptr, (const tcg_insn_unit *)value);
128139c1837SPaolo Bonzini    case R_AARCH64_CONDBR19:
129ffba3eb3SRichard Henderson        return reloc_pc19(code_ptr, (const tcg_insn_unit *)value);
13092a11b93SRichard Henderson    case R_AARCH64_TSTBR14:
13192a11b93SRichard Henderson        return reloc_pc14(code_ptr, (const tcg_insn_unit *)value);
132139c1837SPaolo Bonzini    default:
133139c1837SPaolo Bonzini        g_assert_not_reached();
134139c1837SPaolo Bonzini    }
135139c1837SPaolo Bonzini}
136139c1837SPaolo Bonzini
137139c1837SPaolo Bonzini#define TCG_CT_CONST_AIMM 0x100
138139c1837SPaolo Bonzini#define TCG_CT_CONST_LIMM 0x200
139139c1837SPaolo Bonzini#define TCG_CT_CONST_ZERO 0x400
140139c1837SPaolo Bonzini#define TCG_CT_CONST_MONE 0x800
141139c1837SPaolo Bonzini#define TCG_CT_CONST_ORRI 0x1000
142139c1837SPaolo Bonzini#define TCG_CT_CONST_ANDI 0x2000
143339adf2fSRichard Henderson#define TCG_CT_CONST_CMP  0x4000
144139c1837SPaolo Bonzini
145abc730e1SRichard Henderson#define ALL_GENERAL_REGS  0xffffffffu
146abc730e1SRichard Henderson#define ALL_VECTOR_REGS   0xffffffff00000000ull
147abc730e1SRichard Henderson
148139c1837SPaolo Bonzini/* Match a constant valid for addition (12-bit, optionally shifted).  */
149139c1837SPaolo Bonzinistatic inline bool is_aimm(uint64_t val)
150139c1837SPaolo Bonzini{
151139c1837SPaolo Bonzini    return (val & ~0xfff) == 0 || (val & ~0xfff000) == 0;
152139c1837SPaolo Bonzini}
153139c1837SPaolo Bonzini
154139c1837SPaolo Bonzini/* Match a constant valid for logical operations.  */
155139c1837SPaolo Bonzinistatic inline bool is_limm(uint64_t val)
156139c1837SPaolo Bonzini{
157139c1837SPaolo Bonzini    /* Taking a simplified view of the logical immediates for now, ignoring
158139c1837SPaolo Bonzini       the replication that can happen across the field.  Match bit patterns
159139c1837SPaolo Bonzini       of the forms
160139c1837SPaolo Bonzini           0....01....1
161139c1837SPaolo Bonzini           0..01..10..0
162139c1837SPaolo Bonzini       and their inverses.  */
163139c1837SPaolo Bonzini
164139c1837SPaolo Bonzini    /* Make things easier below, by testing the form with msb clear. */
165139c1837SPaolo Bonzini    if ((int64_t)val < 0) {
166139c1837SPaolo Bonzini        val = ~val;
167139c1837SPaolo Bonzini    }
168139c1837SPaolo Bonzini    if (val == 0) {
169139c1837SPaolo Bonzini        return false;
170139c1837SPaolo Bonzini    }
171139c1837SPaolo Bonzini    val += val & -val;
172139c1837SPaolo Bonzini    return (val & (val - 1)) == 0;
173139c1837SPaolo Bonzini}
174139c1837SPaolo Bonzini
175139c1837SPaolo Bonzini/* Return true if v16 is a valid 16-bit shifted immediate.  */
176139c1837SPaolo Bonzinistatic bool is_shimm16(uint16_t v16, int *cmode, int *imm8)
177139c1837SPaolo Bonzini{
178139c1837SPaolo Bonzini    if (v16 == (v16 & 0xff)) {
179139c1837SPaolo Bonzini        *cmode = 0x8;
180139c1837SPaolo Bonzini        *imm8 = v16 & 0xff;
181139c1837SPaolo Bonzini        return true;
182139c1837SPaolo Bonzini    } else if (v16 == (v16 & 0xff00)) {
183139c1837SPaolo Bonzini        *cmode = 0xa;
184139c1837SPaolo Bonzini        *imm8 = v16 >> 8;
185139c1837SPaolo Bonzini        return true;
186139c1837SPaolo Bonzini    }
187139c1837SPaolo Bonzini    return false;
188139c1837SPaolo Bonzini}
189139c1837SPaolo Bonzini
190139c1837SPaolo Bonzini/* Return true if v32 is a valid 32-bit shifted immediate.  */
191139c1837SPaolo Bonzinistatic bool is_shimm32(uint32_t v32, int *cmode, int *imm8)
192139c1837SPaolo Bonzini{
193139c1837SPaolo Bonzini    if (v32 == (v32 & 0xff)) {
194139c1837SPaolo Bonzini        *cmode = 0x0;
195139c1837SPaolo Bonzini        *imm8 = v32 & 0xff;
196139c1837SPaolo Bonzini        return true;
197139c1837SPaolo Bonzini    } else if (v32 == (v32 & 0xff00)) {
198139c1837SPaolo Bonzini        *cmode = 0x2;
199139c1837SPaolo Bonzini        *imm8 = (v32 >> 8) & 0xff;
200139c1837SPaolo Bonzini        return true;
201139c1837SPaolo Bonzini    } else if (v32 == (v32 & 0xff0000)) {
202139c1837SPaolo Bonzini        *cmode = 0x4;
203139c1837SPaolo Bonzini        *imm8 = (v32 >> 16) & 0xff;
204139c1837SPaolo Bonzini        return true;
205139c1837SPaolo Bonzini    } else if (v32 == (v32 & 0xff000000)) {
206139c1837SPaolo Bonzini        *cmode = 0x6;
207139c1837SPaolo Bonzini        *imm8 = v32 >> 24;
208139c1837SPaolo Bonzini        return true;
209139c1837SPaolo Bonzini    }
210139c1837SPaolo Bonzini    return false;
211139c1837SPaolo Bonzini}
212139c1837SPaolo Bonzini
213139c1837SPaolo Bonzini/* Return true if v32 is a valid 32-bit shifting ones immediate.  */
214139c1837SPaolo Bonzinistatic bool is_soimm32(uint32_t v32, int *cmode, int *imm8)
215139c1837SPaolo Bonzini{
216139c1837SPaolo Bonzini    if ((v32 & 0xffff00ff) == 0xff) {
217139c1837SPaolo Bonzini        *cmode = 0xc;
218139c1837SPaolo Bonzini        *imm8 = (v32 >> 8) & 0xff;
219139c1837SPaolo Bonzini        return true;
220139c1837SPaolo Bonzini    } else if ((v32 & 0xff00ffff) == 0xffff) {
221139c1837SPaolo Bonzini        *cmode = 0xd;
222139c1837SPaolo Bonzini        *imm8 = (v32 >> 16) & 0xff;
223139c1837SPaolo Bonzini        return true;
224139c1837SPaolo Bonzini    }
225139c1837SPaolo Bonzini    return false;
226139c1837SPaolo Bonzini}
227139c1837SPaolo Bonzini
228139c1837SPaolo Bonzini/* Return true if v32 is a valid float32 immediate.  */
229139c1837SPaolo Bonzinistatic bool is_fimm32(uint32_t v32, int *cmode, int *imm8)
230139c1837SPaolo Bonzini{
231139c1837SPaolo Bonzini    if (extract32(v32, 0, 19) == 0
232139c1837SPaolo Bonzini        && (extract32(v32, 25, 6) == 0x20
233139c1837SPaolo Bonzini            || extract32(v32, 25, 6) == 0x1f)) {
234139c1837SPaolo Bonzini        *cmode = 0xf;
235139c1837SPaolo Bonzini        *imm8 = (extract32(v32, 31, 1) << 7)
236139c1837SPaolo Bonzini              | (extract32(v32, 25, 1) << 6)
237139c1837SPaolo Bonzini              | extract32(v32, 19, 6);
238139c1837SPaolo Bonzini        return true;
239139c1837SPaolo Bonzini    }
240139c1837SPaolo Bonzini    return false;
241139c1837SPaolo Bonzini}
242139c1837SPaolo Bonzini
243139c1837SPaolo Bonzini/* Return true if v64 is a valid float64 immediate.  */
244139c1837SPaolo Bonzinistatic bool is_fimm64(uint64_t v64, int *cmode, int *imm8)
245139c1837SPaolo Bonzini{
246139c1837SPaolo Bonzini    if (extract64(v64, 0, 48) == 0
247139c1837SPaolo Bonzini        && (extract64(v64, 54, 9) == 0x100
248139c1837SPaolo Bonzini            || extract64(v64, 54, 9) == 0x0ff)) {
249139c1837SPaolo Bonzini        *cmode = 0xf;
250139c1837SPaolo Bonzini        *imm8 = (extract64(v64, 63, 1) << 7)
251139c1837SPaolo Bonzini              | (extract64(v64, 54, 1) << 6)
252139c1837SPaolo Bonzini              | extract64(v64, 48, 6);
253139c1837SPaolo Bonzini        return true;
254139c1837SPaolo Bonzini    }
255139c1837SPaolo Bonzini    return false;
256139c1837SPaolo Bonzini}
257139c1837SPaolo Bonzini
258139c1837SPaolo Bonzini/*
259139c1837SPaolo Bonzini * Return non-zero if v32 can be formed by MOVI+ORR.
260139c1837SPaolo Bonzini * Place the parameters for MOVI in (cmode, imm8).
261139c1837SPaolo Bonzini * Return the cmode for ORR; the imm8 can be had via extraction from v32.
262139c1837SPaolo Bonzini */
263139c1837SPaolo Bonzinistatic int is_shimm32_pair(uint32_t v32, int *cmode, int *imm8)
264139c1837SPaolo Bonzini{
265139c1837SPaolo Bonzini    int i;
266139c1837SPaolo Bonzini
267139c1837SPaolo Bonzini    for (i = 6; i > 0; i -= 2) {
268139c1837SPaolo Bonzini        /* Mask out one byte we can add with ORR.  */
269139c1837SPaolo Bonzini        uint32_t tmp = v32 & ~(0xffu << (i * 4));
270139c1837SPaolo Bonzini        if (is_shimm32(tmp, cmode, imm8) ||
271139c1837SPaolo Bonzini            is_soimm32(tmp, cmode, imm8)) {
272139c1837SPaolo Bonzini            break;
273139c1837SPaolo Bonzini        }
274139c1837SPaolo Bonzini    }
275139c1837SPaolo Bonzini    return i;
276139c1837SPaolo Bonzini}
277139c1837SPaolo Bonzini
278139c1837SPaolo Bonzini/* Return true if V is a valid 16-bit or 32-bit shifted immediate.  */
279139c1837SPaolo Bonzinistatic bool is_shimm1632(uint32_t v32, int *cmode, int *imm8)
280139c1837SPaolo Bonzini{
281139c1837SPaolo Bonzini    if (v32 == deposit32(v32, 16, 16, v32)) {
282139c1837SPaolo Bonzini        return is_shimm16(v32, cmode, imm8);
283139c1837SPaolo Bonzini    } else {
284139c1837SPaolo Bonzini        return is_shimm32(v32, cmode, imm8);
285139c1837SPaolo Bonzini    }
286139c1837SPaolo Bonzini}
287139c1837SPaolo Bonzini
28821e9a8aeSRichard Hendersonstatic bool tcg_target_const_match(int64_t val, int ct,
28921e9a8aeSRichard Henderson                                   TCGType type, TCGCond cond, int vece)
290139c1837SPaolo Bonzini{
291139c1837SPaolo Bonzini    if (ct & TCG_CT_CONST) {
292139c1837SPaolo Bonzini        return 1;
293139c1837SPaolo Bonzini    }
294139c1837SPaolo Bonzini    if (type == TCG_TYPE_I32) {
295139c1837SPaolo Bonzini        val = (int32_t)val;
296139c1837SPaolo Bonzini    }
297339adf2fSRichard Henderson
298339adf2fSRichard Henderson    if (ct & TCG_CT_CONST_CMP) {
299339adf2fSRichard Henderson        if (is_tst_cond(cond)) {
300339adf2fSRichard Henderson            ct |= TCG_CT_CONST_LIMM;
301339adf2fSRichard Henderson        } else {
302339adf2fSRichard Henderson            ct |= TCG_CT_CONST_AIMM;
303339adf2fSRichard Henderson        }
304339adf2fSRichard Henderson    }
305339adf2fSRichard Henderson
306139c1837SPaolo Bonzini    if ((ct & TCG_CT_CONST_AIMM) && (is_aimm(val) || is_aimm(-val))) {
307139c1837SPaolo Bonzini        return 1;
308139c1837SPaolo Bonzini    }
309139c1837SPaolo Bonzini    if ((ct & TCG_CT_CONST_LIMM) && is_limm(val)) {
310139c1837SPaolo Bonzini        return 1;
311139c1837SPaolo Bonzini    }
312139c1837SPaolo Bonzini    if ((ct & TCG_CT_CONST_ZERO) && val == 0) {
313139c1837SPaolo Bonzini        return 1;
314139c1837SPaolo Bonzini    }
315139c1837SPaolo Bonzini    if ((ct & TCG_CT_CONST_MONE) && val == -1) {
316139c1837SPaolo Bonzini        return 1;
317139c1837SPaolo Bonzini    }
318139c1837SPaolo Bonzini
319139c1837SPaolo Bonzini    switch (ct & (TCG_CT_CONST_ORRI | TCG_CT_CONST_ANDI)) {
320139c1837SPaolo Bonzini    case 0:
321139c1837SPaolo Bonzini        break;
322139c1837SPaolo Bonzini    case TCG_CT_CONST_ANDI:
323139c1837SPaolo Bonzini        val = ~val;
324139c1837SPaolo Bonzini        /* fallthru */
325139c1837SPaolo Bonzini    case TCG_CT_CONST_ORRI:
326139c1837SPaolo Bonzini        if (val == deposit64(val, 32, 32, val)) {
327139c1837SPaolo Bonzini            int cmode, imm8;
328139c1837SPaolo Bonzini            return is_shimm1632(val, &cmode, &imm8);
329139c1837SPaolo Bonzini        }
330139c1837SPaolo Bonzini        break;
331139c1837SPaolo Bonzini    default:
332139c1837SPaolo Bonzini        /* Both bits should not be set for the same insn.  */
333139c1837SPaolo Bonzini        g_assert_not_reached();
334139c1837SPaolo Bonzini    }
335139c1837SPaolo Bonzini
336139c1837SPaolo Bonzini    return 0;
337139c1837SPaolo Bonzini}
338139c1837SPaolo Bonzini
339139c1837SPaolo Bonzinienum aarch64_cond_code {
340139c1837SPaolo Bonzini    COND_EQ = 0x0,
341139c1837SPaolo Bonzini    COND_NE = 0x1,
342139c1837SPaolo Bonzini    COND_CS = 0x2,     /* Unsigned greater or equal */
343139c1837SPaolo Bonzini    COND_HS = COND_CS, /* ALIAS greater or equal */
344139c1837SPaolo Bonzini    COND_CC = 0x3,     /* Unsigned less than */
345139c1837SPaolo Bonzini    COND_LO = COND_CC, /* ALIAS Lower */
346139c1837SPaolo Bonzini    COND_MI = 0x4,     /* Negative */
347139c1837SPaolo Bonzini    COND_PL = 0x5,     /* Zero or greater */
348139c1837SPaolo Bonzini    COND_VS = 0x6,     /* Overflow */
349139c1837SPaolo Bonzini    COND_VC = 0x7,     /* No overflow */
350139c1837SPaolo Bonzini    COND_HI = 0x8,     /* Unsigned greater than */
351139c1837SPaolo Bonzini    COND_LS = 0x9,     /* Unsigned less or equal */
352139c1837SPaolo Bonzini    COND_GE = 0xa,
353139c1837SPaolo Bonzini    COND_LT = 0xb,
354139c1837SPaolo Bonzini    COND_GT = 0xc,
355139c1837SPaolo Bonzini    COND_LE = 0xd,
356139c1837SPaolo Bonzini    COND_AL = 0xe,
357139c1837SPaolo Bonzini    COND_NV = 0xf, /* behaves like COND_AL here */
358139c1837SPaolo Bonzini};
359139c1837SPaolo Bonzini
360139c1837SPaolo Bonzinistatic const enum aarch64_cond_code tcg_cond_to_aarch64[] = {
361139c1837SPaolo Bonzini    [TCG_COND_EQ] = COND_EQ,
362139c1837SPaolo Bonzini    [TCG_COND_NE] = COND_NE,
363139c1837SPaolo Bonzini    [TCG_COND_LT] = COND_LT,
364139c1837SPaolo Bonzini    [TCG_COND_GE] = COND_GE,
365139c1837SPaolo Bonzini    [TCG_COND_LE] = COND_LE,
366139c1837SPaolo Bonzini    [TCG_COND_GT] = COND_GT,
367139c1837SPaolo Bonzini    /* unsigned */
368139c1837SPaolo Bonzini    [TCG_COND_LTU] = COND_LO,
369139c1837SPaolo Bonzini    [TCG_COND_GTU] = COND_HI,
370139c1837SPaolo Bonzini    [TCG_COND_GEU] = COND_HS,
371139c1837SPaolo Bonzini    [TCG_COND_LEU] = COND_LS,
372339adf2fSRichard Henderson    /* bit test */
373339adf2fSRichard Henderson    [TCG_COND_TSTEQ] = COND_EQ,
374339adf2fSRichard Henderson    [TCG_COND_TSTNE] = COND_NE,
375139c1837SPaolo Bonzini};
376139c1837SPaolo Bonzini
377139c1837SPaolo Bonzinitypedef enum {
378139c1837SPaolo Bonzini    LDST_ST = 0,    /* store */
379139c1837SPaolo Bonzini    LDST_LD = 1,    /* load */
380139c1837SPaolo Bonzini    LDST_LD_S_X = 2,  /* load and sign-extend into Xt */
381139c1837SPaolo Bonzini    LDST_LD_S_W = 3,  /* load and sign-extend into Wt */
382139c1837SPaolo Bonzini} AArch64LdstType;
383139c1837SPaolo Bonzini
384139c1837SPaolo Bonzini/* We encode the format of the insn into the beginning of the name, so that
385139c1837SPaolo Bonzini   we can have the preprocessor help "typecheck" the insn vs the output
386139c1837SPaolo Bonzini   function.  Arm didn't provide us with nice names for the formats, so we
387139c1837SPaolo Bonzini   use the section number of the architecture reference manual in which the
388139c1837SPaolo Bonzini   instruction group is described.  */
389139c1837SPaolo Bonzinitypedef enum {
390139c1837SPaolo Bonzini    /* Compare and branch (immediate).  */
391139c1837SPaolo Bonzini    I3201_CBZ       = 0x34000000,
392139c1837SPaolo Bonzini    I3201_CBNZ      = 0x35000000,
393139c1837SPaolo Bonzini
394139c1837SPaolo Bonzini    /* Conditional branch (immediate).  */
395139c1837SPaolo Bonzini    I3202_B_C       = 0x54000000,
396139c1837SPaolo Bonzini
39792a11b93SRichard Henderson    /* Test and branch (immediate).  */
39892a11b93SRichard Henderson    I3205_TBZ       = 0x36000000,
39992a11b93SRichard Henderson    I3205_TBNZ      = 0x37000000,
40092a11b93SRichard Henderson
401139c1837SPaolo Bonzini    /* Unconditional branch (immediate).  */
402139c1837SPaolo Bonzini    I3206_B         = 0x14000000,
403139c1837SPaolo Bonzini    I3206_BL        = 0x94000000,
404139c1837SPaolo Bonzini
405139c1837SPaolo Bonzini    /* Unconditional branch (register).  */
406139c1837SPaolo Bonzini    I3207_BR        = 0xd61f0000,
407139c1837SPaolo Bonzini    I3207_BLR       = 0xd63f0000,
408139c1837SPaolo Bonzini    I3207_RET       = 0xd65f0000,
409139c1837SPaolo Bonzini
410139c1837SPaolo Bonzini    /* AdvSIMD load/store single structure.  */
411139c1837SPaolo Bonzini    I3303_LD1R      = 0x0d40c000,
412139c1837SPaolo Bonzini
413139c1837SPaolo Bonzini    /* Load literal for loading the address at pc-relative offset */
414139c1837SPaolo Bonzini    I3305_LDR       = 0x58000000,
415139c1837SPaolo Bonzini    I3305_LDR_v64   = 0x5c000000,
416139c1837SPaolo Bonzini    I3305_LDR_v128  = 0x9c000000,
417139c1837SPaolo Bonzini
418929124ecSRichard Henderson    /* Load/store exclusive. */
419929124ecSRichard Henderson    I3306_LDXP      = 0xc8600000,
420929124ecSRichard Henderson    I3306_STXP      = 0xc8200000,
421929124ecSRichard Henderson
422139c1837SPaolo Bonzini    /* Load/store register.  Described here as 3.3.12, but the helper
423139c1837SPaolo Bonzini       that emits them can transform to 3.3.10 or 3.3.13.  */
424139c1837SPaolo Bonzini    I3312_STRB      = 0x38000000 | LDST_ST << 22 | MO_8 << 30,
425139c1837SPaolo Bonzini    I3312_STRH      = 0x38000000 | LDST_ST << 22 | MO_16 << 30,
426139c1837SPaolo Bonzini    I3312_STRW      = 0x38000000 | LDST_ST << 22 | MO_32 << 30,
427139c1837SPaolo Bonzini    I3312_STRX      = 0x38000000 | LDST_ST << 22 | MO_64 << 30,
428139c1837SPaolo Bonzini
429139c1837SPaolo Bonzini    I3312_LDRB      = 0x38000000 | LDST_LD << 22 | MO_8 << 30,
430139c1837SPaolo Bonzini    I3312_LDRH      = 0x38000000 | LDST_LD << 22 | MO_16 << 30,
431139c1837SPaolo Bonzini    I3312_LDRW      = 0x38000000 | LDST_LD << 22 | MO_32 << 30,
432139c1837SPaolo Bonzini    I3312_LDRX      = 0x38000000 | LDST_LD << 22 | MO_64 << 30,
433139c1837SPaolo Bonzini
434139c1837SPaolo Bonzini    I3312_LDRSBW    = 0x38000000 | LDST_LD_S_W << 22 | MO_8 << 30,
435139c1837SPaolo Bonzini    I3312_LDRSHW    = 0x38000000 | LDST_LD_S_W << 22 | MO_16 << 30,
436139c1837SPaolo Bonzini
437139c1837SPaolo Bonzini    I3312_LDRSBX    = 0x38000000 | LDST_LD_S_X << 22 | MO_8 << 30,
438139c1837SPaolo Bonzini    I3312_LDRSHX    = 0x38000000 | LDST_LD_S_X << 22 | MO_16 << 30,
439139c1837SPaolo Bonzini    I3312_LDRSWX    = 0x38000000 | LDST_LD_S_X << 22 | MO_32 << 30,
440139c1837SPaolo Bonzini
441139c1837SPaolo Bonzini    I3312_LDRVS     = 0x3c000000 | LDST_LD << 22 | MO_32 << 30,
442139c1837SPaolo Bonzini    I3312_STRVS     = 0x3c000000 | LDST_ST << 22 | MO_32 << 30,
443139c1837SPaolo Bonzini
444139c1837SPaolo Bonzini    I3312_LDRVD     = 0x3c000000 | LDST_LD << 22 | MO_64 << 30,
445139c1837SPaolo Bonzini    I3312_STRVD     = 0x3c000000 | LDST_ST << 22 | MO_64 << 30,
446139c1837SPaolo Bonzini
447139c1837SPaolo Bonzini    I3312_LDRVQ     = 0x3c000000 | 3 << 22 | 0 << 30,
448139c1837SPaolo Bonzini    I3312_STRVQ     = 0x3c000000 | 2 << 22 | 0 << 30,
449139c1837SPaolo Bonzini
450139c1837SPaolo Bonzini    I3312_TO_I3310  = 0x00200800,
451139c1837SPaolo Bonzini    I3312_TO_I3313  = 0x01000000,
452139c1837SPaolo Bonzini
453139c1837SPaolo Bonzini    /* Load/store register pair instructions.  */
454139c1837SPaolo Bonzini    I3314_LDP       = 0x28400000,
455139c1837SPaolo Bonzini    I3314_STP       = 0x28000000,
456139c1837SPaolo Bonzini
457139c1837SPaolo Bonzini    /* Add/subtract immediate instructions.  */
458139c1837SPaolo Bonzini    I3401_ADDI      = 0x11000000,
459139c1837SPaolo Bonzini    I3401_ADDSI     = 0x31000000,
460139c1837SPaolo Bonzini    I3401_SUBI      = 0x51000000,
461139c1837SPaolo Bonzini    I3401_SUBSI     = 0x71000000,
462139c1837SPaolo Bonzini
463139c1837SPaolo Bonzini    /* Bitfield instructions.  */
464139c1837SPaolo Bonzini    I3402_BFM       = 0x33000000,
465139c1837SPaolo Bonzini    I3402_SBFM      = 0x13000000,
466139c1837SPaolo Bonzini    I3402_UBFM      = 0x53000000,
467139c1837SPaolo Bonzini
468139c1837SPaolo Bonzini    /* Extract instruction.  */
469139c1837SPaolo Bonzini    I3403_EXTR      = 0x13800000,
470139c1837SPaolo Bonzini
471139c1837SPaolo Bonzini    /* Logical immediate instructions.  */
472139c1837SPaolo Bonzini    I3404_ANDI      = 0x12000000,
473139c1837SPaolo Bonzini    I3404_ORRI      = 0x32000000,
474139c1837SPaolo Bonzini    I3404_EORI      = 0x52000000,
475f85ab3d2SRichard Henderson    I3404_ANDSI     = 0x72000000,
476139c1837SPaolo Bonzini
477139c1837SPaolo Bonzini    /* Move wide immediate instructions.  */
478139c1837SPaolo Bonzini    I3405_MOVN      = 0x12800000,
479139c1837SPaolo Bonzini    I3405_MOVZ      = 0x52800000,
480139c1837SPaolo Bonzini    I3405_MOVK      = 0x72800000,
481139c1837SPaolo Bonzini
482139c1837SPaolo Bonzini    /* PC relative addressing instructions.  */
483139c1837SPaolo Bonzini    I3406_ADR       = 0x10000000,
484139c1837SPaolo Bonzini    I3406_ADRP      = 0x90000000,
485139c1837SPaolo Bonzini
486929124ecSRichard Henderson    /* Add/subtract extended register instructions. */
487929124ecSRichard Henderson    I3501_ADD       = 0x0b200000,
488929124ecSRichard Henderson
489139c1837SPaolo Bonzini    /* Add/subtract shifted register instructions (without a shift).  */
490139c1837SPaolo Bonzini    I3502_ADD       = 0x0b000000,
491139c1837SPaolo Bonzini    I3502_ADDS      = 0x2b000000,
492139c1837SPaolo Bonzini    I3502_SUB       = 0x4b000000,
493139c1837SPaolo Bonzini    I3502_SUBS      = 0x6b000000,
494139c1837SPaolo Bonzini
495139c1837SPaolo Bonzini    /* Add/subtract shifted register instructions (with a shift).  */
496139c1837SPaolo Bonzini    I3502S_ADD_LSL  = I3502_ADD,
497139c1837SPaolo Bonzini
498139c1837SPaolo Bonzini    /* Add/subtract with carry instructions.  */
499139c1837SPaolo Bonzini    I3503_ADC       = 0x1a000000,
500139c1837SPaolo Bonzini    I3503_SBC       = 0x5a000000,
501139c1837SPaolo Bonzini
502139c1837SPaolo Bonzini    /* Conditional select instructions.  */
503139c1837SPaolo Bonzini    I3506_CSEL      = 0x1a800000,
504139c1837SPaolo Bonzini    I3506_CSINC     = 0x1a800400,
505139c1837SPaolo Bonzini    I3506_CSINV     = 0x5a800000,
506139c1837SPaolo Bonzini    I3506_CSNEG     = 0x5a800400,
507139c1837SPaolo Bonzini
508139c1837SPaolo Bonzini    /* Data-processing (1 source) instructions.  */
509139c1837SPaolo Bonzini    I3507_CLZ       = 0x5ac01000,
510139c1837SPaolo Bonzini    I3507_RBIT      = 0x5ac00000,
511dfa24dfaSRichard Henderson    I3507_REV       = 0x5ac00000, /* + size << 10 */
512139c1837SPaolo Bonzini
513139c1837SPaolo Bonzini    /* Data-processing (2 source) instructions.  */
514139c1837SPaolo Bonzini    I3508_LSLV      = 0x1ac02000,
515139c1837SPaolo Bonzini    I3508_LSRV      = 0x1ac02400,
516139c1837SPaolo Bonzini    I3508_ASRV      = 0x1ac02800,
517139c1837SPaolo Bonzini    I3508_RORV      = 0x1ac02c00,
518139c1837SPaolo Bonzini    I3508_SMULH     = 0x9b407c00,
519139c1837SPaolo Bonzini    I3508_UMULH     = 0x9bc07c00,
520139c1837SPaolo Bonzini    I3508_UDIV      = 0x1ac00800,
521139c1837SPaolo Bonzini    I3508_SDIV      = 0x1ac00c00,
522139c1837SPaolo Bonzini
523139c1837SPaolo Bonzini    /* Data-processing (3 source) instructions.  */
524139c1837SPaolo Bonzini    I3509_MADD      = 0x1b000000,
525139c1837SPaolo Bonzini    I3509_MSUB      = 0x1b008000,
526139c1837SPaolo Bonzini
527139c1837SPaolo Bonzini    /* Logical shifted register instructions (without a shift).  */
528139c1837SPaolo Bonzini    I3510_AND       = 0x0a000000,
529139c1837SPaolo Bonzini    I3510_BIC       = 0x0a200000,
530139c1837SPaolo Bonzini    I3510_ORR       = 0x2a000000,
531139c1837SPaolo Bonzini    I3510_ORN       = 0x2a200000,
532139c1837SPaolo Bonzini    I3510_EOR       = 0x4a000000,
533139c1837SPaolo Bonzini    I3510_EON       = 0x4a200000,
534139c1837SPaolo Bonzini    I3510_ANDS      = 0x6a000000,
535139c1837SPaolo Bonzini
536139c1837SPaolo Bonzini    /* Logical shifted register instructions (with a shift).  */
537139c1837SPaolo Bonzini    I3502S_AND_LSR  = I3510_AND | (1 << 22),
538139c1837SPaolo Bonzini
539139c1837SPaolo Bonzini    /* AdvSIMD copy */
540139c1837SPaolo Bonzini    I3605_DUP      = 0x0e000400,
541139c1837SPaolo Bonzini    I3605_INS      = 0x4e001c00,
542139c1837SPaolo Bonzini    I3605_UMOV     = 0x0e003c00,
543139c1837SPaolo Bonzini
544139c1837SPaolo Bonzini    /* AdvSIMD modified immediate */
545139c1837SPaolo Bonzini    I3606_MOVI      = 0x0f000400,
546139c1837SPaolo Bonzini    I3606_MVNI      = 0x2f000400,
547139c1837SPaolo Bonzini    I3606_BIC       = 0x2f001400,
548139c1837SPaolo Bonzini    I3606_ORR       = 0x0f001400,
549139c1837SPaolo Bonzini
550d81bad24SRichard Henderson    /* AdvSIMD scalar shift by immediate */
551d81bad24SRichard Henderson    I3609_SSHR      = 0x5f000400,
552d81bad24SRichard Henderson    I3609_SSRA      = 0x5f001400,
553d81bad24SRichard Henderson    I3609_SHL       = 0x5f005400,
554d81bad24SRichard Henderson    I3609_USHR      = 0x7f000400,
555d81bad24SRichard Henderson    I3609_USRA      = 0x7f001400,
556d81bad24SRichard Henderson    I3609_SLI       = 0x7f005400,
557d81bad24SRichard Henderson
558d81bad24SRichard Henderson    /* AdvSIMD scalar three same */
559d81bad24SRichard Henderson    I3611_SQADD     = 0x5e200c00,
560d81bad24SRichard Henderson    I3611_SQSUB     = 0x5e202c00,
561d81bad24SRichard Henderson    I3611_CMGT      = 0x5e203400,
562d81bad24SRichard Henderson    I3611_CMGE      = 0x5e203c00,
563d81bad24SRichard Henderson    I3611_SSHL      = 0x5e204400,
564d81bad24SRichard Henderson    I3611_ADD       = 0x5e208400,
565d81bad24SRichard Henderson    I3611_CMTST     = 0x5e208c00,
566d81bad24SRichard Henderson    I3611_UQADD     = 0x7e200c00,
567d81bad24SRichard Henderson    I3611_UQSUB     = 0x7e202c00,
568d81bad24SRichard Henderson    I3611_CMHI      = 0x7e203400,
569d81bad24SRichard Henderson    I3611_CMHS      = 0x7e203c00,
570d81bad24SRichard Henderson    I3611_USHL      = 0x7e204400,
571d81bad24SRichard Henderson    I3611_SUB       = 0x7e208400,
572d81bad24SRichard Henderson    I3611_CMEQ      = 0x7e208c00,
573d81bad24SRichard Henderson
574d81bad24SRichard Henderson    /* AdvSIMD scalar two-reg misc */
575d81bad24SRichard Henderson    I3612_CMGT0     = 0x5e208800,
576d81bad24SRichard Henderson    I3612_CMEQ0     = 0x5e209800,
577d81bad24SRichard Henderson    I3612_CMLT0     = 0x5e20a800,
578d81bad24SRichard Henderson    I3612_ABS       = 0x5e20b800,
579d81bad24SRichard Henderson    I3612_CMGE0     = 0x7e208800,
580d81bad24SRichard Henderson    I3612_CMLE0     = 0x7e209800,
581d81bad24SRichard Henderson    I3612_NEG       = 0x7e20b800,
582d81bad24SRichard Henderson
583139c1837SPaolo Bonzini    /* AdvSIMD shift by immediate */
584139c1837SPaolo Bonzini    I3614_SSHR      = 0x0f000400,
585139c1837SPaolo Bonzini    I3614_SSRA      = 0x0f001400,
586139c1837SPaolo Bonzini    I3614_SHL       = 0x0f005400,
587139c1837SPaolo Bonzini    I3614_SLI       = 0x2f005400,
588139c1837SPaolo Bonzini    I3614_USHR      = 0x2f000400,
589139c1837SPaolo Bonzini    I3614_USRA      = 0x2f001400,
590139c1837SPaolo Bonzini
591139c1837SPaolo Bonzini    /* AdvSIMD three same.  */
592139c1837SPaolo Bonzini    I3616_ADD       = 0x0e208400,
593139c1837SPaolo Bonzini    I3616_AND       = 0x0e201c00,
594139c1837SPaolo Bonzini    I3616_BIC       = 0x0e601c00,
595139c1837SPaolo Bonzini    I3616_BIF       = 0x2ee01c00,
596139c1837SPaolo Bonzini    I3616_BIT       = 0x2ea01c00,
597139c1837SPaolo Bonzini    I3616_BSL       = 0x2e601c00,
598139c1837SPaolo Bonzini    I3616_EOR       = 0x2e201c00,
599139c1837SPaolo Bonzini    I3616_MUL       = 0x0e209c00,
600139c1837SPaolo Bonzini    I3616_ORR       = 0x0ea01c00,
601139c1837SPaolo Bonzini    I3616_ORN       = 0x0ee01c00,
602139c1837SPaolo Bonzini    I3616_SUB       = 0x2e208400,
603139c1837SPaolo Bonzini    I3616_CMGT      = 0x0e203400,
604139c1837SPaolo Bonzini    I3616_CMGE      = 0x0e203c00,
605139c1837SPaolo Bonzini    I3616_CMTST     = 0x0e208c00,
606139c1837SPaolo Bonzini    I3616_CMHI      = 0x2e203400,
607139c1837SPaolo Bonzini    I3616_CMHS      = 0x2e203c00,
608139c1837SPaolo Bonzini    I3616_CMEQ      = 0x2e208c00,
609139c1837SPaolo Bonzini    I3616_SMAX      = 0x0e206400,
610139c1837SPaolo Bonzini    I3616_SMIN      = 0x0e206c00,
611139c1837SPaolo Bonzini    I3616_SSHL      = 0x0e204400,
612139c1837SPaolo Bonzini    I3616_SQADD     = 0x0e200c00,
613139c1837SPaolo Bonzini    I3616_SQSUB     = 0x0e202c00,
614139c1837SPaolo Bonzini    I3616_UMAX      = 0x2e206400,
615139c1837SPaolo Bonzini    I3616_UMIN      = 0x2e206c00,
616139c1837SPaolo Bonzini    I3616_UQADD     = 0x2e200c00,
617139c1837SPaolo Bonzini    I3616_UQSUB     = 0x2e202c00,
618139c1837SPaolo Bonzini    I3616_USHL      = 0x2e204400,
619139c1837SPaolo Bonzini
620139c1837SPaolo Bonzini    /* AdvSIMD two-reg misc.  */
621139c1837SPaolo Bonzini    I3617_CMGT0     = 0x0e208800,
622139c1837SPaolo Bonzini    I3617_CMEQ0     = 0x0e209800,
623139c1837SPaolo Bonzini    I3617_CMLT0     = 0x0e20a800,
624139c1837SPaolo Bonzini    I3617_CMGE0     = 0x2e208800,
6256c2c7772SRichard Henderson    I3617_CMLE0     = 0x2e209800,
626139c1837SPaolo Bonzini    I3617_NOT       = 0x2e205800,
627139c1837SPaolo Bonzini    I3617_ABS       = 0x0e20b800,
628139c1837SPaolo Bonzini    I3617_NEG       = 0x2e20b800,
629139c1837SPaolo Bonzini
630139c1837SPaolo Bonzini    /* System instructions.  */
631139c1837SPaolo Bonzini    NOP             = 0xd503201f,
632139c1837SPaolo Bonzini    DMB_ISH         = 0xd50338bf,
633139c1837SPaolo Bonzini    DMB_LD          = 0x00000100,
634139c1837SPaolo Bonzini    DMB_ST          = 0x00000200,
6355826a0dbSRichard Henderson
6365826a0dbSRichard Henderson    BTI_C           = 0xd503245f,
6375826a0dbSRichard Henderson    BTI_J           = 0xd503249f,
6385826a0dbSRichard Henderson    BTI_JC          = 0xd50324df,
639139c1837SPaolo Bonzini} AArch64Insn;
640139c1837SPaolo Bonzini
641139c1837SPaolo Bonzinistatic inline uint32_t tcg_in32(TCGContext *s)
642139c1837SPaolo Bonzini{
643139c1837SPaolo Bonzini    uint32_t v = *(uint32_t *)s->code_ptr;
644139c1837SPaolo Bonzini    return v;
645139c1837SPaolo Bonzini}
646139c1837SPaolo Bonzini
647139c1837SPaolo Bonzini/* Emit an opcode with "type-checking" of the format.  */
648139c1837SPaolo Bonzini#define tcg_out_insn(S, FMT, OP, ...) \
649139c1837SPaolo Bonzini    glue(tcg_out_insn_,FMT)(S, glue(glue(glue(I,FMT),_),OP), ## __VA_ARGS__)
650139c1837SPaolo Bonzini
651139c1837SPaolo Bonzinistatic void tcg_out_insn_3303(TCGContext *s, AArch64Insn insn, bool q,
652139c1837SPaolo Bonzini                              TCGReg rt, TCGReg rn, unsigned size)
653139c1837SPaolo Bonzini{
654139c1837SPaolo Bonzini    tcg_out32(s, insn | (rt & 0x1f) | (rn << 5) | (size << 10) | (q << 30));
655139c1837SPaolo Bonzini}
656139c1837SPaolo Bonzini
657139c1837SPaolo Bonzinistatic void tcg_out_insn_3305(TCGContext *s, AArch64Insn insn,
658139c1837SPaolo Bonzini                              int imm19, TCGReg rt)
659139c1837SPaolo Bonzini{
660139c1837SPaolo Bonzini    tcg_out32(s, insn | (imm19 & 0x7ffff) << 5 | rt);
661139c1837SPaolo Bonzini}
662139c1837SPaolo Bonzini
663929124ecSRichard Hendersonstatic void tcg_out_insn_3306(TCGContext *s, AArch64Insn insn, TCGReg rs,
664929124ecSRichard Henderson                              TCGReg rt, TCGReg rt2, TCGReg rn)
665929124ecSRichard Henderson{
666929124ecSRichard Henderson    tcg_out32(s, insn | rs << 16 | rt2 << 10 | rn << 5 | rt);
667929124ecSRichard Henderson}
668929124ecSRichard Henderson
669139c1837SPaolo Bonzinistatic void tcg_out_insn_3201(TCGContext *s, AArch64Insn insn, TCGType ext,
670139c1837SPaolo Bonzini                              TCGReg rt, int imm19)
671139c1837SPaolo Bonzini{
672139c1837SPaolo Bonzini    tcg_out32(s, insn | ext << 31 | (imm19 & 0x7ffff) << 5 | rt);
673139c1837SPaolo Bonzini}
674139c1837SPaolo Bonzini
675139c1837SPaolo Bonzinistatic void tcg_out_insn_3202(TCGContext *s, AArch64Insn insn,
676139c1837SPaolo Bonzini                              TCGCond c, int imm19)
677139c1837SPaolo Bonzini{
678139c1837SPaolo Bonzini    tcg_out32(s, insn | tcg_cond_to_aarch64[c] | (imm19 & 0x7ffff) << 5);
679139c1837SPaolo Bonzini}
680139c1837SPaolo Bonzini
68192a11b93SRichard Hendersonstatic void tcg_out_insn_3205(TCGContext *s, AArch64Insn insn,
68292a11b93SRichard Henderson                              TCGReg rt, int imm6, int imm14)
68392a11b93SRichard Henderson{
68492a11b93SRichard Henderson    insn |= (imm6 & 0x20) << (31 - 5);
68592a11b93SRichard Henderson    insn |= (imm6 & 0x1f) << 19;
68692a11b93SRichard Henderson    tcg_out32(s, insn | (imm14 & 0x3fff) << 5 | rt);
68792a11b93SRichard Henderson}
68892a11b93SRichard Henderson
689139c1837SPaolo Bonzinistatic void tcg_out_insn_3206(TCGContext *s, AArch64Insn insn, int imm26)
690139c1837SPaolo Bonzini{
691139c1837SPaolo Bonzini    tcg_out32(s, insn | (imm26 & 0x03ffffff));
692139c1837SPaolo Bonzini}
693139c1837SPaolo Bonzini
694139c1837SPaolo Bonzinistatic void tcg_out_insn_3207(TCGContext *s, AArch64Insn insn, TCGReg rn)
695139c1837SPaolo Bonzini{
696139c1837SPaolo Bonzini    tcg_out32(s, insn | rn << 5);
697139c1837SPaolo Bonzini}
698139c1837SPaolo Bonzini
699139c1837SPaolo Bonzinistatic void tcg_out_insn_3314(TCGContext *s, AArch64Insn insn,
700139c1837SPaolo Bonzini                              TCGReg r1, TCGReg r2, TCGReg rn,
701139c1837SPaolo Bonzini                              tcg_target_long ofs, bool pre, bool w)
702139c1837SPaolo Bonzini{
703139c1837SPaolo Bonzini    insn |= 1u << 31; /* ext */
704139c1837SPaolo Bonzini    insn |= pre << 24;
705139c1837SPaolo Bonzini    insn |= w << 23;
706139c1837SPaolo Bonzini
707139c1837SPaolo Bonzini    tcg_debug_assert(ofs >= -0x200 && ofs < 0x200 && (ofs & 7) == 0);
708139c1837SPaolo Bonzini    insn |= (ofs & (0x7f << 3)) << (15 - 3);
709139c1837SPaolo Bonzini
710139c1837SPaolo Bonzini    tcg_out32(s, insn | r2 << 10 | rn << 5 | r1);
711139c1837SPaolo Bonzini}
712139c1837SPaolo Bonzini
713139c1837SPaolo Bonzinistatic void tcg_out_insn_3401(TCGContext *s, AArch64Insn insn, TCGType ext,
714139c1837SPaolo Bonzini                              TCGReg rd, TCGReg rn, uint64_t aimm)
715139c1837SPaolo Bonzini{
716139c1837SPaolo Bonzini    if (aimm > 0xfff) {
717139c1837SPaolo Bonzini        tcg_debug_assert((aimm & 0xfff) == 0);
718139c1837SPaolo Bonzini        aimm >>= 12;
719139c1837SPaolo Bonzini        tcg_debug_assert(aimm <= 0xfff);
720139c1837SPaolo Bonzini        aimm |= 1 << 12;  /* apply LSL 12 */
721139c1837SPaolo Bonzini    }
722139c1837SPaolo Bonzini    tcg_out32(s, insn | ext << 31 | aimm << 10 | rn << 5 | rd);
723139c1837SPaolo Bonzini}
724139c1837SPaolo Bonzini
725139c1837SPaolo Bonzini/* This function can be used for both 3.4.2 (Bitfield) and 3.4.4
726139c1837SPaolo Bonzini   (Logical immediate).  Both insn groups have N, IMMR and IMMS fields
727139c1837SPaolo Bonzini   that feed the DecodeBitMasks pseudo function.  */
728139c1837SPaolo Bonzinistatic void tcg_out_insn_3402(TCGContext *s, AArch64Insn insn, TCGType ext,
729139c1837SPaolo Bonzini                              TCGReg rd, TCGReg rn, int n, int immr, int imms)
730139c1837SPaolo Bonzini{
731139c1837SPaolo Bonzini    tcg_out32(s, insn | ext << 31 | n << 22 | immr << 16 | imms << 10
732139c1837SPaolo Bonzini              | rn << 5 | rd);
733139c1837SPaolo Bonzini}
734139c1837SPaolo Bonzini
735139c1837SPaolo Bonzini#define tcg_out_insn_3404  tcg_out_insn_3402
736139c1837SPaolo Bonzini
737139c1837SPaolo Bonzinistatic void tcg_out_insn_3403(TCGContext *s, AArch64Insn insn, TCGType ext,
738139c1837SPaolo Bonzini                              TCGReg rd, TCGReg rn, TCGReg rm, int imms)
739139c1837SPaolo Bonzini{
740139c1837SPaolo Bonzini    tcg_out32(s, insn | ext << 31 | ext << 22 | rm << 16 | imms << 10
741139c1837SPaolo Bonzini              | rn << 5 | rd);
742139c1837SPaolo Bonzini}
743139c1837SPaolo Bonzini
744139c1837SPaolo Bonzini/* This function is used for the Move (wide immediate) instruction group.
745139c1837SPaolo Bonzini   Note that SHIFT is a full shift count, not the 2 bit HW field. */
746139c1837SPaolo Bonzinistatic void tcg_out_insn_3405(TCGContext *s, AArch64Insn insn, TCGType ext,
747139c1837SPaolo Bonzini                              TCGReg rd, uint16_t half, unsigned shift)
748139c1837SPaolo Bonzini{
749139c1837SPaolo Bonzini    tcg_debug_assert((shift & ~0x30) == 0);
750139c1837SPaolo Bonzini    tcg_out32(s, insn | ext << 31 | shift << (21 - 4) | half << 5 | rd);
751139c1837SPaolo Bonzini}
752139c1837SPaolo Bonzini
753139c1837SPaolo Bonzinistatic void tcg_out_insn_3406(TCGContext *s, AArch64Insn insn,
754139c1837SPaolo Bonzini                              TCGReg rd, int64_t disp)
755139c1837SPaolo Bonzini{
756139c1837SPaolo Bonzini    tcg_out32(s, insn | (disp & 3) << 29 | (disp & 0x1ffffc) << (5 - 2) | rd);
757139c1837SPaolo Bonzini}
758139c1837SPaolo Bonzini
759929124ecSRichard Hendersonstatic inline void tcg_out_insn_3501(TCGContext *s, AArch64Insn insn,
760929124ecSRichard Henderson                                     TCGType sf, TCGReg rd, TCGReg rn,
761929124ecSRichard Henderson                                     TCGReg rm, int opt, int imm3)
762929124ecSRichard Henderson{
763929124ecSRichard Henderson    tcg_out32(s, insn | sf << 31 | rm << 16 | opt << 13 |
764929124ecSRichard Henderson              imm3 << 10 | rn << 5 | rd);
765929124ecSRichard Henderson}
766929124ecSRichard Henderson
767139c1837SPaolo Bonzini/* This function is for both 3.5.2 (Add/Subtract shifted register), for
768139c1837SPaolo Bonzini   the rare occasion when we actually want to supply a shift amount.  */
769139c1837SPaolo Bonzinistatic inline void tcg_out_insn_3502S(TCGContext *s, AArch64Insn insn,
770139c1837SPaolo Bonzini                                      TCGType ext, TCGReg rd, TCGReg rn,
771139c1837SPaolo Bonzini                                      TCGReg rm, int imm6)
772139c1837SPaolo Bonzini{
773139c1837SPaolo Bonzini    tcg_out32(s, insn | ext << 31 | rm << 16 | imm6 << 10 | rn << 5 | rd);
774139c1837SPaolo Bonzini}
775139c1837SPaolo Bonzini
776139c1837SPaolo Bonzini/* This function is for 3.5.2 (Add/subtract shifted register),
777139c1837SPaolo Bonzini   and 3.5.10 (Logical shifted register), for the vast majorty of cases
778139c1837SPaolo Bonzini   when we don't want to apply a shift.  Thus it can also be used for
779139c1837SPaolo Bonzini   3.5.3 (Add/subtract with carry) and 3.5.8 (Data processing 2 source).  */
780139c1837SPaolo Bonzinistatic void tcg_out_insn_3502(TCGContext *s, AArch64Insn insn, TCGType ext,
781139c1837SPaolo Bonzini                              TCGReg rd, TCGReg rn, TCGReg rm)
782139c1837SPaolo Bonzini{
783139c1837SPaolo Bonzini    tcg_out32(s, insn | ext << 31 | rm << 16 | rn << 5 | rd);
784139c1837SPaolo Bonzini}
785139c1837SPaolo Bonzini
786139c1837SPaolo Bonzini#define tcg_out_insn_3503  tcg_out_insn_3502
787139c1837SPaolo Bonzini#define tcg_out_insn_3508  tcg_out_insn_3502
788139c1837SPaolo Bonzini#define tcg_out_insn_3510  tcg_out_insn_3502
789139c1837SPaolo Bonzini
790139c1837SPaolo Bonzinistatic void tcg_out_insn_3506(TCGContext *s, AArch64Insn insn, TCGType ext,
791139c1837SPaolo Bonzini                              TCGReg rd, TCGReg rn, TCGReg rm, TCGCond c)
792139c1837SPaolo Bonzini{
793139c1837SPaolo Bonzini    tcg_out32(s, insn | ext << 31 | rm << 16 | rn << 5 | rd
794139c1837SPaolo Bonzini              | tcg_cond_to_aarch64[c] << 12);
795139c1837SPaolo Bonzini}
796139c1837SPaolo Bonzini
797139c1837SPaolo Bonzinistatic void tcg_out_insn_3507(TCGContext *s, AArch64Insn insn, TCGType ext,
798139c1837SPaolo Bonzini                              TCGReg rd, TCGReg rn)
799139c1837SPaolo Bonzini{
800139c1837SPaolo Bonzini    tcg_out32(s, insn | ext << 31 | rn << 5 | rd);
801139c1837SPaolo Bonzini}
802139c1837SPaolo Bonzini
803139c1837SPaolo Bonzinistatic void tcg_out_insn_3509(TCGContext *s, AArch64Insn insn, TCGType ext,
804139c1837SPaolo Bonzini                              TCGReg rd, TCGReg rn, TCGReg rm, TCGReg ra)
805139c1837SPaolo Bonzini{
806139c1837SPaolo Bonzini    tcg_out32(s, insn | ext << 31 | rm << 16 | ra << 10 | rn << 5 | rd);
807139c1837SPaolo Bonzini}
808139c1837SPaolo Bonzini
809139c1837SPaolo Bonzinistatic void tcg_out_insn_3605(TCGContext *s, AArch64Insn insn, bool q,
810139c1837SPaolo Bonzini                              TCGReg rd, TCGReg rn, int dst_idx, int src_idx)
811139c1837SPaolo Bonzini{
812139c1837SPaolo Bonzini    /* Note that bit 11 set means general register input.  Therefore
813139c1837SPaolo Bonzini       we can handle both register sets with one function.  */
814139c1837SPaolo Bonzini    tcg_out32(s, insn | q << 30 | (dst_idx << 16) | (src_idx << 11)
815139c1837SPaolo Bonzini              | (rd & 0x1f) | (~rn & 0x20) << 6 | (rn & 0x1f) << 5);
816139c1837SPaolo Bonzini}
817139c1837SPaolo Bonzini
818139c1837SPaolo Bonzinistatic void tcg_out_insn_3606(TCGContext *s, AArch64Insn insn, bool q,
819139c1837SPaolo Bonzini                              TCGReg rd, bool op, int cmode, uint8_t imm8)
820139c1837SPaolo Bonzini{
821139c1837SPaolo Bonzini    tcg_out32(s, insn | q << 30 | op << 29 | cmode << 12 | (rd & 0x1f)
822139c1837SPaolo Bonzini              | (imm8 & 0xe0) << (16 - 5) | (imm8 & 0x1f) << 5);
823139c1837SPaolo Bonzini}
824139c1837SPaolo Bonzini
825d81bad24SRichard Hendersonstatic void tcg_out_insn_3609(TCGContext *s, AArch64Insn insn,
826d81bad24SRichard Henderson                              TCGReg rd, TCGReg rn, unsigned immhb)
827d81bad24SRichard Henderson{
828d81bad24SRichard Henderson    tcg_out32(s, insn | immhb << 16 | (rn & 0x1f) << 5 | (rd & 0x1f));
829d81bad24SRichard Henderson}
830d81bad24SRichard Henderson
831d81bad24SRichard Hendersonstatic void tcg_out_insn_3611(TCGContext *s, AArch64Insn insn,
832d81bad24SRichard Henderson                              unsigned size, TCGReg rd, TCGReg rn, TCGReg rm)
833d81bad24SRichard Henderson{
834d81bad24SRichard Henderson    tcg_out32(s, insn | (size << 22) | (rm & 0x1f) << 16
835d81bad24SRichard Henderson              | (rn & 0x1f) << 5 | (rd & 0x1f));
836d81bad24SRichard Henderson}
837d81bad24SRichard Henderson
838d81bad24SRichard Hendersonstatic void tcg_out_insn_3612(TCGContext *s, AArch64Insn insn,
839d81bad24SRichard Henderson                              unsigned size, TCGReg rd, TCGReg rn)
840d81bad24SRichard Henderson{
841d81bad24SRichard Henderson    tcg_out32(s, insn | (size << 22) | (rn & 0x1f) << 5 | (rd & 0x1f));
842d81bad24SRichard Henderson}
843d81bad24SRichard Henderson
844139c1837SPaolo Bonzinistatic void tcg_out_insn_3614(TCGContext *s, AArch64Insn insn, bool q,
845139c1837SPaolo Bonzini                              TCGReg rd, TCGReg rn, unsigned immhb)
846139c1837SPaolo Bonzini{
847139c1837SPaolo Bonzini    tcg_out32(s, insn | q << 30 | immhb << 16
848139c1837SPaolo Bonzini              | (rn & 0x1f) << 5 | (rd & 0x1f));
849139c1837SPaolo Bonzini}
850139c1837SPaolo Bonzini
851139c1837SPaolo Bonzinistatic void tcg_out_insn_3616(TCGContext *s, AArch64Insn insn, bool q,
852139c1837SPaolo Bonzini                              unsigned size, TCGReg rd, TCGReg rn, TCGReg rm)
853139c1837SPaolo Bonzini{
854139c1837SPaolo Bonzini    tcg_out32(s, insn | q << 30 | (size << 22) | (rm & 0x1f) << 16
855139c1837SPaolo Bonzini              | (rn & 0x1f) << 5 | (rd & 0x1f));
856139c1837SPaolo Bonzini}
857139c1837SPaolo Bonzini
858139c1837SPaolo Bonzinistatic void tcg_out_insn_3617(TCGContext *s, AArch64Insn insn, bool q,
859139c1837SPaolo Bonzini                              unsigned size, TCGReg rd, TCGReg rn)
860139c1837SPaolo Bonzini{
861139c1837SPaolo Bonzini    tcg_out32(s, insn | q << 30 | (size << 22)
862139c1837SPaolo Bonzini              | (rn & 0x1f) << 5 | (rd & 0x1f));
863139c1837SPaolo Bonzini}
864139c1837SPaolo Bonzini
865139c1837SPaolo Bonzinistatic void tcg_out_insn_3310(TCGContext *s, AArch64Insn insn,
866139c1837SPaolo Bonzini                              TCGReg rd, TCGReg base, TCGType ext,
867139c1837SPaolo Bonzini                              TCGReg regoff)
868139c1837SPaolo Bonzini{
869139c1837SPaolo Bonzini    /* Note the AArch64Insn constants above are for C3.3.12.  Adjust.  */
870139c1837SPaolo Bonzini    tcg_out32(s, insn | I3312_TO_I3310 | regoff << 16 |
871139c1837SPaolo Bonzini              0x4000 | ext << 13 | base << 5 | (rd & 0x1f));
872139c1837SPaolo Bonzini}
873139c1837SPaolo Bonzini
874139c1837SPaolo Bonzinistatic void tcg_out_insn_3312(TCGContext *s, AArch64Insn insn,
875139c1837SPaolo Bonzini                              TCGReg rd, TCGReg rn, intptr_t offset)
876139c1837SPaolo Bonzini{
877139c1837SPaolo Bonzini    tcg_out32(s, insn | (offset & 0x1ff) << 12 | rn << 5 | (rd & 0x1f));
878139c1837SPaolo Bonzini}
879139c1837SPaolo Bonzini
880139c1837SPaolo Bonzinistatic void tcg_out_insn_3313(TCGContext *s, AArch64Insn insn,
881139c1837SPaolo Bonzini                              TCGReg rd, TCGReg rn, uintptr_t scaled_uimm)
882139c1837SPaolo Bonzini{
883139c1837SPaolo Bonzini    /* Note the AArch64Insn constants above are for C3.3.12.  Adjust.  */
884139c1837SPaolo Bonzini    tcg_out32(s, insn | I3312_TO_I3313 | scaled_uimm << 10
885139c1837SPaolo Bonzini              | rn << 5 | (rd & 0x1f));
886139c1837SPaolo Bonzini}
887139c1837SPaolo Bonzini
8885826a0dbSRichard Hendersonstatic void tcg_out_bti(TCGContext *s, AArch64Insn insn)
8895826a0dbSRichard Henderson{
8905826a0dbSRichard Henderson    /*
8915826a0dbSRichard Henderson     * While BTI insns are nops on hosts without FEAT_BTI,
8925826a0dbSRichard Henderson     * there is no point in emitting them in that case either.
8935826a0dbSRichard Henderson     */
8945826a0dbSRichard Henderson    if (cpuinfo & CPUINFO_BTI) {
8955826a0dbSRichard Henderson        tcg_out32(s, insn);
8965826a0dbSRichard Henderson    }
8975826a0dbSRichard Henderson}
8985826a0dbSRichard Henderson
899139c1837SPaolo Bonzini/* Register to register move using ORR (shifted register with no shift). */
900139c1837SPaolo Bonzinistatic void tcg_out_movr(TCGContext *s, TCGType ext, TCGReg rd, TCGReg rm)
901139c1837SPaolo Bonzini{
902139c1837SPaolo Bonzini    tcg_out_insn(s, 3510, ORR, ext, rd, TCG_REG_XZR, rm);
903139c1837SPaolo Bonzini}
904139c1837SPaolo Bonzini
905139c1837SPaolo Bonzini/* Register to register move using ADDI (move to/from SP).  */
906139c1837SPaolo Bonzinistatic void tcg_out_movr_sp(TCGContext *s, TCGType ext, TCGReg rd, TCGReg rn)
907139c1837SPaolo Bonzini{
908139c1837SPaolo Bonzini    tcg_out_insn(s, 3401, ADDI, ext, rd, rn, 0);
909139c1837SPaolo Bonzini}
910139c1837SPaolo Bonzini
911139c1837SPaolo Bonzini/* This function is used for the Logical (immediate) instruction group.
912139c1837SPaolo Bonzini   The value of LIMM must satisfy IS_LIMM.  See the comment above about
913139c1837SPaolo Bonzini   only supporting simplified logical immediates.  */
914139c1837SPaolo Bonzinistatic void tcg_out_logicali(TCGContext *s, AArch64Insn insn, TCGType ext,
915139c1837SPaolo Bonzini                             TCGReg rd, TCGReg rn, uint64_t limm)
916139c1837SPaolo Bonzini{
917139c1837SPaolo Bonzini    unsigned h, l, r, c;
918139c1837SPaolo Bonzini
919139c1837SPaolo Bonzini    tcg_debug_assert(is_limm(limm));
920139c1837SPaolo Bonzini
921139c1837SPaolo Bonzini    h = clz64(limm);
922139c1837SPaolo Bonzini    l = ctz64(limm);
923139c1837SPaolo Bonzini    if (l == 0) {
924139c1837SPaolo Bonzini        r = 0;                  /* form 0....01....1 */
925139c1837SPaolo Bonzini        c = ctz64(~limm) - 1;
926139c1837SPaolo Bonzini        if (h == 0) {
927139c1837SPaolo Bonzini            r = clz64(~limm);   /* form 1..10..01..1 */
928139c1837SPaolo Bonzini            c += r;
929139c1837SPaolo Bonzini        }
930139c1837SPaolo Bonzini    } else {
931139c1837SPaolo Bonzini        r = 64 - l;             /* form 1....10....0 or 0..01..10..0 */
932139c1837SPaolo Bonzini        c = r - h - 1;
933139c1837SPaolo Bonzini    }
934139c1837SPaolo Bonzini    if (ext == TCG_TYPE_I32) {
935139c1837SPaolo Bonzini        r &= 31;
936139c1837SPaolo Bonzini        c &= 31;
937139c1837SPaolo Bonzini    }
938139c1837SPaolo Bonzini
939139c1837SPaolo Bonzini    tcg_out_insn_3404(s, insn, ext, rd, rn, ext, r, c);
940139c1837SPaolo Bonzini}
941139c1837SPaolo Bonzini
9424e186175SRichard Hendersonstatic void tcg_out_dupi_vec(TCGContext *s, TCGType type, unsigned vece,
9434e186175SRichard Henderson                             TCGReg rd, int64_t v64)
944139c1837SPaolo Bonzini{
945139c1837SPaolo Bonzini    bool q = type == TCG_TYPE_V128;
946139c1837SPaolo Bonzini    int cmode, imm8, i;
947139c1837SPaolo Bonzini
948139c1837SPaolo Bonzini    /* Test all bytes equal first.  */
9494e186175SRichard Henderson    if (vece == MO_8) {
950139c1837SPaolo Bonzini        imm8 = (uint8_t)v64;
951139c1837SPaolo Bonzini        tcg_out_insn(s, 3606, MOVI, q, rd, 0, 0xe, imm8);
952139c1837SPaolo Bonzini        return;
953139c1837SPaolo Bonzini    }
954139c1837SPaolo Bonzini
955139c1837SPaolo Bonzini    /*
956139c1837SPaolo Bonzini     * Test all bytes 0x00 or 0xff second.  This can match cases that
957139c1837SPaolo Bonzini     * might otherwise take 2 or 3 insns for MO_16 or MO_32 below.
958139c1837SPaolo Bonzini     */
959139c1837SPaolo Bonzini    for (i = imm8 = 0; i < 8; i++) {
960139c1837SPaolo Bonzini        uint8_t byte = v64 >> (i * 8);
961139c1837SPaolo Bonzini        if (byte == 0xff) {
962139c1837SPaolo Bonzini            imm8 |= 1 << i;
963139c1837SPaolo Bonzini        } else if (byte != 0) {
964139c1837SPaolo Bonzini            goto fail_bytes;
965139c1837SPaolo Bonzini        }
966139c1837SPaolo Bonzini    }
967139c1837SPaolo Bonzini    tcg_out_insn(s, 3606, MOVI, q, rd, 1, 0xe, imm8);
968139c1837SPaolo Bonzini    return;
969139c1837SPaolo Bonzini fail_bytes:
970139c1837SPaolo Bonzini
971139c1837SPaolo Bonzini    /*
972139c1837SPaolo Bonzini     * Tests for various replications.  For each element width, if we
973139c1837SPaolo Bonzini     * cannot find an expansion there's no point checking a larger
974139c1837SPaolo Bonzini     * width because we already know by replication it cannot match.
975139c1837SPaolo Bonzini     */
9764e186175SRichard Henderson    if (vece == MO_16) {
977139c1837SPaolo Bonzini        uint16_t v16 = v64;
978139c1837SPaolo Bonzini
979139c1837SPaolo Bonzini        if (is_shimm16(v16, &cmode, &imm8)) {
980139c1837SPaolo Bonzini            tcg_out_insn(s, 3606, MOVI, q, rd, 0, cmode, imm8);
981139c1837SPaolo Bonzini            return;
982139c1837SPaolo Bonzini        }
983139c1837SPaolo Bonzini        if (is_shimm16(~v16, &cmode, &imm8)) {
984139c1837SPaolo Bonzini            tcg_out_insn(s, 3606, MVNI, q, rd, 0, cmode, imm8);
985139c1837SPaolo Bonzini            return;
986139c1837SPaolo Bonzini        }
987139c1837SPaolo Bonzini
988139c1837SPaolo Bonzini        /*
989139c1837SPaolo Bonzini         * Otherwise, all remaining constants can be loaded in two insns:
990139c1837SPaolo Bonzini         * rd = v16 & 0xff, rd |= v16 & 0xff00.
991139c1837SPaolo Bonzini         */
992139c1837SPaolo Bonzini        tcg_out_insn(s, 3606, MOVI, q, rd, 0, 0x8, v16 & 0xff);
993139c1837SPaolo Bonzini        tcg_out_insn(s, 3606, ORR, q, rd, 0, 0xa, v16 >> 8);
994139c1837SPaolo Bonzini        return;
9954e186175SRichard Henderson    } else if (vece == MO_32) {
996139c1837SPaolo Bonzini        uint32_t v32 = v64;
997139c1837SPaolo Bonzini        uint32_t n32 = ~v32;
998139c1837SPaolo Bonzini
999139c1837SPaolo Bonzini        if (is_shimm32(v32, &cmode, &imm8) ||
1000139c1837SPaolo Bonzini            is_soimm32(v32, &cmode, &imm8) ||
1001139c1837SPaolo Bonzini            is_fimm32(v32, &cmode, &imm8)) {
1002139c1837SPaolo Bonzini            tcg_out_insn(s, 3606, MOVI, q, rd, 0, cmode, imm8);
1003139c1837SPaolo Bonzini            return;
1004139c1837SPaolo Bonzini        }
1005139c1837SPaolo Bonzini        if (is_shimm32(n32, &cmode, &imm8) ||
1006139c1837SPaolo Bonzini            is_soimm32(n32, &cmode, &imm8)) {
1007139c1837SPaolo Bonzini            tcg_out_insn(s, 3606, MVNI, q, rd, 0, cmode, imm8);
1008139c1837SPaolo Bonzini            return;
1009139c1837SPaolo Bonzini        }
1010139c1837SPaolo Bonzini
1011139c1837SPaolo Bonzini        /*
1012139c1837SPaolo Bonzini         * Restrict the set of constants to those we can load with
1013139c1837SPaolo Bonzini         * two instructions.  Others we load from the pool.
1014139c1837SPaolo Bonzini         */
1015139c1837SPaolo Bonzini        i = is_shimm32_pair(v32, &cmode, &imm8);
1016139c1837SPaolo Bonzini        if (i) {
1017139c1837SPaolo Bonzini            tcg_out_insn(s, 3606, MOVI, q, rd, 0, cmode, imm8);
1018139c1837SPaolo Bonzini            tcg_out_insn(s, 3606, ORR, q, rd, 0, i, extract32(v32, i * 4, 8));
1019139c1837SPaolo Bonzini            return;
1020139c1837SPaolo Bonzini        }
1021139c1837SPaolo Bonzini        i = is_shimm32_pair(n32, &cmode, &imm8);
1022139c1837SPaolo Bonzini        if (i) {
1023139c1837SPaolo Bonzini            tcg_out_insn(s, 3606, MVNI, q, rd, 0, cmode, imm8);
1024139c1837SPaolo Bonzini            tcg_out_insn(s, 3606, BIC, q, rd, 0, i, extract32(n32, i * 4, 8));
1025139c1837SPaolo Bonzini            return;
1026139c1837SPaolo Bonzini        }
1027139c1837SPaolo Bonzini    } else if (is_fimm64(v64, &cmode, &imm8)) {
1028139c1837SPaolo Bonzini        tcg_out_insn(s, 3606, MOVI, q, rd, 1, cmode, imm8);
1029139c1837SPaolo Bonzini        return;
1030139c1837SPaolo Bonzini    }
1031139c1837SPaolo Bonzini
1032139c1837SPaolo Bonzini    /*
1033139c1837SPaolo Bonzini     * As a last resort, load from the constant pool.  Sadly there
1034139c1837SPaolo Bonzini     * is no LD1R (literal), so store the full 16-byte vector.
1035139c1837SPaolo Bonzini     */
1036139c1837SPaolo Bonzini    if (type == TCG_TYPE_V128) {
1037139c1837SPaolo Bonzini        new_pool_l2(s, R_AARCH64_CONDBR19, s->code_ptr, 0, v64, v64);
1038139c1837SPaolo Bonzini        tcg_out_insn(s, 3305, LDR_v128, 0, rd);
1039139c1837SPaolo Bonzini    } else {
1040139c1837SPaolo Bonzini        new_pool_label(s, v64, R_AARCH64_CONDBR19, s->code_ptr, 0);
1041139c1837SPaolo Bonzini        tcg_out_insn(s, 3305, LDR_v64, 0, rd);
1042139c1837SPaolo Bonzini    }
1043139c1837SPaolo Bonzini}
1044139c1837SPaolo Bonzini
1045139c1837SPaolo Bonzinistatic bool tcg_out_dup_vec(TCGContext *s, TCGType type, unsigned vece,
1046139c1837SPaolo Bonzini                            TCGReg rd, TCGReg rs)
1047139c1837SPaolo Bonzini{
1048139c1837SPaolo Bonzini    int is_q = type - TCG_TYPE_V64;
1049139c1837SPaolo Bonzini    tcg_out_insn(s, 3605, DUP, is_q, rd, rs, 1 << vece, 0);
1050139c1837SPaolo Bonzini    return true;
1051139c1837SPaolo Bonzini}
1052139c1837SPaolo Bonzini
1053139c1837SPaolo Bonzinistatic bool tcg_out_dupm_vec(TCGContext *s, TCGType type, unsigned vece,
1054139c1837SPaolo Bonzini                             TCGReg r, TCGReg base, intptr_t offset)
1055139c1837SPaolo Bonzini{
1056d67bcbddSRichard Henderson    TCGReg temp = TCG_REG_TMP0;
1057139c1837SPaolo Bonzini
1058139c1837SPaolo Bonzini    if (offset < -0xffffff || offset > 0xffffff) {
1059139c1837SPaolo Bonzini        tcg_out_movi(s, TCG_TYPE_PTR, temp, offset);
1060139c1837SPaolo Bonzini        tcg_out_insn(s, 3502, ADD, 1, temp, temp, base);
1061139c1837SPaolo Bonzini        base = temp;
1062139c1837SPaolo Bonzini    } else {
1063139c1837SPaolo Bonzini        AArch64Insn add_insn = I3401_ADDI;
1064139c1837SPaolo Bonzini
1065139c1837SPaolo Bonzini        if (offset < 0) {
1066139c1837SPaolo Bonzini            add_insn = I3401_SUBI;
1067139c1837SPaolo Bonzini            offset = -offset;
1068139c1837SPaolo Bonzini        }
1069139c1837SPaolo Bonzini        if (offset & 0xfff000) {
1070139c1837SPaolo Bonzini            tcg_out_insn_3401(s, add_insn, 1, temp, base, offset & 0xfff000);
1071139c1837SPaolo Bonzini            base = temp;
1072139c1837SPaolo Bonzini        }
1073139c1837SPaolo Bonzini        if (offset & 0xfff) {
1074139c1837SPaolo Bonzini            tcg_out_insn_3401(s, add_insn, 1, temp, base, offset & 0xfff);
1075139c1837SPaolo Bonzini            base = temp;
1076139c1837SPaolo Bonzini        }
1077139c1837SPaolo Bonzini    }
1078139c1837SPaolo Bonzini    tcg_out_insn(s, 3303, LD1R, type == TCG_TYPE_V128, r, base, vece);
1079139c1837SPaolo Bonzini    return true;
1080139c1837SPaolo Bonzini}
1081139c1837SPaolo Bonzini
1082139c1837SPaolo Bonzinistatic void tcg_out_movi(TCGContext *s, TCGType type, TCGReg rd,
1083139c1837SPaolo Bonzini                         tcg_target_long value)
1084139c1837SPaolo Bonzini{
1085139c1837SPaolo Bonzini    tcg_target_long svalue = value;
1086139c1837SPaolo Bonzini    tcg_target_long ivalue = ~value;
1087139c1837SPaolo Bonzini    tcg_target_long t0, t1, t2;
1088139c1837SPaolo Bonzini    int s0, s1;
1089139c1837SPaolo Bonzini    AArch64Insn opc;
1090139c1837SPaolo Bonzini
1091139c1837SPaolo Bonzini    switch (type) {
1092139c1837SPaolo Bonzini    case TCG_TYPE_I32:
1093139c1837SPaolo Bonzini    case TCG_TYPE_I64:
1094139c1837SPaolo Bonzini        tcg_debug_assert(rd < 32);
1095139c1837SPaolo Bonzini        break;
1096139c1837SPaolo Bonzini    default:
1097139c1837SPaolo Bonzini        g_assert_not_reached();
1098139c1837SPaolo Bonzini    }
1099139c1837SPaolo Bonzini
1100139c1837SPaolo Bonzini    /* For 32-bit values, discard potential garbage in value.  For 64-bit
1101139c1837SPaolo Bonzini       values within [2**31, 2**32-1], we can create smaller sequences by
1102139c1837SPaolo Bonzini       interpreting this as a negative 32-bit number, while ensuring that
1103139c1837SPaolo Bonzini       the high 32 bits are cleared by setting SF=0.  */
1104139c1837SPaolo Bonzini    if (type == TCG_TYPE_I32 || (value & ~0xffffffffull) == 0) {
1105139c1837SPaolo Bonzini        svalue = (int32_t)value;
1106139c1837SPaolo Bonzini        value = (uint32_t)value;
1107139c1837SPaolo Bonzini        ivalue = (uint32_t)ivalue;
1108139c1837SPaolo Bonzini        type = TCG_TYPE_I32;
1109139c1837SPaolo Bonzini    }
1110139c1837SPaolo Bonzini
1111139c1837SPaolo Bonzini    /* Speed things up by handling the common case of small positive
1112139c1837SPaolo Bonzini       and negative values specially.  */
1113139c1837SPaolo Bonzini    if ((value & ~0xffffull) == 0) {
1114139c1837SPaolo Bonzini        tcg_out_insn(s, 3405, MOVZ, type, rd, value, 0);
1115139c1837SPaolo Bonzini        return;
1116139c1837SPaolo Bonzini    } else if ((ivalue & ~0xffffull) == 0) {
1117139c1837SPaolo Bonzini        tcg_out_insn(s, 3405, MOVN, type, rd, ivalue, 0);
1118139c1837SPaolo Bonzini        return;
1119139c1837SPaolo Bonzini    }
1120139c1837SPaolo Bonzini
1121139c1837SPaolo Bonzini    /* Check for bitfield immediates.  For the benefit of 32-bit quantities,
1122139c1837SPaolo Bonzini       use the sign-extended value.  That lets us match rotated values such
1123139c1837SPaolo Bonzini       as 0xff0000ff with the same 64-bit logic matching 0xffffffffff0000ff. */
1124139c1837SPaolo Bonzini    if (is_limm(svalue)) {
1125139c1837SPaolo Bonzini        tcg_out_logicali(s, I3404_ORRI, type, rd, TCG_REG_XZR, svalue);
1126139c1837SPaolo Bonzini        return;
1127139c1837SPaolo Bonzini    }
1128139c1837SPaolo Bonzini
1129139c1837SPaolo Bonzini    /* Look for host pointer values within 4G of the PC.  This happens
1130139c1837SPaolo Bonzini       often when loading pointers to QEMU's own data structures.  */
1131139c1837SPaolo Bonzini    if (type == TCG_TYPE_I64) {
1132ffba3eb3SRichard Henderson        intptr_t src_rx = (intptr_t)tcg_splitwx_to_rx(s->code_ptr);
1133ffba3eb3SRichard Henderson        tcg_target_long disp = value - src_rx;
1134139c1837SPaolo Bonzini        if (disp == sextract64(disp, 0, 21)) {
1135139c1837SPaolo Bonzini            tcg_out_insn(s, 3406, ADR, rd, disp);
1136139c1837SPaolo Bonzini            return;
1137139c1837SPaolo Bonzini        }
1138ffba3eb3SRichard Henderson        disp = (value >> 12) - (src_rx >> 12);
1139139c1837SPaolo Bonzini        if (disp == sextract64(disp, 0, 21)) {
1140139c1837SPaolo Bonzini            tcg_out_insn(s, 3406, ADRP, rd, disp);
1141139c1837SPaolo Bonzini            if (value & 0xfff) {
1142139c1837SPaolo Bonzini                tcg_out_insn(s, 3401, ADDI, type, rd, rd, value & 0xfff);
1143139c1837SPaolo Bonzini            }
1144139c1837SPaolo Bonzini            return;
1145139c1837SPaolo Bonzini        }
1146139c1837SPaolo Bonzini    }
1147139c1837SPaolo Bonzini
1148139c1837SPaolo Bonzini    /* Would it take fewer insns to begin with MOVN?  */
1149139c1837SPaolo Bonzini    if (ctpop64(value) >= 32) {
1150139c1837SPaolo Bonzini        t0 = ivalue;
1151139c1837SPaolo Bonzini        opc = I3405_MOVN;
1152139c1837SPaolo Bonzini    } else {
1153139c1837SPaolo Bonzini        t0 = value;
1154139c1837SPaolo Bonzini        opc = I3405_MOVZ;
1155139c1837SPaolo Bonzini    }
1156139c1837SPaolo Bonzini    s0 = ctz64(t0) & (63 & -16);
11577ceee3a1SRichard Henderson    t1 = t0 & ~(0xffffull << s0);
1158139c1837SPaolo Bonzini    s1 = ctz64(t1) & (63 & -16);
11597ceee3a1SRichard Henderson    t2 = t1 & ~(0xffffull << s1);
1160139c1837SPaolo Bonzini    if (t2 == 0) {
1161139c1837SPaolo Bonzini        tcg_out_insn_3405(s, opc, type, rd, t0 >> s0, s0);
1162139c1837SPaolo Bonzini        if (t1 != 0) {
1163139c1837SPaolo Bonzini            tcg_out_insn(s, 3405, MOVK, type, rd, value >> s1, s1);
1164139c1837SPaolo Bonzini        }
1165139c1837SPaolo Bonzini        return;
1166139c1837SPaolo Bonzini    }
1167139c1837SPaolo Bonzini
1168139c1837SPaolo Bonzini    /* For more than 2 insns, dump it into the constant pool.  */
1169139c1837SPaolo Bonzini    new_pool_label(s, value, R_AARCH64_CONDBR19, s->code_ptr, 0);
1170139c1837SPaolo Bonzini    tcg_out_insn(s, 3305, LDR, 0, rd);
1171139c1837SPaolo Bonzini}
1172139c1837SPaolo Bonzini
1173767c2503SRichard Hendersonstatic bool tcg_out_xchg(TCGContext *s, TCGType type, TCGReg r1, TCGReg r2)
1174767c2503SRichard Henderson{
1175767c2503SRichard Henderson    return false;
1176767c2503SRichard Henderson}
1177767c2503SRichard Henderson
11786a6d772eSRichard Hendersonstatic void tcg_out_addi_ptr(TCGContext *s, TCGReg rd, TCGReg rs,
11796a6d772eSRichard Henderson                             tcg_target_long imm)
11806a6d772eSRichard Henderson{
11816a6d772eSRichard Henderson    /* This function is only used for passing structs by reference. */
11826a6d772eSRichard Henderson    g_assert_not_reached();
11836a6d772eSRichard Henderson}
11846a6d772eSRichard Henderson
1185139c1837SPaolo Bonzini/* Define something more legible for general use.  */
1186139c1837SPaolo Bonzini#define tcg_out_ldst_r  tcg_out_insn_3310
1187139c1837SPaolo Bonzini
1188139c1837SPaolo Bonzinistatic void tcg_out_ldst(TCGContext *s, AArch64Insn insn, TCGReg rd,
1189139c1837SPaolo Bonzini                         TCGReg rn, intptr_t offset, int lgsize)
1190139c1837SPaolo Bonzini{
1191139c1837SPaolo Bonzini    /* If the offset is naturally aligned and in range, then we can
1192139c1837SPaolo Bonzini       use the scaled uimm12 encoding */
1193139c1837SPaolo Bonzini    if (offset >= 0 && !(offset & ((1 << lgsize) - 1))) {
1194139c1837SPaolo Bonzini        uintptr_t scaled_uimm = offset >> lgsize;
1195139c1837SPaolo Bonzini        if (scaled_uimm <= 0xfff) {
1196139c1837SPaolo Bonzini            tcg_out_insn_3313(s, insn, rd, rn, scaled_uimm);
1197139c1837SPaolo Bonzini            return;
1198139c1837SPaolo Bonzini        }
1199139c1837SPaolo Bonzini    }
1200139c1837SPaolo Bonzini
1201139c1837SPaolo Bonzini    /* Small signed offsets can use the unscaled encoding.  */
1202139c1837SPaolo Bonzini    if (offset >= -256 && offset < 256) {
1203139c1837SPaolo Bonzini        tcg_out_insn_3312(s, insn, rd, rn, offset);
1204139c1837SPaolo Bonzini        return;
1205139c1837SPaolo Bonzini    }
1206139c1837SPaolo Bonzini
1207139c1837SPaolo Bonzini    /* Worst-case scenario, move offset to temp register, use reg offset.  */
1208d67bcbddSRichard Henderson    tcg_out_movi(s, TCG_TYPE_I64, TCG_REG_TMP0, offset);
1209d67bcbddSRichard Henderson    tcg_out_ldst_r(s, insn, rd, rn, TCG_TYPE_I64, TCG_REG_TMP0);
1210139c1837SPaolo Bonzini}
1211139c1837SPaolo Bonzini
1212139c1837SPaolo Bonzinistatic bool tcg_out_mov(TCGContext *s, TCGType type, TCGReg ret, TCGReg arg)
1213139c1837SPaolo Bonzini{
1214139c1837SPaolo Bonzini    if (ret == arg) {
1215139c1837SPaolo Bonzini        return true;
1216139c1837SPaolo Bonzini    }
1217139c1837SPaolo Bonzini    switch (type) {
1218139c1837SPaolo Bonzini    case TCG_TYPE_I32:
1219139c1837SPaolo Bonzini    case TCG_TYPE_I64:
1220139c1837SPaolo Bonzini        if (ret < 32 && arg < 32) {
1221139c1837SPaolo Bonzini            tcg_out_movr(s, type, ret, arg);
1222139c1837SPaolo Bonzini            break;
1223139c1837SPaolo Bonzini        } else if (ret < 32) {
1224139c1837SPaolo Bonzini            tcg_out_insn(s, 3605, UMOV, type, ret, arg, 0, 0);
1225139c1837SPaolo Bonzini            break;
1226139c1837SPaolo Bonzini        } else if (arg < 32) {
1227139c1837SPaolo Bonzini            tcg_out_insn(s, 3605, INS, 0, ret, arg, 4 << type, 0);
1228139c1837SPaolo Bonzini            break;
1229139c1837SPaolo Bonzini        }
1230139c1837SPaolo Bonzini        /* FALLTHRU */
1231139c1837SPaolo Bonzini
1232139c1837SPaolo Bonzini    case TCG_TYPE_V64:
1233139c1837SPaolo Bonzini        tcg_debug_assert(ret >= 32 && arg >= 32);
1234139c1837SPaolo Bonzini        tcg_out_insn(s, 3616, ORR, 0, 0, ret, arg, arg);
1235139c1837SPaolo Bonzini        break;
1236139c1837SPaolo Bonzini    case TCG_TYPE_V128:
1237139c1837SPaolo Bonzini        tcg_debug_assert(ret >= 32 && arg >= 32);
1238139c1837SPaolo Bonzini        tcg_out_insn(s, 3616, ORR, 1, 0, ret, arg, arg);
1239139c1837SPaolo Bonzini        break;
1240139c1837SPaolo Bonzini
1241139c1837SPaolo Bonzini    default:
1242139c1837SPaolo Bonzini        g_assert_not_reached();
1243139c1837SPaolo Bonzini    }
1244139c1837SPaolo Bonzini    return true;
1245139c1837SPaolo Bonzini}
1246139c1837SPaolo Bonzini
1247139c1837SPaolo Bonzinistatic void tcg_out_ld(TCGContext *s, TCGType type, TCGReg ret,
1248139c1837SPaolo Bonzini                       TCGReg base, intptr_t ofs)
1249139c1837SPaolo Bonzini{
1250139c1837SPaolo Bonzini    AArch64Insn insn;
1251139c1837SPaolo Bonzini    int lgsz;
1252139c1837SPaolo Bonzini
1253139c1837SPaolo Bonzini    switch (type) {
1254139c1837SPaolo Bonzini    case TCG_TYPE_I32:
1255139c1837SPaolo Bonzini        insn = (ret < 32 ? I3312_LDRW : I3312_LDRVS);
1256139c1837SPaolo Bonzini        lgsz = 2;
1257139c1837SPaolo Bonzini        break;
1258139c1837SPaolo Bonzini    case TCG_TYPE_I64:
1259139c1837SPaolo Bonzini        insn = (ret < 32 ? I3312_LDRX : I3312_LDRVD);
1260139c1837SPaolo Bonzini        lgsz = 3;
1261139c1837SPaolo Bonzini        break;
1262139c1837SPaolo Bonzini    case TCG_TYPE_V64:
1263139c1837SPaolo Bonzini        insn = I3312_LDRVD;
1264139c1837SPaolo Bonzini        lgsz = 3;
1265139c1837SPaolo Bonzini        break;
1266139c1837SPaolo Bonzini    case TCG_TYPE_V128:
1267139c1837SPaolo Bonzini        insn = I3312_LDRVQ;
1268139c1837SPaolo Bonzini        lgsz = 4;
1269139c1837SPaolo Bonzini        break;
1270139c1837SPaolo Bonzini    default:
1271139c1837SPaolo Bonzini        g_assert_not_reached();
1272139c1837SPaolo Bonzini    }
1273139c1837SPaolo Bonzini    tcg_out_ldst(s, insn, ret, base, ofs, lgsz);
1274139c1837SPaolo Bonzini}
1275139c1837SPaolo Bonzini
1276139c1837SPaolo Bonzinistatic void tcg_out_st(TCGContext *s, TCGType type, TCGReg src,
1277139c1837SPaolo Bonzini                       TCGReg base, intptr_t ofs)
1278139c1837SPaolo Bonzini{
1279139c1837SPaolo Bonzini    AArch64Insn insn;
1280139c1837SPaolo Bonzini    int lgsz;
1281139c1837SPaolo Bonzini
1282139c1837SPaolo Bonzini    switch (type) {
1283139c1837SPaolo Bonzini    case TCG_TYPE_I32:
1284139c1837SPaolo Bonzini        insn = (src < 32 ? I3312_STRW : I3312_STRVS);
1285139c1837SPaolo Bonzini        lgsz = 2;
1286139c1837SPaolo Bonzini        break;
1287139c1837SPaolo Bonzini    case TCG_TYPE_I64:
1288139c1837SPaolo Bonzini        insn = (src < 32 ? I3312_STRX : I3312_STRVD);
1289139c1837SPaolo Bonzini        lgsz = 3;
1290139c1837SPaolo Bonzini        break;
1291139c1837SPaolo Bonzini    case TCG_TYPE_V64:
1292139c1837SPaolo Bonzini        insn = I3312_STRVD;
1293139c1837SPaolo Bonzini        lgsz = 3;
1294139c1837SPaolo Bonzini        break;
1295139c1837SPaolo Bonzini    case TCG_TYPE_V128:
1296139c1837SPaolo Bonzini        insn = I3312_STRVQ;
1297139c1837SPaolo Bonzini        lgsz = 4;
1298139c1837SPaolo Bonzini        break;
1299139c1837SPaolo Bonzini    default:
1300139c1837SPaolo Bonzini        g_assert_not_reached();
1301139c1837SPaolo Bonzini    }
1302139c1837SPaolo Bonzini    tcg_out_ldst(s, insn, src, base, ofs, lgsz);
1303139c1837SPaolo Bonzini}
1304139c1837SPaolo Bonzini
1305139c1837SPaolo Bonzinistatic inline bool tcg_out_sti(TCGContext *s, TCGType type, TCGArg val,
1306139c1837SPaolo Bonzini                               TCGReg base, intptr_t ofs)
1307139c1837SPaolo Bonzini{
1308139c1837SPaolo Bonzini    if (type <= TCG_TYPE_I64 && val == 0) {
1309139c1837SPaolo Bonzini        tcg_out_st(s, type, TCG_REG_XZR, base, ofs);
1310139c1837SPaolo Bonzini        return true;
1311139c1837SPaolo Bonzini    }
1312139c1837SPaolo Bonzini    return false;
1313139c1837SPaolo Bonzini}
1314139c1837SPaolo Bonzini
1315139c1837SPaolo Bonzinistatic inline void tcg_out_bfm(TCGContext *s, TCGType ext, TCGReg rd,
1316139c1837SPaolo Bonzini                               TCGReg rn, unsigned int a, unsigned int b)
1317139c1837SPaolo Bonzini{
1318139c1837SPaolo Bonzini    tcg_out_insn(s, 3402, BFM, ext, rd, rn, ext, a, b);
1319139c1837SPaolo Bonzini}
1320139c1837SPaolo Bonzini
1321139c1837SPaolo Bonzinistatic inline void tcg_out_ubfm(TCGContext *s, TCGType ext, TCGReg rd,
1322139c1837SPaolo Bonzini                                TCGReg rn, unsigned int a, unsigned int b)
1323139c1837SPaolo Bonzini{
1324139c1837SPaolo Bonzini    tcg_out_insn(s, 3402, UBFM, ext, rd, rn, ext, a, b);
1325139c1837SPaolo Bonzini}
1326139c1837SPaolo Bonzini
1327139c1837SPaolo Bonzinistatic inline void tcg_out_sbfm(TCGContext *s, TCGType ext, TCGReg rd,
1328139c1837SPaolo Bonzini                                TCGReg rn, unsigned int a, unsigned int b)
1329139c1837SPaolo Bonzini{
1330139c1837SPaolo Bonzini    tcg_out_insn(s, 3402, SBFM, ext, rd, rn, ext, a, b);
1331139c1837SPaolo Bonzini}
1332139c1837SPaolo Bonzini
1333139c1837SPaolo Bonzinistatic inline void tcg_out_extr(TCGContext *s, TCGType ext, TCGReg rd,
1334139c1837SPaolo Bonzini                                TCGReg rn, TCGReg rm, unsigned int a)
1335139c1837SPaolo Bonzini{
1336139c1837SPaolo Bonzini    tcg_out_insn(s, 3403, EXTR, ext, rd, rn, rm, a);
1337139c1837SPaolo Bonzini}
1338139c1837SPaolo Bonzini
1339139c1837SPaolo Bonzinistatic inline void tcg_out_shl(TCGContext *s, TCGType ext,
1340139c1837SPaolo Bonzini                               TCGReg rd, TCGReg rn, unsigned int m)
1341139c1837SPaolo Bonzini{
1342139c1837SPaolo Bonzini    int bits = ext ? 64 : 32;
1343139c1837SPaolo Bonzini    int max = bits - 1;
134494bcc91bSRichard Henderson    tcg_out_ubfm(s, ext, rd, rn, (bits - m) & max, (max - m) & max);
1345139c1837SPaolo Bonzini}
1346139c1837SPaolo Bonzini
1347139c1837SPaolo Bonzinistatic inline void tcg_out_shr(TCGContext *s, TCGType ext,
1348139c1837SPaolo Bonzini                               TCGReg rd, TCGReg rn, unsigned int m)
1349139c1837SPaolo Bonzini{
1350139c1837SPaolo Bonzini    int max = ext ? 63 : 31;
1351139c1837SPaolo Bonzini    tcg_out_ubfm(s, ext, rd, rn, m & max, max);
1352139c1837SPaolo Bonzini}
1353139c1837SPaolo Bonzini
1354139c1837SPaolo Bonzinistatic inline void tcg_out_sar(TCGContext *s, TCGType ext,
1355139c1837SPaolo Bonzini                               TCGReg rd, TCGReg rn, unsigned int m)
1356139c1837SPaolo Bonzini{
1357139c1837SPaolo Bonzini    int max = ext ? 63 : 31;
1358139c1837SPaolo Bonzini    tcg_out_sbfm(s, ext, rd, rn, m & max, max);
1359139c1837SPaolo Bonzini}
1360139c1837SPaolo Bonzini
1361139c1837SPaolo Bonzinistatic inline void tcg_out_rotr(TCGContext *s, TCGType ext,
1362139c1837SPaolo Bonzini                                TCGReg rd, TCGReg rn, unsigned int m)
1363139c1837SPaolo Bonzini{
1364139c1837SPaolo Bonzini    int max = ext ? 63 : 31;
1365139c1837SPaolo Bonzini    tcg_out_extr(s, ext, rd, rn, rn, m & max);
1366139c1837SPaolo Bonzini}
1367139c1837SPaolo Bonzini
1368139c1837SPaolo Bonzinistatic inline void tcg_out_rotl(TCGContext *s, TCGType ext,
1369139c1837SPaolo Bonzini                                TCGReg rd, TCGReg rn, unsigned int m)
1370139c1837SPaolo Bonzini{
137126b1248fSYasuo Kuwahara    int max = ext ? 63 : 31;
137226b1248fSYasuo Kuwahara    tcg_out_extr(s, ext, rd, rn, rn, -m & max);
1373139c1837SPaolo Bonzini}
1374139c1837SPaolo Bonzini
1375139c1837SPaolo Bonzinistatic inline void tcg_out_dep(TCGContext *s, TCGType ext, TCGReg rd,
1376139c1837SPaolo Bonzini                               TCGReg rn, unsigned lsb, unsigned width)
1377139c1837SPaolo Bonzini{
1378139c1837SPaolo Bonzini    unsigned size = ext ? 64 : 32;
1379139c1837SPaolo Bonzini    unsigned a = (size - lsb) & (size - 1);
1380139c1837SPaolo Bonzini    unsigned b = width - 1;
1381139c1837SPaolo Bonzini    tcg_out_bfm(s, ext, rd, rn, a, b);
1382139c1837SPaolo Bonzini}
1383139c1837SPaolo Bonzini
1384339adf2fSRichard Hendersonstatic void tcg_out_cmp(TCGContext *s, TCGType ext, TCGCond cond, TCGReg a,
1385139c1837SPaolo Bonzini                        tcg_target_long b, bool const_b)
1386139c1837SPaolo Bonzini{
1387339adf2fSRichard Henderson    if (is_tst_cond(cond)) {
1388339adf2fSRichard Henderson        if (!const_b) {
1389339adf2fSRichard Henderson            tcg_out_insn(s, 3510, ANDS, ext, TCG_REG_XZR, a, b);
1390139c1837SPaolo Bonzini        } else {
13911d24c36bSRichard Henderson            tcg_out_logicali(s, I3404_ANDSI, ext, TCG_REG_XZR, a, b);
1392139c1837SPaolo Bonzini        }
1393139c1837SPaolo Bonzini    } else {
1394339adf2fSRichard Henderson        if (!const_b) {
1395139c1837SPaolo Bonzini            tcg_out_insn(s, 3502, SUBS, ext, TCG_REG_XZR, a, b);
1396339adf2fSRichard Henderson        } else if (b >= 0) {
1397339adf2fSRichard Henderson            tcg_debug_assert(is_aimm(b));
1398339adf2fSRichard Henderson            tcg_out_insn(s, 3401, SUBSI, ext, TCG_REG_XZR, a, b);
1399339adf2fSRichard Henderson        } else {
1400339adf2fSRichard Henderson            tcg_debug_assert(is_aimm(-b));
1401339adf2fSRichard Henderson            tcg_out_insn(s, 3401, ADDSI, ext, TCG_REG_XZR, a, -b);
1402339adf2fSRichard Henderson        }
1403139c1837SPaolo Bonzini    }
1404139c1837SPaolo Bonzini}
1405139c1837SPaolo Bonzini
1406ffd0e507SRichard Hendersonstatic void tcg_out_goto(TCGContext *s, const tcg_insn_unit *target)
1407139c1837SPaolo Bonzini{
1408ffba3eb3SRichard Henderson    ptrdiff_t offset = tcg_pcrel_diff(s, target) >> 2;
1409139c1837SPaolo Bonzini    tcg_debug_assert(offset == sextract64(offset, 0, 26));
1410139c1837SPaolo Bonzini    tcg_out_insn(s, 3206, B, offset);
1411139c1837SPaolo Bonzini}
1412139c1837SPaolo Bonzini
1413cee44b03SRichard Hendersonstatic void tcg_out_call_int(TCGContext *s, const tcg_insn_unit *target)
1414139c1837SPaolo Bonzini{
1415ffba3eb3SRichard Henderson    ptrdiff_t offset = tcg_pcrel_diff(s, target) >> 2;
1416139c1837SPaolo Bonzini    if (offset == sextract64(offset, 0, 26)) {
1417139c1837SPaolo Bonzini        tcg_out_insn(s, 3206, BL, offset);
1418139c1837SPaolo Bonzini    } else {
1419d67bcbddSRichard Henderson        tcg_out_movi(s, TCG_TYPE_I64, TCG_REG_TMP0, (intptr_t)target);
1420d67bcbddSRichard Henderson        tcg_out_insn(s, 3207, BLR, TCG_REG_TMP0);
1421139c1837SPaolo Bonzini    }
1422139c1837SPaolo Bonzini}
1423139c1837SPaolo Bonzini
1424cee44b03SRichard Hendersonstatic void tcg_out_call(TCGContext *s, const tcg_insn_unit *target,
1425cee44b03SRichard Henderson                         const TCGHelperInfo *info)
1426cee44b03SRichard Henderson{
1427cee44b03SRichard Henderson    tcg_out_call_int(s, target);
1428cee44b03SRichard Henderson}
1429cee44b03SRichard Henderson
1430139c1837SPaolo Bonzinistatic inline void tcg_out_goto_label(TCGContext *s, TCGLabel *l)
1431139c1837SPaolo Bonzini{
1432139c1837SPaolo Bonzini    if (!l->has_value) {
1433139c1837SPaolo Bonzini        tcg_out_reloc(s, s->code_ptr, R_AARCH64_JUMP26, l, 0);
1434139c1837SPaolo Bonzini        tcg_out_insn(s, 3206, B, 0);
1435139c1837SPaolo Bonzini    } else {
1436139c1837SPaolo Bonzini        tcg_out_goto(s, l->u.value_ptr);
1437139c1837SPaolo Bonzini    }
1438139c1837SPaolo Bonzini}
1439139c1837SPaolo Bonzini
1440139c1837SPaolo Bonzinistatic void tcg_out_brcond(TCGContext *s, TCGType ext, TCGCond c, TCGArg a,
1441139c1837SPaolo Bonzini                           TCGArg b, bool b_const, TCGLabel *l)
1442139c1837SPaolo Bonzini{
144392a11b93SRichard Henderson    int tbit = -1;
1444a0f5b3fcSPhilippe Mathieu-Daudé    bool need_cmp = true;
1445139c1837SPaolo Bonzini
1446a0f5b3fcSPhilippe Mathieu-Daudé    switch (c) {
1447a0f5b3fcSPhilippe Mathieu-Daudé    case TCG_COND_EQ:
1448a0f5b3fcSPhilippe Mathieu-Daudé    case TCG_COND_NE:
144992a11b93SRichard Henderson        /* cmp xN,0; b.ne L -> cbnz xN,L */
1450a0f5b3fcSPhilippe Mathieu-Daudé        if (b_const && b == 0) {
1451139c1837SPaolo Bonzini            need_cmp = false;
1452a0f5b3fcSPhilippe Mathieu-Daudé        }
1453a0f5b3fcSPhilippe Mathieu-Daudé        break;
145492a11b93SRichard Henderson    case TCG_COND_LT:
145592a11b93SRichard Henderson    case TCG_COND_GE:
145692a11b93SRichard Henderson        /* cmp xN,0; b.mi L -> tbnz xN,63,L */
145792a11b93SRichard Henderson        if (b_const && b == 0) {
145892a11b93SRichard Henderson            c = (c == TCG_COND_LT ? TCG_COND_TSTNE : TCG_COND_TSTEQ);
145992a11b93SRichard Henderson            tbit = ext ? 63 : 31;
146092a11b93SRichard Henderson            need_cmp = false;
146192a11b93SRichard Henderson        }
146292a11b93SRichard Henderson        break;
146392a11b93SRichard Henderson    case TCG_COND_TSTEQ:
146492a11b93SRichard Henderson    case TCG_COND_TSTNE:
146534aff3c2SRichard Henderson        /* tst xN,0xffffffff; b.ne L -> cbnz wN,L */
146634aff3c2SRichard Henderson        if (b_const && b == UINT32_MAX) {
14674fe19bbbSRichard Henderson            c = tcg_tst_eqne_cond(c);
146834aff3c2SRichard Henderson            ext = TCG_TYPE_I32;
146934aff3c2SRichard Henderson            need_cmp = false;
147034aff3c2SRichard Henderson            break;
147134aff3c2SRichard Henderson        }
147292a11b93SRichard Henderson        /* tst xN,1<<B; b.ne L -> tbnz xN,B,L */
147392a11b93SRichard Henderson        if (b_const && is_power_of_2(b)) {
147492a11b93SRichard Henderson            tbit = ctz64(b);
147592a11b93SRichard Henderson            need_cmp = false;
147692a11b93SRichard Henderson        }
147792a11b93SRichard Henderson        break;
1478a0f5b3fcSPhilippe Mathieu-Daudé    default:
1479a0f5b3fcSPhilippe Mathieu-Daudé        break;
1480a0f5b3fcSPhilippe Mathieu-Daudé    }
1481a0f5b3fcSPhilippe Mathieu-Daudé
1482a0f5b3fcSPhilippe Mathieu-Daudé    if (need_cmp) {
1483339adf2fSRichard Henderson        tcg_out_cmp(s, ext, c, a, b, b_const);
1484139c1837SPaolo Bonzini        tcg_out_reloc(s, s->code_ptr, R_AARCH64_CONDBR19, l, 0);
148592a11b93SRichard Henderson        tcg_out_insn(s, 3202, B_C, c, 0);
148692a11b93SRichard Henderson        return;
1487139c1837SPaolo Bonzini    }
1488139c1837SPaolo Bonzini
148992a11b93SRichard Henderson    if (tbit >= 0) {
149092a11b93SRichard Henderson        tcg_out_reloc(s, s->code_ptr, R_AARCH64_TSTBR14, l, 0);
149192a11b93SRichard Henderson        switch (c) {
149292a11b93SRichard Henderson        case TCG_COND_TSTEQ:
149392a11b93SRichard Henderson            tcg_out_insn(s, 3205, TBZ, a, tbit, 0);
149492a11b93SRichard Henderson            break;
149592a11b93SRichard Henderson        case TCG_COND_TSTNE:
149692a11b93SRichard Henderson            tcg_out_insn(s, 3205, TBNZ, a, tbit, 0);
149792a11b93SRichard Henderson            break;
149892a11b93SRichard Henderson        default:
149992a11b93SRichard Henderson            g_assert_not_reached();
150092a11b93SRichard Henderson        }
1501139c1837SPaolo Bonzini    } else {
150292a11b93SRichard Henderson        tcg_out_reloc(s, s->code_ptr, R_AARCH64_CONDBR19, l, 0);
1503a0f5b3fcSPhilippe Mathieu-Daudé        switch (c) {
1504a0f5b3fcSPhilippe Mathieu-Daudé        case TCG_COND_EQ:
150592a11b93SRichard Henderson            tcg_out_insn(s, 3201, CBZ, ext, a, 0);
1506a0f5b3fcSPhilippe Mathieu-Daudé            break;
1507a0f5b3fcSPhilippe Mathieu-Daudé        case TCG_COND_NE:
150892a11b93SRichard Henderson            tcg_out_insn(s, 3201, CBNZ, ext, a, 0);
1509a0f5b3fcSPhilippe Mathieu-Daudé            break;
1510a0f5b3fcSPhilippe Mathieu-Daudé        default:
1511a0f5b3fcSPhilippe Mathieu-Daudé            g_assert_not_reached();
1512a0f5b3fcSPhilippe Mathieu-Daudé        }
1513139c1837SPaolo Bonzini    }
1514139c1837SPaolo Bonzini}
1515139c1837SPaolo Bonzini
1516dfa24dfaSRichard Hendersonstatic inline void tcg_out_rev(TCGContext *s, int ext, MemOp s_bits,
1517dfa24dfaSRichard Henderson                               TCGReg rd, TCGReg rn)
1518139c1837SPaolo Bonzini{
1519dfa24dfaSRichard Henderson    /* REV, REV16, REV32 */
1520dfa24dfaSRichard Henderson    tcg_out_insn_3507(s, I3507_REV | (s_bits << 10), ext, rd, rn);
1521139c1837SPaolo Bonzini}
1522139c1837SPaolo Bonzini
1523139c1837SPaolo Bonzinistatic inline void tcg_out_sxt(TCGContext *s, TCGType ext, MemOp s_bits,
1524139c1837SPaolo Bonzini                               TCGReg rd, TCGReg rn)
1525139c1837SPaolo Bonzini{
1526139c1837SPaolo Bonzini    /* Using ALIASes SXTB, SXTH, SXTW, of SBFM Xd, Xn, #0, #7|15|31 */
1527139c1837SPaolo Bonzini    int bits = (8 << s_bits) - 1;
1528139c1837SPaolo Bonzini    tcg_out_sbfm(s, ext, rd, rn, 0, bits);
1529139c1837SPaolo Bonzini}
1530139c1837SPaolo Bonzini
1531678155b2SRichard Hendersonstatic void tcg_out_ext8s(TCGContext *s, TCGType type, TCGReg rd, TCGReg rn)
1532678155b2SRichard Henderson{
1533678155b2SRichard Henderson    tcg_out_sxt(s, type, MO_8, rd, rn);
1534678155b2SRichard Henderson}
1535678155b2SRichard Henderson
1536753e42eaSRichard Hendersonstatic void tcg_out_ext16s(TCGContext *s, TCGType type, TCGReg rd, TCGReg rn)
1537753e42eaSRichard Henderson{
1538753e42eaSRichard Henderson    tcg_out_sxt(s, type, MO_16, rd, rn);
1539753e42eaSRichard Henderson}
1540753e42eaSRichard Henderson
154152bf3398SRichard Hendersonstatic void tcg_out_ext32s(TCGContext *s, TCGReg rd, TCGReg rn)
154252bf3398SRichard Henderson{
154352bf3398SRichard Henderson    tcg_out_sxt(s, TCG_TYPE_I64, MO_32, rd, rn);
154452bf3398SRichard Henderson}
154552bf3398SRichard Henderson
15469c6aa274SRichard Hendersonstatic void tcg_out_exts_i32_i64(TCGContext *s, TCGReg rd, TCGReg rn)
15479c6aa274SRichard Henderson{
15489c6aa274SRichard Henderson    tcg_out_ext32s(s, rd, rn);
15499c6aa274SRichard Henderson}
15509c6aa274SRichard Henderson
1551139c1837SPaolo Bonzinistatic inline void tcg_out_uxt(TCGContext *s, MemOp s_bits,
1552139c1837SPaolo Bonzini                               TCGReg rd, TCGReg rn)
1553139c1837SPaolo Bonzini{
1554139c1837SPaolo Bonzini    /* Using ALIASes UXTB, UXTH of UBFM Wd, Wn, #0, #7|15 */
1555139c1837SPaolo Bonzini    int bits = (8 << s_bits) - 1;
1556139c1837SPaolo Bonzini    tcg_out_ubfm(s, 0, rd, rn, 0, bits);
1557139c1837SPaolo Bonzini}
1558139c1837SPaolo Bonzini
1559d0e66c89SRichard Hendersonstatic void tcg_out_ext8u(TCGContext *s, TCGReg rd, TCGReg rn)
1560d0e66c89SRichard Henderson{
1561d0e66c89SRichard Henderson    tcg_out_uxt(s, MO_8, rd, rn);
1562d0e66c89SRichard Henderson}
1563d0e66c89SRichard Henderson
1564379afdffSRichard Hendersonstatic void tcg_out_ext16u(TCGContext *s, TCGReg rd, TCGReg rn)
1565379afdffSRichard Henderson{
1566379afdffSRichard Henderson    tcg_out_uxt(s, MO_16, rd, rn);
1567379afdffSRichard Henderson}
1568379afdffSRichard Henderson
15699ecf5f61SRichard Hendersonstatic void tcg_out_ext32u(TCGContext *s, TCGReg rd, TCGReg rn)
15709ecf5f61SRichard Henderson{
15719ecf5f61SRichard Henderson    tcg_out_movr(s, TCG_TYPE_I32, rd, rn);
15729ecf5f61SRichard Henderson}
15739ecf5f61SRichard Henderson
1574b9bfe000SRichard Hendersonstatic void tcg_out_extu_i32_i64(TCGContext *s, TCGReg rd, TCGReg rn)
1575b9bfe000SRichard Henderson{
1576b9bfe000SRichard Henderson    tcg_out_ext32u(s, rd, rn);
1577b9bfe000SRichard Henderson}
1578b9bfe000SRichard Henderson
1579b8b94ac6SRichard Hendersonstatic void tcg_out_extrl_i64_i32(TCGContext *s, TCGReg rd, TCGReg rn)
1580b8b94ac6SRichard Henderson{
1581b8b94ac6SRichard Henderson    tcg_out_mov(s, TCG_TYPE_I32, rd, rn);
1582b8b94ac6SRichard Henderson}
1583b8b94ac6SRichard Henderson
1584139c1837SPaolo Bonzinistatic void tcg_out_addsubi(TCGContext *s, int ext, TCGReg rd,
1585139c1837SPaolo Bonzini                            TCGReg rn, int64_t aimm)
1586139c1837SPaolo Bonzini{
1587139c1837SPaolo Bonzini    if (aimm >= 0) {
1588139c1837SPaolo Bonzini        tcg_out_insn(s, 3401, ADDI, ext, rd, rn, aimm);
1589139c1837SPaolo Bonzini    } else {
1590139c1837SPaolo Bonzini        tcg_out_insn(s, 3401, SUBI, ext, rd, rn, -aimm);
1591139c1837SPaolo Bonzini    }
1592139c1837SPaolo Bonzini}
1593139c1837SPaolo Bonzini
1594707b45a2SRichard Hendersonstatic void tcg_out_addsub2(TCGContext *s, TCGType ext, TCGReg rl,
1595139c1837SPaolo Bonzini                            TCGReg rh, TCGReg al, TCGReg ah,
1596139c1837SPaolo Bonzini                            tcg_target_long bl, tcg_target_long bh,
1597139c1837SPaolo Bonzini                            bool const_bl, bool const_bh, bool sub)
1598139c1837SPaolo Bonzini{
1599139c1837SPaolo Bonzini    TCGReg orig_rl = rl;
1600139c1837SPaolo Bonzini    AArch64Insn insn;
1601139c1837SPaolo Bonzini
1602139c1837SPaolo Bonzini    if (rl == ah || (!const_bh && rl == bh)) {
1603d67bcbddSRichard Henderson        rl = TCG_REG_TMP0;
1604139c1837SPaolo Bonzini    }
1605139c1837SPaolo Bonzini
1606139c1837SPaolo Bonzini    if (const_bl) {
1607707b45a2SRichard Henderson        if (bl < 0) {
1608139c1837SPaolo Bonzini            bl = -bl;
1609707b45a2SRichard Henderson            insn = sub ? I3401_ADDSI : I3401_SUBSI;
1610707b45a2SRichard Henderson        } else {
1611707b45a2SRichard Henderson            insn = sub ? I3401_SUBSI : I3401_ADDSI;
1612139c1837SPaolo Bonzini        }
1613707b45a2SRichard Henderson
1614139c1837SPaolo Bonzini        if (unlikely(al == TCG_REG_XZR)) {
1615139c1837SPaolo Bonzini            /* ??? We want to allow al to be zero for the benefit of
1616139c1837SPaolo Bonzini               negation via subtraction.  However, that leaves open the
1617139c1837SPaolo Bonzini               possibility of adding 0+const in the low part, and the
1618139c1837SPaolo Bonzini               immediate add instructions encode XSP not XZR.  Don't try
1619139c1837SPaolo Bonzini               anything more elaborate here than loading another zero.  */
1620d67bcbddSRichard Henderson            al = TCG_REG_TMP0;
1621139c1837SPaolo Bonzini            tcg_out_movi(s, ext, al, 0);
1622139c1837SPaolo Bonzini        }
1623139c1837SPaolo Bonzini        tcg_out_insn_3401(s, insn, ext, rl, al, bl);
1624139c1837SPaolo Bonzini    } else {
1625139c1837SPaolo Bonzini        tcg_out_insn_3502(s, sub ? I3502_SUBS : I3502_ADDS, ext, rl, al, bl);
1626139c1837SPaolo Bonzini    }
1627139c1837SPaolo Bonzini
1628139c1837SPaolo Bonzini    insn = I3503_ADC;
1629139c1837SPaolo Bonzini    if (const_bh) {
1630139c1837SPaolo Bonzini        /* Note that the only two constants we support are 0 and -1, and
1631139c1837SPaolo Bonzini           that SBC = rn + ~rm + c, so adc -1 is sbc 0, and vice-versa.  */
1632139c1837SPaolo Bonzini        if ((bh != 0) ^ sub) {
1633139c1837SPaolo Bonzini            insn = I3503_SBC;
1634139c1837SPaolo Bonzini        }
1635139c1837SPaolo Bonzini        bh = TCG_REG_XZR;
1636139c1837SPaolo Bonzini    } else if (sub) {
1637139c1837SPaolo Bonzini        insn = I3503_SBC;
1638139c1837SPaolo Bonzini    }
1639139c1837SPaolo Bonzini    tcg_out_insn_3503(s, insn, ext, rh, ah, bh);
1640139c1837SPaolo Bonzini
1641139c1837SPaolo Bonzini    tcg_out_mov(s, ext, orig_rl, rl);
1642139c1837SPaolo Bonzini}
1643139c1837SPaolo Bonzini
1644139c1837SPaolo Bonzinistatic inline void tcg_out_mb(TCGContext *s, TCGArg a0)
1645139c1837SPaolo Bonzini{
1646139c1837SPaolo Bonzini    static const uint32_t sync[] = {
1647139c1837SPaolo Bonzini        [0 ... TCG_MO_ALL]            = DMB_ISH | DMB_LD | DMB_ST,
1648139c1837SPaolo Bonzini        [TCG_MO_ST_ST]                = DMB_ISH | DMB_ST,
1649139c1837SPaolo Bonzini        [TCG_MO_LD_LD]                = DMB_ISH | DMB_LD,
1650139c1837SPaolo Bonzini        [TCG_MO_LD_ST]                = DMB_ISH | DMB_LD,
1651139c1837SPaolo Bonzini        [TCG_MO_LD_ST | TCG_MO_LD_LD] = DMB_ISH | DMB_LD,
1652139c1837SPaolo Bonzini    };
1653139c1837SPaolo Bonzini    tcg_out32(s, sync[a0 & TCG_MO_ALL]);
1654139c1837SPaolo Bonzini}
1655139c1837SPaolo Bonzini
1656139c1837SPaolo Bonzinistatic void tcg_out_cltz(TCGContext *s, TCGType ext, TCGReg d,
1657139c1837SPaolo Bonzini                         TCGReg a0, TCGArg b, bool const_b, bool is_ctz)
1658139c1837SPaolo Bonzini{
1659139c1837SPaolo Bonzini    TCGReg a1 = a0;
1660139c1837SPaolo Bonzini    if (is_ctz) {
1661d67bcbddSRichard Henderson        a1 = TCG_REG_TMP0;
1662139c1837SPaolo Bonzini        tcg_out_insn(s, 3507, RBIT, ext, a1, a0);
1663139c1837SPaolo Bonzini    }
1664139c1837SPaolo Bonzini    if (const_b && b == (ext ? 64 : 32)) {
1665139c1837SPaolo Bonzini        tcg_out_insn(s, 3507, CLZ, ext, d, a1);
1666139c1837SPaolo Bonzini    } else {
1667139c1837SPaolo Bonzini        AArch64Insn sel = I3506_CSEL;
1668139c1837SPaolo Bonzini
1669339adf2fSRichard Henderson        tcg_out_cmp(s, ext, TCG_COND_NE, a0, 0, 1);
1670d67bcbddSRichard Henderson        tcg_out_insn(s, 3507, CLZ, ext, TCG_REG_TMP0, a1);
1671139c1837SPaolo Bonzini
1672139c1837SPaolo Bonzini        if (const_b) {
1673139c1837SPaolo Bonzini            if (b == -1) {
1674139c1837SPaolo Bonzini                b = TCG_REG_XZR;
1675139c1837SPaolo Bonzini                sel = I3506_CSINV;
1676139c1837SPaolo Bonzini            } else if (b == 0) {
1677139c1837SPaolo Bonzini                b = TCG_REG_XZR;
1678139c1837SPaolo Bonzini            } else {
1679139c1837SPaolo Bonzini                tcg_out_movi(s, ext, d, b);
1680139c1837SPaolo Bonzini                b = d;
1681139c1837SPaolo Bonzini            }
1682139c1837SPaolo Bonzini        }
1683d67bcbddSRichard Henderson        tcg_out_insn_3506(s, sel, ext, d, TCG_REG_TMP0, b, TCG_COND_NE);
1684139c1837SPaolo Bonzini    }
1685139c1837SPaolo Bonzini}
1686139c1837SPaolo Bonzini
16877f65be51SRichard Hendersontypedef struct {
16887f65be51SRichard Henderson    TCGReg base;
16897f65be51SRichard Henderson    TCGReg index;
16907f65be51SRichard Henderson    TCGType index_ext;
169164741d99SRichard Henderson    TCGAtomAlign aa;
16927f65be51SRichard Henderson} HostAddress;
16937f65be51SRichard Henderson
16947b880107SRichard Hendersonbool tcg_target_has_memory_bswap(MemOp memop)
16957b880107SRichard Henderson{
16967b880107SRichard Henderson    return false;
16977b880107SRichard Henderson}
16987b880107SRichard Henderson
16996e96422bSRichard Hendersonstatic const TCGLdstHelperParam ldst_helper_param = {
1700d67bcbddSRichard Henderson    .ntmp = 1, .tmp = { TCG_REG_TMP0 }
17016e96422bSRichard Henderson};
17026e96422bSRichard Henderson
1703139c1837SPaolo Bonzinistatic bool tcg_out_qemu_ld_slow_path(TCGContext *s, TCGLabelQemuLdst *lb)
1704139c1837SPaolo Bonzini{
17056e96422bSRichard Henderson    MemOp opc = get_memop(lb->oi);
1706139c1837SPaolo Bonzini
1707ffba3eb3SRichard Henderson    if (!reloc_pc19(lb->label_ptr[0], tcg_splitwx_to_rx(s->code_ptr))) {
1708139c1837SPaolo Bonzini        return false;
1709139c1837SPaolo Bonzini    }
1710139c1837SPaolo Bonzini
17116e96422bSRichard Henderson    tcg_out_ld_helper_args(s, lb, &ldst_helper_param);
1712cee44b03SRichard Henderson    tcg_out_call_int(s, qemu_ld_helpers[opc & MO_SIZE]);
17136e96422bSRichard Henderson    tcg_out_ld_helper_ret(s, lb, false, &ldst_helper_param);
1714139c1837SPaolo Bonzini    tcg_out_goto(s, lb->raddr);
1715139c1837SPaolo Bonzini    return true;
1716139c1837SPaolo Bonzini}
1717139c1837SPaolo Bonzini
1718139c1837SPaolo Bonzinistatic bool tcg_out_qemu_st_slow_path(TCGContext *s, TCGLabelQemuLdst *lb)
1719139c1837SPaolo Bonzini{
17206e96422bSRichard Henderson    MemOp opc = get_memop(lb->oi);
1721139c1837SPaolo Bonzini
1722ffba3eb3SRichard Henderson    if (!reloc_pc19(lb->label_ptr[0], tcg_splitwx_to_rx(s->code_ptr))) {
1723139c1837SPaolo Bonzini        return false;
1724139c1837SPaolo Bonzini    }
1725139c1837SPaolo Bonzini
17266e96422bSRichard Henderson    tcg_out_st_helper_args(s, lb, &ldst_helper_param);
1727cee44b03SRichard Henderson    tcg_out_call_int(s, qemu_st_helpers[opc & MO_SIZE]);
1728139c1837SPaolo Bonzini    tcg_out_goto(s, lb->raddr);
1729139c1837SPaolo Bonzini    return true;
1730139c1837SPaolo Bonzini}
1731139c1837SPaolo Bonzini
1732d0a9bb5eSRichard Henderson/* We expect to use a 7-bit scaled negative offset from ENV.  */
1733d0a9bb5eSRichard Henderson#define MIN_TLB_MASK_TABLE_OFS  -512
1734d0a9bb5eSRichard Henderson
17351e612dd6SRichard Henderson/*
17367893e42dSPhilippe Mathieu-Daudé * For system-mode, perform the TLB load and compare.
17377893e42dSPhilippe Mathieu-Daudé * For user-mode, perform any required alignment tests.
17381e612dd6SRichard Henderson * In both cases, return a TCGLabelQemuLdst structure if the slow path
17391e612dd6SRichard Henderson * is required and fill in @h with the host address for the fast path.
17401e612dd6SRichard Henderson */
17411e612dd6SRichard Hendersonstatic TCGLabelQemuLdst *prepare_host_addr(TCGContext *s, HostAddress *h,
17421e612dd6SRichard Henderson                                           TCGReg addr_reg, MemOpIdx oi,
17431e612dd6SRichard Henderson                                           bool is_ld)
17441e612dd6SRichard Henderson{
174560c452a1SRichard Henderson    TCGType addr_type = s->addr_type;
17461e612dd6SRichard Henderson    TCGLabelQemuLdst *ldst = NULL;
17471e612dd6SRichard Henderson    MemOp opc = get_memop(oi);
1748929124ecSRichard Henderson    MemOp s_bits = opc & MO_SIZE;
174964741d99SRichard Henderson    unsigned a_mask;
175064741d99SRichard Henderson
175164741d99SRichard Henderson    h->aa = atom_and_align_for_opc(s, opc,
175264741d99SRichard Henderson                                   have_lse2 ? MO_ATOM_WITHIN16
175364741d99SRichard Henderson                                             : MO_ATOM_IFALIGN,
1754929124ecSRichard Henderson                                   s_bits == MO_128);
175564741d99SRichard Henderson    a_mask = (1 << h->aa.align) - 1;
17561e612dd6SRichard Henderson
1757e2b7a40dSRichard Henderson    if (tcg_use_softmmu) {
17581e612dd6SRichard Henderson        unsigned s_mask = (1u << s_bits) - 1;
17591e612dd6SRichard Henderson        unsigned mem_index = get_mmuidx(oi);
1760285a691fSRichard Henderson        TCGReg addr_adj;
17611e612dd6SRichard Henderson        TCGType mask_type;
17621e612dd6SRichard Henderson        uint64_t compare_mask;
17631e612dd6SRichard Henderson
17641e612dd6SRichard Henderson        ldst = new_ldst_label(s);
17651e612dd6SRichard Henderson        ldst->is_ld = is_ld;
17661e612dd6SRichard Henderson        ldst->oi = oi;
17671e612dd6SRichard Henderson        ldst->addrlo_reg = addr_reg;
17681e612dd6SRichard Henderson
1769a66efde1SRichard Henderson        mask_type = (s->page_bits + s->tlb_dyn_max_bits > 32
17701e612dd6SRichard Henderson                     ? TCG_TYPE_I64 : TCG_TYPE_I32);
17711e612dd6SRichard Henderson
1772623912ccSAnton Johansson        /* Load cpu->neg.tlb.f[mmu_idx].{mask,table} into {tmp0,tmp1}. */
17731e612dd6SRichard Henderson        QEMU_BUILD_BUG_ON(offsetof(CPUTLBDescFast, mask) != 0);
17741e612dd6SRichard Henderson        QEMU_BUILD_BUG_ON(offsetof(CPUTLBDescFast, table) != 8);
1775285a691fSRichard Henderson        tcg_out_insn(s, 3314, LDP, TCG_REG_TMP0, TCG_REG_TMP1, TCG_AREG0,
1776d0a9bb5eSRichard Henderson                     tlb_mask_table_ofs(s, mem_index), 1, 0);
17771e612dd6SRichard Henderson
17781e612dd6SRichard Henderson        /* Extract the TLB index from the address into X0.  */
17791e612dd6SRichard Henderson        tcg_out_insn(s, 3502S, AND_LSR, mask_type == TCG_TYPE_I64,
1780285a691fSRichard Henderson                     TCG_REG_TMP0, TCG_REG_TMP0, addr_reg,
1781aece72b7SRichard Henderson                     s->page_bits - CPU_TLB_ENTRY_BITS);
17821e612dd6SRichard Henderson
1783e2b7a40dSRichard Henderson        /* Add the tlb_table pointer, forming the CPUTLBEntry address. */
1784285a691fSRichard Henderson        tcg_out_insn(s, 3502, ADD, 1, TCG_REG_TMP1, TCG_REG_TMP1, TCG_REG_TMP0);
17851e612dd6SRichard Henderson
1786e2b7a40dSRichard Henderson        /* Load the tlb comparator into TMP0, and the fast path addend. */
1787238f4380SRichard Henderson        QEMU_BUILD_BUG_ON(HOST_BIG_ENDIAN);
1788285a691fSRichard Henderson        tcg_out_ld(s, addr_type, TCG_REG_TMP0, TCG_REG_TMP1,
17891e612dd6SRichard Henderson                   is_ld ? offsetof(CPUTLBEntry, addr_read)
17901e612dd6SRichard Henderson                         : offsetof(CPUTLBEntry, addr_write));
1791285a691fSRichard Henderson        tcg_out_ld(s, TCG_TYPE_PTR, TCG_REG_TMP1, TCG_REG_TMP1,
17921e612dd6SRichard Henderson                   offsetof(CPUTLBEntry, addend));
17931e612dd6SRichard Henderson
17941e612dd6SRichard Henderson        /*
1795e2b7a40dSRichard Henderson         * For aligned accesses, we check the first byte and include
1796e2b7a40dSRichard Henderson         * the alignment bits within the address.  For unaligned access,
1797e2b7a40dSRichard Henderson         * we check that we don't cross pages using the address of the
1798e2b7a40dSRichard Henderson         * last byte of the access.
17991e612dd6SRichard Henderson         */
180064741d99SRichard Henderson        if (a_mask >= s_mask) {
1801285a691fSRichard Henderson            addr_adj = addr_reg;
18021e612dd6SRichard Henderson        } else {
1803285a691fSRichard Henderson            addr_adj = TCG_REG_TMP2;
180460c452a1SRichard Henderson            tcg_out_insn(s, 3401, ADDI, addr_type,
1805285a691fSRichard Henderson                         addr_adj, addr_reg, s_mask - a_mask);
18061e612dd6SRichard Henderson        }
1807aece72b7SRichard Henderson        compare_mask = (uint64_t)s->page_mask | a_mask;
18081e612dd6SRichard Henderson
1809285a691fSRichard Henderson        /* Store the page mask part of the address into TMP2.  */
1810285a691fSRichard Henderson        tcg_out_logicali(s, I3404_ANDI, addr_type, TCG_REG_TMP2,
1811285a691fSRichard Henderson                         addr_adj, compare_mask);
18121e612dd6SRichard Henderson
18131e612dd6SRichard Henderson        /* Perform the address comparison. */
1814339adf2fSRichard Henderson        tcg_out_cmp(s, addr_type, TCG_COND_NE, TCG_REG_TMP0, TCG_REG_TMP2, 0);
18151e612dd6SRichard Henderson
18161e612dd6SRichard Henderson        /* If not equal, we jump to the slow path. */
18171e612dd6SRichard Henderson        ldst->label_ptr[0] = s->code_ptr;
18181e612dd6SRichard Henderson        tcg_out_insn(s, 3202, B_C, TCG_COND_NE, 0);
18191e612dd6SRichard Henderson
1820285a691fSRichard Henderson        h->base = TCG_REG_TMP1;
182164741d99SRichard Henderson        h->index = addr_reg;
182264741d99SRichard Henderson        h->index_ext = addr_type;
1823e2b7a40dSRichard Henderson    } else {
18241e612dd6SRichard Henderson        if (a_mask) {
18251e612dd6SRichard Henderson            ldst = new_ldst_label(s);
18261e612dd6SRichard Henderson
18271e612dd6SRichard Henderson            ldst->is_ld = is_ld;
18281e612dd6SRichard Henderson            ldst->oi = oi;
18291e612dd6SRichard Henderson            ldst->addrlo_reg = addr_reg;
18301e612dd6SRichard Henderson
18311e612dd6SRichard Henderson            /* tst addr, #mask */
18321e612dd6SRichard Henderson            tcg_out_logicali(s, I3404_ANDSI, 0, TCG_REG_XZR, addr_reg, a_mask);
18331e612dd6SRichard Henderson
18341e612dd6SRichard Henderson            /* b.ne slow_path */
18351e612dd6SRichard Henderson            ldst->label_ptr[0] = s->code_ptr;
18361e612dd6SRichard Henderson            tcg_out_insn(s, 3202, B_C, TCG_COND_NE, 0);
18371e612dd6SRichard Henderson        }
18381e612dd6SRichard Henderson
183952533157SRichard Henderson        if (guest_base || addr_type == TCG_TYPE_I32) {
184064741d99SRichard Henderson            h->base = TCG_REG_GUEST_BASE;
184164741d99SRichard Henderson            h->index = addr_reg;
184264741d99SRichard Henderson            h->index_ext = addr_type;
18431e612dd6SRichard Henderson        } else {
184464741d99SRichard Henderson            h->base = addr_reg;
184564741d99SRichard Henderson            h->index = TCG_REG_XZR;
184664741d99SRichard Henderson            h->index_ext = TCG_TYPE_I64;
18471e612dd6SRichard Henderson        }
1848e2b7a40dSRichard Henderson    }
18491e612dd6SRichard Henderson
18501e612dd6SRichard Henderson    return ldst;
18511e612dd6SRichard Henderson}
18521e612dd6SRichard Henderson
1853139c1837SPaolo Bonzinistatic void tcg_out_qemu_ld_direct(TCGContext *s, MemOp memop, TCGType ext,
18547f65be51SRichard Henderson                                   TCGReg data_r, HostAddress h)
1855139c1837SPaolo Bonzini{
1856139c1837SPaolo Bonzini    switch (memop & MO_SSIZE) {
1857139c1837SPaolo Bonzini    case MO_UB:
18587f65be51SRichard Henderson        tcg_out_ldst_r(s, I3312_LDRB, data_r, h.base, h.index_ext, h.index);
1859139c1837SPaolo Bonzini        break;
1860139c1837SPaolo Bonzini    case MO_SB:
1861139c1837SPaolo Bonzini        tcg_out_ldst_r(s, ext ? I3312_LDRSBX : I3312_LDRSBW,
18627f65be51SRichard Henderson                       data_r, h.base, h.index_ext, h.index);
1863139c1837SPaolo Bonzini        break;
1864139c1837SPaolo Bonzini    case MO_UW:
18657f65be51SRichard Henderson        tcg_out_ldst_r(s, I3312_LDRH, data_r, h.base, h.index_ext, h.index);
1866139c1837SPaolo Bonzini        break;
1867139c1837SPaolo Bonzini    case MO_SW:
1868139c1837SPaolo Bonzini        tcg_out_ldst_r(s, (ext ? I3312_LDRSHX : I3312_LDRSHW),
18697f65be51SRichard Henderson                       data_r, h.base, h.index_ext, h.index);
1870139c1837SPaolo Bonzini        break;
1871139c1837SPaolo Bonzini    case MO_UL:
18727f65be51SRichard Henderson        tcg_out_ldst_r(s, I3312_LDRW, data_r, h.base, h.index_ext, h.index);
1873139c1837SPaolo Bonzini        break;
1874139c1837SPaolo Bonzini    case MO_SL:
18757f65be51SRichard Henderson        tcg_out_ldst_r(s, I3312_LDRSWX, data_r, h.base, h.index_ext, h.index);
1876139c1837SPaolo Bonzini        break;
1877fc313c64SFrédéric Pétrot    case MO_UQ:
18787f65be51SRichard Henderson        tcg_out_ldst_r(s, I3312_LDRX, data_r, h.base, h.index_ext, h.index);
1879139c1837SPaolo Bonzini        break;
1880139c1837SPaolo Bonzini    default:
1881732e89f4SRichard Henderson        g_assert_not_reached();
1882139c1837SPaolo Bonzini    }
1883139c1837SPaolo Bonzini}
1884139c1837SPaolo Bonzini
1885139c1837SPaolo Bonzinistatic void tcg_out_qemu_st_direct(TCGContext *s, MemOp memop,
18867f65be51SRichard Henderson                                   TCGReg data_r, HostAddress h)
1887139c1837SPaolo Bonzini{
1888139c1837SPaolo Bonzini    switch (memop & MO_SIZE) {
1889139c1837SPaolo Bonzini    case MO_8:
18907f65be51SRichard Henderson        tcg_out_ldst_r(s, I3312_STRB, data_r, h.base, h.index_ext, h.index);
1891139c1837SPaolo Bonzini        break;
1892139c1837SPaolo Bonzini    case MO_16:
18937f65be51SRichard Henderson        tcg_out_ldst_r(s, I3312_STRH, data_r, h.base, h.index_ext, h.index);
1894139c1837SPaolo Bonzini        break;
1895139c1837SPaolo Bonzini    case MO_32:
18967f65be51SRichard Henderson        tcg_out_ldst_r(s, I3312_STRW, data_r, h.base, h.index_ext, h.index);
1897139c1837SPaolo Bonzini        break;
1898139c1837SPaolo Bonzini    case MO_64:
18997f65be51SRichard Henderson        tcg_out_ldst_r(s, I3312_STRX, data_r, h.base, h.index_ext, h.index);
1900139c1837SPaolo Bonzini        break;
1901139c1837SPaolo Bonzini    default:
1902732e89f4SRichard Henderson        g_assert_not_reached();
1903139c1837SPaolo Bonzini    }
1904139c1837SPaolo Bonzini}
1905139c1837SPaolo Bonzini
1906139c1837SPaolo Bonzinistatic void tcg_out_qemu_ld(TCGContext *s, TCGReg data_reg, TCGReg addr_reg,
1907ff0cc85eSRichard Henderson                            MemOpIdx oi, TCGType data_type)
1908139c1837SPaolo Bonzini{
19091e612dd6SRichard Henderson    TCGLabelQemuLdst *ldst;
19107f65be51SRichard Henderson    HostAddress h;
1911f85ab3d2SRichard Henderson
19121e612dd6SRichard Henderson    ldst = prepare_host_addr(s, &h, addr_reg, oi, true);
19131e612dd6SRichard Henderson    tcg_out_qemu_ld_direct(s, get_memop(oi), data_type, data_reg, h);
1914f85ab3d2SRichard Henderson
19151e612dd6SRichard Henderson    if (ldst) {
19161e612dd6SRichard Henderson        ldst->type = data_type;
19171e612dd6SRichard Henderson        ldst->datalo_reg = data_reg;
19181e612dd6SRichard Henderson        ldst->raddr = tcg_splitwx_to_rx(s->code_ptr);
1919f85ab3d2SRichard Henderson    }
1920139c1837SPaolo Bonzini}
1921139c1837SPaolo Bonzini
1922139c1837SPaolo Bonzinistatic void tcg_out_qemu_st(TCGContext *s, TCGReg data_reg, TCGReg addr_reg,
1923ff0cc85eSRichard Henderson                            MemOpIdx oi, TCGType data_type)
1924139c1837SPaolo Bonzini{
19251e612dd6SRichard Henderson    TCGLabelQemuLdst *ldst;
19267f65be51SRichard Henderson    HostAddress h;
1927f85ab3d2SRichard Henderson
19281e612dd6SRichard Henderson    ldst = prepare_host_addr(s, &h, addr_reg, oi, false);
19291e612dd6SRichard Henderson    tcg_out_qemu_st_direct(s, get_memop(oi), data_reg, h);
1930f85ab3d2SRichard Henderson
19311e612dd6SRichard Henderson    if (ldst) {
19321e612dd6SRichard Henderson        ldst->type = data_type;
19331e612dd6SRichard Henderson        ldst->datalo_reg = data_reg;
19341e612dd6SRichard Henderson        ldst->raddr = tcg_splitwx_to_rx(s->code_ptr);
1935f85ab3d2SRichard Henderson    }
1936139c1837SPaolo Bonzini}
1937139c1837SPaolo Bonzini
1938929124ecSRichard Hendersonstatic void tcg_out_qemu_ldst_i128(TCGContext *s, TCGReg datalo, TCGReg datahi,
1939929124ecSRichard Henderson                                   TCGReg addr_reg, MemOpIdx oi, bool is_ld)
1940929124ecSRichard Henderson{
1941929124ecSRichard Henderson    TCGLabelQemuLdst *ldst;
1942929124ecSRichard Henderson    HostAddress h;
1943929124ecSRichard Henderson    TCGReg base;
1944929124ecSRichard Henderson    bool use_pair;
1945929124ecSRichard Henderson
1946929124ecSRichard Henderson    ldst = prepare_host_addr(s, &h, addr_reg, oi, is_ld);
1947929124ecSRichard Henderson
1948929124ecSRichard Henderson    /* Compose the final address, as LDP/STP have no indexing. */
1949929124ecSRichard Henderson    if (h.index == TCG_REG_XZR) {
1950929124ecSRichard Henderson        base = h.base;
1951929124ecSRichard Henderson    } else {
1952929124ecSRichard Henderson        base = TCG_REG_TMP2;
1953929124ecSRichard Henderson        if (h.index_ext == TCG_TYPE_I32) {
1954929124ecSRichard Henderson            /* add base, base, index, uxtw */
1955929124ecSRichard Henderson            tcg_out_insn(s, 3501, ADD, TCG_TYPE_I64, base,
1956929124ecSRichard Henderson                         h.base, h.index, MO_32, 0);
1957929124ecSRichard Henderson        } else {
1958929124ecSRichard Henderson            /* add base, base, index */
1959929124ecSRichard Henderson            tcg_out_insn(s, 3502, ADD, 1, base, h.base, h.index);
1960929124ecSRichard Henderson        }
1961929124ecSRichard Henderson    }
1962929124ecSRichard Henderson
1963929124ecSRichard Henderson    use_pair = h.aa.atom < MO_128 || have_lse2;
1964929124ecSRichard Henderson
1965929124ecSRichard Henderson    if (!use_pair) {
1966929124ecSRichard Henderson        tcg_insn_unit *branch = NULL;
1967929124ecSRichard Henderson        TCGReg ll, lh, sl, sh;
1968929124ecSRichard Henderson
1969929124ecSRichard Henderson        /*
1970929124ecSRichard Henderson         * If we have already checked for 16-byte alignment, that's all
1971929124ecSRichard Henderson         * we need. Otherwise we have determined that misaligned atomicity
1972929124ecSRichard Henderson         * may be handled with two 8-byte loads.
1973929124ecSRichard Henderson         */
1974929124ecSRichard Henderson        if (h.aa.align < MO_128) {
1975929124ecSRichard Henderson            /*
1976929124ecSRichard Henderson             * TODO: align should be MO_64, so we only need test bit 3,
1977929124ecSRichard Henderson             * which means we could use TBNZ instead of ANDS+B_C.
1978929124ecSRichard Henderson             */
1979929124ecSRichard Henderson            tcg_out_logicali(s, I3404_ANDSI, 0, TCG_REG_XZR, addr_reg, 15);
1980929124ecSRichard Henderson            branch = s->code_ptr;
1981929124ecSRichard Henderson            tcg_out_insn(s, 3202, B_C, TCG_COND_NE, 0);
1982929124ecSRichard Henderson            use_pair = true;
1983929124ecSRichard Henderson        }
1984929124ecSRichard Henderson
1985929124ecSRichard Henderson        if (is_ld) {
1986929124ecSRichard Henderson            /*
1987929124ecSRichard Henderson             * 16-byte atomicity without LSE2 requires LDXP+STXP loop:
1988929124ecSRichard Henderson             *    ldxp lo, hi, [base]
1989929124ecSRichard Henderson             *    stxp t0, lo, hi, [base]
1990929124ecSRichard Henderson             *    cbnz t0, .-8
1991929124ecSRichard Henderson             * Require no overlap between data{lo,hi} and base.
1992929124ecSRichard Henderson             */
1993929124ecSRichard Henderson            if (datalo == base || datahi == base) {
1994929124ecSRichard Henderson                tcg_out_mov(s, TCG_TYPE_REG, TCG_REG_TMP2, base);
1995929124ecSRichard Henderson                base = TCG_REG_TMP2;
1996929124ecSRichard Henderson            }
1997929124ecSRichard Henderson            ll = sl = datalo;
1998929124ecSRichard Henderson            lh = sh = datahi;
1999929124ecSRichard Henderson        } else {
2000929124ecSRichard Henderson            /*
2001929124ecSRichard Henderson             * 16-byte atomicity without LSE2 requires LDXP+STXP loop:
2002929124ecSRichard Henderson             * 1: ldxp t0, t1, [base]
2003929124ecSRichard Henderson             *    stxp t0, lo, hi, [base]
2004929124ecSRichard Henderson             *    cbnz t0, 1b
2005929124ecSRichard Henderson             */
2006929124ecSRichard Henderson            tcg_debug_assert(base != TCG_REG_TMP0 && base != TCG_REG_TMP1);
2007929124ecSRichard Henderson            ll = TCG_REG_TMP0;
2008929124ecSRichard Henderson            lh = TCG_REG_TMP1;
2009929124ecSRichard Henderson            sl = datalo;
2010929124ecSRichard Henderson            sh = datahi;
2011929124ecSRichard Henderson        }
2012929124ecSRichard Henderson
2013929124ecSRichard Henderson        tcg_out_insn(s, 3306, LDXP, TCG_REG_XZR, ll, lh, base);
2014929124ecSRichard Henderson        tcg_out_insn(s, 3306, STXP, TCG_REG_TMP0, sl, sh, base);
2015929124ecSRichard Henderson        tcg_out_insn(s, 3201, CBNZ, 0, TCG_REG_TMP0, -2);
2016929124ecSRichard Henderson
2017929124ecSRichard Henderson        if (use_pair) {
2018929124ecSRichard Henderson            /* "b .+8", branching across the one insn of use_pair. */
2019929124ecSRichard Henderson            tcg_out_insn(s, 3206, B, 2);
2020929124ecSRichard Henderson            reloc_pc19(branch, tcg_splitwx_to_rx(s->code_ptr));
2021929124ecSRichard Henderson        }
2022929124ecSRichard Henderson    }
2023929124ecSRichard Henderson
2024929124ecSRichard Henderson    if (use_pair) {
2025929124ecSRichard Henderson        if (is_ld) {
2026929124ecSRichard Henderson            tcg_out_insn(s, 3314, LDP, datalo, datahi, base, 0, 1, 0);
2027929124ecSRichard Henderson        } else {
2028929124ecSRichard Henderson            tcg_out_insn(s, 3314, STP, datalo, datahi, base, 0, 1, 0);
2029929124ecSRichard Henderson        }
2030929124ecSRichard Henderson    }
2031929124ecSRichard Henderson
2032929124ecSRichard Henderson    if (ldst) {
2033929124ecSRichard Henderson        ldst->type = TCG_TYPE_I128;
2034929124ecSRichard Henderson        ldst->datalo_reg = datalo;
2035929124ecSRichard Henderson        ldst->datahi_reg = datahi;
2036929124ecSRichard Henderson        ldst->raddr = tcg_splitwx_to_rx(s->code_ptr);
2037929124ecSRichard Henderson    }
2038929124ecSRichard Henderson}
2039929124ecSRichard Henderson
2040ffba3eb3SRichard Hendersonstatic const tcg_insn_unit *tb_ret_addr;
2041139c1837SPaolo Bonzini
2042b55a8d9dSRichard Hendersonstatic void tcg_out_exit_tb(TCGContext *s, uintptr_t a0)
2043b55a8d9dSRichard Henderson{
20445826a0dbSRichard Henderson    const tcg_insn_unit *target;
20455826a0dbSRichard Henderson    ptrdiff_t offset;
20465826a0dbSRichard Henderson
2047b55a8d9dSRichard Henderson    /* Reuse the zeroing that exists for goto_ptr.  */
2048b55a8d9dSRichard Henderson    if (a0 == 0) {
20495826a0dbSRichard Henderson        target = tcg_code_gen_epilogue;
2050b55a8d9dSRichard Henderson    } else {
2051b55a8d9dSRichard Henderson        tcg_out_movi(s, TCG_TYPE_I64, TCG_REG_X0, a0);
20525826a0dbSRichard Henderson        target = tb_ret_addr;
20535826a0dbSRichard Henderson    }
20545826a0dbSRichard Henderson
20555826a0dbSRichard Henderson    offset = tcg_pcrel_diff(s, target) >> 2;
20565826a0dbSRichard Henderson    if (offset == sextract64(offset, 0, 26)) {
20575826a0dbSRichard Henderson        tcg_out_insn(s, 3206, B, offset);
20585826a0dbSRichard Henderson    } else {
20595826a0dbSRichard Henderson        /*
20605826a0dbSRichard Henderson         * Only x16/x17 generate BTI type Jump (2),
20615826a0dbSRichard Henderson         * other registers generate BTI type Jump|Call (3).
20625826a0dbSRichard Henderson         */
20635826a0dbSRichard Henderson        QEMU_BUILD_BUG_ON(TCG_REG_TMP0 != TCG_REG_X16);
20645826a0dbSRichard Henderson        tcg_out_movi(s, TCG_TYPE_I64, TCG_REG_TMP0, (intptr_t)target);
20655826a0dbSRichard Henderson        tcg_out_insn(s, 3207, BR, TCG_REG_TMP0);
2066b55a8d9dSRichard Henderson    }
2067b55a8d9dSRichard Henderson}
2068b55a8d9dSRichard Henderson
2069cf7d6b8eSRichard Hendersonstatic void tcg_out_goto_tb(TCGContext *s, int which)
2070cf7d6b8eSRichard Henderson{
2071cf7d6b8eSRichard Henderson    /*
2072d59d83a1SRichard Henderson     * Direct branch, or indirect address load, will be patched
2073d59d83a1SRichard Henderson     * by tb_target_set_jmp_target.  Assert indirect load offset
2074d59d83a1SRichard Henderson     * in range early, regardless of direct branch distance.
2075cf7d6b8eSRichard Henderson     */
2076d59d83a1SRichard Henderson    intptr_t i_off = tcg_pcrel_diff(s, (void *)get_jmp_target_addr(s, which));
2077d59d83a1SRichard Henderson    tcg_debug_assert(i_off == sextract64(i_off, 0, 21));
2078d59d83a1SRichard Henderson
2079cf7d6b8eSRichard Henderson    set_jmp_insn_offset(s, which);
2080d59d83a1SRichard Henderson    tcg_out32(s, I3206_B);
2081d67bcbddSRichard Henderson    tcg_out_insn(s, 3207, BR, TCG_REG_TMP0);
2082cf7d6b8eSRichard Henderson    set_jmp_reset_offset(s, which);
20835826a0dbSRichard Henderson    tcg_out_bti(s, BTI_J);
2084cf7d6b8eSRichard Henderson}
2085cf7d6b8eSRichard Henderson
2086d59d83a1SRichard Hendersonvoid tb_target_set_jmp_target(const TranslationBlock *tb, int n,
2087d59d83a1SRichard Henderson                              uintptr_t jmp_rx, uintptr_t jmp_rw)
2088d59d83a1SRichard Henderson{
2089d59d83a1SRichard Henderson    uintptr_t d_addr = tb->jmp_target_addr[n];
2090d59d83a1SRichard Henderson    ptrdiff_t d_offset = d_addr - jmp_rx;
2091d59d83a1SRichard Henderson    tcg_insn_unit insn;
2092d59d83a1SRichard Henderson
2093d59d83a1SRichard Henderson    /* Either directly branch, or indirect branch load. */
2094d59d83a1SRichard Henderson    if (d_offset == sextract64(d_offset, 0, 28)) {
2095d59d83a1SRichard Henderson        insn = deposit32(I3206_B, 0, 26, d_offset >> 2);
2096d59d83a1SRichard Henderson    } else {
2097d59d83a1SRichard Henderson        uintptr_t i_addr = (uintptr_t)&tb->jmp_target_addr[n];
2098d59d83a1SRichard Henderson        ptrdiff_t i_offset = i_addr - jmp_rx;
2099d59d83a1SRichard Henderson
2100d59d83a1SRichard Henderson        /* Note that we asserted this in range in tcg_out_goto_tb. */
2101d67bcbddSRichard Henderson        insn = deposit32(I3305_LDR | TCG_REG_TMP0, 5, 19, i_offset >> 2);
2102d59d83a1SRichard Henderson    }
2103d59d83a1SRichard Henderson    qatomic_set((uint32_t *)jmp_rw, insn);
2104d59d83a1SRichard Henderson    flush_idcache_range(jmp_rx, jmp_rw, 4);
2105d59d83a1SRichard Henderson}
2106d59d83a1SRichard Henderson
2107139c1837SPaolo Bonzinistatic void tcg_out_op(TCGContext *s, TCGOpcode opc,
2108139c1837SPaolo Bonzini                       const TCGArg args[TCG_MAX_OP_ARGS],
2109139c1837SPaolo Bonzini                       const int const_args[TCG_MAX_OP_ARGS])
2110139c1837SPaolo Bonzini{
2111139c1837SPaolo Bonzini    /* 99% of the time, we can signal the use of extension registers
2112139c1837SPaolo Bonzini       by looking to see if the opcode handles 64-bit data.  */
2113139c1837SPaolo Bonzini    TCGType ext = (tcg_op_defs[opc].flags & TCG_OPF_64BIT) != 0;
2114139c1837SPaolo Bonzini
2115139c1837SPaolo Bonzini    /* Hoist the loads of the most common arguments.  */
2116139c1837SPaolo Bonzini    TCGArg a0 = args[0];
2117139c1837SPaolo Bonzini    TCGArg a1 = args[1];
2118139c1837SPaolo Bonzini    TCGArg a2 = args[2];
2119139c1837SPaolo Bonzini    int c2 = const_args[2];
2120139c1837SPaolo Bonzini
2121139c1837SPaolo Bonzini    /* Some operands are defined with "rZ" constraint, a register or
2122139c1837SPaolo Bonzini       the zero register.  These need not actually test args[I] == 0.  */
2123139c1837SPaolo Bonzini#define REG0(I)  (const_args[I] ? TCG_REG_XZR : (TCGReg)args[I])
2124139c1837SPaolo Bonzini
2125139c1837SPaolo Bonzini    switch (opc) {
2126139c1837SPaolo Bonzini    case INDEX_op_goto_ptr:
2127139c1837SPaolo Bonzini        tcg_out_insn(s, 3207, BR, a0);
2128139c1837SPaolo Bonzini        break;
2129139c1837SPaolo Bonzini
2130139c1837SPaolo Bonzini    case INDEX_op_br:
2131139c1837SPaolo Bonzini        tcg_out_goto_label(s, arg_label(a0));
2132139c1837SPaolo Bonzini        break;
2133139c1837SPaolo Bonzini
2134139c1837SPaolo Bonzini    case INDEX_op_ld8u_i32:
2135139c1837SPaolo Bonzini    case INDEX_op_ld8u_i64:
2136139c1837SPaolo Bonzini        tcg_out_ldst(s, I3312_LDRB, a0, a1, a2, 0);
2137139c1837SPaolo Bonzini        break;
2138139c1837SPaolo Bonzini    case INDEX_op_ld8s_i32:
2139139c1837SPaolo Bonzini        tcg_out_ldst(s, I3312_LDRSBW, a0, a1, a2, 0);
2140139c1837SPaolo Bonzini        break;
2141139c1837SPaolo Bonzini    case INDEX_op_ld8s_i64:
2142139c1837SPaolo Bonzini        tcg_out_ldst(s, I3312_LDRSBX, a0, a1, a2, 0);
2143139c1837SPaolo Bonzini        break;
2144139c1837SPaolo Bonzini    case INDEX_op_ld16u_i32:
2145139c1837SPaolo Bonzini    case INDEX_op_ld16u_i64:
2146139c1837SPaolo Bonzini        tcg_out_ldst(s, I3312_LDRH, a0, a1, a2, 1);
2147139c1837SPaolo Bonzini        break;
2148139c1837SPaolo Bonzini    case INDEX_op_ld16s_i32:
2149139c1837SPaolo Bonzini        tcg_out_ldst(s, I3312_LDRSHW, a0, a1, a2, 1);
2150139c1837SPaolo Bonzini        break;
2151139c1837SPaolo Bonzini    case INDEX_op_ld16s_i64:
2152139c1837SPaolo Bonzini        tcg_out_ldst(s, I3312_LDRSHX, a0, a1, a2, 1);
2153139c1837SPaolo Bonzini        break;
2154139c1837SPaolo Bonzini    case INDEX_op_ld_i32:
2155139c1837SPaolo Bonzini    case INDEX_op_ld32u_i64:
2156139c1837SPaolo Bonzini        tcg_out_ldst(s, I3312_LDRW, a0, a1, a2, 2);
2157139c1837SPaolo Bonzini        break;
2158139c1837SPaolo Bonzini    case INDEX_op_ld32s_i64:
2159139c1837SPaolo Bonzini        tcg_out_ldst(s, I3312_LDRSWX, a0, a1, a2, 2);
2160139c1837SPaolo Bonzini        break;
2161139c1837SPaolo Bonzini    case INDEX_op_ld_i64:
2162139c1837SPaolo Bonzini        tcg_out_ldst(s, I3312_LDRX, a0, a1, a2, 3);
2163139c1837SPaolo Bonzini        break;
2164139c1837SPaolo Bonzini
2165139c1837SPaolo Bonzini    case INDEX_op_st8_i32:
2166139c1837SPaolo Bonzini    case INDEX_op_st8_i64:
2167139c1837SPaolo Bonzini        tcg_out_ldst(s, I3312_STRB, REG0(0), a1, a2, 0);
2168139c1837SPaolo Bonzini        break;
2169139c1837SPaolo Bonzini    case INDEX_op_st16_i32:
2170139c1837SPaolo Bonzini    case INDEX_op_st16_i64:
2171139c1837SPaolo Bonzini        tcg_out_ldst(s, I3312_STRH, REG0(0), a1, a2, 1);
2172139c1837SPaolo Bonzini        break;
2173139c1837SPaolo Bonzini    case INDEX_op_st_i32:
2174139c1837SPaolo Bonzini    case INDEX_op_st32_i64:
2175139c1837SPaolo Bonzini        tcg_out_ldst(s, I3312_STRW, REG0(0), a1, a2, 2);
2176139c1837SPaolo Bonzini        break;
2177139c1837SPaolo Bonzini    case INDEX_op_st_i64:
2178139c1837SPaolo Bonzini        tcg_out_ldst(s, I3312_STRX, REG0(0), a1, a2, 3);
2179139c1837SPaolo Bonzini        break;
2180139c1837SPaolo Bonzini
2181139c1837SPaolo Bonzini    case INDEX_op_add_i32:
2182139c1837SPaolo Bonzini        a2 = (int32_t)a2;
2183139c1837SPaolo Bonzini        /* FALLTHRU */
2184139c1837SPaolo Bonzini    case INDEX_op_add_i64:
2185139c1837SPaolo Bonzini        if (c2) {
2186139c1837SPaolo Bonzini            tcg_out_addsubi(s, ext, a0, a1, a2);
2187139c1837SPaolo Bonzini        } else {
2188139c1837SPaolo Bonzini            tcg_out_insn(s, 3502, ADD, ext, a0, a1, a2);
2189139c1837SPaolo Bonzini        }
2190139c1837SPaolo Bonzini        break;
2191139c1837SPaolo Bonzini
2192139c1837SPaolo Bonzini    case INDEX_op_sub_i32:
2193139c1837SPaolo Bonzini        a2 = (int32_t)a2;
2194139c1837SPaolo Bonzini        /* FALLTHRU */
2195139c1837SPaolo Bonzini    case INDEX_op_sub_i64:
2196139c1837SPaolo Bonzini        if (c2) {
2197139c1837SPaolo Bonzini            tcg_out_addsubi(s, ext, a0, a1, -a2);
2198139c1837SPaolo Bonzini        } else {
2199139c1837SPaolo Bonzini            tcg_out_insn(s, 3502, SUB, ext, a0, a1, a2);
2200139c1837SPaolo Bonzini        }
2201139c1837SPaolo Bonzini        break;
2202139c1837SPaolo Bonzini
2203139c1837SPaolo Bonzini    case INDEX_op_neg_i64:
2204139c1837SPaolo Bonzini    case INDEX_op_neg_i32:
2205139c1837SPaolo Bonzini        tcg_out_insn(s, 3502, SUB, ext, a0, TCG_REG_XZR, a1);
2206139c1837SPaolo Bonzini        break;
2207139c1837SPaolo Bonzini
2208139c1837SPaolo Bonzini    case INDEX_op_and_i32:
2209139c1837SPaolo Bonzini        a2 = (int32_t)a2;
2210139c1837SPaolo Bonzini        /* FALLTHRU */
2211139c1837SPaolo Bonzini    case INDEX_op_and_i64:
2212139c1837SPaolo Bonzini        if (c2) {
2213139c1837SPaolo Bonzini            tcg_out_logicali(s, I3404_ANDI, ext, a0, a1, a2);
2214139c1837SPaolo Bonzini        } else {
2215139c1837SPaolo Bonzini            tcg_out_insn(s, 3510, AND, ext, a0, a1, a2);
2216139c1837SPaolo Bonzini        }
2217139c1837SPaolo Bonzini        break;
2218139c1837SPaolo Bonzini
2219139c1837SPaolo Bonzini    case INDEX_op_andc_i32:
2220139c1837SPaolo Bonzini        a2 = (int32_t)a2;
2221139c1837SPaolo Bonzini        /* FALLTHRU */
2222139c1837SPaolo Bonzini    case INDEX_op_andc_i64:
2223139c1837SPaolo Bonzini        if (c2) {
2224139c1837SPaolo Bonzini            tcg_out_logicali(s, I3404_ANDI, ext, a0, a1, ~a2);
2225139c1837SPaolo Bonzini        } else {
2226139c1837SPaolo Bonzini            tcg_out_insn(s, 3510, BIC, ext, a0, a1, a2);
2227139c1837SPaolo Bonzini        }
2228139c1837SPaolo Bonzini        break;
2229139c1837SPaolo Bonzini
2230139c1837SPaolo Bonzini    case INDEX_op_or_i32:
2231139c1837SPaolo Bonzini        a2 = (int32_t)a2;
2232139c1837SPaolo Bonzini        /* FALLTHRU */
2233139c1837SPaolo Bonzini    case INDEX_op_or_i64:
2234139c1837SPaolo Bonzini        if (c2) {
2235139c1837SPaolo Bonzini            tcg_out_logicali(s, I3404_ORRI, ext, a0, a1, a2);
2236139c1837SPaolo Bonzini        } else {
2237139c1837SPaolo Bonzini            tcg_out_insn(s, 3510, ORR, ext, a0, a1, a2);
2238139c1837SPaolo Bonzini        }
2239139c1837SPaolo Bonzini        break;
2240139c1837SPaolo Bonzini
2241139c1837SPaolo Bonzini    case INDEX_op_orc_i32:
2242139c1837SPaolo Bonzini        a2 = (int32_t)a2;
2243139c1837SPaolo Bonzini        /* FALLTHRU */
2244139c1837SPaolo Bonzini    case INDEX_op_orc_i64:
2245139c1837SPaolo Bonzini        if (c2) {
2246139c1837SPaolo Bonzini            tcg_out_logicali(s, I3404_ORRI, ext, a0, a1, ~a2);
2247139c1837SPaolo Bonzini        } else {
2248139c1837SPaolo Bonzini            tcg_out_insn(s, 3510, ORN, ext, a0, a1, a2);
2249139c1837SPaolo Bonzini        }
2250139c1837SPaolo Bonzini        break;
2251139c1837SPaolo Bonzini
2252139c1837SPaolo Bonzini    case INDEX_op_xor_i32:
2253139c1837SPaolo Bonzini        a2 = (int32_t)a2;
2254139c1837SPaolo Bonzini        /* FALLTHRU */
2255139c1837SPaolo Bonzini    case INDEX_op_xor_i64:
2256139c1837SPaolo Bonzini        if (c2) {
2257139c1837SPaolo Bonzini            tcg_out_logicali(s, I3404_EORI, ext, a0, a1, a2);
2258139c1837SPaolo Bonzini        } else {
2259139c1837SPaolo Bonzini            tcg_out_insn(s, 3510, EOR, ext, a0, a1, a2);
2260139c1837SPaolo Bonzini        }
2261139c1837SPaolo Bonzini        break;
2262139c1837SPaolo Bonzini
2263139c1837SPaolo Bonzini    case INDEX_op_eqv_i32:
2264139c1837SPaolo Bonzini        a2 = (int32_t)a2;
2265139c1837SPaolo Bonzini        /* FALLTHRU */
2266139c1837SPaolo Bonzini    case INDEX_op_eqv_i64:
2267139c1837SPaolo Bonzini        if (c2) {
2268139c1837SPaolo Bonzini            tcg_out_logicali(s, I3404_EORI, ext, a0, a1, ~a2);
2269139c1837SPaolo Bonzini        } else {
2270139c1837SPaolo Bonzini            tcg_out_insn(s, 3510, EON, ext, a0, a1, a2);
2271139c1837SPaolo Bonzini        }
2272139c1837SPaolo Bonzini        break;
2273139c1837SPaolo Bonzini
2274139c1837SPaolo Bonzini    case INDEX_op_not_i64:
2275139c1837SPaolo Bonzini    case INDEX_op_not_i32:
2276139c1837SPaolo Bonzini        tcg_out_insn(s, 3510, ORN, ext, a0, TCG_REG_XZR, a1);
2277139c1837SPaolo Bonzini        break;
2278139c1837SPaolo Bonzini
2279139c1837SPaolo Bonzini    case INDEX_op_mul_i64:
2280139c1837SPaolo Bonzini    case INDEX_op_mul_i32:
2281139c1837SPaolo Bonzini        tcg_out_insn(s, 3509, MADD, ext, a0, a1, a2, TCG_REG_XZR);
2282139c1837SPaolo Bonzini        break;
2283139c1837SPaolo Bonzini
2284139c1837SPaolo Bonzini    case INDEX_op_div_i64:
2285139c1837SPaolo Bonzini    case INDEX_op_div_i32:
2286139c1837SPaolo Bonzini        tcg_out_insn(s, 3508, SDIV, ext, a0, a1, a2);
2287139c1837SPaolo Bonzini        break;
2288139c1837SPaolo Bonzini    case INDEX_op_divu_i64:
2289139c1837SPaolo Bonzini    case INDEX_op_divu_i32:
2290139c1837SPaolo Bonzini        tcg_out_insn(s, 3508, UDIV, ext, a0, a1, a2);
2291139c1837SPaolo Bonzini        break;
2292139c1837SPaolo Bonzini
2293139c1837SPaolo Bonzini    case INDEX_op_rem_i64:
2294139c1837SPaolo Bonzini    case INDEX_op_rem_i32:
2295d67bcbddSRichard Henderson        tcg_out_insn(s, 3508, SDIV, ext, TCG_REG_TMP0, a1, a2);
2296d67bcbddSRichard Henderson        tcg_out_insn(s, 3509, MSUB, ext, a0, TCG_REG_TMP0, a2, a1);
2297139c1837SPaolo Bonzini        break;
2298139c1837SPaolo Bonzini    case INDEX_op_remu_i64:
2299139c1837SPaolo Bonzini    case INDEX_op_remu_i32:
2300d67bcbddSRichard Henderson        tcg_out_insn(s, 3508, UDIV, ext, TCG_REG_TMP0, a1, a2);
2301d67bcbddSRichard Henderson        tcg_out_insn(s, 3509, MSUB, ext, a0, TCG_REG_TMP0, a2, a1);
2302139c1837SPaolo Bonzini        break;
2303139c1837SPaolo Bonzini
2304139c1837SPaolo Bonzini    case INDEX_op_shl_i64:
2305139c1837SPaolo Bonzini    case INDEX_op_shl_i32:
2306139c1837SPaolo Bonzini        if (c2) {
2307139c1837SPaolo Bonzini            tcg_out_shl(s, ext, a0, a1, a2);
2308139c1837SPaolo Bonzini        } else {
2309139c1837SPaolo Bonzini            tcg_out_insn(s, 3508, LSLV, ext, a0, a1, a2);
2310139c1837SPaolo Bonzini        }
2311139c1837SPaolo Bonzini        break;
2312139c1837SPaolo Bonzini
2313139c1837SPaolo Bonzini    case INDEX_op_shr_i64:
2314139c1837SPaolo Bonzini    case INDEX_op_shr_i32:
2315139c1837SPaolo Bonzini        if (c2) {
2316139c1837SPaolo Bonzini            tcg_out_shr(s, ext, a0, a1, a2);
2317139c1837SPaolo Bonzini        } else {
2318139c1837SPaolo Bonzini            tcg_out_insn(s, 3508, LSRV, ext, a0, a1, a2);
2319139c1837SPaolo Bonzini        }
2320139c1837SPaolo Bonzini        break;
2321139c1837SPaolo Bonzini
2322139c1837SPaolo Bonzini    case INDEX_op_sar_i64:
2323139c1837SPaolo Bonzini    case INDEX_op_sar_i32:
2324139c1837SPaolo Bonzini        if (c2) {
2325139c1837SPaolo Bonzini            tcg_out_sar(s, ext, a0, a1, a2);
2326139c1837SPaolo Bonzini        } else {
2327139c1837SPaolo Bonzini            tcg_out_insn(s, 3508, ASRV, ext, a0, a1, a2);
2328139c1837SPaolo Bonzini        }
2329139c1837SPaolo Bonzini        break;
2330139c1837SPaolo Bonzini
2331139c1837SPaolo Bonzini    case INDEX_op_rotr_i64:
2332139c1837SPaolo Bonzini    case INDEX_op_rotr_i32:
2333139c1837SPaolo Bonzini        if (c2) {
2334139c1837SPaolo Bonzini            tcg_out_rotr(s, ext, a0, a1, a2);
2335139c1837SPaolo Bonzini        } else {
2336139c1837SPaolo Bonzini            tcg_out_insn(s, 3508, RORV, ext, a0, a1, a2);
2337139c1837SPaolo Bonzini        }
2338139c1837SPaolo Bonzini        break;
2339139c1837SPaolo Bonzini
2340139c1837SPaolo Bonzini    case INDEX_op_rotl_i64:
2341139c1837SPaolo Bonzini    case INDEX_op_rotl_i32:
2342139c1837SPaolo Bonzini        if (c2) {
2343139c1837SPaolo Bonzini            tcg_out_rotl(s, ext, a0, a1, a2);
2344139c1837SPaolo Bonzini        } else {
2345d67bcbddSRichard Henderson            tcg_out_insn(s, 3502, SUB, 0, TCG_REG_TMP0, TCG_REG_XZR, a2);
2346d67bcbddSRichard Henderson            tcg_out_insn(s, 3508, RORV, ext, a0, a1, TCG_REG_TMP0);
2347139c1837SPaolo Bonzini        }
2348139c1837SPaolo Bonzini        break;
2349139c1837SPaolo Bonzini
2350139c1837SPaolo Bonzini    case INDEX_op_clz_i64:
2351139c1837SPaolo Bonzini    case INDEX_op_clz_i32:
2352139c1837SPaolo Bonzini        tcg_out_cltz(s, ext, a0, a1, a2, c2, false);
2353139c1837SPaolo Bonzini        break;
2354139c1837SPaolo Bonzini    case INDEX_op_ctz_i64:
2355139c1837SPaolo Bonzini    case INDEX_op_ctz_i32:
2356139c1837SPaolo Bonzini        tcg_out_cltz(s, ext, a0, a1, a2, c2, true);
2357139c1837SPaolo Bonzini        break;
2358139c1837SPaolo Bonzini
2359139c1837SPaolo Bonzini    case INDEX_op_brcond_i32:
2360139c1837SPaolo Bonzini        a1 = (int32_t)a1;
2361139c1837SPaolo Bonzini        /* FALLTHRU */
2362139c1837SPaolo Bonzini    case INDEX_op_brcond_i64:
2363139c1837SPaolo Bonzini        tcg_out_brcond(s, ext, a2, a0, a1, const_args[1], arg_label(args[3]));
2364139c1837SPaolo Bonzini        break;
2365139c1837SPaolo Bonzini
2366139c1837SPaolo Bonzini    case INDEX_op_setcond_i32:
2367139c1837SPaolo Bonzini        a2 = (int32_t)a2;
2368139c1837SPaolo Bonzini        /* FALLTHRU */
2369139c1837SPaolo Bonzini    case INDEX_op_setcond_i64:
2370339adf2fSRichard Henderson        tcg_out_cmp(s, ext, args[3], a1, a2, c2);
2371139c1837SPaolo Bonzini        /* Use CSET alias of CSINC Wd, WZR, WZR, invert(cond).  */
2372139c1837SPaolo Bonzini        tcg_out_insn(s, 3506, CSINC, TCG_TYPE_I32, a0, TCG_REG_XZR,
2373139c1837SPaolo Bonzini                     TCG_REG_XZR, tcg_invert_cond(args[3]));
2374139c1837SPaolo Bonzini        break;
2375139c1837SPaolo Bonzini
2376f58a7deaSRichard Henderson    case INDEX_op_negsetcond_i32:
2377f58a7deaSRichard Henderson        a2 = (int32_t)a2;
2378f58a7deaSRichard Henderson        /* FALLTHRU */
2379f58a7deaSRichard Henderson    case INDEX_op_negsetcond_i64:
2380339adf2fSRichard Henderson        tcg_out_cmp(s, ext, args[3], a1, a2, c2);
2381f58a7deaSRichard Henderson        /* Use CSETM alias of CSINV Wd, WZR, WZR, invert(cond).  */
2382f58a7deaSRichard Henderson        tcg_out_insn(s, 3506, CSINV, ext, a0, TCG_REG_XZR,
2383f58a7deaSRichard Henderson                     TCG_REG_XZR, tcg_invert_cond(args[3]));
2384f58a7deaSRichard Henderson        break;
2385f58a7deaSRichard Henderson
2386139c1837SPaolo Bonzini    case INDEX_op_movcond_i32:
2387139c1837SPaolo Bonzini        a2 = (int32_t)a2;
2388139c1837SPaolo Bonzini        /* FALLTHRU */
2389139c1837SPaolo Bonzini    case INDEX_op_movcond_i64:
2390339adf2fSRichard Henderson        tcg_out_cmp(s, ext, args[5], a1, a2, c2);
2391139c1837SPaolo Bonzini        tcg_out_insn(s, 3506, CSEL, ext, a0, REG0(3), REG0(4), args[5]);
2392139c1837SPaolo Bonzini        break;
2393139c1837SPaolo Bonzini
2394fecccfccSRichard Henderson    case INDEX_op_qemu_ld_a32_i32:
2395fecccfccSRichard Henderson    case INDEX_op_qemu_ld_a64_i32:
2396fecccfccSRichard Henderson    case INDEX_op_qemu_ld_a32_i64:
2397fecccfccSRichard Henderson    case INDEX_op_qemu_ld_a64_i64:
2398139c1837SPaolo Bonzini        tcg_out_qemu_ld(s, a0, a1, a2, ext);
2399139c1837SPaolo Bonzini        break;
2400fecccfccSRichard Henderson    case INDEX_op_qemu_st_a32_i32:
2401fecccfccSRichard Henderson    case INDEX_op_qemu_st_a64_i32:
2402fecccfccSRichard Henderson    case INDEX_op_qemu_st_a32_i64:
2403fecccfccSRichard Henderson    case INDEX_op_qemu_st_a64_i64:
2404ff0cc85eSRichard Henderson        tcg_out_qemu_st(s, REG0(0), a1, a2, ext);
2405139c1837SPaolo Bonzini        break;
2406929124ecSRichard Henderson    case INDEX_op_qemu_ld_a32_i128:
2407929124ecSRichard Henderson    case INDEX_op_qemu_ld_a64_i128:
2408929124ecSRichard Henderson        tcg_out_qemu_ldst_i128(s, a0, a1, a2, args[3], true);
2409929124ecSRichard Henderson        break;
2410929124ecSRichard Henderson    case INDEX_op_qemu_st_a32_i128:
2411929124ecSRichard Henderson    case INDEX_op_qemu_st_a64_i128:
2412929124ecSRichard Henderson        tcg_out_qemu_ldst_i128(s, REG0(0), REG0(1), a2, args[3], false);
2413929124ecSRichard Henderson        break;
2414139c1837SPaolo Bonzini
2415139c1837SPaolo Bonzini    case INDEX_op_bswap64_i64:
2416dfa24dfaSRichard Henderson        tcg_out_rev(s, TCG_TYPE_I64, MO_64, a0, a1);
2417139c1837SPaolo Bonzini        break;
2418139c1837SPaolo Bonzini    case INDEX_op_bswap32_i64:
24198fcfc6bfSRichard Henderson        tcg_out_rev(s, TCG_TYPE_I32, MO_32, a0, a1);
24208fcfc6bfSRichard Henderson        if (a2 & TCG_BSWAP_OS) {
242152bf3398SRichard Henderson            tcg_out_ext32s(s, a0, a0);
24228fcfc6bfSRichard Henderson        }
24238fcfc6bfSRichard Henderson        break;
2424139c1837SPaolo Bonzini    case INDEX_op_bswap32_i32:
2425dfa24dfaSRichard Henderson        tcg_out_rev(s, TCG_TYPE_I32, MO_32, a0, a1);
2426139c1837SPaolo Bonzini        break;
2427139c1837SPaolo Bonzini    case INDEX_op_bswap16_i64:
2428139c1837SPaolo Bonzini    case INDEX_op_bswap16_i32:
2429dfa24dfaSRichard Henderson        tcg_out_rev(s, TCG_TYPE_I32, MO_16, a0, a1);
24308fcfc6bfSRichard Henderson        if (a2 & TCG_BSWAP_OS) {
24318fcfc6bfSRichard Henderson            /* Output must be sign-extended. */
2432753e42eaSRichard Henderson            tcg_out_ext16s(s, ext, a0, a0);
24338fcfc6bfSRichard Henderson        } else if ((a2 & (TCG_BSWAP_IZ | TCG_BSWAP_OZ)) == TCG_BSWAP_OZ) {
24348fcfc6bfSRichard Henderson            /* Output must be zero-extended, but input isn't. */
2435379afdffSRichard Henderson            tcg_out_ext16u(s, a0, a0);
24368fcfc6bfSRichard Henderson        }
2437139c1837SPaolo Bonzini        break;
2438139c1837SPaolo Bonzini
2439139c1837SPaolo Bonzini    case INDEX_op_deposit_i64:
2440139c1837SPaolo Bonzini    case INDEX_op_deposit_i32:
2441139c1837SPaolo Bonzini        tcg_out_dep(s, ext, a0, REG0(2), args[3], args[4]);
2442139c1837SPaolo Bonzini        break;
2443139c1837SPaolo Bonzini
2444139c1837SPaolo Bonzini    case INDEX_op_extract_i64:
2445139c1837SPaolo Bonzini    case INDEX_op_extract_i32:
2446139c1837SPaolo Bonzini        tcg_out_ubfm(s, ext, a0, a1, a2, a2 + args[3] - 1);
2447139c1837SPaolo Bonzini        break;
2448139c1837SPaolo Bonzini
2449139c1837SPaolo Bonzini    case INDEX_op_sextract_i64:
2450139c1837SPaolo Bonzini    case INDEX_op_sextract_i32:
2451139c1837SPaolo Bonzini        tcg_out_sbfm(s, ext, a0, a1, a2, a2 + args[3] - 1);
2452139c1837SPaolo Bonzini        break;
2453139c1837SPaolo Bonzini
2454139c1837SPaolo Bonzini    case INDEX_op_extract2_i64:
2455139c1837SPaolo Bonzini    case INDEX_op_extract2_i32:
2456139c1837SPaolo Bonzini        tcg_out_extr(s, ext, a0, REG0(2), REG0(1), args[3]);
2457139c1837SPaolo Bonzini        break;
2458139c1837SPaolo Bonzini
2459139c1837SPaolo Bonzini    case INDEX_op_add2_i32:
2460139c1837SPaolo Bonzini        tcg_out_addsub2(s, TCG_TYPE_I32, a0, a1, REG0(2), REG0(3),
2461139c1837SPaolo Bonzini                        (int32_t)args[4], args[5], const_args[4],
2462139c1837SPaolo Bonzini                        const_args[5], false);
2463139c1837SPaolo Bonzini        break;
2464139c1837SPaolo Bonzini    case INDEX_op_add2_i64:
2465139c1837SPaolo Bonzini        tcg_out_addsub2(s, TCG_TYPE_I64, a0, a1, REG0(2), REG0(3), args[4],
2466139c1837SPaolo Bonzini                        args[5], const_args[4], const_args[5], false);
2467139c1837SPaolo Bonzini        break;
2468139c1837SPaolo Bonzini    case INDEX_op_sub2_i32:
2469139c1837SPaolo Bonzini        tcg_out_addsub2(s, TCG_TYPE_I32, a0, a1, REG0(2), REG0(3),
2470139c1837SPaolo Bonzini                        (int32_t)args[4], args[5], const_args[4],
2471139c1837SPaolo Bonzini                        const_args[5], true);
2472139c1837SPaolo Bonzini        break;
2473139c1837SPaolo Bonzini    case INDEX_op_sub2_i64:
2474139c1837SPaolo Bonzini        tcg_out_addsub2(s, TCG_TYPE_I64, a0, a1, REG0(2), REG0(3), args[4],
2475139c1837SPaolo Bonzini                        args[5], const_args[4], const_args[5], true);
2476139c1837SPaolo Bonzini        break;
2477139c1837SPaolo Bonzini
2478139c1837SPaolo Bonzini    case INDEX_op_muluh_i64:
2479139c1837SPaolo Bonzini        tcg_out_insn(s, 3508, UMULH, TCG_TYPE_I64, a0, a1, a2);
2480139c1837SPaolo Bonzini        break;
2481139c1837SPaolo Bonzini    case INDEX_op_mulsh_i64:
2482139c1837SPaolo Bonzini        tcg_out_insn(s, 3508, SMULH, TCG_TYPE_I64, a0, a1, a2);
2483139c1837SPaolo Bonzini        break;
2484139c1837SPaolo Bonzini
2485139c1837SPaolo Bonzini    case INDEX_op_mb:
2486139c1837SPaolo Bonzini        tcg_out_mb(s, a0);
2487139c1837SPaolo Bonzini        break;
2488139c1837SPaolo Bonzini
2489139c1837SPaolo Bonzini    case INDEX_op_mov_i32:  /* Always emitted via tcg_out_mov.  */
2490139c1837SPaolo Bonzini    case INDEX_op_mov_i64:
2491139c1837SPaolo Bonzini    case INDEX_op_call:     /* Always emitted via tcg_out_call.  */
2492b55a8d9dSRichard Henderson    case INDEX_op_exit_tb:  /* Always emitted via tcg_out_exit_tb.  */
2493cf7d6b8eSRichard Henderson    case INDEX_op_goto_tb:  /* Always emitted via tcg_out_goto_tb.  */
2494678155b2SRichard Henderson    case INDEX_op_ext8s_i32:  /* Always emitted via tcg_reg_alloc_op.  */
2495678155b2SRichard Henderson    case INDEX_op_ext8s_i64:
2496d0e66c89SRichard Henderson    case INDEX_op_ext8u_i32:
2497d0e66c89SRichard Henderson    case INDEX_op_ext8u_i64:
2498753e42eaSRichard Henderson    case INDEX_op_ext16s_i64:
2499753e42eaSRichard Henderson    case INDEX_op_ext16s_i32:
2500379afdffSRichard Henderson    case INDEX_op_ext16u_i64:
2501379afdffSRichard Henderson    case INDEX_op_ext16u_i32:
250252bf3398SRichard Henderson    case INDEX_op_ext32s_i64:
25039ecf5f61SRichard Henderson    case INDEX_op_ext32u_i64:
25049c6aa274SRichard Henderson    case INDEX_op_ext_i32_i64:
2505b9bfe000SRichard Henderson    case INDEX_op_extu_i32_i64:
2506b8b94ac6SRichard Henderson    case INDEX_op_extrl_i64_i32:
2507139c1837SPaolo Bonzini    default:
2508139c1837SPaolo Bonzini        g_assert_not_reached();
2509139c1837SPaolo Bonzini    }
2510139c1837SPaolo Bonzini
2511139c1837SPaolo Bonzini#undef REG0
2512139c1837SPaolo Bonzini}
2513139c1837SPaolo Bonzini
2514139c1837SPaolo Bonzinistatic void tcg_out_vec_op(TCGContext *s, TCGOpcode opc,
2515139c1837SPaolo Bonzini                           unsigned vecl, unsigned vece,
25165e8892dbSMiroslav Rezanina                           const TCGArg args[TCG_MAX_OP_ARGS],
25175e8892dbSMiroslav Rezanina                           const int const_args[TCG_MAX_OP_ARGS])
2518139c1837SPaolo Bonzini{
2519d81bad24SRichard Henderson    static const AArch64Insn cmp_vec_insn[16] = {
2520139c1837SPaolo Bonzini        [TCG_COND_EQ] = I3616_CMEQ,
2521139c1837SPaolo Bonzini        [TCG_COND_GT] = I3616_CMGT,
2522139c1837SPaolo Bonzini        [TCG_COND_GE] = I3616_CMGE,
2523139c1837SPaolo Bonzini        [TCG_COND_GTU] = I3616_CMHI,
2524139c1837SPaolo Bonzini        [TCG_COND_GEU] = I3616_CMHS,
2525139c1837SPaolo Bonzini    };
2526d81bad24SRichard Henderson    static const AArch64Insn cmp_scalar_insn[16] = {
2527d81bad24SRichard Henderson        [TCG_COND_EQ] = I3611_CMEQ,
2528d81bad24SRichard Henderson        [TCG_COND_GT] = I3611_CMGT,
2529d81bad24SRichard Henderson        [TCG_COND_GE] = I3611_CMGE,
2530d81bad24SRichard Henderson        [TCG_COND_GTU] = I3611_CMHI,
2531d81bad24SRichard Henderson        [TCG_COND_GEU] = I3611_CMHS,
2532d81bad24SRichard Henderson    };
2533d81bad24SRichard Henderson    static const AArch64Insn cmp0_vec_insn[16] = {
2534139c1837SPaolo Bonzini        [TCG_COND_EQ] = I3617_CMEQ0,
2535139c1837SPaolo Bonzini        [TCG_COND_GT] = I3617_CMGT0,
2536139c1837SPaolo Bonzini        [TCG_COND_GE] = I3617_CMGE0,
2537139c1837SPaolo Bonzini        [TCG_COND_LT] = I3617_CMLT0,
2538139c1837SPaolo Bonzini        [TCG_COND_LE] = I3617_CMLE0,
2539139c1837SPaolo Bonzini    };
2540d81bad24SRichard Henderson    static const AArch64Insn cmp0_scalar_insn[16] = {
2541d81bad24SRichard Henderson        [TCG_COND_EQ] = I3612_CMEQ0,
2542d81bad24SRichard Henderson        [TCG_COND_GT] = I3612_CMGT0,
2543d81bad24SRichard Henderson        [TCG_COND_GE] = I3612_CMGE0,
2544d81bad24SRichard Henderson        [TCG_COND_LT] = I3612_CMLT0,
2545d81bad24SRichard Henderson        [TCG_COND_LE] = I3612_CMLE0,
2546d81bad24SRichard Henderson    };
2547139c1837SPaolo Bonzini
2548139c1837SPaolo Bonzini    TCGType type = vecl + TCG_TYPE_V64;
2549139c1837SPaolo Bonzini    unsigned is_q = vecl;
2550d81bad24SRichard Henderson    bool is_scalar = !is_q && vece == MO_64;
2551139c1837SPaolo Bonzini    TCGArg a0, a1, a2, a3;
2552139c1837SPaolo Bonzini    int cmode, imm8;
2553139c1837SPaolo Bonzini
2554139c1837SPaolo Bonzini    a0 = args[0];
2555139c1837SPaolo Bonzini    a1 = args[1];
2556139c1837SPaolo Bonzini    a2 = args[2];
2557139c1837SPaolo Bonzini
2558139c1837SPaolo Bonzini    switch (opc) {
2559139c1837SPaolo Bonzini    case INDEX_op_ld_vec:
2560139c1837SPaolo Bonzini        tcg_out_ld(s, type, a0, a1, a2);
2561139c1837SPaolo Bonzini        break;
2562139c1837SPaolo Bonzini    case INDEX_op_st_vec:
2563139c1837SPaolo Bonzini        tcg_out_st(s, type, a0, a1, a2);
2564139c1837SPaolo Bonzini        break;
2565139c1837SPaolo Bonzini    case INDEX_op_dupm_vec:
2566139c1837SPaolo Bonzini        tcg_out_dupm_vec(s, type, vece, a0, a1, a2);
2567139c1837SPaolo Bonzini        break;
2568139c1837SPaolo Bonzini    case INDEX_op_add_vec:
2569d81bad24SRichard Henderson        if (is_scalar) {
2570d81bad24SRichard Henderson            tcg_out_insn(s, 3611, ADD, vece, a0, a1, a2);
2571d81bad24SRichard Henderson        } else {
2572139c1837SPaolo Bonzini            tcg_out_insn(s, 3616, ADD, is_q, vece, a0, a1, a2);
2573d81bad24SRichard Henderson        }
2574139c1837SPaolo Bonzini        break;
2575139c1837SPaolo Bonzini    case INDEX_op_sub_vec:
2576d81bad24SRichard Henderson        if (is_scalar) {
2577d81bad24SRichard Henderson            tcg_out_insn(s, 3611, SUB, vece, a0, a1, a2);
2578d81bad24SRichard Henderson        } else {
2579139c1837SPaolo Bonzini            tcg_out_insn(s, 3616, SUB, is_q, vece, a0, a1, a2);
2580d81bad24SRichard Henderson        }
2581139c1837SPaolo Bonzini        break;
2582139c1837SPaolo Bonzini    case INDEX_op_mul_vec:
2583139c1837SPaolo Bonzini        tcg_out_insn(s, 3616, MUL, is_q, vece, a0, a1, a2);
2584139c1837SPaolo Bonzini        break;
2585139c1837SPaolo Bonzini    case INDEX_op_neg_vec:
2586d81bad24SRichard Henderson        if (is_scalar) {
2587d81bad24SRichard Henderson            tcg_out_insn(s, 3612, NEG, vece, a0, a1);
2588d81bad24SRichard Henderson        } else {
2589139c1837SPaolo Bonzini            tcg_out_insn(s, 3617, NEG, is_q, vece, a0, a1);
2590d81bad24SRichard Henderson        }
2591139c1837SPaolo Bonzini        break;
2592139c1837SPaolo Bonzini    case INDEX_op_abs_vec:
2593d81bad24SRichard Henderson        if (is_scalar) {
2594d81bad24SRichard Henderson            tcg_out_insn(s, 3612, ABS, vece, a0, a1);
2595d81bad24SRichard Henderson        } else {
2596139c1837SPaolo Bonzini            tcg_out_insn(s, 3617, ABS, is_q, vece, a0, a1);
2597d81bad24SRichard Henderson        }
2598139c1837SPaolo Bonzini        break;
2599139c1837SPaolo Bonzini    case INDEX_op_and_vec:
2600139c1837SPaolo Bonzini        if (const_args[2]) {
2601139c1837SPaolo Bonzini            is_shimm1632(~a2, &cmode, &imm8);
2602139c1837SPaolo Bonzini            if (a0 == a1) {
2603139c1837SPaolo Bonzini                tcg_out_insn(s, 3606, BIC, is_q, a0, 0, cmode, imm8);
2604139c1837SPaolo Bonzini                return;
2605139c1837SPaolo Bonzini            }
2606139c1837SPaolo Bonzini            tcg_out_insn(s, 3606, MVNI, is_q, a0, 0, cmode, imm8);
2607139c1837SPaolo Bonzini            a2 = a0;
2608139c1837SPaolo Bonzini        }
2609139c1837SPaolo Bonzini        tcg_out_insn(s, 3616, AND, is_q, 0, a0, a1, a2);
2610139c1837SPaolo Bonzini        break;
2611139c1837SPaolo Bonzini    case INDEX_op_or_vec:
2612139c1837SPaolo Bonzini        if (const_args[2]) {
2613139c1837SPaolo Bonzini            is_shimm1632(a2, &cmode, &imm8);
2614139c1837SPaolo Bonzini            if (a0 == a1) {
2615139c1837SPaolo Bonzini                tcg_out_insn(s, 3606, ORR, is_q, a0, 0, cmode, imm8);
2616139c1837SPaolo Bonzini                return;
2617139c1837SPaolo Bonzini            }
2618139c1837SPaolo Bonzini            tcg_out_insn(s, 3606, MOVI, is_q, a0, 0, cmode, imm8);
2619139c1837SPaolo Bonzini            a2 = a0;
2620139c1837SPaolo Bonzini        }
2621139c1837SPaolo Bonzini        tcg_out_insn(s, 3616, ORR, is_q, 0, a0, a1, a2);
2622139c1837SPaolo Bonzini        break;
2623139c1837SPaolo Bonzini    case INDEX_op_andc_vec:
2624139c1837SPaolo Bonzini        if (const_args[2]) {
2625139c1837SPaolo Bonzini            is_shimm1632(a2, &cmode, &imm8);
2626139c1837SPaolo Bonzini            if (a0 == a1) {
2627139c1837SPaolo Bonzini                tcg_out_insn(s, 3606, BIC, is_q, a0, 0, cmode, imm8);
2628139c1837SPaolo Bonzini                return;
2629139c1837SPaolo Bonzini            }
2630139c1837SPaolo Bonzini            tcg_out_insn(s, 3606, MOVI, is_q, a0, 0, cmode, imm8);
2631139c1837SPaolo Bonzini            a2 = a0;
2632139c1837SPaolo Bonzini        }
2633139c1837SPaolo Bonzini        tcg_out_insn(s, 3616, BIC, is_q, 0, a0, a1, a2);
2634139c1837SPaolo Bonzini        break;
2635139c1837SPaolo Bonzini    case INDEX_op_orc_vec:
2636139c1837SPaolo Bonzini        if (const_args[2]) {
2637139c1837SPaolo Bonzini            is_shimm1632(~a2, &cmode, &imm8);
2638139c1837SPaolo Bonzini            if (a0 == a1) {
2639139c1837SPaolo Bonzini                tcg_out_insn(s, 3606, ORR, is_q, a0, 0, cmode, imm8);
2640139c1837SPaolo Bonzini                return;
2641139c1837SPaolo Bonzini            }
2642139c1837SPaolo Bonzini            tcg_out_insn(s, 3606, MVNI, is_q, a0, 0, cmode, imm8);
2643139c1837SPaolo Bonzini            a2 = a0;
2644139c1837SPaolo Bonzini        }
2645139c1837SPaolo Bonzini        tcg_out_insn(s, 3616, ORN, is_q, 0, a0, a1, a2);
2646139c1837SPaolo Bonzini        break;
2647139c1837SPaolo Bonzini    case INDEX_op_xor_vec:
2648139c1837SPaolo Bonzini        tcg_out_insn(s, 3616, EOR, is_q, 0, a0, a1, a2);
2649139c1837SPaolo Bonzini        break;
2650139c1837SPaolo Bonzini    case INDEX_op_ssadd_vec:
2651d81bad24SRichard Henderson        if (is_scalar) {
2652d81bad24SRichard Henderson            tcg_out_insn(s, 3611, SQADD, vece, a0, a1, a2);
2653d81bad24SRichard Henderson        } else {
2654139c1837SPaolo Bonzini            tcg_out_insn(s, 3616, SQADD, is_q, vece, a0, a1, a2);
2655d81bad24SRichard Henderson        }
2656139c1837SPaolo Bonzini        break;
2657139c1837SPaolo Bonzini    case INDEX_op_sssub_vec:
2658d81bad24SRichard Henderson        if (is_scalar) {
2659d81bad24SRichard Henderson            tcg_out_insn(s, 3611, SQSUB, vece, a0, a1, a2);
2660d81bad24SRichard Henderson        } else {
2661139c1837SPaolo Bonzini            tcg_out_insn(s, 3616, SQSUB, is_q, vece, a0, a1, a2);
2662d81bad24SRichard Henderson        }
2663139c1837SPaolo Bonzini        break;
2664139c1837SPaolo Bonzini    case INDEX_op_usadd_vec:
2665d81bad24SRichard Henderson        if (is_scalar) {
2666d81bad24SRichard Henderson            tcg_out_insn(s, 3611, UQADD, vece, a0, a1, a2);
2667d81bad24SRichard Henderson        } else {
2668139c1837SPaolo Bonzini            tcg_out_insn(s, 3616, UQADD, is_q, vece, a0, a1, a2);
2669d81bad24SRichard Henderson        }
2670139c1837SPaolo Bonzini        break;
2671139c1837SPaolo Bonzini    case INDEX_op_ussub_vec:
2672d81bad24SRichard Henderson        if (is_scalar) {
2673d81bad24SRichard Henderson            tcg_out_insn(s, 3611, UQSUB, vece, a0, a1, a2);
2674d81bad24SRichard Henderson        } else {
2675139c1837SPaolo Bonzini            tcg_out_insn(s, 3616, UQSUB, is_q, vece, a0, a1, a2);
2676d81bad24SRichard Henderson        }
2677139c1837SPaolo Bonzini        break;
2678139c1837SPaolo Bonzini    case INDEX_op_smax_vec:
2679139c1837SPaolo Bonzini        tcg_out_insn(s, 3616, SMAX, is_q, vece, a0, a1, a2);
2680139c1837SPaolo Bonzini        break;
2681139c1837SPaolo Bonzini    case INDEX_op_smin_vec:
2682139c1837SPaolo Bonzini        tcg_out_insn(s, 3616, SMIN, is_q, vece, a0, a1, a2);
2683139c1837SPaolo Bonzini        break;
2684139c1837SPaolo Bonzini    case INDEX_op_umax_vec:
2685139c1837SPaolo Bonzini        tcg_out_insn(s, 3616, UMAX, is_q, vece, a0, a1, a2);
2686139c1837SPaolo Bonzini        break;
2687139c1837SPaolo Bonzini    case INDEX_op_umin_vec:
2688139c1837SPaolo Bonzini        tcg_out_insn(s, 3616, UMIN, is_q, vece, a0, a1, a2);
2689139c1837SPaolo Bonzini        break;
2690139c1837SPaolo Bonzini    case INDEX_op_not_vec:
2691139c1837SPaolo Bonzini        tcg_out_insn(s, 3617, NOT, is_q, 0, a0, a1);
2692139c1837SPaolo Bonzini        break;
2693139c1837SPaolo Bonzini    case INDEX_op_shli_vec:
2694d81bad24SRichard Henderson        if (is_scalar) {
2695d81bad24SRichard Henderson            tcg_out_insn(s, 3609, SHL, a0, a1, a2 + (8 << vece));
2696d81bad24SRichard Henderson        } else {
2697139c1837SPaolo Bonzini            tcg_out_insn(s, 3614, SHL, is_q, a0, a1, a2 + (8 << vece));
2698d81bad24SRichard Henderson        }
2699139c1837SPaolo Bonzini        break;
2700139c1837SPaolo Bonzini    case INDEX_op_shri_vec:
2701d81bad24SRichard Henderson        if (is_scalar) {
2702d81bad24SRichard Henderson            tcg_out_insn(s, 3609, USHR, a0, a1, (16 << vece) - a2);
2703d81bad24SRichard Henderson        } else {
2704139c1837SPaolo Bonzini            tcg_out_insn(s, 3614, USHR, is_q, a0, a1, (16 << vece) - a2);
2705d81bad24SRichard Henderson        }
2706139c1837SPaolo Bonzini        break;
2707139c1837SPaolo Bonzini    case INDEX_op_sari_vec:
2708d81bad24SRichard Henderson        if (is_scalar) {
2709d81bad24SRichard Henderson            tcg_out_insn(s, 3609, SSHR, a0, a1, (16 << vece) - a2);
2710d81bad24SRichard Henderson        } else {
2711139c1837SPaolo Bonzini            tcg_out_insn(s, 3614, SSHR, is_q, a0, a1, (16 << vece) - a2);
2712d81bad24SRichard Henderson        }
2713139c1837SPaolo Bonzini        break;
2714139c1837SPaolo Bonzini    case INDEX_op_aa64_sli_vec:
2715d81bad24SRichard Henderson        if (is_scalar) {
2716d81bad24SRichard Henderson            tcg_out_insn(s, 3609, SLI, a0, a2, args[3] + (8 << vece));
2717d81bad24SRichard Henderson        } else {
2718139c1837SPaolo Bonzini            tcg_out_insn(s, 3614, SLI, is_q, a0, a2, args[3] + (8 << vece));
2719d81bad24SRichard Henderson        }
2720139c1837SPaolo Bonzini        break;
2721139c1837SPaolo Bonzini    case INDEX_op_shlv_vec:
2722d81bad24SRichard Henderson        if (is_scalar) {
2723d81bad24SRichard Henderson            tcg_out_insn(s, 3611, USHL, vece, a0, a1, a2);
2724d81bad24SRichard Henderson        } else {
2725139c1837SPaolo Bonzini            tcg_out_insn(s, 3616, USHL, is_q, vece, a0, a1, a2);
2726d81bad24SRichard Henderson        }
2727139c1837SPaolo Bonzini        break;
2728139c1837SPaolo Bonzini    case INDEX_op_aa64_sshl_vec:
2729d81bad24SRichard Henderson        if (is_scalar) {
2730d81bad24SRichard Henderson            tcg_out_insn(s, 3611, SSHL, vece, a0, a1, a2);
2731d81bad24SRichard Henderson        } else {
2732139c1837SPaolo Bonzini            tcg_out_insn(s, 3616, SSHL, is_q, vece, a0, a1, a2);
2733d81bad24SRichard Henderson        }
2734139c1837SPaolo Bonzini        break;
2735139c1837SPaolo Bonzini    case INDEX_op_cmp_vec:
2736139c1837SPaolo Bonzini        {
2737139c1837SPaolo Bonzini            TCGCond cond = args[3];
2738139c1837SPaolo Bonzini            AArch64Insn insn;
2739139c1837SPaolo Bonzini
2740*b04574d4SRichard Henderson            switch (cond) {
2741*b04574d4SRichard Henderson            case TCG_COND_NE:
2742139c1837SPaolo Bonzini                if (const_args[2]) {
2743d81bad24SRichard Henderson                    if (is_scalar) {
2744d81bad24SRichard Henderson                        tcg_out_insn(s, 3611, CMTST, vece, a0, a1, a1);
2745d81bad24SRichard Henderson                    } else {
2746139c1837SPaolo Bonzini                        tcg_out_insn(s, 3616, CMTST, is_q, vece, a0, a1, a1);
2747d81bad24SRichard Henderson                    }
2748d81bad24SRichard Henderson                } else {
2749d81bad24SRichard Henderson                    if (is_scalar) {
2750d81bad24SRichard Henderson                        tcg_out_insn(s, 3611, CMEQ, vece, a0, a1, a2);
2751139c1837SPaolo Bonzini                    } else {
2752139c1837SPaolo Bonzini                        tcg_out_insn(s, 3616, CMEQ, is_q, vece, a0, a1, a2);
2753d81bad24SRichard Henderson                    }
2754139c1837SPaolo Bonzini                    tcg_out_insn(s, 3617, NOT, is_q, 0, a0, a0);
2755139c1837SPaolo Bonzini                }
2756*b04574d4SRichard Henderson                break;
2757*b04574d4SRichard Henderson
2758*b04574d4SRichard Henderson            case TCG_COND_TSTNE:
2759*b04574d4SRichard Henderson            case TCG_COND_TSTEQ:
2760*b04574d4SRichard Henderson                if (const_args[2]) {
2761*b04574d4SRichard Henderson                    /* (x & 0) == 0 */
2762*b04574d4SRichard Henderson                    tcg_out_dupi_vec(s, type, MO_8, a0,
2763*b04574d4SRichard Henderson                                     -(cond == TCG_COND_TSTEQ));
2764*b04574d4SRichard Henderson                    break;
2765*b04574d4SRichard Henderson                }
2766*b04574d4SRichard Henderson                if (is_scalar) {
2767*b04574d4SRichard Henderson                    tcg_out_insn(s, 3611, CMTST, vece, a0, a1, a2);
2768139c1837SPaolo Bonzini                } else {
2769*b04574d4SRichard Henderson                    tcg_out_insn(s, 3616, CMTST, is_q, vece, a0, a1, a2);
2770*b04574d4SRichard Henderson                }
2771*b04574d4SRichard Henderson                if (cond == TCG_COND_TSTEQ) {
2772*b04574d4SRichard Henderson                    tcg_out_insn(s, 3617, NOT, is_q, 0, a0, a0);
2773*b04574d4SRichard Henderson                }
2774*b04574d4SRichard Henderson                break;
2775*b04574d4SRichard Henderson
2776*b04574d4SRichard Henderson            default:
2777139c1837SPaolo Bonzini                if (const_args[2]) {
2778d81bad24SRichard Henderson                    if (is_scalar) {
2779d81bad24SRichard Henderson                        insn = cmp0_scalar_insn[cond];
2780d81bad24SRichard Henderson                        if (insn) {
2781d81bad24SRichard Henderson                            tcg_out_insn_3612(s, insn, vece, a0, a1);
2782d81bad24SRichard Henderson                            break;
2783d81bad24SRichard Henderson                        }
2784d81bad24SRichard Henderson                    } else {
2785d81bad24SRichard Henderson                        insn = cmp0_vec_insn[cond];
2786139c1837SPaolo Bonzini                        if (insn) {
2787139c1837SPaolo Bonzini                            tcg_out_insn_3617(s, insn, is_q, vece, a0, a1);
2788139c1837SPaolo Bonzini                            break;
2789139c1837SPaolo Bonzini                        }
2790d81bad24SRichard Henderson                    }
2791d67bcbddSRichard Henderson                    tcg_out_dupi_vec(s, type, MO_8, TCG_VEC_TMP0, 0);
2792d67bcbddSRichard Henderson                    a2 = TCG_VEC_TMP0;
2793139c1837SPaolo Bonzini                }
2794d81bad24SRichard Henderson                if (is_scalar) {
2795d81bad24SRichard Henderson                    insn = cmp_scalar_insn[cond];
2796139c1837SPaolo Bonzini                    if (insn == 0) {
2797139c1837SPaolo Bonzini                        TCGArg t;
2798139c1837SPaolo Bonzini                        t = a1, a1 = a2, a2 = t;
2799139c1837SPaolo Bonzini                        cond = tcg_swap_cond(cond);
2800d81bad24SRichard Henderson                        insn = cmp_scalar_insn[cond];
2801d81bad24SRichard Henderson                        tcg_debug_assert(insn != 0);
2802d81bad24SRichard Henderson                    }
2803d81bad24SRichard Henderson                    tcg_out_insn_3611(s, insn, vece, a0, a1, a2);
2804d81bad24SRichard Henderson                } else {
2805d81bad24SRichard Henderson                    insn = cmp_vec_insn[cond];
2806d81bad24SRichard Henderson                    if (insn == 0) {
2807d81bad24SRichard Henderson                        TCGArg t;
2808d81bad24SRichard Henderson                        t = a1, a1 = a2, a2 = t;
2809d81bad24SRichard Henderson                        cond = tcg_swap_cond(cond);
2810d81bad24SRichard Henderson                        insn = cmp_vec_insn[cond];
2811139c1837SPaolo Bonzini                        tcg_debug_assert(insn != 0);
2812139c1837SPaolo Bonzini                    }
2813139c1837SPaolo Bonzini                    tcg_out_insn_3616(s, insn, is_q, vece, a0, a1, a2);
2814139c1837SPaolo Bonzini                }
2815*b04574d4SRichard Henderson                break;
2816139c1837SPaolo Bonzini            }
2817d81bad24SRichard Henderson        }
2818139c1837SPaolo Bonzini        break;
2819139c1837SPaolo Bonzini
2820139c1837SPaolo Bonzini    case INDEX_op_bitsel_vec:
2821139c1837SPaolo Bonzini        a3 = args[3];
2822139c1837SPaolo Bonzini        if (a0 == a3) {
2823139c1837SPaolo Bonzini            tcg_out_insn(s, 3616, BIT, is_q, 0, a0, a2, a1);
2824139c1837SPaolo Bonzini        } else if (a0 == a2) {
2825139c1837SPaolo Bonzini            tcg_out_insn(s, 3616, BIF, is_q, 0, a0, a3, a1);
2826139c1837SPaolo Bonzini        } else {
2827139c1837SPaolo Bonzini            if (a0 != a1) {
2828139c1837SPaolo Bonzini                tcg_out_mov(s, type, a0, a1);
2829139c1837SPaolo Bonzini            }
2830139c1837SPaolo Bonzini            tcg_out_insn(s, 3616, BSL, is_q, 0, a0, a2, a3);
2831139c1837SPaolo Bonzini        }
2832139c1837SPaolo Bonzini        break;
2833139c1837SPaolo Bonzini
2834139c1837SPaolo Bonzini    case INDEX_op_mov_vec:  /* Always emitted via tcg_out_mov.  */
2835139c1837SPaolo Bonzini    case INDEX_op_dup_vec:  /* Always emitted via tcg_out_dup_vec.  */
2836139c1837SPaolo Bonzini    default:
2837139c1837SPaolo Bonzini        g_assert_not_reached();
2838139c1837SPaolo Bonzini    }
2839139c1837SPaolo Bonzini}
2840139c1837SPaolo Bonzini
2841139c1837SPaolo Bonziniint tcg_can_emit_vec_op(TCGOpcode opc, TCGType type, unsigned vece)
2842139c1837SPaolo Bonzini{
2843139c1837SPaolo Bonzini    switch (opc) {
2844139c1837SPaolo Bonzini    case INDEX_op_add_vec:
2845139c1837SPaolo Bonzini    case INDEX_op_sub_vec:
2846139c1837SPaolo Bonzini    case INDEX_op_and_vec:
2847139c1837SPaolo Bonzini    case INDEX_op_or_vec:
2848139c1837SPaolo Bonzini    case INDEX_op_xor_vec:
2849139c1837SPaolo Bonzini    case INDEX_op_andc_vec:
2850139c1837SPaolo Bonzini    case INDEX_op_orc_vec:
2851139c1837SPaolo Bonzini    case INDEX_op_neg_vec:
2852139c1837SPaolo Bonzini    case INDEX_op_abs_vec:
2853139c1837SPaolo Bonzini    case INDEX_op_not_vec:
2854139c1837SPaolo Bonzini    case INDEX_op_cmp_vec:
2855139c1837SPaolo Bonzini    case INDEX_op_shli_vec:
2856139c1837SPaolo Bonzini    case INDEX_op_shri_vec:
2857139c1837SPaolo Bonzini    case INDEX_op_sari_vec:
2858139c1837SPaolo Bonzini    case INDEX_op_ssadd_vec:
2859139c1837SPaolo Bonzini    case INDEX_op_sssub_vec:
2860139c1837SPaolo Bonzini    case INDEX_op_usadd_vec:
2861139c1837SPaolo Bonzini    case INDEX_op_ussub_vec:
2862139c1837SPaolo Bonzini    case INDEX_op_shlv_vec:
2863139c1837SPaolo Bonzini    case INDEX_op_bitsel_vec:
2864139c1837SPaolo Bonzini        return 1;
2865139c1837SPaolo Bonzini    case INDEX_op_rotli_vec:
2866139c1837SPaolo Bonzini    case INDEX_op_shrv_vec:
2867139c1837SPaolo Bonzini    case INDEX_op_sarv_vec:
2868139c1837SPaolo Bonzini    case INDEX_op_rotlv_vec:
2869139c1837SPaolo Bonzini    case INDEX_op_rotrv_vec:
2870139c1837SPaolo Bonzini        return -1;
2871139c1837SPaolo Bonzini    case INDEX_op_mul_vec:
2872139c1837SPaolo Bonzini    case INDEX_op_smax_vec:
2873139c1837SPaolo Bonzini    case INDEX_op_smin_vec:
2874139c1837SPaolo Bonzini    case INDEX_op_umax_vec:
2875139c1837SPaolo Bonzini    case INDEX_op_umin_vec:
2876139c1837SPaolo Bonzini        return vece < MO_64;
2877139c1837SPaolo Bonzini
2878139c1837SPaolo Bonzini    default:
2879139c1837SPaolo Bonzini        return 0;
2880139c1837SPaolo Bonzini    }
2881139c1837SPaolo Bonzini}
2882139c1837SPaolo Bonzini
2883139c1837SPaolo Bonzinivoid tcg_expand_vec_op(TCGOpcode opc, TCGType type, unsigned vece,
2884139c1837SPaolo Bonzini                       TCGArg a0, ...)
2885139c1837SPaolo Bonzini{
2886139c1837SPaolo Bonzini    va_list va;
288710061ffeSRichard Henderson    TCGv_vec v0, v1, v2, t1, t2, c1;
2888139c1837SPaolo Bonzini    TCGArg a2;
2889139c1837SPaolo Bonzini
2890139c1837SPaolo Bonzini    va_start(va, a0);
2891139c1837SPaolo Bonzini    v0 = temp_tcgv_vec(arg_temp(a0));
2892139c1837SPaolo Bonzini    v1 = temp_tcgv_vec(arg_temp(va_arg(va, TCGArg)));
2893139c1837SPaolo Bonzini    a2 = va_arg(va, TCGArg);
28942dfa2f18SRichard Henderson    va_end(va);
2895139c1837SPaolo Bonzini
2896139c1837SPaolo Bonzini    switch (opc) {
2897139c1837SPaolo Bonzini    case INDEX_op_rotli_vec:
2898139c1837SPaolo Bonzini        t1 = tcg_temp_new_vec(type);
2899139c1837SPaolo Bonzini        tcg_gen_shri_vec(vece, t1, v1, -a2 & ((8 << vece) - 1));
2900139c1837SPaolo Bonzini        vec_gen_4(INDEX_op_aa64_sli_vec, type, vece,
2901139c1837SPaolo Bonzini                  tcgv_vec_arg(v0), tcgv_vec_arg(t1), tcgv_vec_arg(v1), a2);
2902139c1837SPaolo Bonzini        tcg_temp_free_vec(t1);
2903139c1837SPaolo Bonzini        break;
2904139c1837SPaolo Bonzini
2905139c1837SPaolo Bonzini    case INDEX_op_shrv_vec:
2906139c1837SPaolo Bonzini    case INDEX_op_sarv_vec:
2907139c1837SPaolo Bonzini        /* Right shifts are negative left shifts for AArch64.  */
29082dfa2f18SRichard Henderson        v2 = temp_tcgv_vec(arg_temp(a2));
2909139c1837SPaolo Bonzini        t1 = tcg_temp_new_vec(type);
2910139c1837SPaolo Bonzini        tcg_gen_neg_vec(vece, t1, v2);
2911139c1837SPaolo Bonzini        opc = (opc == INDEX_op_shrv_vec
2912139c1837SPaolo Bonzini               ? INDEX_op_shlv_vec : INDEX_op_aa64_sshl_vec);
2913139c1837SPaolo Bonzini        vec_gen_3(opc, type, vece, tcgv_vec_arg(v0),
2914139c1837SPaolo Bonzini                  tcgv_vec_arg(v1), tcgv_vec_arg(t1));
2915139c1837SPaolo Bonzini        tcg_temp_free_vec(t1);
2916139c1837SPaolo Bonzini        break;
2917139c1837SPaolo Bonzini
2918139c1837SPaolo Bonzini    case INDEX_op_rotlv_vec:
29192dfa2f18SRichard Henderson        v2 = temp_tcgv_vec(arg_temp(a2));
2920139c1837SPaolo Bonzini        t1 = tcg_temp_new_vec(type);
292110061ffeSRichard Henderson        c1 = tcg_constant_vec(type, vece, 8 << vece);
292210061ffeSRichard Henderson        tcg_gen_sub_vec(vece, t1, v2, c1);
2923139c1837SPaolo Bonzini        /* Right shifts are negative left shifts for AArch64.  */
2924139c1837SPaolo Bonzini        vec_gen_3(INDEX_op_shlv_vec, type, vece, tcgv_vec_arg(t1),
2925139c1837SPaolo Bonzini                  tcgv_vec_arg(v1), tcgv_vec_arg(t1));
2926139c1837SPaolo Bonzini        vec_gen_3(INDEX_op_shlv_vec, type, vece, tcgv_vec_arg(v0),
2927139c1837SPaolo Bonzini                  tcgv_vec_arg(v1), tcgv_vec_arg(v2));
2928139c1837SPaolo Bonzini        tcg_gen_or_vec(vece, v0, v0, t1);
2929139c1837SPaolo Bonzini        tcg_temp_free_vec(t1);
2930139c1837SPaolo Bonzini        break;
2931139c1837SPaolo Bonzini
2932139c1837SPaolo Bonzini    case INDEX_op_rotrv_vec:
29332dfa2f18SRichard Henderson        v2 = temp_tcgv_vec(arg_temp(a2));
2934139c1837SPaolo Bonzini        t1 = tcg_temp_new_vec(type);
2935139c1837SPaolo Bonzini        t2 = tcg_temp_new_vec(type);
293610061ffeSRichard Henderson        c1 = tcg_constant_vec(type, vece, 8 << vece);
2937139c1837SPaolo Bonzini        tcg_gen_neg_vec(vece, t1, v2);
293810061ffeSRichard Henderson        tcg_gen_sub_vec(vece, t2, c1, v2);
2939139c1837SPaolo Bonzini        /* Right shifts are negative left shifts for AArch64.  */
2940139c1837SPaolo Bonzini        vec_gen_3(INDEX_op_shlv_vec, type, vece, tcgv_vec_arg(t1),
2941139c1837SPaolo Bonzini                  tcgv_vec_arg(v1), tcgv_vec_arg(t1));
2942139c1837SPaolo Bonzini        vec_gen_3(INDEX_op_shlv_vec, type, vece, tcgv_vec_arg(t2),
2943139c1837SPaolo Bonzini                  tcgv_vec_arg(v1), tcgv_vec_arg(t2));
2944139c1837SPaolo Bonzini        tcg_gen_or_vec(vece, v0, t1, t2);
2945139c1837SPaolo Bonzini        tcg_temp_free_vec(t1);
2946139c1837SPaolo Bonzini        tcg_temp_free_vec(t2);
2947139c1837SPaolo Bonzini        break;
2948139c1837SPaolo Bonzini
2949139c1837SPaolo Bonzini    default:
2950139c1837SPaolo Bonzini        g_assert_not_reached();
2951139c1837SPaolo Bonzini    }
2952139c1837SPaolo Bonzini}
2953139c1837SPaolo Bonzini
295439e7522bSRichard Hendersonstatic TCGConstraintSetIndex tcg_target_op_def(TCGOpcode op)
2955139c1837SPaolo Bonzini{
2956139c1837SPaolo Bonzini    switch (op) {
2957139c1837SPaolo Bonzini    case INDEX_op_goto_ptr:
295839e7522bSRichard Henderson        return C_O0_I1(r);
2959139c1837SPaolo Bonzini
2960139c1837SPaolo Bonzini    case INDEX_op_ld8u_i32:
2961139c1837SPaolo Bonzini    case INDEX_op_ld8s_i32:
2962139c1837SPaolo Bonzini    case INDEX_op_ld16u_i32:
2963139c1837SPaolo Bonzini    case INDEX_op_ld16s_i32:
2964139c1837SPaolo Bonzini    case INDEX_op_ld_i32:
2965139c1837SPaolo Bonzini    case INDEX_op_ld8u_i64:
2966139c1837SPaolo Bonzini    case INDEX_op_ld8s_i64:
2967139c1837SPaolo Bonzini    case INDEX_op_ld16u_i64:
2968139c1837SPaolo Bonzini    case INDEX_op_ld16s_i64:
2969139c1837SPaolo Bonzini    case INDEX_op_ld32u_i64:
2970139c1837SPaolo Bonzini    case INDEX_op_ld32s_i64:
2971139c1837SPaolo Bonzini    case INDEX_op_ld_i64:
2972139c1837SPaolo Bonzini    case INDEX_op_neg_i32:
2973139c1837SPaolo Bonzini    case INDEX_op_neg_i64:
2974139c1837SPaolo Bonzini    case INDEX_op_not_i32:
2975139c1837SPaolo Bonzini    case INDEX_op_not_i64:
2976139c1837SPaolo Bonzini    case INDEX_op_bswap16_i32:
2977139c1837SPaolo Bonzini    case INDEX_op_bswap32_i32:
2978139c1837SPaolo Bonzini    case INDEX_op_bswap16_i64:
2979139c1837SPaolo Bonzini    case INDEX_op_bswap32_i64:
2980139c1837SPaolo Bonzini    case INDEX_op_bswap64_i64:
2981139c1837SPaolo Bonzini    case INDEX_op_ext8s_i32:
2982139c1837SPaolo Bonzini    case INDEX_op_ext16s_i32:
2983139c1837SPaolo Bonzini    case INDEX_op_ext8u_i32:
2984139c1837SPaolo Bonzini    case INDEX_op_ext16u_i32:
2985139c1837SPaolo Bonzini    case INDEX_op_ext8s_i64:
2986139c1837SPaolo Bonzini    case INDEX_op_ext16s_i64:
2987139c1837SPaolo Bonzini    case INDEX_op_ext32s_i64:
2988139c1837SPaolo Bonzini    case INDEX_op_ext8u_i64:
2989139c1837SPaolo Bonzini    case INDEX_op_ext16u_i64:
2990139c1837SPaolo Bonzini    case INDEX_op_ext32u_i64:
2991139c1837SPaolo Bonzini    case INDEX_op_ext_i32_i64:
2992139c1837SPaolo Bonzini    case INDEX_op_extu_i32_i64:
2993139c1837SPaolo Bonzini    case INDEX_op_extract_i32:
2994139c1837SPaolo Bonzini    case INDEX_op_extract_i64:
2995139c1837SPaolo Bonzini    case INDEX_op_sextract_i32:
2996139c1837SPaolo Bonzini    case INDEX_op_sextract_i64:
299739e7522bSRichard Henderson        return C_O1_I1(r, r);
2998139c1837SPaolo Bonzini
2999139c1837SPaolo Bonzini    case INDEX_op_st8_i32:
3000139c1837SPaolo Bonzini    case INDEX_op_st16_i32:
3001139c1837SPaolo Bonzini    case INDEX_op_st_i32:
3002139c1837SPaolo Bonzini    case INDEX_op_st8_i64:
3003139c1837SPaolo Bonzini    case INDEX_op_st16_i64:
3004139c1837SPaolo Bonzini    case INDEX_op_st32_i64:
3005139c1837SPaolo Bonzini    case INDEX_op_st_i64:
300639e7522bSRichard Henderson        return C_O0_I2(rZ, r);
3007139c1837SPaolo Bonzini
3008139c1837SPaolo Bonzini    case INDEX_op_add_i32:
3009139c1837SPaolo Bonzini    case INDEX_op_add_i64:
3010139c1837SPaolo Bonzini    case INDEX_op_sub_i32:
3011139c1837SPaolo Bonzini    case INDEX_op_sub_i64:
3012339adf2fSRichard Henderson        return C_O1_I2(r, r, rA);
3013339adf2fSRichard Henderson
3014139c1837SPaolo Bonzini    case INDEX_op_setcond_i32:
3015139c1837SPaolo Bonzini    case INDEX_op_setcond_i64:
3016f58a7deaSRichard Henderson    case INDEX_op_negsetcond_i32:
3017f58a7deaSRichard Henderson    case INDEX_op_negsetcond_i64:
3018339adf2fSRichard Henderson        return C_O1_I2(r, r, rC);
3019139c1837SPaolo Bonzini
3020139c1837SPaolo Bonzini    case INDEX_op_mul_i32:
3021139c1837SPaolo Bonzini    case INDEX_op_mul_i64:
3022139c1837SPaolo Bonzini    case INDEX_op_div_i32:
3023139c1837SPaolo Bonzini    case INDEX_op_div_i64:
3024139c1837SPaolo Bonzini    case INDEX_op_divu_i32:
3025139c1837SPaolo Bonzini    case INDEX_op_divu_i64:
3026139c1837SPaolo Bonzini    case INDEX_op_rem_i32:
3027139c1837SPaolo Bonzini    case INDEX_op_rem_i64:
3028139c1837SPaolo Bonzini    case INDEX_op_remu_i32:
3029139c1837SPaolo Bonzini    case INDEX_op_remu_i64:
3030139c1837SPaolo Bonzini    case INDEX_op_muluh_i64:
3031139c1837SPaolo Bonzini    case INDEX_op_mulsh_i64:
303239e7522bSRichard Henderson        return C_O1_I2(r, r, r);
3033139c1837SPaolo Bonzini
3034139c1837SPaolo Bonzini    case INDEX_op_and_i32:
3035139c1837SPaolo Bonzini    case INDEX_op_and_i64:
3036139c1837SPaolo Bonzini    case INDEX_op_or_i32:
3037139c1837SPaolo Bonzini    case INDEX_op_or_i64:
3038139c1837SPaolo Bonzini    case INDEX_op_xor_i32:
3039139c1837SPaolo Bonzini    case INDEX_op_xor_i64:
3040139c1837SPaolo Bonzini    case INDEX_op_andc_i32:
3041139c1837SPaolo Bonzini    case INDEX_op_andc_i64:
3042139c1837SPaolo Bonzini    case INDEX_op_orc_i32:
3043139c1837SPaolo Bonzini    case INDEX_op_orc_i64:
3044139c1837SPaolo Bonzini    case INDEX_op_eqv_i32:
3045139c1837SPaolo Bonzini    case INDEX_op_eqv_i64:
304639e7522bSRichard Henderson        return C_O1_I2(r, r, rL);
3047139c1837SPaolo Bonzini
3048139c1837SPaolo Bonzini    case INDEX_op_shl_i32:
3049139c1837SPaolo Bonzini    case INDEX_op_shr_i32:
3050139c1837SPaolo Bonzini    case INDEX_op_sar_i32:
3051139c1837SPaolo Bonzini    case INDEX_op_rotl_i32:
3052139c1837SPaolo Bonzini    case INDEX_op_rotr_i32:
3053139c1837SPaolo Bonzini    case INDEX_op_shl_i64:
3054139c1837SPaolo Bonzini    case INDEX_op_shr_i64:
3055139c1837SPaolo Bonzini    case INDEX_op_sar_i64:
3056139c1837SPaolo Bonzini    case INDEX_op_rotl_i64:
3057139c1837SPaolo Bonzini    case INDEX_op_rotr_i64:
305839e7522bSRichard Henderson        return C_O1_I2(r, r, ri);
3059139c1837SPaolo Bonzini
3060139c1837SPaolo Bonzini    case INDEX_op_clz_i32:
3061139c1837SPaolo Bonzini    case INDEX_op_ctz_i32:
3062139c1837SPaolo Bonzini    case INDEX_op_clz_i64:
3063139c1837SPaolo Bonzini    case INDEX_op_ctz_i64:
306439e7522bSRichard Henderson        return C_O1_I2(r, r, rAL);
3065139c1837SPaolo Bonzini
3066139c1837SPaolo Bonzini    case INDEX_op_brcond_i32:
3067139c1837SPaolo Bonzini    case INDEX_op_brcond_i64:
3068339adf2fSRichard Henderson        return C_O0_I2(r, rC);
3069139c1837SPaolo Bonzini
3070139c1837SPaolo Bonzini    case INDEX_op_movcond_i32:
3071139c1837SPaolo Bonzini    case INDEX_op_movcond_i64:
3072339adf2fSRichard Henderson        return C_O1_I4(r, r, rC, rZ, rZ);
3073139c1837SPaolo Bonzini
3074fecccfccSRichard Henderson    case INDEX_op_qemu_ld_a32_i32:
3075fecccfccSRichard Henderson    case INDEX_op_qemu_ld_a64_i32:
3076fecccfccSRichard Henderson    case INDEX_op_qemu_ld_a32_i64:
3077fecccfccSRichard Henderson    case INDEX_op_qemu_ld_a64_i64:
3078285a691fSRichard Henderson        return C_O1_I1(r, r);
3079929124ecSRichard Henderson    case INDEX_op_qemu_ld_a32_i128:
3080929124ecSRichard Henderson    case INDEX_op_qemu_ld_a64_i128:
3081929124ecSRichard Henderson        return C_O2_I1(r, r, r);
3082fecccfccSRichard Henderson    case INDEX_op_qemu_st_a32_i32:
3083fecccfccSRichard Henderson    case INDEX_op_qemu_st_a64_i32:
3084fecccfccSRichard Henderson    case INDEX_op_qemu_st_a32_i64:
3085fecccfccSRichard Henderson    case INDEX_op_qemu_st_a64_i64:
3086285a691fSRichard Henderson        return C_O0_I2(rZ, r);
3087929124ecSRichard Henderson    case INDEX_op_qemu_st_a32_i128:
3088929124ecSRichard Henderson    case INDEX_op_qemu_st_a64_i128:
3089929124ecSRichard Henderson        return C_O0_I3(rZ, rZ, r);
3090139c1837SPaolo Bonzini
3091139c1837SPaolo Bonzini    case INDEX_op_deposit_i32:
3092139c1837SPaolo Bonzini    case INDEX_op_deposit_i64:
309339e7522bSRichard Henderson        return C_O1_I2(r, 0, rZ);
3094139c1837SPaolo Bonzini
3095139c1837SPaolo Bonzini    case INDEX_op_extract2_i32:
3096139c1837SPaolo Bonzini    case INDEX_op_extract2_i64:
309739e7522bSRichard Henderson        return C_O1_I2(r, rZ, rZ);
3098139c1837SPaolo Bonzini
3099139c1837SPaolo Bonzini    case INDEX_op_add2_i32:
3100139c1837SPaolo Bonzini    case INDEX_op_add2_i64:
3101139c1837SPaolo Bonzini    case INDEX_op_sub2_i32:
3102139c1837SPaolo Bonzini    case INDEX_op_sub2_i64:
310339e7522bSRichard Henderson        return C_O2_I4(r, r, rZ, rZ, rA, rMZ);
3104139c1837SPaolo Bonzini
3105139c1837SPaolo Bonzini    case INDEX_op_add_vec:
3106139c1837SPaolo Bonzini    case INDEX_op_sub_vec:
3107139c1837SPaolo Bonzini    case INDEX_op_mul_vec:
3108139c1837SPaolo Bonzini    case INDEX_op_xor_vec:
3109139c1837SPaolo Bonzini    case INDEX_op_ssadd_vec:
3110139c1837SPaolo Bonzini    case INDEX_op_sssub_vec:
3111139c1837SPaolo Bonzini    case INDEX_op_usadd_vec:
3112139c1837SPaolo Bonzini    case INDEX_op_ussub_vec:
3113139c1837SPaolo Bonzini    case INDEX_op_smax_vec:
3114139c1837SPaolo Bonzini    case INDEX_op_smin_vec:
3115139c1837SPaolo Bonzini    case INDEX_op_umax_vec:
3116139c1837SPaolo Bonzini    case INDEX_op_umin_vec:
3117139c1837SPaolo Bonzini    case INDEX_op_shlv_vec:
3118139c1837SPaolo Bonzini    case INDEX_op_shrv_vec:
3119139c1837SPaolo Bonzini    case INDEX_op_sarv_vec:
3120139c1837SPaolo Bonzini    case INDEX_op_aa64_sshl_vec:
312139e7522bSRichard Henderson        return C_O1_I2(w, w, w);
3122139c1837SPaolo Bonzini    case INDEX_op_not_vec:
3123139c1837SPaolo Bonzini    case INDEX_op_neg_vec:
3124139c1837SPaolo Bonzini    case INDEX_op_abs_vec:
3125139c1837SPaolo Bonzini    case INDEX_op_shli_vec:
3126139c1837SPaolo Bonzini    case INDEX_op_shri_vec:
3127139c1837SPaolo Bonzini    case INDEX_op_sari_vec:
312839e7522bSRichard Henderson        return C_O1_I1(w, w);
3129139c1837SPaolo Bonzini    case INDEX_op_ld_vec:
3130139c1837SPaolo Bonzini    case INDEX_op_dupm_vec:
313139e7522bSRichard Henderson        return C_O1_I1(w, r);
313239e7522bSRichard Henderson    case INDEX_op_st_vec:
313339e7522bSRichard Henderson        return C_O0_I2(w, r);
3134139c1837SPaolo Bonzini    case INDEX_op_dup_vec:
313539e7522bSRichard Henderson        return C_O1_I1(w, wr);
3136139c1837SPaolo Bonzini    case INDEX_op_or_vec:
3137139c1837SPaolo Bonzini    case INDEX_op_andc_vec:
313839e7522bSRichard Henderson        return C_O1_I2(w, w, wO);
3139139c1837SPaolo Bonzini    case INDEX_op_and_vec:
3140139c1837SPaolo Bonzini    case INDEX_op_orc_vec:
314139e7522bSRichard Henderson        return C_O1_I2(w, w, wN);
3142139c1837SPaolo Bonzini    case INDEX_op_cmp_vec:
314339e7522bSRichard Henderson        return C_O1_I2(w, w, wZ);
3144139c1837SPaolo Bonzini    case INDEX_op_bitsel_vec:
314539e7522bSRichard Henderson        return C_O1_I3(w, w, w, w);
3146139c1837SPaolo Bonzini    case INDEX_op_aa64_sli_vec:
314739e7522bSRichard Henderson        return C_O1_I2(w, 0, w);
3148139c1837SPaolo Bonzini
3149139c1837SPaolo Bonzini    default:
315039e7522bSRichard Henderson        g_assert_not_reached();
3151139c1837SPaolo Bonzini    }
3152139c1837SPaolo Bonzini}
3153139c1837SPaolo Bonzini
3154139c1837SPaolo Bonzinistatic void tcg_target_init(TCGContext *s)
3155139c1837SPaolo Bonzini{
3156139c1837SPaolo Bonzini    tcg_target_available_regs[TCG_TYPE_I32] = 0xffffffffu;
3157139c1837SPaolo Bonzini    tcg_target_available_regs[TCG_TYPE_I64] = 0xffffffffu;
3158139c1837SPaolo Bonzini    tcg_target_available_regs[TCG_TYPE_V64] = 0xffffffff00000000ull;
3159139c1837SPaolo Bonzini    tcg_target_available_regs[TCG_TYPE_V128] = 0xffffffff00000000ull;
3160139c1837SPaolo Bonzini
3161139c1837SPaolo Bonzini    tcg_target_call_clobber_regs = -1ull;
3162139c1837SPaolo Bonzini    tcg_regset_reset_reg(tcg_target_call_clobber_regs, TCG_REG_X19);
3163139c1837SPaolo Bonzini    tcg_regset_reset_reg(tcg_target_call_clobber_regs, TCG_REG_X20);
3164139c1837SPaolo Bonzini    tcg_regset_reset_reg(tcg_target_call_clobber_regs, TCG_REG_X21);
3165139c1837SPaolo Bonzini    tcg_regset_reset_reg(tcg_target_call_clobber_regs, TCG_REG_X22);
3166139c1837SPaolo Bonzini    tcg_regset_reset_reg(tcg_target_call_clobber_regs, TCG_REG_X23);
3167139c1837SPaolo Bonzini    tcg_regset_reset_reg(tcg_target_call_clobber_regs, TCG_REG_X24);
3168139c1837SPaolo Bonzini    tcg_regset_reset_reg(tcg_target_call_clobber_regs, TCG_REG_X25);
3169139c1837SPaolo Bonzini    tcg_regset_reset_reg(tcg_target_call_clobber_regs, TCG_REG_X26);
3170139c1837SPaolo Bonzini    tcg_regset_reset_reg(tcg_target_call_clobber_regs, TCG_REG_X27);
3171139c1837SPaolo Bonzini    tcg_regset_reset_reg(tcg_target_call_clobber_regs, TCG_REG_X28);
3172139c1837SPaolo Bonzini    tcg_regset_reset_reg(tcg_target_call_clobber_regs, TCG_REG_X29);
3173139c1837SPaolo Bonzini    tcg_regset_reset_reg(tcg_target_call_clobber_regs, TCG_REG_V8);
3174139c1837SPaolo Bonzini    tcg_regset_reset_reg(tcg_target_call_clobber_regs, TCG_REG_V9);
3175139c1837SPaolo Bonzini    tcg_regset_reset_reg(tcg_target_call_clobber_regs, TCG_REG_V10);
3176139c1837SPaolo Bonzini    tcg_regset_reset_reg(tcg_target_call_clobber_regs, TCG_REG_V11);
3177139c1837SPaolo Bonzini    tcg_regset_reset_reg(tcg_target_call_clobber_regs, TCG_REG_V12);
3178139c1837SPaolo Bonzini    tcg_regset_reset_reg(tcg_target_call_clobber_regs, TCG_REG_V13);
3179139c1837SPaolo Bonzini    tcg_regset_reset_reg(tcg_target_call_clobber_regs, TCG_REG_V14);
3180139c1837SPaolo Bonzini    tcg_regset_reset_reg(tcg_target_call_clobber_regs, TCG_REG_V15);
3181139c1837SPaolo Bonzini
3182139c1837SPaolo Bonzini    s->reserved_regs = 0;
3183139c1837SPaolo Bonzini    tcg_regset_set_reg(s->reserved_regs, TCG_REG_SP);
3184139c1837SPaolo Bonzini    tcg_regset_set_reg(s->reserved_regs, TCG_REG_FP);
3185139c1837SPaolo Bonzini    tcg_regset_set_reg(s->reserved_regs, TCG_REG_X18); /* platform register */
3186d67bcbddSRichard Henderson    tcg_regset_set_reg(s->reserved_regs, TCG_REG_TMP0);
3187da4d0d95SRichard Henderson    tcg_regset_set_reg(s->reserved_regs, TCG_REG_TMP1);
3188da4d0d95SRichard Henderson    tcg_regset_set_reg(s->reserved_regs, TCG_REG_TMP2);
3189d67bcbddSRichard Henderson    tcg_regset_set_reg(s->reserved_regs, TCG_VEC_TMP0);
3190139c1837SPaolo Bonzini}
3191139c1837SPaolo Bonzini
3192139c1837SPaolo Bonzini/* Saving pairs: (X19, X20) .. (X27, X28), (X29(fp), X30(lr)).  */
3193139c1837SPaolo Bonzini#define PUSH_SIZE  ((30 - 19 + 1) * 8)
3194139c1837SPaolo Bonzini
3195139c1837SPaolo Bonzini#define FRAME_SIZE \
3196139c1837SPaolo Bonzini    ((PUSH_SIZE \
3197139c1837SPaolo Bonzini      + TCG_STATIC_CALL_ARGS_SIZE \
3198139c1837SPaolo Bonzini      + CPU_TEMP_BUF_NLONGS * sizeof(long) \
3199139c1837SPaolo Bonzini      + TCG_TARGET_STACK_ALIGN - 1) \
3200139c1837SPaolo Bonzini     & ~(TCG_TARGET_STACK_ALIGN - 1))
3201139c1837SPaolo Bonzini
3202139c1837SPaolo Bonzini/* We're expecting a 2 byte uleb128 encoded value.  */
3203139c1837SPaolo BonziniQEMU_BUILD_BUG_ON(FRAME_SIZE >= (1 << 14));
3204139c1837SPaolo Bonzini
3205139c1837SPaolo Bonzini/* We're expecting to use a single ADDI insn.  */
3206139c1837SPaolo BonziniQEMU_BUILD_BUG_ON(FRAME_SIZE - PUSH_SIZE > 0xfff);
3207139c1837SPaolo Bonzini
3208139c1837SPaolo Bonzinistatic void tcg_target_qemu_prologue(TCGContext *s)
3209139c1837SPaolo Bonzini{
3210139c1837SPaolo Bonzini    TCGReg r;
3211139c1837SPaolo Bonzini
32125826a0dbSRichard Henderson    tcg_out_bti(s, BTI_C);
32135826a0dbSRichard Henderson
3214139c1837SPaolo Bonzini    /* Push (FP, LR) and allocate space for all saved registers.  */
3215139c1837SPaolo Bonzini    tcg_out_insn(s, 3314, STP, TCG_REG_FP, TCG_REG_LR,
3216139c1837SPaolo Bonzini                 TCG_REG_SP, -PUSH_SIZE, 1, 1);
3217139c1837SPaolo Bonzini
3218139c1837SPaolo Bonzini    /* Set up frame pointer for canonical unwinding.  */
3219139c1837SPaolo Bonzini    tcg_out_movr_sp(s, TCG_TYPE_I64, TCG_REG_FP, TCG_REG_SP);
3220139c1837SPaolo Bonzini
3221139c1837SPaolo Bonzini    /* Store callee-preserved regs x19..x28.  */
3222139c1837SPaolo Bonzini    for (r = TCG_REG_X19; r <= TCG_REG_X27; r += 2) {
3223139c1837SPaolo Bonzini        int ofs = (r - TCG_REG_X19 + 2) * 8;
3224139c1837SPaolo Bonzini        tcg_out_insn(s, 3314, STP, r, r + 1, TCG_REG_SP, ofs, 1, 0);
3225139c1837SPaolo Bonzini    }
3226139c1837SPaolo Bonzini
3227139c1837SPaolo Bonzini    /* Make stack space for TCG locals.  */
3228139c1837SPaolo Bonzini    tcg_out_insn(s, 3401, SUBI, TCG_TYPE_I64, TCG_REG_SP, TCG_REG_SP,
3229139c1837SPaolo Bonzini                 FRAME_SIZE - PUSH_SIZE);
3230139c1837SPaolo Bonzini
3231139c1837SPaolo Bonzini    /* Inform TCG about how to find TCG locals with register, offset, size.  */
3232139c1837SPaolo Bonzini    tcg_set_frame(s, TCG_REG_SP, TCG_STATIC_CALL_ARGS_SIZE,
3233139c1837SPaolo Bonzini                  CPU_TEMP_BUF_NLONGS * sizeof(long));
3234139c1837SPaolo Bonzini
3235e2b7a40dSRichard Henderson    if (!tcg_use_softmmu) {
323652533157SRichard Henderson        /*
323752533157SRichard Henderson         * Note that XZR cannot be encoded in the address base register slot,
32384daad8d9SMichael Tokarev         * as that actually encodes SP.  Depending on the guest, we may need
323952533157SRichard Henderson         * to zero-extend the guest address via the address index register slot,
324052533157SRichard Henderson         * therefore we need to load even a zero guest base into a register.
324152533157SRichard Henderson         */
3242139c1837SPaolo Bonzini        tcg_out_movi(s, TCG_TYPE_PTR, TCG_REG_GUEST_BASE, guest_base);
3243139c1837SPaolo Bonzini        tcg_regset_set_reg(s->reserved_regs, TCG_REG_GUEST_BASE);
3244e2b7a40dSRichard Henderson    }
3245139c1837SPaolo Bonzini
3246139c1837SPaolo Bonzini    tcg_out_mov(s, TCG_TYPE_PTR, TCG_AREG0, tcg_target_call_iarg_regs[0]);
3247139c1837SPaolo Bonzini    tcg_out_insn(s, 3207, BR, tcg_target_call_iarg_regs[1]);
3248139c1837SPaolo Bonzini
3249139c1837SPaolo Bonzini    /*
3250139c1837SPaolo Bonzini     * Return path for goto_ptr. Set return value to 0, a-la exit_tb,
3251139c1837SPaolo Bonzini     * and fall through to the rest of the epilogue.
3252139c1837SPaolo Bonzini     */
3253c8bc1168SRichard Henderson    tcg_code_gen_epilogue = tcg_splitwx_to_rx(s->code_ptr);
32545826a0dbSRichard Henderson    tcg_out_bti(s, BTI_J);
3255139c1837SPaolo Bonzini    tcg_out_movi(s, TCG_TYPE_REG, TCG_REG_X0, 0);
3256139c1837SPaolo Bonzini
3257139c1837SPaolo Bonzini    /* TB epilogue */
3258ffba3eb3SRichard Henderson    tb_ret_addr = tcg_splitwx_to_rx(s->code_ptr);
32595826a0dbSRichard Henderson    tcg_out_bti(s, BTI_J);
3260139c1837SPaolo Bonzini
3261139c1837SPaolo Bonzini    /* Remove TCG locals stack space.  */
3262139c1837SPaolo Bonzini    tcg_out_insn(s, 3401, ADDI, TCG_TYPE_I64, TCG_REG_SP, TCG_REG_SP,
3263139c1837SPaolo Bonzini                 FRAME_SIZE - PUSH_SIZE);
3264139c1837SPaolo Bonzini
3265139c1837SPaolo Bonzini    /* Restore registers x19..x28.  */
3266139c1837SPaolo Bonzini    for (r = TCG_REG_X19; r <= TCG_REG_X27; r += 2) {
3267139c1837SPaolo Bonzini        int ofs = (r - TCG_REG_X19 + 2) * 8;
3268139c1837SPaolo Bonzini        tcg_out_insn(s, 3314, LDP, r, r + 1, TCG_REG_SP, ofs, 1, 0);
3269139c1837SPaolo Bonzini    }
3270139c1837SPaolo Bonzini
3271139c1837SPaolo Bonzini    /* Pop (FP, LR), restore SP to previous frame.  */
3272139c1837SPaolo Bonzini    tcg_out_insn(s, 3314, LDP, TCG_REG_FP, TCG_REG_LR,
3273139c1837SPaolo Bonzini                 TCG_REG_SP, PUSH_SIZE, 0, 1);
3274139c1837SPaolo Bonzini    tcg_out_insn(s, 3207, RET, TCG_REG_LR);
3275139c1837SPaolo Bonzini}
3276139c1837SPaolo Bonzini
32779358fbbfSRichard Hendersonstatic void tcg_out_tb_start(TCGContext *s)
32789358fbbfSRichard Henderson{
32795826a0dbSRichard Henderson    tcg_out_bti(s, BTI_J);
32809358fbbfSRichard Henderson}
32819358fbbfSRichard Henderson
3282139c1837SPaolo Bonzinistatic void tcg_out_nop_fill(tcg_insn_unit *p, int count)
3283139c1837SPaolo Bonzini{
3284139c1837SPaolo Bonzini    int i;
3285139c1837SPaolo Bonzini    for (i = 0; i < count; ++i) {
3286139c1837SPaolo Bonzini        p[i] = NOP;
3287139c1837SPaolo Bonzini    }
3288139c1837SPaolo Bonzini}
3289139c1837SPaolo Bonzini
3290139c1837SPaolo Bonzinitypedef struct {
3291139c1837SPaolo Bonzini    DebugFrameHeader h;
3292139c1837SPaolo Bonzini    uint8_t fde_def_cfa[4];
3293139c1837SPaolo Bonzini    uint8_t fde_reg_ofs[24];
3294139c1837SPaolo Bonzini} DebugFrame;
3295139c1837SPaolo Bonzini
3296139c1837SPaolo Bonzini#define ELF_HOST_MACHINE EM_AARCH64
3297139c1837SPaolo Bonzini
3298139c1837SPaolo Bonzinistatic const DebugFrame debug_frame = {
3299139c1837SPaolo Bonzini    .h.cie.len = sizeof(DebugFrameCIE)-4, /* length after .len member */
3300139c1837SPaolo Bonzini    .h.cie.id = -1,
3301139c1837SPaolo Bonzini    .h.cie.version = 1,
3302139c1837SPaolo Bonzini    .h.cie.code_align = 1,
3303139c1837SPaolo Bonzini    .h.cie.data_align = 0x78,             /* sleb128 -8 */
3304139c1837SPaolo Bonzini    .h.cie.return_column = TCG_REG_LR,
3305139c1837SPaolo Bonzini
3306139c1837SPaolo Bonzini    /* Total FDE size does not include the "len" member.  */
3307139c1837SPaolo Bonzini    .h.fde.len = sizeof(DebugFrame) - offsetof(DebugFrame, h.fde.cie_offset),
3308139c1837SPaolo Bonzini
3309139c1837SPaolo Bonzini    .fde_def_cfa = {
3310139c1837SPaolo Bonzini        12, TCG_REG_SP,                 /* DW_CFA_def_cfa sp, ... */
3311139c1837SPaolo Bonzini        (FRAME_SIZE & 0x7f) | 0x80,     /* ... uleb128 FRAME_SIZE */
3312139c1837SPaolo Bonzini        (FRAME_SIZE >> 7)
3313139c1837SPaolo Bonzini    },
3314139c1837SPaolo Bonzini    .fde_reg_ofs = {
3315139c1837SPaolo Bonzini        0x80 + 28, 1,                   /* DW_CFA_offset, x28,  -8 */
3316139c1837SPaolo Bonzini        0x80 + 27, 2,                   /* DW_CFA_offset, x27, -16 */
3317139c1837SPaolo Bonzini        0x80 + 26, 3,                   /* DW_CFA_offset, x26, -24 */
3318139c1837SPaolo Bonzini        0x80 + 25, 4,                   /* DW_CFA_offset, x25, -32 */
3319139c1837SPaolo Bonzini        0x80 + 24, 5,                   /* DW_CFA_offset, x24, -40 */
3320139c1837SPaolo Bonzini        0x80 + 23, 6,                   /* DW_CFA_offset, x23, -48 */
3321139c1837SPaolo Bonzini        0x80 + 22, 7,                   /* DW_CFA_offset, x22, -56 */
3322139c1837SPaolo Bonzini        0x80 + 21, 8,                   /* DW_CFA_offset, x21, -64 */
3323139c1837SPaolo Bonzini        0x80 + 20, 9,                   /* DW_CFA_offset, x20, -72 */
3324139c1837SPaolo Bonzini        0x80 + 19, 10,                  /* DW_CFA_offset, x1p, -80 */
3325139c1837SPaolo Bonzini        0x80 + 30, 11,                  /* DW_CFA_offset,  lr, -88 */
3326139c1837SPaolo Bonzini        0x80 + 29, 12,                  /* DW_CFA_offset,  fp, -96 */
3327139c1837SPaolo Bonzini    }
3328139c1837SPaolo Bonzini};
3329139c1837SPaolo Bonzini
3330755bf9e5SRichard Hendersonvoid tcg_register_jit(const void *buf, size_t buf_size)
3331139c1837SPaolo Bonzini{
3332139c1837SPaolo Bonzini    tcg_register_jit_int(buf, buf_size, &debug_frame, sizeof(debug_frame));
3333139c1837SPaolo Bonzini}
3334