xref: /openbmc/qemu/target/arm/tcg/translate.h (revision a75e415ca55df01d6d9e0e1698d8bc0c620dcc85)
1f0984d40SFabiano Rosas #ifndef TARGET_ARM_TRANSLATE_H
2f0984d40SFabiano Rosas #define TARGET_ARM_TRANSLATE_H
3f0984d40SFabiano Rosas 
45d05e5a1SRichard Henderson #include "cpu.h"
55d05e5a1SRichard Henderson #include "tcg/tcg-op.h"
65d05e5a1SRichard Henderson #include "tcg/tcg-op-gvec.h"
71f17f91dSRichard Henderson #include "exec/exec-all.h"
8f0984d40SFabiano Rosas #include "exec/translator.h"
9a46f42d9SRichard Henderson #include "exec/helper-gen.h"
10f0984d40SFabiano Rosas #include "internals.h"
115a534314SPeter Maydell #include "cpu-features.h"
12f0984d40SFabiano Rosas 
13f0984d40SFabiano Rosas /* internal defines */
14f0984d40SFabiano Rosas 
15f0984d40SFabiano Rosas /*
16f0984d40SFabiano Rosas  * Save pc_save across a branch, so that we may restore the value from
17f0984d40SFabiano Rosas  * before the branch at the point the label is emitted.
18f0984d40SFabiano Rosas  */
19f0984d40SFabiano Rosas typedef struct DisasLabel {
20f0984d40SFabiano Rosas     TCGLabel *label;
21f0984d40SFabiano Rosas     target_ulong pc_save;
22f0984d40SFabiano Rosas } DisasLabel;
23f0984d40SFabiano Rosas 
24f0984d40SFabiano Rosas typedef struct DisasContext {
25f0984d40SFabiano Rosas     DisasContextBase base;
26f0984d40SFabiano Rosas     const ARMISARegisters *isar;
27f0984d40SFabiano Rosas 
28f0984d40SFabiano Rosas     /* The address of the current instruction being translated. */
29f0984d40SFabiano Rosas     target_ulong pc_curr;
30f0984d40SFabiano Rosas     /*
3103a648c4SAnton Johansson      * For CF_PCREL, the full value of cpu_pc is not known
32f0984d40SFabiano Rosas      * (although the page offset is known).  For convenience, the
33f0984d40SFabiano Rosas      * translation loop uses the full virtual address that triggered
34f0984d40SFabiano Rosas      * the translation, from base.pc_start through pc_curr.
35f0984d40SFabiano Rosas      * For efficiency, we do not update cpu_pc for every instruction.
36f0984d40SFabiano Rosas      * Instead, pc_save has the value of pc_curr at the time of the
37f0984d40SFabiano Rosas      * last update to cpu_pc, which allows us to compute the addend
38f0984d40SFabiano Rosas      * needed to bring cpu_pc current: pc_curr - pc_save.
39f0984d40SFabiano Rosas      * If cpu_pc now contains the destination of an indirect branch,
40f0984d40SFabiano Rosas      * pc_save contains -1 to indicate that relative updates are no
41f0984d40SFabiano Rosas      * longer possible.
42f0984d40SFabiano Rosas      */
43f0984d40SFabiano Rosas     target_ulong pc_save;
44f0984d40SFabiano Rosas     target_ulong page_start;
45f0984d40SFabiano Rosas     uint32_t insn;
46f0984d40SFabiano Rosas     /* Nonzero if this instruction has been conditionally skipped.  */
47f0984d40SFabiano Rosas     int condjmp;
48f0984d40SFabiano Rosas     /* The label that will be jumped to when the instruction is skipped.  */
49f0984d40SFabiano Rosas     DisasLabel condlabel;
50f0984d40SFabiano Rosas     /* Thumb-2 conditional execution bits.  */
51f0984d40SFabiano Rosas     int condexec_mask;
52f0984d40SFabiano Rosas     int condexec_cond;
53f0984d40SFabiano Rosas     /* M-profile ECI/ICI exception-continuable instruction state */
54f0984d40SFabiano Rosas     int eci;
55f0984d40SFabiano Rosas     /*
56f0984d40SFabiano Rosas      * trans_ functions for insns which are continuable should set this true
57f0984d40SFabiano Rosas      * after decode (ie after any UNDEF checks)
58f0984d40SFabiano Rosas      */
59f0984d40SFabiano Rosas     bool eci_handled;
60f0984d40SFabiano Rosas     int sctlr_b;
61f0984d40SFabiano Rosas     MemOp be_data;
62f0984d40SFabiano Rosas #if !defined(CONFIG_USER_ONLY)
63f0984d40SFabiano Rosas     int user;
64f0984d40SFabiano Rosas #endif
65f0984d40SFabiano Rosas     ARMMMUIdx mmu_idx; /* MMU index to use for normal loads/stores */
66f0984d40SFabiano Rosas     uint8_t tbii;      /* TBI1|TBI0 for insns */
67f0984d40SFabiano Rosas     uint8_t tbid;      /* TBI1|TBI0 for data */
68f0984d40SFabiano Rosas     uint8_t tcma;      /* TCMA1|TCMA0 for MTE */
69f0984d40SFabiano Rosas     bool ns;        /* Use non-secure CPREG bank on access */
70f0984d40SFabiano Rosas     int fp_excp_el; /* FP exception EL or 0 if enabled */
71f0984d40SFabiano Rosas     int sve_excp_el; /* SVE exception EL or 0 if enabled */
72f0984d40SFabiano Rosas     int sme_excp_el; /* SME exception EL or 0 if enabled */
73f0984d40SFabiano Rosas     int vl;          /* current vector length in bytes */
74f0984d40SFabiano Rosas     int svl;         /* current streaming vector length in bytes */
75f0984d40SFabiano Rosas     bool vfp_enabled; /* FP enabled via FPSCR.EN */
76f0984d40SFabiano Rosas     int vec_len;
77f0984d40SFabiano Rosas     int vec_stride;
78f0984d40SFabiano Rosas     bool v7m_handler_mode;
79f0984d40SFabiano Rosas     bool v8m_secure; /* true if v8M and we're in Secure mode */
80f0984d40SFabiano Rosas     bool v8m_stackcheck; /* true if we need to perform v8M stack limit checks */
81f0984d40SFabiano Rosas     bool v8m_fpccr_s_wrong; /* true if v8M FPCCR.S != v8m_secure */
82f0984d40SFabiano Rosas     bool v7m_new_fp_ctxt_needed; /* ASPEN set but no active FP context */
83f0984d40SFabiano Rosas     bool v7m_lspact; /* FPCCR.LSPACT set */
84f0984d40SFabiano Rosas     /* Immediate value in AArch32 SVC insn; must be set if is_jmp == DISAS_SWI
85f0984d40SFabiano Rosas      * so that top level loop can generate correct syndrome information.
86f0984d40SFabiano Rosas      */
87f0984d40SFabiano Rosas     uint32_t svc_imm;
88f0984d40SFabiano Rosas     int current_el;
89f0984d40SFabiano Rosas     GHashTable *cp_regs;
90f0984d40SFabiano Rosas     uint64_t features; /* CPU features bits */
91f0984d40SFabiano Rosas     bool aarch64;
92f0984d40SFabiano Rosas     bool thumb;
93e452ca5aSRichard Henderson     bool lse2;
94*a75e415cSRichard Henderson     /*
95*a75e415cSRichard Henderson      * Because unallocated encodings generate different exception syndrome
96f0984d40SFabiano Rosas      * information from traps due to FP being disabled, we can't do a single
97f0984d40SFabiano Rosas      * "is fp access disabled" check at a high level in the decode tree.
98f0984d40SFabiano Rosas      * To help in catching bugs where the access check was forgotten in some
99f0984d40SFabiano Rosas      * code path, we set this flag when the access check is done, and assert
100f0984d40SFabiano Rosas      * that it is set at the point where we actually touch the FP regs.
101*a75e415cSRichard Henderson      *   0: not checked,
102*a75e415cSRichard Henderson      *   1: checked, access ok
103*a75e415cSRichard Henderson      *  -1: checked, access denied
104f0984d40SFabiano Rosas      */
105*a75e415cSRichard Henderson     int8_t fp_access_checked;
106*a75e415cSRichard Henderson     int8_t sve_access_checked;
107f0984d40SFabiano Rosas     /* ARMv8 single-step state (this is distinct from the QEMU gdbstub
108f0984d40SFabiano Rosas      * single-step support).
109f0984d40SFabiano Rosas      */
110f0984d40SFabiano Rosas     bool ss_active;
111f0984d40SFabiano Rosas     bool pstate_ss;
112f0984d40SFabiano Rosas     /* True if the insn just emitted was a load-exclusive instruction
113f0984d40SFabiano Rosas      * (necessary for syndrome information for single step exceptions),
114f0984d40SFabiano Rosas      * ie A64 LDX*, LDAX*, A32/T32 LDREX*, LDAEX*.
115f0984d40SFabiano Rosas      */
116f0984d40SFabiano Rosas     bool is_ldex;
117f0984d40SFabiano Rosas     /* True if AccType_UNPRIV should be used for LDTR et al */
118f0984d40SFabiano Rosas     bool unpriv;
119f0984d40SFabiano Rosas     /* True if v8.3-PAuth is active.  */
120f0984d40SFabiano Rosas     bool pauth_active;
121179e9a3bSPeter Maydell     /* True if v8.5-MTE access to tags is enabled; index with is_unpriv.  */
122179e9a3bSPeter Maydell     bool ata[2];
123f0984d40SFabiano Rosas     /* True if v8.5-MTE tag checks affect the PE; index with is_unpriv.  */
124f0984d40SFabiano Rosas     bool mte_active[2];
125f0984d40SFabiano Rosas     /* True with v8.5-BTI and SCTLR_ELx.BT* set.  */
126f0984d40SFabiano Rosas     bool bt;
127f0984d40SFabiano Rosas     /* True if any CP15 access is trapped by HSTR_EL2 */
128f0984d40SFabiano Rosas     bool hstr_active;
129f0984d40SFabiano Rosas     /* True if memory operations require alignment */
130f0984d40SFabiano Rosas     bool align_mem;
131f0984d40SFabiano Rosas     /* True if PSTATE.IL is set */
132f0984d40SFabiano Rosas     bool pstate_il;
133f0984d40SFabiano Rosas     /* True if PSTATE.SM is set. */
134f0984d40SFabiano Rosas     bool pstate_sm;
135f0984d40SFabiano Rosas     /* True if PSTATE.ZA is set. */
136f0984d40SFabiano Rosas     bool pstate_za;
137f0984d40SFabiano Rosas     /* True if non-streaming insns should raise an SME Streaming exception. */
138f0984d40SFabiano Rosas     bool sme_trap_nonstreaming;
139f0984d40SFabiano Rosas     /* True if the current instruction is non-streaming. */
140f0984d40SFabiano Rosas     bool is_nonstreaming;
141f0984d40SFabiano Rosas     /* True if MVE insns are definitely not predicated by VPR or LTPSIZE */
142f0984d40SFabiano Rosas     bool mve_no_pred;
143f0984d40SFabiano Rosas     /* True if fine-grained traps are active */
144f0984d40SFabiano Rosas     bool fgt_active;
145f0984d40SFabiano Rosas     /* True if fine-grained trap on SVC is enabled */
146f0984d40SFabiano Rosas     bool fgt_svc;
147e37e98b7SPeter Maydell     /* True if a trap on ERET is enabled (FGT or NV) */
148e37e98b7SPeter Maydell     bool trap_eret;
14983f624d9SRichard Henderson     /* True if FEAT_LSE2 SCTLR_ELx.nAA is set */
15083f624d9SRichard Henderson     bool naa;
15167d10fc4SPeter Maydell     /* True if FEAT_NV HCR_EL2.NV is enabled */
15267d10fc4SPeter Maydell     bool nv;
153c35da11dSPeter Maydell     /* True if NV enabled and HCR_EL2.NV1 is set */
154c35da11dSPeter Maydell     bool nv1;
155c35da11dSPeter Maydell     /* True if NV enabled and HCR_EL2.NV2 is set */
156c35da11dSPeter Maydell     bool nv2;
157daf9b4a0SPeter Maydell     /* True if NV2 enabled and NV2 RAM accesses use EL2&0 translation regime */
158daf9b4a0SPeter Maydell     bool nv2_mem_e20;
159daf9b4a0SPeter Maydell     /* True if NV2 enabled and NV2 RAM accesses are big-endian */
160daf9b4a0SPeter Maydell     bool nv2_mem_be;
161f0984d40SFabiano Rosas     /*
162f0984d40SFabiano Rosas      * >= 0, a copy of PSTATE.BTYPE, which will be 0 without v8.5-BTI.
163f0984d40SFabiano Rosas      *  < 0, set by the current instruction.
164f0984d40SFabiano Rosas      */
165f0984d40SFabiano Rosas     int8_t btype;
166f0984d40SFabiano Rosas     /* A copy of cpu->dcz_blocksize. */
167f0984d40SFabiano Rosas     uint8_t dcz_blocksize;
168851ec6ebSRichard Henderson     /* A copy of cpu->gm_blocksize. */
169851ec6ebSRichard Henderson     uint8_t gm_blocksize;
1704642250eSRichard Henderson     /* True if the current insn_start has been updated. */
1714642250eSRichard Henderson     bool insn_start_updated;
172f0984d40SFabiano Rosas     /* Bottom two bits of XScale c15_cpar coprocessor access control reg */
173f0984d40SFabiano Rosas     int c15_cpar;
174daf9b4a0SPeter Maydell     /* Offset from VNCR_EL2 when FEAT_NV2 redirects this reg to memory */
175daf9b4a0SPeter Maydell     uint32_t nv2_redirect_offset;
176f0984d40SFabiano Rosas } DisasContext;
177f0984d40SFabiano Rosas 
178f0984d40SFabiano Rosas typedef struct DisasCompare {
179f0984d40SFabiano Rosas     TCGCond cond;
180f0984d40SFabiano Rosas     TCGv_i32 value;
181f0984d40SFabiano Rosas } DisasCompare;
182f0984d40SFabiano Rosas 
183f0984d40SFabiano Rosas /* Share the TCG temporaries common between 32 and 64 bit modes.  */
184f0984d40SFabiano Rosas extern TCGv_i32 cpu_NF, cpu_ZF, cpu_CF, cpu_VF;
185f0984d40SFabiano Rosas extern TCGv_i64 cpu_exclusive_addr;
186f0984d40SFabiano Rosas extern TCGv_i64 cpu_exclusive_val;
187f0984d40SFabiano Rosas 
negate(DisasContext * s,int x)188f0984d40SFabiano Rosas /*
189f0984d40SFabiano Rosas  * Constant expanders for the decoders.
190f0984d40SFabiano Rosas  */
191f0984d40SFabiano Rosas 
192f0984d40SFabiano Rosas static inline int negate(DisasContext *s, int x)
193f0984d40SFabiano Rosas {
194f0984d40SFabiano Rosas     return -x;
195f0984d40SFabiano Rosas }
196f0984d40SFabiano Rosas 
197f0984d40SFabiano Rosas static inline int plus_1(DisasContext *s, int x)
plus_2(DisasContext * s,int x)198f0984d40SFabiano Rosas {
199f0984d40SFabiano Rosas     return x + 1;
200f0984d40SFabiano Rosas }
201f0984d40SFabiano Rosas 
202f0984d40SFabiano Rosas static inline int plus_2(DisasContext *s, int x)
plus_12(DisasContext * s,int x)203f0984d40SFabiano Rosas {
204f0984d40SFabiano Rosas     return x + 2;
205f0984d40SFabiano Rosas }
206f0984d40SFabiano Rosas 
207f0984d40SFabiano Rosas static inline int plus_12(DisasContext *s, int x)
times_2(DisasContext * s,int x)208f0984d40SFabiano Rosas {
209f0984d40SFabiano Rosas     return x + 12;
210f0984d40SFabiano Rosas }
211f0984d40SFabiano Rosas 
212f0984d40SFabiano Rosas static inline int times_2(DisasContext *s, int x)
times_4(DisasContext * s,int x)213f0984d40SFabiano Rosas {
214f0984d40SFabiano Rosas     return x * 2;
215f0984d40SFabiano Rosas }
216f0984d40SFabiano Rosas 
217f0984d40SFabiano Rosas static inline int times_4(DisasContext *s, int x)
times_8(DisasContext * s,int x)218f0984d40SFabiano Rosas {
219f0984d40SFabiano Rosas     return x * 4;
220f0984d40SFabiano Rosas }
221f0984d40SFabiano Rosas 
2225722fc47SPeter Maydell static inline int times_8(DisasContext *s, int x)
times_2_plus_1(DisasContext * s,int x)2235722fc47SPeter Maydell {
2245722fc47SPeter Maydell     return x * 8;
2255722fc47SPeter Maydell }
2265722fc47SPeter Maydell 
227f0984d40SFabiano Rosas static inline int times_2_plus_1(DisasContext *s, int x)
rsub_64(DisasContext * s,int x)228f0984d40SFabiano Rosas {
229f0984d40SFabiano Rosas     return x * 2 + 1;
230f0984d40SFabiano Rosas }
231f0984d40SFabiano Rosas 
232f0984d40SFabiano Rosas static inline int rsub_64(DisasContext *s, int x)
rsub_32(DisasContext * s,int x)233f0984d40SFabiano Rosas {
234f0984d40SFabiano Rosas     return 64 - x;
235f0984d40SFabiano Rosas }
236f0984d40SFabiano Rosas 
237f0984d40SFabiano Rosas static inline int rsub_32(DisasContext *s, int x)
rsub_16(DisasContext * s,int x)238f0984d40SFabiano Rosas {
239f0984d40SFabiano Rosas     return 32 - x;
240f0984d40SFabiano Rosas }
241f0984d40SFabiano Rosas 
242f0984d40SFabiano Rosas static inline int rsub_16(DisasContext *s, int x)
rsub_8(DisasContext * s,int x)243f0984d40SFabiano Rosas {
244f0984d40SFabiano Rosas     return 16 - x;
245f0984d40SFabiano Rosas }
246f0984d40SFabiano Rosas 
247f0984d40SFabiano Rosas static inline int rsub_8(DisasContext *s, int x)
shl_12(DisasContext * s,int x)248f0984d40SFabiano Rosas {
249f0984d40SFabiano Rosas     return 8 - x;
250f0984d40SFabiano Rosas }
251f0984d40SFabiano Rosas 
2523ce7b5eaSRichard Henderson static inline int shl_12(DisasContext *s, int x)
xor_2(DisasContext * s,int x)2533ce7b5eaSRichard Henderson {
2543ce7b5eaSRichard Henderson     return x << 12;
2553ce7b5eaSRichard Henderson }
2563ce7b5eaSRichard Henderson 
257e0300a9aSRichard Henderson static inline int xor_2(DisasContext *s, int x)
neon_3same_fp_size(DisasContext * s,int x)258e0300a9aSRichard Henderson {
259e0300a9aSRichard Henderson     return x ^ 2;
260e0300a9aSRichard Henderson }
261e0300a9aSRichard Henderson 
262f0984d40SFabiano Rosas static inline int neon_3same_fp_size(DisasContext *s, int x)
263f0984d40SFabiano Rosas {
arm_dc_feature(DisasContext * dc,int feature)264f0984d40SFabiano Rosas     /* Convert 0==fp32, 1==fp16 into a MO_* value */
265f0984d40SFabiano Rosas     return MO_32 - x;
266f0984d40SFabiano Rosas }
267f0984d40SFabiano Rosas 
268f0984d40SFabiano Rosas static inline int arm_dc_feature(DisasContext *dc, int feature)
get_mem_index(DisasContext * s)269f0984d40SFabiano Rosas {
270f0984d40SFabiano Rosas     return (dc->features & (1ULL << feature)) != 0;
271f0984d40SFabiano Rosas }
272f0984d40SFabiano Rosas 
273f0984d40SFabiano Rosas static inline int get_mem_index(DisasContext *s)
disas_set_insn_syndrome(DisasContext * s,uint32_t syn)274f0984d40SFabiano Rosas {
275f0984d40SFabiano Rosas     return arm_to_core_mmu_idx(s->mmu_idx);
276f0984d40SFabiano Rosas }
277f0984d40SFabiano Rosas 
278f0984d40SFabiano Rosas static inline void disas_set_insn_syndrome(DisasContext *s, uint32_t syn)
279f0984d40SFabiano Rosas {
280f0984d40SFabiano Rosas     /* We don't need to save all of the syndrome so we mask and shift
281f0984d40SFabiano Rosas      * out unneeded bits to help the sleb128 encoder do a better job.
282f0984d40SFabiano Rosas      */
283f0984d40SFabiano Rosas     syn &= ARM_INSN_START_WORD2_MASK;
284f0984d40SFabiano Rosas     syn >>= ARM_INSN_START_WORD2_SHIFT;
285f0984d40SFabiano Rosas 
2864642250eSRichard Henderson     /* Check for multiple updates.  */
2874642250eSRichard Henderson     assert(!s->insn_start_updated);
curr_insn_len(DisasContext * s)2884642250eSRichard Henderson     s->insn_start_updated = true;
2894642250eSRichard Henderson     tcg_set_insn_start_param(s->base.insn_start, 2, syn);
290f0984d40SFabiano Rosas }
291f0984d40SFabiano Rosas 
292f0984d40SFabiano Rosas static inline int curr_insn_len(DisasContext *s)
293f0984d40SFabiano Rosas {
294f0984d40SFabiano Rosas     return s->base.pc_next - s->pc_curr;
295f0984d40SFabiano Rosas }
296f0984d40SFabiano Rosas 
297f0984d40SFabiano Rosas /* is_jmp field values */
298f0984d40SFabiano Rosas #define DISAS_JUMP      DISAS_TARGET_0 /* only pc was modified dynamically */
299f0984d40SFabiano Rosas /* CPU state was modified dynamically; exit to main loop for interrupts. */
300f0984d40SFabiano Rosas #define DISAS_UPDATE_EXIT  DISAS_TARGET_1
301f0984d40SFabiano Rosas /* These instructions trap after executing, so the A32/T32 decoder must
302f0984d40SFabiano Rosas  * defer them until after the conditional execution state has been updated.
303f0984d40SFabiano Rosas  * WFI also needs special handling when single-stepping.
304f0984d40SFabiano Rosas  */
305f0984d40SFabiano Rosas #define DISAS_WFI       DISAS_TARGET_2
306f0984d40SFabiano Rosas #define DISAS_SWI       DISAS_TARGET_3
307f0984d40SFabiano Rosas /* WFE */
308f0984d40SFabiano Rosas #define DISAS_WFE       DISAS_TARGET_4
309f0984d40SFabiano Rosas #define DISAS_HVC       DISAS_TARGET_5
310f0984d40SFabiano Rosas #define DISAS_SMC       DISAS_TARGET_6
311f0984d40SFabiano Rosas #define DISAS_YIELD     DISAS_TARGET_7
312f0984d40SFabiano Rosas /* M profile branch which might be an exception return (and so needs
313f0984d40SFabiano Rosas  * custom end-of-TB code)
314f0984d40SFabiano Rosas  */
315f0984d40SFabiano Rosas #define DISAS_BX_EXCRET DISAS_TARGET_8
316f0984d40SFabiano Rosas /*
317f0984d40SFabiano Rosas  * For instructions which want an immediate exit to the main loop, as opposed
318f0984d40SFabiano Rosas  * to attempting to use lookup_and_goto_ptr.  Unlike DISAS_UPDATE_EXIT, this
319f0984d40SFabiano Rosas  * doesn't write the PC on exiting the translation loop so you need to ensure
320f0984d40SFabiano Rosas  * something (gen_a64_update_pc or runtime helper) has done so before we reach
321f0984d40SFabiano Rosas  * return from cpu_tb_exec.
322f0984d40SFabiano Rosas  */
323f0984d40SFabiano Rosas #define DISAS_EXIT      DISAS_TARGET_9
324f0984d40SFabiano Rosas /* CPU state was modified dynamically; no need to exit, but do not chain. */
325f0984d40SFabiano Rosas #define DISAS_UPDATE_NOCHAIN  DISAS_TARGET_10
326f0984d40SFabiano Rosas 
327f0984d40SFabiano Rosas #ifdef TARGET_AARCH64
a64_translate_init(void)328f0984d40SFabiano Rosas void a64_translate_init(void);
329f0984d40SFabiano Rosas void gen_a64_update_pc(DisasContext *s, target_long diff);
330f0984d40SFabiano Rosas extern const TranslatorOps aarch64_translator_ops;
331f0984d40SFabiano Rosas #else
gen_a64_update_pc(DisasContext * s,target_long diff)332f0984d40SFabiano Rosas static inline void a64_translate_init(void)
333f0984d40SFabiano Rosas {
334f0984d40SFabiano Rosas }
335f0984d40SFabiano Rosas 
336f0984d40SFabiano Rosas static inline void gen_a64_update_pc(DisasContext *s, target_long diff)
337f0984d40SFabiano Rosas {
338f0984d40SFabiano Rosas }
339f0984d40SFabiano Rosas #endif
340f0984d40SFabiano Rosas 
341f0984d40SFabiano Rosas void arm_test_cc(DisasCompare *cmp, int cc);
342f0984d40SFabiano Rosas void arm_jump_cc(DisasCompare *cmp, TCGLabel *label);
343f0984d40SFabiano Rosas void arm_gen_test_cc(int cc, TCGLabel *label);
344f0984d40SFabiano Rosas MemOp pow2_align(unsigned i);
345f0984d40SFabiano Rosas void unallocated_encoding(DisasContext *s);
346f0984d40SFabiano Rosas void gen_exception_insn_el(DisasContext *s, target_long pc_diff, int excp,
347f0984d40SFabiano Rosas                            uint32_t syn, uint32_t target_el);
get_ahp_flag(void)348f0984d40SFabiano Rosas void gen_exception_insn(DisasContext *s, target_long pc_diff,
349f0984d40SFabiano Rosas                         int excp, uint32_t syn);
350f0984d40SFabiano Rosas 
351f0984d40SFabiano Rosas /* Return state of Alternate Half-precision flag, caller frees result */
352f0984d40SFabiano Rosas static inline TCGv_i32 get_ahp_flag(void)
353f0984d40SFabiano Rosas {
354f0984d40SFabiano Rosas     TCGv_i32 ret = tcg_temp_new_i32();
355f0984d40SFabiano Rosas 
356ce07ea61SPeter Maydell     tcg_gen_ld_i32(ret, tcg_env, offsetoflow32(CPUARMState, vfp.fpcr));
357f0984d40SFabiano Rosas     tcg_gen_extract_i32(ret, ret, 26, 1);
358f0984d40SFabiano Rosas 
set_pstate_bits(uint32_t bits)359f0984d40SFabiano Rosas     return ret;
360f0984d40SFabiano Rosas }
361f0984d40SFabiano Rosas 
362f0984d40SFabiano Rosas /* Set bits within PSTATE.  */
363f0984d40SFabiano Rosas static inline void set_pstate_bits(uint32_t bits)
364f0984d40SFabiano Rosas {
365f0984d40SFabiano Rosas     TCGv_i32 p = tcg_temp_new_i32();
366f0984d40SFabiano Rosas 
367f0984d40SFabiano Rosas     tcg_debug_assert(!(bits & CACHED_PSTATE_BITS));
368f0984d40SFabiano Rosas 
369ad75a51eSRichard Henderson     tcg_gen_ld_i32(p, tcg_env, offsetof(CPUARMState, pstate));
370f0984d40SFabiano Rosas     tcg_gen_ori_i32(p, p, bits);
clear_pstate_bits(uint32_t bits)371ad75a51eSRichard Henderson     tcg_gen_st_i32(p, tcg_env, offsetof(CPUARMState, pstate));
372f0984d40SFabiano Rosas }
373f0984d40SFabiano Rosas 
374f0984d40SFabiano Rosas /* Clear bits within PSTATE.  */
375f0984d40SFabiano Rosas static inline void clear_pstate_bits(uint32_t bits)
376f0984d40SFabiano Rosas {
377f0984d40SFabiano Rosas     TCGv_i32 p = tcg_temp_new_i32();
378f0984d40SFabiano Rosas 
379f0984d40SFabiano Rosas     tcg_debug_assert(!(bits & CACHED_PSTATE_BITS));
380f0984d40SFabiano Rosas 
381ad75a51eSRichard Henderson     tcg_gen_ld_i32(p, tcg_env, offsetof(CPUARMState, pstate));
382f0984d40SFabiano Rosas     tcg_gen_andi_i32(p, p, ~bits);
gen_ss_advance(DisasContext * s)383ad75a51eSRichard Henderson     tcg_gen_st_i32(p, tcg_env, offsetof(CPUARMState, pstate));
384f0984d40SFabiano Rosas }
385f0984d40SFabiano Rosas 
386f0984d40SFabiano Rosas /* If the singlestep state is Active-not-pending, advance to Active-pending. */
387f0984d40SFabiano Rosas static inline void gen_ss_advance(DisasContext *s)
388f0984d40SFabiano Rosas {
389f0984d40SFabiano Rosas     if (s->ss_active) {
390f0984d40SFabiano Rosas         s->pstate_ss = 0;
391f0984d40SFabiano Rosas         clear_pstate_bits(PSTATE_SS);
gen_swstep_exception(DisasContext * s,int isv,int ex)392f0984d40SFabiano Rosas     }
393f0984d40SFabiano Rosas }
394f0984d40SFabiano Rosas 
395f0984d40SFabiano Rosas /* Generate an architectural singlestep exception */
396f0984d40SFabiano Rosas static inline void gen_swstep_exception(DisasContext *s, int isv, int ex)
397f0984d40SFabiano Rosas {
398f0984d40SFabiano Rosas     /* Fill in the same_el field of the syndrome in the helper. */
399f0984d40SFabiano Rosas     uint32_t syn = syn_swstep(false, isv, ex);
400ad75a51eSRichard Henderson     gen_helper_exception_swstep(tcg_env, tcg_constant_i32(syn));
401f0984d40SFabiano Rosas }
402f0984d40SFabiano Rosas 
403f0984d40SFabiano Rosas /*
404f0984d40SFabiano Rosas  * Given a VFP floating point constant encoded into an 8 bit immediate in an
405f0984d40SFabiano Rosas  * instruction, expand it to the actual constant value of the specified
gen_vfp_absh(TCGv_i32 d,TCGv_i32 s)406f0984d40SFabiano Rosas  * size, as per the VFPExpandImm() pseudocode in the Arm ARM.
407f0984d40SFabiano Rosas  */
408f0984d40SFabiano Rosas uint64_t vfp_expand_imm(int size, uint8_t imm8);
409f0984d40SFabiano Rosas 
41021e885afSRichard Henderson static inline void gen_vfp_absh(TCGv_i32 d, TCGv_i32 s)
gen_vfp_abss(TCGv_i32 d,TCGv_i32 s)41121e885afSRichard Henderson {
41221e885afSRichard Henderson     tcg_gen_andi_i32(d, s, INT16_MAX);
41321e885afSRichard Henderson }
41421e885afSRichard Henderson 
41521e885afSRichard Henderson static inline void gen_vfp_abss(TCGv_i32 d, TCGv_i32 s)
gen_vfp_absd(TCGv_i64 d,TCGv_i64 s)41621e885afSRichard Henderson {
41721e885afSRichard Henderson     tcg_gen_andi_i32(d, s, INT32_MAX);
41821e885afSRichard Henderson }
41921e885afSRichard Henderson 
42021e885afSRichard Henderson static inline void gen_vfp_absd(TCGv_i64 d, TCGv_i64 s)
gen_vfp_negh(TCGv_i32 d,TCGv_i32 s)42121e885afSRichard Henderson {
42221e885afSRichard Henderson     tcg_gen_andi_i64(d, s, INT64_MAX);
42321e885afSRichard Henderson }
42421e885afSRichard Henderson 
42521e885afSRichard Henderson static inline void gen_vfp_negh(TCGv_i32 d, TCGv_i32 s)
gen_vfp_negs(TCGv_i32 d,TCGv_i32 s)42621e885afSRichard Henderson {
42721e885afSRichard Henderson     tcg_gen_xori_i32(d, s, 1u << 15);
42821e885afSRichard Henderson }
42921e885afSRichard Henderson 
43021e885afSRichard Henderson static inline void gen_vfp_negs(TCGv_i32 d, TCGv_i32 s)
gen_vfp_negd(TCGv_i64 d,TCGv_i64 s)43121e885afSRichard Henderson {
43221e885afSRichard Henderson     tcg_gen_xori_i32(d, s, 1u << 31);
43321e885afSRichard Henderson }
43421e885afSRichard Henderson 
43521e885afSRichard Henderson static inline void gen_vfp_negd(TCGv_i64 d, TCGv_i64 s)
43621e885afSRichard Henderson {
43721e885afSRichard Henderson     tcg_gen_xori_i64(d, s, 1ull << 63);
43821e885afSRichard Henderson }
43921e885afSRichard Henderson 
440f0984d40SFabiano Rosas /* Vector operations shared between ARM and AArch64.  */
441f0984d40SFabiano Rosas void gen_gvec_ceq0(unsigned vece, uint32_t rd_ofs, uint32_t rm_ofs,
442f0984d40SFabiano Rosas                    uint32_t opr_sz, uint32_t max_sz);
443f0984d40SFabiano Rosas void gen_gvec_clt0(unsigned vece, uint32_t rd_ofs, uint32_t rm_ofs,
444f0984d40SFabiano Rosas                    uint32_t opr_sz, uint32_t max_sz);
445f0984d40SFabiano Rosas void gen_gvec_cgt0(unsigned vece, uint32_t rd_ofs, uint32_t rm_ofs,
446f0984d40SFabiano Rosas                    uint32_t opr_sz, uint32_t max_sz);
447f0984d40SFabiano Rosas void gen_gvec_cle0(unsigned vece, uint32_t rd_ofs, uint32_t rm_ofs,
448f0984d40SFabiano Rosas                    uint32_t opr_sz, uint32_t max_sz);
449f0984d40SFabiano Rosas void gen_gvec_cge0(unsigned vece, uint32_t rd_ofs, uint32_t rm_ofs,
450f0984d40SFabiano Rosas                    uint32_t opr_sz, uint32_t max_sz);
451f0984d40SFabiano Rosas 
452f0984d40SFabiano Rosas void gen_gvec_mla(unsigned vece, uint32_t rd_ofs, uint32_t rn_ofs,
453f0984d40SFabiano Rosas                   uint32_t rm_ofs, uint32_t opr_sz, uint32_t max_sz);
454f0984d40SFabiano Rosas void gen_gvec_mls(unsigned vece, uint32_t rd_ofs, uint32_t rn_ofs,
455f0984d40SFabiano Rosas                   uint32_t rm_ofs, uint32_t opr_sz, uint32_t max_sz);
456f0984d40SFabiano Rosas 
457f0984d40SFabiano Rosas void gen_gvec_cmtst(unsigned vece, uint32_t rd_ofs, uint32_t rn_ofs,
458f0984d40SFabiano Rosas                     uint32_t rm_ofs, uint32_t opr_sz, uint32_t max_sz);
459f0984d40SFabiano Rosas void gen_gvec_sshl(unsigned vece, uint32_t rd_ofs, uint32_t rn_ofs,
460f0984d40SFabiano Rosas                    uint32_t rm_ofs, uint32_t opr_sz, uint32_t max_sz);
461f0984d40SFabiano Rosas void gen_gvec_ushl(unsigned vece, uint32_t rd_ofs, uint32_t rn_ofs,
462f0984d40SFabiano Rosas                    uint32_t rm_ofs, uint32_t opr_sz, uint32_t max_sz);
463940392c8SRichard Henderson void gen_gvec_srshl(unsigned vece, uint32_t rd_ofs, uint32_t rn_ofs,
464940392c8SRichard Henderson                     uint32_t rm_ofs, uint32_t opr_sz, uint32_t max_sz);
465940392c8SRichard Henderson void gen_gvec_urshl(unsigned vece, uint32_t rd_ofs, uint32_t rn_ofs,
466940392c8SRichard Henderson                     uint32_t rm_ofs, uint32_t opr_sz, uint32_t max_sz);
467e72a6878SRichard Henderson void gen_neon_sqshl(unsigned vece, uint32_t rd_ofs, uint32_t rn_ofs,
468e72a6878SRichard Henderson                     uint32_t rm_ofs, uint32_t opr_sz, uint32_t max_sz);
469e72a6878SRichard Henderson void gen_neon_uqshl(unsigned vece, uint32_t rd_ofs, uint32_t rn_ofs,
470e72a6878SRichard Henderson                     uint32_t rm_ofs, uint32_t opr_sz, uint32_t max_sz);
471cef9d54fSRichard Henderson void gen_neon_sqrshl(unsigned vece, uint32_t rd_ofs, uint32_t rn_ofs,
472cef9d54fSRichard Henderson                      uint32_t rm_ofs, uint32_t opr_sz, uint32_t max_sz);
473cef9d54fSRichard Henderson void gen_neon_uqrshl(unsigned vece, uint32_t rd_ofs, uint32_t rn_ofs,
474cef9d54fSRichard Henderson                      uint32_t rm_ofs, uint32_t opr_sz, uint32_t max_sz);
475f0984d40SFabiano Rosas 
476ef2b80ebSRichard Henderson void gen_neon_sqshli(unsigned vece, uint32_t rd_ofs, uint32_t rn_ofs,
477ef2b80ebSRichard Henderson                      int64_t c, uint32_t opr_sz, uint32_t max_sz);
478ef2b80ebSRichard Henderson void gen_neon_uqshli(unsigned vece, uint32_t rd_ofs, uint32_t rn_ofs,
479ef2b80ebSRichard Henderson                      int64_t c, uint32_t opr_sz, uint32_t max_sz);
480ef2b80ebSRichard Henderson void gen_neon_sqshlui(unsigned vece, uint32_t rd_ofs, uint32_t rn_ofs,
481ef2b80ebSRichard Henderson                       int64_t c, uint32_t opr_sz, uint32_t max_sz);
482ef2b80ebSRichard Henderson 
483203aca91SRichard Henderson void gen_gvec_shadd(unsigned vece, uint32_t rd_ofs, uint32_t rn_ofs,
484203aca91SRichard Henderson                     uint32_t rm_ofs, uint32_t opr_sz, uint32_t max_sz);
485203aca91SRichard Henderson void gen_gvec_uhadd(unsigned vece, uint32_t rd_ofs, uint32_t rn_ofs,
486203aca91SRichard Henderson                     uint32_t rm_ofs, uint32_t opr_sz, uint32_t max_sz);
48734c0d865SRichard Henderson void gen_gvec_shsub(unsigned vece, uint32_t rd_ofs, uint32_t rn_ofs,
48834c0d865SRichard Henderson                     uint32_t rm_ofs, uint32_t opr_sz, uint32_t max_sz);
48934c0d865SRichard Henderson void gen_gvec_uhsub(unsigned vece, uint32_t rd_ofs, uint32_t rn_ofs,
49034c0d865SRichard Henderson                     uint32_t rm_ofs, uint32_t opr_sz, uint32_t max_sz);
4918989b95eSRichard Henderson void gen_gvec_srhadd(unsigned vece, uint32_t rd_ofs, uint32_t rn_ofs,
4928989b95eSRichard Henderson                      uint32_t rm_ofs, uint32_t opr_sz, uint32_t max_sz);
4938989b95eSRichard Henderson void gen_gvec_urhadd(unsigned vece, uint32_t rd_ofs, uint32_t rn_ofs,
4948989b95eSRichard Henderson                      uint32_t rm_ofs, uint32_t opr_sz, uint32_t max_sz);
495203aca91SRichard Henderson 
496f0984d40SFabiano Rosas void gen_cmtst_i64(TCGv_i64 d, TCGv_i64 a, TCGv_i64 b);
497f0984d40SFabiano Rosas void gen_ushl_i32(TCGv_i32 d, TCGv_i32 a, TCGv_i32 b);
498f0984d40SFabiano Rosas void gen_sshl_i32(TCGv_i32 d, TCGv_i32 a, TCGv_i32 b);
499f0984d40SFabiano Rosas void gen_ushl_i64(TCGv_i64 d, TCGv_i64 a, TCGv_i64 b);
500f0984d40SFabiano Rosas void gen_sshl_i64(TCGv_i64 d, TCGv_i64 a, TCGv_i64 b);
501f0984d40SFabiano Rosas 
502f4fa83d6SRichard Henderson void gen_uqadd_bhs(TCGv_i64 res, TCGv_i64 qc,
503f4fa83d6SRichard Henderson                    TCGv_i64 a, TCGv_i64 b, MemOp esz);
504f4fa83d6SRichard Henderson void gen_uqadd_d(TCGv_i64 d, TCGv_i64 q, TCGv_i64 a, TCGv_i64 b);
505f0984d40SFabiano Rosas void gen_gvec_uqadd_qc(unsigned vece, uint32_t rd_ofs, uint32_t rn_ofs,
506f0984d40SFabiano Rosas                        uint32_t rm_ofs, uint32_t opr_sz, uint32_t max_sz);
507f4fa83d6SRichard Henderson 
508f4fa83d6SRichard Henderson void gen_sqadd_bhs(TCGv_i64 res, TCGv_i64 qc,
509f4fa83d6SRichard Henderson                    TCGv_i64 a, TCGv_i64 b, MemOp esz);
510f4fa83d6SRichard Henderson void gen_sqadd_d(TCGv_i64 d, TCGv_i64 q, TCGv_i64 a, TCGv_i64 b);
511f0984d40SFabiano Rosas void gen_gvec_sqadd_qc(unsigned vece, uint32_t rd_ofs, uint32_t rn_ofs,
512f0984d40SFabiano Rosas                        uint32_t rm_ofs, uint32_t opr_sz, uint32_t max_sz);
513f4fa83d6SRichard Henderson 
514f4fa83d6SRichard Henderson void gen_uqsub_bhs(TCGv_i64 res, TCGv_i64 qc,
515f4fa83d6SRichard Henderson                    TCGv_i64 a, TCGv_i64 b, MemOp esz);
516f4fa83d6SRichard Henderson void gen_uqsub_d(TCGv_i64 d, TCGv_i64 q, TCGv_i64 a, TCGv_i64 b);
517f0984d40SFabiano Rosas void gen_gvec_uqsub_qc(unsigned vece, uint32_t rd_ofs, uint32_t rn_ofs,
518f0984d40SFabiano Rosas                        uint32_t rm_ofs, uint32_t opr_sz, uint32_t max_sz);
519f4fa83d6SRichard Henderson 
520f4fa83d6SRichard Henderson void gen_sqsub_bhs(TCGv_i64 res, TCGv_i64 qc,
521f4fa83d6SRichard Henderson                    TCGv_i64 a, TCGv_i64 b, MemOp esz);
522f4fa83d6SRichard Henderson void gen_sqsub_d(TCGv_i64 d, TCGv_i64 q, TCGv_i64 a, TCGv_i64 b);
523f0984d40SFabiano Rosas void gen_gvec_sqsub_qc(unsigned vece, uint32_t rd_ofs, uint32_t rn_ofs,
524f0984d40SFabiano Rosas                        uint32_t rm_ofs, uint32_t opr_sz, uint32_t max_sz);
525f0984d40SFabiano Rosas 
52600bcab5bSRichard Henderson void gen_gvec_sshr(unsigned vece, uint32_t rd_ofs, uint32_t rm_ofs,
52700bcab5bSRichard Henderson                    int64_t shift, uint32_t opr_sz, uint32_t max_sz);
52800bcab5bSRichard Henderson void gen_gvec_ushr(unsigned vece, uint32_t rd_ofs, uint32_t rm_ofs,
52900bcab5bSRichard Henderson                    int64_t shift, uint32_t opr_sz, uint32_t max_sz);
53000bcab5bSRichard Henderson 
531f0984d40SFabiano Rosas void gen_gvec_ssra(unsigned vece, uint32_t rd_ofs, uint32_t rm_ofs,
532f0984d40SFabiano Rosas                    int64_t shift, uint32_t opr_sz, uint32_t max_sz);
533f0984d40SFabiano Rosas void gen_gvec_usra(unsigned vece, uint32_t rd_ofs, uint32_t rm_ofs,
534f0984d40SFabiano Rosas                    int64_t shift, uint32_t opr_sz, uint32_t max_sz);
535f0984d40SFabiano Rosas 
53609a52d85SRichard Henderson void gen_srshr32_i32(TCGv_i32 d, TCGv_i32 a, int32_t sh);
53709a52d85SRichard Henderson void gen_srshr64_i64(TCGv_i64 d, TCGv_i64 a, int64_t sh);
53809a52d85SRichard Henderson void gen_urshr32_i32(TCGv_i32 d, TCGv_i32 a, int32_t sh);
53909a52d85SRichard Henderson void gen_urshr64_i64(TCGv_i64 d, TCGv_i64 a, int64_t sh);
54009a52d85SRichard Henderson 
541f0984d40SFabiano Rosas void gen_gvec_srshr(unsigned vece, uint32_t rd_ofs, uint32_t rm_ofs,
542f0984d40SFabiano Rosas                     int64_t shift, uint32_t opr_sz, uint32_t max_sz);
543f0984d40SFabiano Rosas void gen_gvec_urshr(unsigned vece, uint32_t rd_ofs, uint32_t rm_ofs,
544f0984d40SFabiano Rosas                     int64_t shift, uint32_t opr_sz, uint32_t max_sz);
545f0984d40SFabiano Rosas void gen_gvec_srsra(unsigned vece, uint32_t rd_ofs, uint32_t rm_ofs,
546f0984d40SFabiano Rosas                     int64_t shift, uint32_t opr_sz, uint32_t max_sz);
547f0984d40SFabiano Rosas void gen_gvec_ursra(unsigned vece, uint32_t rd_ofs, uint32_t rm_ofs,
548f0984d40SFabiano Rosas                     int64_t shift, uint32_t opr_sz, uint32_t max_sz);
549f0984d40SFabiano Rosas 
550f0984d40SFabiano Rosas void gen_gvec_sri(unsigned vece, uint32_t rd_ofs, uint32_t rm_ofs,
551f0984d40SFabiano Rosas                   int64_t shift, uint32_t opr_sz, uint32_t max_sz);
552f0984d40SFabiano Rosas void gen_gvec_sli(unsigned vece, uint32_t rd_ofs, uint32_t rm_ofs,
553f0984d40SFabiano Rosas                   int64_t shift, uint32_t opr_sz, uint32_t max_sz);
554f0984d40SFabiano Rosas 
5558f81dcedSRichard Henderson void gen_gvec_sqdmulh_qc(unsigned vece, uint32_t rd_ofs, uint32_t rn_ofs,
5568f81dcedSRichard Henderson                          uint32_t rm_ofs, uint32_t opr_sz, uint32_t max_sz);
5578f81dcedSRichard Henderson void gen_gvec_sqrdmulh_qc(unsigned vece, uint32_t rd_ofs, uint32_t rn_ofs,
5588f81dcedSRichard Henderson                           uint32_t rm_ofs, uint32_t opr_sz, uint32_t max_sz);
559f0984d40SFabiano Rosas void gen_gvec_sqrdmlah_qc(unsigned vece, uint32_t rd_ofs, uint32_t rn_ofs,
560f0984d40SFabiano Rosas                           uint32_t rm_ofs, uint32_t opr_sz, uint32_t max_sz);
561f0984d40SFabiano Rosas void gen_gvec_sqrdmlsh_qc(unsigned vece, uint32_t rd_ofs, uint32_t rn_ofs,
562f0984d40SFabiano Rosas                           uint32_t rm_ofs, uint32_t opr_sz, uint32_t max_sz);
563f0984d40SFabiano Rosas 
564f0984d40SFabiano Rosas void gen_gvec_sabd(unsigned vece, uint32_t rd_ofs, uint32_t rn_ofs,
565f0984d40SFabiano Rosas                    uint32_t rm_ofs, uint32_t opr_sz, uint32_t max_sz);
566f0984d40SFabiano Rosas void gen_gvec_uabd(unsigned vece, uint32_t rd_ofs, uint32_t rn_ofs,
567f0984d40SFabiano Rosas                    uint32_t rm_ofs, uint32_t opr_sz, uint32_t max_sz);
568f0984d40SFabiano Rosas 
569f0984d40SFabiano Rosas void gen_gvec_saba(unsigned vece, uint32_t rd_ofs, uint32_t rn_ofs,
570f0984d40SFabiano Rosas                    uint32_t rm_ofs, uint32_t opr_sz, uint32_t max_sz);
571f0984d40SFabiano Rosas void gen_gvec_uaba(unsigned vece, uint32_t rd_ofs, uint32_t rn_ofs,
572f0984d40SFabiano Rosas                    uint32_t rm_ofs, uint32_t opr_sz, uint32_t max_sz);
573f0984d40SFabiano Rosas 
574a7e4eec6SRichard Henderson void gen_gvec_addp(unsigned vece, uint32_t rd_ofs, uint32_t rn_ofs,
575a7e4eec6SRichard Henderson                    uint32_t rm_ofs, uint32_t opr_sz, uint32_t max_sz);
57628b5451bSRichard Henderson void gen_gvec_smaxp(unsigned vece, uint32_t rd_ofs, uint32_t rn_ofs,
57728b5451bSRichard Henderson                     uint32_t rm_ofs, uint32_t opr_sz, uint32_t max_sz);
57828b5451bSRichard Henderson void gen_gvec_sminp(unsigned vece, uint32_t rd_ofs, uint32_t rn_ofs,
57928b5451bSRichard Henderson                     uint32_t rm_ofs, uint32_t opr_sz, uint32_t max_sz);
58028b5451bSRichard Henderson void gen_gvec_umaxp(unsigned vece, uint32_t rd_ofs, uint32_t rn_ofs,
58128b5451bSRichard Henderson                     uint32_t rm_ofs, uint32_t opr_sz, uint32_t max_sz);
58228b5451bSRichard Henderson void gen_gvec_uminp(unsigned vece, uint32_t rd_ofs, uint32_t rn_ofs,
58328b5451bSRichard Henderson                     uint32_t rm_ofs, uint32_t opr_sz, uint32_t max_sz);
584a7e4eec6SRichard Henderson 
585f0984d40SFabiano Rosas /*
586f0984d40SFabiano Rosas  * Forward to the isar_feature_* tests given a DisasContext pointer.
587f0984d40SFabiano Rosas  */
588f0984d40SFabiano Rosas #define dc_isar_feature(name, ctx) \
589f0984d40SFabiano Rosas     ({ DisasContext *ctx_ = (ctx); isar_feature_##name(ctx_->isar); })
590f0984d40SFabiano Rosas 
591f0984d40SFabiano Rosas /* Note that the gvec expanders operate on offsets + sizes.  */
592f0984d40SFabiano Rosas typedef void GVecGen2Fn(unsigned, uint32_t, uint32_t, uint32_t, uint32_t);
593f0984d40SFabiano Rosas typedef void GVecGen2iFn(unsigned, uint32_t, uint32_t, int64_t,
594f0984d40SFabiano Rosas                          uint32_t, uint32_t);
595f0984d40SFabiano Rosas typedef void GVecGen3Fn(unsigned, uint32_t, uint32_t,
596f0984d40SFabiano Rosas                         uint32_t, uint32_t, uint32_t);
597f0984d40SFabiano Rosas typedef void GVecGen4Fn(unsigned, uint32_t, uint32_t, uint32_t,
598f0984d40SFabiano Rosas                         uint32_t, uint32_t, uint32_t);
599f0984d40SFabiano Rosas 
600f0984d40SFabiano Rosas /* Function prototype for gen_ functions for calling Neon helpers */
601f0984d40SFabiano Rosas typedef void NeonGenOneOpFn(TCGv_i32, TCGv_i32);
602f0984d40SFabiano Rosas typedef void NeonGenOneOpEnvFn(TCGv_i32, TCGv_ptr, TCGv_i32);
603f0984d40SFabiano Rosas typedef void NeonGenTwoOpFn(TCGv_i32, TCGv_i32, TCGv_i32);
604f0984d40SFabiano Rosas typedef void NeonGenTwoOpEnvFn(TCGv_i32, TCGv_ptr, TCGv_i32, TCGv_i32);
605f0984d40SFabiano Rosas typedef void NeonGenThreeOpEnvFn(TCGv_i32, TCGv_env, TCGv_i32,
606f0984d40SFabiano Rosas                                  TCGv_i32, TCGv_i32);
607f0984d40SFabiano Rosas typedef void NeonGenTwo64OpFn(TCGv_i64, TCGv_i64, TCGv_i64);
608f0984d40SFabiano Rosas typedef void NeonGenTwo64OpEnvFn(TCGv_i64, TCGv_ptr, TCGv_i64, TCGv_i64);
609f0984d40SFabiano Rosas typedef void NeonGenNarrowFn(TCGv_i32, TCGv_i64);
610f0984d40SFabiano Rosas typedef void NeonGenWidenFn(TCGv_i64, TCGv_i32);
611f0984d40SFabiano Rosas typedef void NeonGenTwoOpWidenFn(TCGv_i64, TCGv_i32, TCGv_i32);
612f0984d40SFabiano Rosas typedef void NeonGenOneSingleOpFn(TCGv_i32, TCGv_i32, TCGv_ptr);
613f0984d40SFabiano Rosas typedef void NeonGenTwoSingleOpFn(TCGv_i32, TCGv_i32, TCGv_i32, TCGv_ptr);
614f0984d40SFabiano Rosas typedef void NeonGenTwoDoubleOpFn(TCGv_i64, TCGv_i64, TCGv_i64, TCGv_ptr);
615f0984d40SFabiano Rosas typedef void NeonGenOne64OpFn(TCGv_i64, TCGv_i64);
6163e683f0aSRichard Henderson typedef void NeonGenOne64OpEnvFn(TCGv_i64, TCGv_env, TCGv_i64);
617f0984d40SFabiano Rosas typedef void CryptoTwoOpFn(TCGv_ptr, TCGv_ptr);
618f0984d40SFabiano Rosas typedef void CryptoThreeOpIntFn(TCGv_ptr, TCGv_ptr, TCGv_i32);
619f0984d40SFabiano Rosas typedef void CryptoThreeOpFn(TCGv_ptr, TCGv_ptr, TCGv_ptr);
620f0984d40SFabiano Rosas typedef void AtomicThreeOpFn(TCGv_i64, TCGv_i64, TCGv_i64, TCGArg, MemOp);
621f0984d40SFabiano Rosas typedef void WideShiftImmFn(TCGv_i64, TCGv_i64, int64_t shift);
622f0984d40SFabiano Rosas typedef void WideShiftFn(TCGv_i64, TCGv_ptr, TCGv_i64, TCGv_i32);
623f0984d40SFabiano Rosas typedef void ShiftImmFn(TCGv_i32, TCGv_i32, int32_t shift);
624f0984d40SFabiano Rosas typedef void ShiftFn(TCGv_i32, TCGv_ptr, TCGv_i32, TCGv_i32);
625f0984d40SFabiano Rosas 
626f0984d40SFabiano Rosas /**
627f0984d40SFabiano Rosas  * arm_tbflags_from_tb:
arm_tbflags_from_tb(const TranslationBlock * tb)628f0984d40SFabiano Rosas  * @tb: the TranslationBlock
629f0984d40SFabiano Rosas  *
630f0984d40SFabiano Rosas  * Extract the flag values from @tb.
631f0984d40SFabiano Rosas  */
632f0984d40SFabiano Rosas static inline CPUARMTBFlags arm_tbflags_from_tb(const TranslationBlock *tb)
633f0984d40SFabiano Rosas {
634f0984d40SFabiano Rosas     return (CPUARMTBFlags){ tb->flags, tb->cs_base };
635f0984d40SFabiano Rosas }
636f0984d40SFabiano Rosas 
637f0984d40SFabiano Rosas /*
638f0984d40SFabiano Rosas  * Enum for argument to fpstatus_ptr().
639f0984d40SFabiano Rosas  */
640f0984d40SFabiano Rosas typedef enum ARMFPStatusFlavour {
641f0984d40SFabiano Rosas     FPST_FPCR,
642f0984d40SFabiano Rosas     FPST_FPCR_F16,
643f0984d40SFabiano Rosas     FPST_STD,
644f0984d40SFabiano Rosas     FPST_STD_F16,
645f0984d40SFabiano Rosas } ARMFPStatusFlavour;
646f0984d40SFabiano Rosas 
647f0984d40SFabiano Rosas /**
648f0984d40SFabiano Rosas  * fpstatus_ptr: return TCGv_ptr to the specified fp_status field
649f0984d40SFabiano Rosas  *
650f0984d40SFabiano Rosas  * We have multiple softfloat float_status fields in the Arm CPU state struct
651f0984d40SFabiano Rosas  * (see the comment in cpu.h for details). Return a TCGv_ptr which has
652f0984d40SFabiano Rosas  * been set up to point to the requested field in the CPU state struct.
653f0984d40SFabiano Rosas  * The options are:
654f0984d40SFabiano Rosas  *
655f0984d40SFabiano Rosas  * FPST_FPCR
656f0984d40SFabiano Rosas  *   for non-FP16 operations controlled by the FPCR
657f0984d40SFabiano Rosas  * FPST_FPCR_F16
658f0984d40SFabiano Rosas  *   for operations controlled by the FPCR where FPCR.FZ16 is to be used
659f0984d40SFabiano Rosas  * FPST_STD
fpstatus_ptr(ARMFPStatusFlavour flavour)660f0984d40SFabiano Rosas  *   for A32/T32 Neon operations using the "standard FPSCR value"
661f0984d40SFabiano Rosas  * FPST_STD_F16
662f0984d40SFabiano Rosas  *   as FPST_STD, but where FPCR.FZ16 is to be used
663f0984d40SFabiano Rosas  */
664f0984d40SFabiano Rosas static inline TCGv_ptr fpstatus_ptr(ARMFPStatusFlavour flavour)
665f0984d40SFabiano Rosas {
666f0984d40SFabiano Rosas     TCGv_ptr statusptr = tcg_temp_new_ptr();
667f0984d40SFabiano Rosas     int offset;
668f0984d40SFabiano Rosas 
669f0984d40SFabiano Rosas     switch (flavour) {
670f0984d40SFabiano Rosas     case FPST_FPCR:
671f0984d40SFabiano Rosas         offset = offsetof(CPUARMState, vfp.fp_status);
672f0984d40SFabiano Rosas         break;
673f0984d40SFabiano Rosas     case FPST_FPCR_F16:
674f0984d40SFabiano Rosas         offset = offsetof(CPUARMState, vfp.fp_status_f16);
675f0984d40SFabiano Rosas         break;
676f0984d40SFabiano Rosas     case FPST_STD:
677f0984d40SFabiano Rosas         offset = offsetof(CPUARMState, vfp.standard_fp_status);
678f0984d40SFabiano Rosas         break;
679f0984d40SFabiano Rosas     case FPST_STD_F16:
680f0984d40SFabiano Rosas         offset = offsetof(CPUARMState, vfp.standard_fp_status_f16);
681f0984d40SFabiano Rosas         break;
682f0984d40SFabiano Rosas     default:
683f0984d40SFabiano Rosas         g_assert_not_reached();
684f0984d40SFabiano Rosas     }
685ad75a51eSRichard Henderson     tcg_gen_addi_ptr(statusptr, tcg_env, offset);
686f0984d40SFabiano Rosas     return statusptr;
687f0984d40SFabiano Rosas }
688f0984d40SFabiano Rosas 
689f0984d40SFabiano Rosas /**
690e452ca5aSRichard Henderson  * finalize_memop_atom:
691f0984d40SFabiano Rosas  * @s: DisasContext
692f0984d40SFabiano Rosas  * @opc: size+sign+align of the memory operation
693e452ca5aSRichard Henderson  * @atom: atomicity of the memory operation
694f0984d40SFabiano Rosas  *
695e452ca5aSRichard Henderson  * Build the complete MemOp for a memory operation, including alignment,
696e452ca5aSRichard Henderson  * endianness, and atomicity.
697f0984d40SFabiano Rosas  *
698f0984d40SFabiano Rosas  * If (op & MO_AMASK) then the operation already contains the required
699f0984d40SFabiano Rosas  * alignment, e.g. for AccType_ATOMIC.  Otherwise, this an optionally
700f0984d40SFabiano Rosas  * unaligned operation, e.g. for AccType_NORMAL.
701f0984d40SFabiano Rosas  *
finalize_memop_atom(DisasContext * s,MemOp opc,MemOp atom)702f0984d40SFabiano Rosas  * In the latter case, there are configuration bits that require alignment,
703f0984d40SFabiano Rosas  * and this is applied here.  Note that there is no way to indicate that
704f0984d40SFabiano Rosas  * no alignment should ever be enforced; this must be handled manually.
705f0984d40SFabiano Rosas  */
706e452ca5aSRichard Henderson static inline MemOp finalize_memop_atom(DisasContext *s, MemOp opc, MemOp atom)
707f0984d40SFabiano Rosas {
708f0984d40SFabiano Rosas     if (s->align_mem && !(opc & MO_AMASK)) {
709f0984d40SFabiano Rosas         opc |= MO_ALIGN;
710f0984d40SFabiano Rosas     }
711e452ca5aSRichard Henderson     return opc | atom | s->be_data;
712e452ca5aSRichard Henderson }
713e452ca5aSRichard Henderson 
714e452ca5aSRichard Henderson /**
715e452ca5aSRichard Henderson  * finalize_memop:
716e452ca5aSRichard Henderson  * @s: DisasContext
finalize_memop(DisasContext * s,MemOp opc)717e452ca5aSRichard Henderson  * @opc: size+sign+align of the memory operation
718e452ca5aSRichard Henderson  *
719e452ca5aSRichard Henderson  * Like finalize_memop_atom, but with default atomicity.
720e452ca5aSRichard Henderson  */
721e452ca5aSRichard Henderson static inline MemOp finalize_memop(DisasContext *s, MemOp opc)
722e452ca5aSRichard Henderson {
723e452ca5aSRichard Henderson     MemOp atom = s->lse2 ? MO_ATOM_WITHIN16 : MO_ATOM_IFALIGN;
724e452ca5aSRichard Henderson     return finalize_memop_atom(s, opc, atom);
725e452ca5aSRichard Henderson }
726e452ca5aSRichard Henderson 
727e452ca5aSRichard Henderson /**
728e452ca5aSRichard Henderson  * finalize_memop_pair:
729e452ca5aSRichard Henderson  * @s: DisasContext
730e452ca5aSRichard Henderson  * @opc: size+sign+align of the memory operation
finalize_memop_pair(DisasContext * s,MemOp opc)731e452ca5aSRichard Henderson  *
732e452ca5aSRichard Henderson  * Like finalize_memop_atom, but with atomicity for a pair.
733e452ca5aSRichard Henderson  * C.f. Pseudocode for Mem[], operand ispair.
734e452ca5aSRichard Henderson  */
735e452ca5aSRichard Henderson static inline MemOp finalize_memop_pair(DisasContext *s, MemOp opc)
736e452ca5aSRichard Henderson {
737e452ca5aSRichard Henderson     MemOp atom = s->lse2 ? MO_ATOM_WITHIN16_PAIR : MO_ATOM_IFALIGN_PAIR;
738e452ca5aSRichard Henderson     return finalize_memop_atom(s, opc, atom);
739f0984d40SFabiano Rosas }
740f0984d40SFabiano Rosas 
741f0984d40SFabiano Rosas /**
742d450bd01SRichard Henderson  * finalize_memop_asimd:
743d450bd01SRichard Henderson  * @s: DisasContext
finalize_memop_asimd(DisasContext * s,MemOp opc)744d450bd01SRichard Henderson  * @opc: size+sign+align of the memory operation
745d450bd01SRichard Henderson  *
746d450bd01SRichard Henderson  * Like finalize_memop_atom, but with atomicity of AccessType_ASIMD.
747d450bd01SRichard Henderson  */
748d450bd01SRichard Henderson static inline MemOp finalize_memop_asimd(DisasContext *s, MemOp opc)
749d450bd01SRichard Henderson {
750d450bd01SRichard Henderson     /*
751d450bd01SRichard Henderson      * In the pseudocode for Mem[], with AccessType_ASIMD, size == 16,
752d450bd01SRichard Henderson      * if IsAligned(8), the first case provides separate atomicity for
753d450bd01SRichard Henderson      * the pair of 64-bit accesses.  If !IsAligned(8), the middle cases
754d450bd01SRichard Henderson      * do not apply, and we're left with the final case of no atomicity.
755d450bd01SRichard Henderson      * Thus MO_ATOM_IFALIGN_PAIR.
756d450bd01SRichard Henderson      *
757d450bd01SRichard Henderson      * For other sizes, normal LSE2 rules apply.
758d450bd01SRichard Henderson      */
759d450bd01SRichard Henderson     if ((opc & MO_SIZE) == MO_128) {
760d450bd01SRichard Henderson         return finalize_memop_atom(s, opc, MO_ATOM_IFALIGN_PAIR);
761d450bd01SRichard Henderson     }
762d450bd01SRichard Henderson     return finalize_memop(s, opc);
763d450bd01SRichard Henderson }
764d450bd01SRichard Henderson 
765d450bd01SRichard Henderson /**
766f0984d40SFabiano Rosas  * asimd_imm_const: Expand an encoded SIMD constant value
767f0984d40SFabiano Rosas  *
768f0984d40SFabiano Rosas  * Expand a SIMD constant value. This is essentially the pseudocode
769f0984d40SFabiano Rosas  * AdvSIMDExpandImm, except that we also perform the boolean NOT needed for
770f0984d40SFabiano Rosas  * VMVN and VBIC (when cmode < 14 && op == 1).
771f0984d40SFabiano Rosas  *
772f0984d40SFabiano Rosas  * The combination cmode == 15 op == 1 is a reserved encoding for AArch32;
773f0984d40SFabiano Rosas  * callers must catch this; we return the 64-bit constant value defined
774f0984d40SFabiano Rosas  * for AArch64.
775f0984d40SFabiano Rosas  *
776f0984d40SFabiano Rosas  * cmode = 2,3,4,5,6,7,10,11,12,13 imm=0 was UNPREDICTABLE in v7A but
777f0984d40SFabiano Rosas  * is either not unpredictable or merely CONSTRAINED UNPREDICTABLE in v8A;
778f0984d40SFabiano Rosas  * we produce an immediate constant value of 0 in these cases.
779f0984d40SFabiano Rosas  */
780f0984d40SFabiano Rosas uint64_t asimd_imm_const(uint32_t imm, int cmode, int op);
781f0984d40SFabiano Rosas 
gen_disas_label(DisasContext * s)782f0984d40SFabiano Rosas /*
783f0984d40SFabiano Rosas  * gen_disas_label:
784f0984d40SFabiano Rosas  * Create a label and cache a copy of pc_save.
785f0984d40SFabiano Rosas  */
786f0984d40SFabiano Rosas static inline DisasLabel gen_disas_label(DisasContext *s)
787f0984d40SFabiano Rosas {
788f0984d40SFabiano Rosas     return (DisasLabel){
789f0984d40SFabiano Rosas         .label = gen_new_label(),
790f0984d40SFabiano Rosas         .pc_save = s->pc_save,
791f0984d40SFabiano Rosas     };
792f0984d40SFabiano Rosas }
793f0984d40SFabiano Rosas 
set_disas_label(DisasContext * s,DisasLabel l)794f0984d40SFabiano Rosas /*
795f0984d40SFabiano Rosas  * set_disas_label:
796f0984d40SFabiano Rosas  * Emit a label and restore the cached copy of pc_save.
797f0984d40SFabiano Rosas  */
798f0984d40SFabiano Rosas static inline void set_disas_label(DisasContext *s, DisasLabel l)
799f0984d40SFabiano Rosas {
800f0984d40SFabiano Rosas     gen_set_label(l.label);
801f0984d40SFabiano Rosas     s->pc_save = l.pc_save;
802f0984d40SFabiano Rosas }
803f0984d40SFabiano Rosas 
804f0984d40SFabiano Rosas static inline TCGv_ptr gen_lookup_cp_reg(uint32_t key)
805f0984d40SFabiano Rosas {
806f0984d40SFabiano Rosas     TCGv_ptr ret = tcg_temp_new_ptr();
807ad75a51eSRichard Henderson     gen_helper_lookup_cp_reg(ret, tcg_env, tcg_constant_i32(key));
808f0984d40SFabiano Rosas     return ret;
809f0984d40SFabiano Rosas }
gen_set_rmode(ARMFPRounding rmode,TCGv_ptr fpst)810f0984d40SFabiano Rosas 
811f0984d40SFabiano Rosas /*
8128d1b02a6SRichard Henderson  * Set and reset rounding mode around another operation.
8138d1b02a6SRichard Henderson  */
8148d1b02a6SRichard Henderson static inline TCGv_i32 gen_set_rmode(ARMFPRounding rmode, TCGv_ptr fpst)
8158d1b02a6SRichard Henderson {
8168d1b02a6SRichard Henderson     TCGv_i32 new = tcg_constant_i32(arm_rmode_to_sf(rmode));
8178d1b02a6SRichard Henderson     TCGv_i32 old = tcg_temp_new_i32();
8188d1b02a6SRichard Henderson 
8198d1b02a6SRichard Henderson     gen_helper_set_rmode(old, new, fpst);
8208d1b02a6SRichard Henderson     return old;
8218d1b02a6SRichard Henderson }
8228d1b02a6SRichard Henderson 
8238d1b02a6SRichard Henderson static inline void gen_restore_rmode(TCGv_i32 old, TCGv_ptr fpst)
8248d1b02a6SRichard Henderson {
8258d1b02a6SRichard Henderson     gen_helper_set_rmode(old, old, fpst);
8268d1b02a6SRichard Henderson }
8278d1b02a6SRichard Henderson 
8288d1b02a6SRichard Henderson /*
829f0984d40SFabiano Rosas  * Helpers for implementing sets of trans_* functions.
830f0984d40SFabiano Rosas  * Defer the implementation of NAME to FUNC, with optional extra arguments.
831f0984d40SFabiano Rosas  */
832f0984d40SFabiano Rosas #define TRANS(NAME, FUNC, ...) \
833f0984d40SFabiano Rosas     static bool trans_##NAME(DisasContext *s, arg_##NAME *a) \
834f0984d40SFabiano Rosas     { return FUNC(s, __VA_ARGS__); }
835f0984d40SFabiano Rosas #define TRANS_FEAT(NAME, FEAT, FUNC, ...) \
836f0984d40SFabiano Rosas     static bool trans_##NAME(DisasContext *s, arg_##NAME *a) \
837f0984d40SFabiano Rosas     { return dc_isar_feature(FEAT, s) && FUNC(s, __VA_ARGS__); }
838f0984d40SFabiano Rosas 
839f0984d40SFabiano Rosas #define TRANS_FEAT_NONSTREAMING(NAME, FEAT, FUNC, ...)            \
840f0984d40SFabiano Rosas     static bool trans_##NAME(DisasContext *s, arg_##NAME *a)      \
841f0984d40SFabiano Rosas     {                                                             \
842f0984d40SFabiano Rosas         s->is_nonstreaming = true;                                \
843f0984d40SFabiano Rosas         return dc_isar_feature(FEAT, s) && FUNC(s, __VA_ARGS__);  \
844f0984d40SFabiano Rosas     }
845f0984d40SFabiano Rosas 
846f0984d40SFabiano Rosas #endif /* TARGET_ARM_TRANSLATE_H */
847