1#ifndef TARGET_ARM_TRANSLATE_H
2#define TARGET_ARM_TRANSLATE_H
3
4#include "exec/translator.h"
5#include "internals.h"
6
7
8
9
10
11
12
13
14typedef struct DisasLabel {
15 TCGLabel *label;
16 target_ulong pc_save;
17} DisasLabel;
18
19typedef struct DisasContext {
20 DisasContextBase base;
21 const ARMISARegisters *isar;
22
23
24 target_ulong pc_curr;
25
26
27
28
29
30
31
32
33
34
35
36
37
38 target_ulong pc_save;
39 target_ulong page_start;
40 uint32_t insn;
41
42 int condjmp;
43
44 DisasLabel condlabel;
45
46 int condexec_mask;
47 int condexec_cond;
48
49 int eci;
50
51
52
53
54 bool eci_handled;
55 int sctlr_b;
56 MemOp be_data;
57#if !defined(CONFIG_USER_ONLY)
58 int user;
59#endif
60 ARMMMUIdx mmu_idx;
61 uint8_t tbii;
62 uint8_t tbid;
63 uint8_t tcma;
64 bool ns;
65 int fp_excp_el;
66 int sve_excp_el;
67 int sme_excp_el;
68 int vl;
69 int svl;
70 bool vfp_enabled;
71 int vec_len;
72 int vec_stride;
73 bool v7m_handler_mode;
74 bool v8m_secure;
75 bool v8m_stackcheck;
76 bool v8m_fpccr_s_wrong;
77 bool v7m_new_fp_ctxt_needed;
78 bool v7m_lspact;
79
80
81
82 uint32_t svc_imm;
83 int current_el;
84 GHashTable *cp_regs;
85 uint64_t features;
86 bool aarch64;
87 bool thumb;
88
89
90
91
92
93
94
95 bool fp_access_checked;
96 bool sve_access_checked;
97
98
99
100 bool ss_active;
101 bool pstate_ss;
102
103
104
105
106 bool is_ldex;
107
108 bool unpriv;
109
110 bool pauth_active;
111
112 bool ata;
113
114 bool mte_active[2];
115
116 bool bt;
117
118 bool hstr_active;
119
120 bool align_mem;
121
122 bool pstate_il;
123
124 bool pstate_sm;
125
126 bool pstate_za;
127
128 bool sme_trap_nonstreaming;
129
130 bool is_nonstreaming;
131
132 bool mve_no_pred;
133
134 bool fgt_active;
135
136 bool fgt_eret;
137
138 bool fgt_svc;
139
140
141
142
143 int8_t btype;
144
145 uint8_t dcz_blocksize;
146
147 bool guarded_page;
148
149 int c15_cpar;
150
151 TCGOp *insn_start;
152} DisasContext;
153
154typedef struct DisasCompare {
155 TCGCond cond;
156 TCGv_i32 value;
157} DisasCompare;
158
159
160extern TCGv_i32 cpu_NF, cpu_ZF, cpu_CF, cpu_VF;
161extern TCGv_i64 cpu_exclusive_addr;
162extern TCGv_i64 cpu_exclusive_val;
163
164
165
166
167
168static inline int negate(DisasContext *s, int x)
169{
170 return -x;
171}
172
173static inline int plus_1(DisasContext *s, int x)
174{
175 return x + 1;
176}
177
178static inline int plus_2(DisasContext *s, int x)
179{
180 return x + 2;
181}
182
183static inline int plus_12(DisasContext *s, int x)
184{
185 return x + 12;
186}
187
188static inline int times_2(DisasContext *s, int x)
189{
190 return x * 2;
191}
192
193static inline int times_4(DisasContext *s, int x)
194{
195 return x * 4;
196}
197
198static inline int times_2_plus_1(DisasContext *s, int x)
199{
200 return x * 2 + 1;
201}
202
203static inline int rsub_64(DisasContext *s, int x)
204{
205 return 64 - x;
206}
207
208static inline int rsub_32(DisasContext *s, int x)
209{
210 return 32 - x;
211}
212
213static inline int rsub_16(DisasContext *s, int x)
214{
215 return 16 - x;
216}
217
218static inline int rsub_8(DisasContext *s, int x)
219{
220 return 8 - x;
221}
222
223static inline int neon_3same_fp_size(DisasContext *s, int x)
224{
225
226 return MO_32 - x;
227}
228
229static inline int arm_dc_feature(DisasContext *dc, int feature)
230{
231 return (dc->features & (1ULL << feature)) != 0;
232}
233
234static inline int get_mem_index(DisasContext *s)
235{
236 return arm_to_core_mmu_idx(s->mmu_idx);
237}
238
239static inline void disas_set_insn_syndrome(DisasContext *s, uint32_t syn)
240{
241
242
243
244 syn &= ARM_INSN_START_WORD2_MASK;
245 syn >>= ARM_INSN_START_WORD2_SHIFT;
246
247
248 assert(s->insn_start != NULL);
249 tcg_set_insn_start_param(s->insn_start, 2, syn);
250 s->insn_start = NULL;
251}
252
253static inline int curr_insn_len(DisasContext *s)
254{
255 return s->base.pc_next - s->pc_curr;
256}
257
258
259#define DISAS_JUMP DISAS_TARGET_0
260
261#define DISAS_UPDATE_EXIT DISAS_TARGET_1
262
263
264
265
266#define DISAS_WFI DISAS_TARGET_2
267#define DISAS_SWI DISAS_TARGET_3
268
269#define DISAS_WFE DISAS_TARGET_4
270#define DISAS_HVC DISAS_TARGET_5
271#define DISAS_SMC DISAS_TARGET_6
272#define DISAS_YIELD DISAS_TARGET_7
273
274
275
276#define DISAS_BX_EXCRET DISAS_TARGET_8
277
278
279
280
281
282
283
284#define DISAS_EXIT DISAS_TARGET_9
285
286#define DISAS_UPDATE_NOCHAIN DISAS_TARGET_10
287
288#ifdef TARGET_AARCH64
289void a64_translate_init(void);
290void gen_a64_update_pc(DisasContext *s, target_long diff);
291extern const TranslatorOps aarch64_translator_ops;
292#else
293static inline void a64_translate_init(void)
294{
295}
296
297static inline void gen_a64_update_pc(DisasContext *s, target_long diff)
298{
299}
300#endif
301
302void arm_test_cc(DisasCompare *cmp, int cc);
303void arm_jump_cc(DisasCompare *cmp, TCGLabel *label);
304void arm_gen_test_cc(int cc, TCGLabel *label);
305MemOp pow2_align(unsigned i);
306void unallocated_encoding(DisasContext *s);
307void gen_exception_insn_el(DisasContext *s, target_long pc_diff, int excp,
308 uint32_t syn, uint32_t target_el);
309void gen_exception_insn(DisasContext *s, target_long pc_diff,
310 int excp, uint32_t syn);
311
312
313static inline TCGv_i32 get_ahp_flag(void)
314{
315 TCGv_i32 ret = tcg_temp_new_i32();
316
317 tcg_gen_ld_i32(ret, cpu_env,
318 offsetof(CPUARMState, vfp.xregs[ARM_VFP_FPSCR]));
319 tcg_gen_extract_i32(ret, ret, 26, 1);
320
321 return ret;
322}
323
324
325static inline void set_pstate_bits(uint32_t bits)
326{
327 TCGv_i32 p = tcg_temp_new_i32();
328
329 tcg_debug_assert(!(bits & CACHED_PSTATE_BITS));
330
331 tcg_gen_ld_i32(p, cpu_env, offsetof(CPUARMState, pstate));
332 tcg_gen_ori_i32(p, p, bits);
333 tcg_gen_st_i32(p, cpu_env, offsetof(CPUARMState, pstate));
334}
335
336
337static inline void clear_pstate_bits(uint32_t bits)
338{
339 TCGv_i32 p = tcg_temp_new_i32();
340
341 tcg_debug_assert(!(bits & CACHED_PSTATE_BITS));
342
343 tcg_gen_ld_i32(p, cpu_env, offsetof(CPUARMState, pstate));
344 tcg_gen_andi_i32(p, p, ~bits);
345 tcg_gen_st_i32(p, cpu_env, offsetof(CPUARMState, pstate));
346}
347
348
349static inline void gen_ss_advance(DisasContext *s)
350{
351 if (s->ss_active) {
352 s->pstate_ss = 0;
353 clear_pstate_bits(PSTATE_SS);
354 }
355}
356
357
358static inline void gen_swstep_exception(DisasContext *s, int isv, int ex)
359{
360
361 uint32_t syn = syn_swstep(false, isv, ex);
362 gen_helper_exception_swstep(cpu_env, tcg_constant_i32(syn));
363}
364
365
366
367
368
369
370uint64_t vfp_expand_imm(int size, uint8_t imm8);
371
372
373void gen_gvec_ceq0(unsigned vece, uint32_t rd_ofs, uint32_t rm_ofs,
374 uint32_t opr_sz, uint32_t max_sz);
375void gen_gvec_clt0(unsigned vece, uint32_t rd_ofs, uint32_t rm_ofs,
376 uint32_t opr_sz, uint32_t max_sz);
377void gen_gvec_cgt0(unsigned vece, uint32_t rd_ofs, uint32_t rm_ofs,
378 uint32_t opr_sz, uint32_t max_sz);
379void gen_gvec_cle0(unsigned vece, uint32_t rd_ofs, uint32_t rm_ofs,
380 uint32_t opr_sz, uint32_t max_sz);
381void gen_gvec_cge0(unsigned vece, uint32_t rd_ofs, uint32_t rm_ofs,
382 uint32_t opr_sz, uint32_t max_sz);
383
384void gen_gvec_mla(unsigned vece, uint32_t rd_ofs, uint32_t rn_ofs,
385 uint32_t rm_ofs, uint32_t opr_sz, uint32_t max_sz);
386void gen_gvec_mls(unsigned vece, uint32_t rd_ofs, uint32_t rn_ofs,
387 uint32_t rm_ofs, uint32_t opr_sz, uint32_t max_sz);
388
389void gen_gvec_cmtst(unsigned vece, uint32_t rd_ofs, uint32_t rn_ofs,
390 uint32_t rm_ofs, uint32_t opr_sz, uint32_t max_sz);
391void gen_gvec_sshl(unsigned vece, uint32_t rd_ofs, uint32_t rn_ofs,
392 uint32_t rm_ofs, uint32_t opr_sz, uint32_t max_sz);
393void gen_gvec_ushl(unsigned vece, uint32_t rd_ofs, uint32_t rn_ofs,
394 uint32_t rm_ofs, uint32_t opr_sz, uint32_t max_sz);
395
396void gen_cmtst_i64(TCGv_i64 d, TCGv_i64 a, TCGv_i64 b);
397void gen_ushl_i32(TCGv_i32 d, TCGv_i32 a, TCGv_i32 b);
398void gen_sshl_i32(TCGv_i32 d, TCGv_i32 a, TCGv_i32 b);
399void gen_ushl_i64(TCGv_i64 d, TCGv_i64 a, TCGv_i64 b);
400void gen_sshl_i64(TCGv_i64 d, TCGv_i64 a, TCGv_i64 b);
401
402void gen_gvec_uqadd_qc(unsigned vece, uint32_t rd_ofs, uint32_t rn_ofs,
403 uint32_t rm_ofs, uint32_t opr_sz, uint32_t max_sz);
404void gen_gvec_sqadd_qc(unsigned vece, uint32_t rd_ofs, uint32_t rn_ofs,
405 uint32_t rm_ofs, uint32_t opr_sz, uint32_t max_sz);
406void gen_gvec_uqsub_qc(unsigned vece, uint32_t rd_ofs, uint32_t rn_ofs,
407 uint32_t rm_ofs, uint32_t opr_sz, uint32_t max_sz);
408void gen_gvec_sqsub_qc(unsigned vece, uint32_t rd_ofs, uint32_t rn_ofs,
409 uint32_t rm_ofs, uint32_t opr_sz, uint32_t max_sz);
410
411void gen_gvec_ssra(unsigned vece, uint32_t rd_ofs, uint32_t rm_ofs,
412 int64_t shift, uint32_t opr_sz, uint32_t max_sz);
413void gen_gvec_usra(unsigned vece, uint32_t rd_ofs, uint32_t rm_ofs,
414 int64_t shift, uint32_t opr_sz, uint32_t max_sz);
415
416void gen_gvec_srshr(unsigned vece, uint32_t rd_ofs, uint32_t rm_ofs,
417 int64_t shift, uint32_t opr_sz, uint32_t max_sz);
418void gen_gvec_urshr(unsigned vece, uint32_t rd_ofs, uint32_t rm_ofs,
419 int64_t shift, uint32_t opr_sz, uint32_t max_sz);
420void gen_gvec_srsra(unsigned vece, uint32_t rd_ofs, uint32_t rm_ofs,
421 int64_t shift, uint32_t opr_sz, uint32_t max_sz);
422void gen_gvec_ursra(unsigned vece, uint32_t rd_ofs, uint32_t rm_ofs,
423 int64_t shift, uint32_t opr_sz, uint32_t max_sz);
424
425void gen_gvec_sri(unsigned vece, uint32_t rd_ofs, uint32_t rm_ofs,
426 int64_t shift, uint32_t opr_sz, uint32_t max_sz);
427void gen_gvec_sli(unsigned vece, uint32_t rd_ofs, uint32_t rm_ofs,
428 int64_t shift, uint32_t opr_sz, uint32_t max_sz);
429
430void gen_gvec_sqrdmlah_qc(unsigned vece, uint32_t rd_ofs, uint32_t rn_ofs,
431 uint32_t rm_ofs, uint32_t opr_sz, uint32_t max_sz);
432void gen_gvec_sqrdmlsh_qc(unsigned vece, uint32_t rd_ofs, uint32_t rn_ofs,
433 uint32_t rm_ofs, uint32_t opr_sz, uint32_t max_sz);
434
435void gen_gvec_sabd(unsigned vece, uint32_t rd_ofs, uint32_t rn_ofs,
436 uint32_t rm_ofs, uint32_t opr_sz, uint32_t max_sz);
437void gen_gvec_uabd(unsigned vece, uint32_t rd_ofs, uint32_t rn_ofs,
438 uint32_t rm_ofs, uint32_t opr_sz, uint32_t max_sz);
439
440void gen_gvec_saba(unsigned vece, uint32_t rd_ofs, uint32_t rn_ofs,
441 uint32_t rm_ofs, uint32_t opr_sz, uint32_t max_sz);
442void gen_gvec_uaba(unsigned vece, uint32_t rd_ofs, uint32_t rn_ofs,
443 uint32_t rm_ofs, uint32_t opr_sz, uint32_t max_sz);
444
445
446
447
448#define dc_isar_feature(name, ctx) \
449 ({ DisasContext *ctx_ = (ctx); isar_feature_##name(ctx_->isar); })
450
451
452typedef void GVecGen2Fn(unsigned, uint32_t, uint32_t, uint32_t, uint32_t);
453typedef void GVecGen2iFn(unsigned, uint32_t, uint32_t, int64_t,
454 uint32_t, uint32_t);
455typedef void GVecGen3Fn(unsigned, uint32_t, uint32_t,
456 uint32_t, uint32_t, uint32_t);
457typedef void GVecGen4Fn(unsigned, uint32_t, uint32_t, uint32_t,
458 uint32_t, uint32_t, uint32_t);
459
460
461typedef void NeonGenOneOpFn(TCGv_i32, TCGv_i32);
462typedef void NeonGenOneOpEnvFn(TCGv_i32, TCGv_ptr, TCGv_i32);
463typedef void NeonGenTwoOpFn(TCGv_i32, TCGv_i32, TCGv_i32);
464typedef void NeonGenTwoOpEnvFn(TCGv_i32, TCGv_ptr, TCGv_i32, TCGv_i32);
465typedef void NeonGenThreeOpEnvFn(TCGv_i32, TCGv_env, TCGv_i32,
466 TCGv_i32, TCGv_i32);
467typedef void NeonGenTwo64OpFn(TCGv_i64, TCGv_i64, TCGv_i64);
468typedef void NeonGenTwo64OpEnvFn(TCGv_i64, TCGv_ptr, TCGv_i64, TCGv_i64);
469typedef void NeonGenNarrowFn(TCGv_i32, TCGv_i64);
470typedef void NeonGenNarrowEnvFn(TCGv_i32, TCGv_ptr, TCGv_i64);
471typedef void NeonGenWidenFn(TCGv_i64, TCGv_i32);
472typedef void NeonGenTwoOpWidenFn(TCGv_i64, TCGv_i32, TCGv_i32);
473typedef void NeonGenOneSingleOpFn(TCGv_i32, TCGv_i32, TCGv_ptr);
474typedef void NeonGenTwoSingleOpFn(TCGv_i32, TCGv_i32, TCGv_i32, TCGv_ptr);
475typedef void NeonGenTwoDoubleOpFn(TCGv_i64, TCGv_i64, TCGv_i64, TCGv_ptr);
476typedef void NeonGenOne64OpFn(TCGv_i64, TCGv_i64);
477typedef void CryptoTwoOpFn(TCGv_ptr, TCGv_ptr);
478typedef void CryptoThreeOpIntFn(TCGv_ptr, TCGv_ptr, TCGv_i32);
479typedef void CryptoThreeOpFn(TCGv_ptr, TCGv_ptr, TCGv_ptr);
480typedef void AtomicThreeOpFn(TCGv_i64, TCGv_i64, TCGv_i64, TCGArg, MemOp);
481typedef void WideShiftImmFn(TCGv_i64, TCGv_i64, int64_t shift);
482typedef void WideShiftFn(TCGv_i64, TCGv_ptr, TCGv_i64, TCGv_i32);
483typedef void ShiftImmFn(TCGv_i32, TCGv_i32, int32_t shift);
484typedef void ShiftFn(TCGv_i32, TCGv_ptr, TCGv_i32, TCGv_i32);
485
486
487
488
489
490
491
492static inline CPUARMTBFlags arm_tbflags_from_tb(const TranslationBlock *tb)
493{
494 return (CPUARMTBFlags){ tb->flags, tb->cs_base };
495}
496
497
498
499
500typedef enum ARMFPStatusFlavour {
501 FPST_FPCR,
502 FPST_FPCR_F16,
503 FPST_STD,
504 FPST_STD_F16,
505} ARMFPStatusFlavour;
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524static inline TCGv_ptr fpstatus_ptr(ARMFPStatusFlavour flavour)
525{
526 TCGv_ptr statusptr = tcg_temp_new_ptr();
527 int offset;
528
529 switch (flavour) {
530 case FPST_FPCR:
531 offset = offsetof(CPUARMState, vfp.fp_status);
532 break;
533 case FPST_FPCR_F16:
534 offset = offsetof(CPUARMState, vfp.fp_status_f16);
535 break;
536 case FPST_STD:
537 offset = offsetof(CPUARMState, vfp.standard_fp_status);
538 break;
539 case FPST_STD_F16:
540 offset = offsetof(CPUARMState, vfp.standard_fp_status_f16);
541 break;
542 default:
543 g_assert_not_reached();
544 }
545 tcg_gen_addi_ptr(statusptr, cpu_env, offset);
546 return statusptr;
547}
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565static inline MemOp finalize_memop(DisasContext *s, MemOp opc)
566{
567 if (s->align_mem && !(opc & MO_AMASK)) {
568 opc |= MO_ALIGN;
569 }
570 return opc | s->be_data;
571}
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588uint64_t asimd_imm_const(uint32_t imm, int cmode, int op);
589
590
591
592
593
594static inline DisasLabel gen_disas_label(DisasContext *s)
595{
596 return (DisasLabel){
597 .label = gen_new_label(),
598 .pc_save = s->pc_save,
599 };
600}
601
602
603
604
605
606static inline void set_disas_label(DisasContext *s, DisasLabel l)
607{
608 gen_set_label(l.label);
609 s->pc_save = l.pc_save;
610}
611
612static inline TCGv_ptr gen_lookup_cp_reg(uint32_t key)
613{
614 TCGv_ptr ret = tcg_temp_new_ptr();
615 gen_helper_lookup_cp_reg(ret, cpu_env, tcg_constant_i32(key));
616 return ret;
617}
618
619
620
621
622static inline TCGv_i32 gen_set_rmode(ARMFPRounding rmode, TCGv_ptr fpst)
623{
624 TCGv_i32 new = tcg_constant_i32(arm_rmode_to_sf(rmode));
625 TCGv_i32 old = tcg_temp_new_i32();
626
627 gen_helper_set_rmode(old, new, fpst);
628 return old;
629}
630
631static inline void gen_restore_rmode(TCGv_i32 old, TCGv_ptr fpst)
632{
633 gen_helper_set_rmode(old, old, fpst);
634}
635
636
637
638
639
640#define TRANS(NAME, FUNC, ...) \
641 static bool trans_##NAME(DisasContext *s, arg_##NAME *a) \
642 { return FUNC(s, __VA_ARGS__); }
643#define TRANS_FEAT(NAME, FEAT, FUNC, ...) \
644 static bool trans_##NAME(DisasContext *s, arg_##NAME *a) \
645 { return dc_isar_feature(FEAT, s) && FUNC(s, __VA_ARGS__); }
646
647#define TRANS_FEAT_NONSTREAMING(NAME, FEAT, FUNC, ...) \
648 static bool trans_##NAME(DisasContext *s, arg_##NAME *a) \
649 { \
650 s->is_nonstreaming = true; \
651 return dc_isar_feature(FEAT, s) && FUNC(s, __VA_ARGS__); \
652 }
653
654#endif
655