]>
Commit | Line | Data |
---|---|---|
8c71baed RH |
1 | /* |
2 | * AArch64 translation, common definitions. | |
3 | * | |
4 | * This library is free software; you can redistribute it and/or | |
5 | * modify it under the terms of the GNU Lesser General Public | |
6 | * License as published by the Free Software Foundation; either | |
7 | * version 2 of the License, or (at your option) any later version. | |
8 | * | |
9 | * This library is distributed in the hope that it will be useful, | |
10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |
12 | * Lesser General Public License for more details. | |
13 | * | |
14 | * You should have received a copy of the GNU Lesser General Public | |
15 | * License along with this library; if not, see <http://www.gnu.org/licenses/>. | |
16 | */ | |
17 | ||
18 | #ifndef TARGET_ARM_TRANSLATE_A64_H | |
19 | #define TARGET_ARM_TRANSLATE_A64_H | |
20 | ||
21 | void unallocated_encoding(DisasContext *s); | |
22 | ||
23 | #define unsupported_encoding(s, insn) \ | |
24 | do { \ | |
25 | qemu_log_mask(LOG_UNIMP, \ | |
26 | "%s:%d: unsupported instruction encoding 0x%08x " \ | |
27 | "at pc=%016" PRIx64 "\n", \ | |
28 | __FILE__, __LINE__, insn, s->pc - 4); \ | |
29 | unallocated_encoding(s); \ | |
30 | } while (0) | |
31 | ||
32 | TCGv_i64 new_tmp_a64(DisasContext *s); | |
33 | TCGv_i64 new_tmp_a64_zero(DisasContext *s); | |
34 | TCGv_i64 cpu_reg(DisasContext *s, int reg); | |
35 | TCGv_i64 cpu_reg_sp(DisasContext *s, int reg); | |
36 | TCGv_i64 read_cpu_reg(DisasContext *s, int reg, int sf); | |
37 | TCGv_i64 read_cpu_reg_sp(DisasContext *s, int reg, int sf); | |
38 | void write_fp_dreg(DisasContext *s, int reg, TCGv_i64 v); | |
39 | TCGv_ptr get_fpstatus_ptr(bool); | |
40 | bool logic_imm_decode_wmask(uint64_t *result, unsigned int immn, | |
41 | unsigned int imms, unsigned int immr); | |
8c71baed RH |
42 | bool sve_access_check(DisasContext *s); |
43 | ||
44 | /* We should have at some point before trying to access an FP register | |
45 | * done the necessary access check, so assert that | |
46 | * (a) we did the check and | |
47 | * (b) we didn't then just plough ahead anyway if it failed. | |
48 | * Print the instruction pattern in the abort message so we can figure | |
49 | * out what we need to fix if a user encounters this problem in the wild. | |
50 | */ | |
51 | static inline void assert_fp_access_checked(DisasContext *s) | |
52 | { | |
53 | #ifdef CONFIG_DEBUG_TCG | |
54 | if (unlikely(!s->fp_access_checked || s->fp_excp_el)) { | |
55 | fprintf(stderr, "target-arm: FP access check missing for " | |
56 | "instruction 0x%08x\n", s->insn); | |
57 | abort(); | |
58 | } | |
59 | #endif | |
60 | } | |
61 | ||
62 | /* Return the offset into CPUARMState of an element of specified | |
63 | * size, 'element' places in from the least significant end of | |
64 | * the FP/vector register Qn. | |
65 | */ | |
66 | static inline int vec_reg_offset(DisasContext *s, int regno, | |
67 | int element, TCGMemOp size) | |
68 | { | |
66f2dbd7 RH |
69 | int element_size = 1 << size; |
70 | int offs = element * element_size; | |
8c71baed RH |
71 | #ifdef HOST_WORDS_BIGENDIAN |
72 | /* This is complicated slightly because vfp.zregs[n].d[0] is | |
66f2dbd7 RH |
73 | * still the lowest and vfp.zregs[n].d[15] the highest of the |
74 | * 256 byte vector, even on big endian systems. | |
75 | * | |
76 | * Calculate the offset assuming fully little-endian, | |
77 | * then XOR to account for the order of the 8-byte units. | |
78 | * | |
79 | * For 16 byte elements, the two 8 byte halves will not form a | |
80 | * host int128 if the host is bigendian, since they're in the | |
81 | * wrong order. However the only 16 byte operation we have is | |
82 | * a move, so we can ignore this for the moment. More complicated | |
83 | * operations will have to special case loading and storing from | |
84 | * the zregs array. | |
8c71baed | 85 | */ |
66f2dbd7 RH |
86 | if (element_size < 8) { |
87 | offs ^= 8 - element_size; | |
88 | } | |
8c71baed RH |
89 | #endif |
90 | offs += offsetof(CPUARMState, vfp.zregs[regno]); | |
91 | assert_fp_access_checked(s); | |
92 | return offs; | |
93 | } | |
94 | ||
95 | /* Return the offset info CPUARMState of the "whole" vector register Qn. */ | |
96 | static inline int vec_full_reg_offset(DisasContext *s, int regno) | |
97 | { | |
98 | assert_fp_access_checked(s); | |
99 | return offsetof(CPUARMState, vfp.zregs[regno]); | |
100 | } | |
101 | ||
102 | /* Return a newly allocated pointer to the vector register. */ | |
103 | static inline TCGv_ptr vec_full_reg_ptr(DisasContext *s, int regno) | |
104 | { | |
105 | TCGv_ptr ret = tcg_temp_new_ptr(); | |
106 | tcg_gen_addi_ptr(ret, cpu_env, vec_full_reg_offset(s, regno)); | |
107 | return ret; | |
108 | } | |
109 | ||
110 | /* Return the byte size of the "whole" vector register, VL / 8. */ | |
111 | static inline int vec_full_reg_size(DisasContext *s) | |
112 | { | |
113 | return s->sve_len; | |
114 | } | |
115 | ||
116 | bool disas_sve(DisasContext *, uint32_t); | |
117 | ||
118 | /* Note that the gvec expanders operate on offsets + sizes. */ | |
119 | typedef void GVecGen2Fn(unsigned, uint32_t, uint32_t, uint32_t, uint32_t); | |
120 | typedef void GVecGen2iFn(unsigned, uint32_t, uint32_t, int64_t, | |
121 | uint32_t, uint32_t); | |
122 | typedef void GVecGen3Fn(unsigned, uint32_t, uint32_t, | |
123 | uint32_t, uint32_t, uint32_t); | |
3a7a2b4e RH |
124 | typedef void GVecGen4Fn(unsigned, uint32_t, uint32_t, uint32_t, |
125 | uint32_t, uint32_t, uint32_t); | |
8c71baed RH |
126 | |
127 | #endif /* TARGET_ARM_TRANSLATE_A64_H */ |