]>
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); | |
42 | uint64_t vfp_expand_imm(int size, uint8_t imm8); | |
43 | bool sve_access_check(DisasContext *s); | |
44 | ||
45 | /* We should have at some point before trying to access an FP register | |
46 | * done the necessary access check, so assert that | |
47 | * (a) we did the check and | |
48 | * (b) we didn't then just plough ahead anyway if it failed. | |
49 | * Print the instruction pattern in the abort message so we can figure | |
50 | * out what we need to fix if a user encounters this problem in the wild. | |
51 | */ | |
52 | static inline void assert_fp_access_checked(DisasContext *s) | |
53 | { | |
54 | #ifdef CONFIG_DEBUG_TCG | |
55 | if (unlikely(!s->fp_access_checked || s->fp_excp_el)) { | |
56 | fprintf(stderr, "target-arm: FP access check missing for " | |
57 | "instruction 0x%08x\n", s->insn); | |
58 | abort(); | |
59 | } | |
60 | #endif | |
61 | } | |
62 | ||
63 | /* Return the offset into CPUARMState of an element of specified | |
64 | * size, 'element' places in from the least significant end of | |
65 | * the FP/vector register Qn. | |
66 | */ | |
67 | static inline int vec_reg_offset(DisasContext *s, int regno, | |
68 | int element, TCGMemOp size) | |
69 | { | |
66f2dbd7 RH |
70 | int element_size = 1 << size; |
71 | int offs = element * element_size; | |
8c71baed RH |
72 | #ifdef HOST_WORDS_BIGENDIAN |
73 | /* This is complicated slightly because vfp.zregs[n].d[0] is | |
66f2dbd7 RH |
74 | * still the lowest and vfp.zregs[n].d[15] the highest of the |
75 | * 256 byte vector, even on big endian systems. | |
76 | * | |
77 | * Calculate the offset assuming fully little-endian, | |
78 | * then XOR to account for the order of the 8-byte units. | |
79 | * | |
80 | * For 16 byte elements, the two 8 byte halves will not form a | |
81 | * host int128 if the host is bigendian, since they're in the | |
82 | * wrong order. However the only 16 byte operation we have is | |
83 | * a move, so we can ignore this for the moment. More complicated | |
84 | * operations will have to special case loading and storing from | |
85 | * the zregs array. | |
8c71baed | 86 | */ |
66f2dbd7 RH |
87 | if (element_size < 8) { |
88 | offs ^= 8 - element_size; | |
89 | } | |
8c71baed RH |
90 | #endif |
91 | offs += offsetof(CPUARMState, vfp.zregs[regno]); | |
92 | assert_fp_access_checked(s); | |
93 | return offs; | |
94 | } | |
95 | ||
96 | /* Return the offset info CPUARMState of the "whole" vector register Qn. */ | |
97 | static inline int vec_full_reg_offset(DisasContext *s, int regno) | |
98 | { | |
99 | assert_fp_access_checked(s); | |
100 | return offsetof(CPUARMState, vfp.zregs[regno]); | |
101 | } | |
102 | ||
103 | /* Return a newly allocated pointer to the vector register. */ | |
104 | static inline TCGv_ptr vec_full_reg_ptr(DisasContext *s, int regno) | |
105 | { | |
106 | TCGv_ptr ret = tcg_temp_new_ptr(); | |
107 | tcg_gen_addi_ptr(ret, cpu_env, vec_full_reg_offset(s, regno)); | |
108 | return ret; | |
109 | } | |
110 | ||
111 | /* Return the byte size of the "whole" vector register, VL / 8. */ | |
112 | static inline int vec_full_reg_size(DisasContext *s) | |
113 | { | |
114 | return s->sve_len; | |
115 | } | |
116 | ||
117 | bool disas_sve(DisasContext *, uint32_t); | |
118 | ||
119 | /* Note that the gvec expanders operate on offsets + sizes. */ | |
120 | typedef void GVecGen2Fn(unsigned, uint32_t, uint32_t, uint32_t, uint32_t); | |
121 | typedef void GVecGen2iFn(unsigned, uint32_t, uint32_t, int64_t, | |
122 | uint32_t, uint32_t); | |
123 | typedef void GVecGen3Fn(unsigned, uint32_t, uint32_t, | |
124 | uint32_t, uint32_t, uint32_t); | |
125 | ||
126 | #endif /* TARGET_ARM_TRANSLATE_A64_H */ |