2 * ARM SVE Load/Store Helpers
4 * Copyright (c) 2018-2022 Linaro
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, see <http://www.gnu.org/licenses/>.
20 #ifndef TARGET_ARM_SVE_LDST_INTERNAL_H
21 #define TARGET_ARM_SVE_LDST_INTERNAL_H
23 #include "exec/cpu_ldst.h"
26 * Load one element into @vd + @reg_off from @host.
27 * The controlling predicate is known to be true.
29 typedef void sve_ldst1_host_fn(void *vd
, intptr_t reg_off
, void *host
);
32 * Load one element into @vd + @reg_off from (@env, @vaddr, @ra).
33 * The controlling predicate is known to be true.
35 typedef void sve_ldst1_tlb_fn(CPUARMState
*env
, void *vd
, intptr_t reg_off
,
36 target_ulong vaddr
, uintptr_t retaddr
);
39 * Generate the above primitives.
42 #define DO_LD_HOST(NAME, H, TYPEE, TYPEM, HOST) \
43 static inline void sve_##NAME##_host(void *vd, intptr_t reg_off, void *host) \
44 { TYPEM val = HOST(host); *(TYPEE *)(vd + H(reg_off)) = val; }
46 #define DO_ST_HOST(NAME, H, TYPEE, TYPEM, HOST) \
47 static inline void sve_##NAME##_host(void *vd, intptr_t reg_off, void *host) \
48 { TYPEM val = *(TYPEE *)(vd + H(reg_off)); HOST(host, val); }
50 #define DO_LD_TLB(NAME, H, TYPEE, TYPEM, TLB) \
51 static inline void sve_##NAME##_tlb(CPUARMState *env, void *vd, \
52 intptr_t reg_off, target_ulong addr, uintptr_t ra) \
54 TYPEM val = TLB(env, useronly_clean_ptr(addr), ra); \
55 *(TYPEE *)(vd + H(reg_off)) = val; \
58 #define DO_ST_TLB(NAME, H, TYPEE, TYPEM, TLB) \
59 static inline void sve_##NAME##_tlb(CPUARMState *env, void *vd, \
60 intptr_t reg_off, target_ulong addr, uintptr_t ra) \
62 TYPEM val = *(TYPEE *)(vd + H(reg_off)); \
63 TLB(env, useronly_clean_ptr(addr), val, ra); \
66 #define DO_LD_PRIM_1(NAME, H, TE, TM) \
67 DO_LD_HOST(NAME, H, TE, TM, ldub_p) \
68 DO_LD_TLB(NAME, H, TE, TM, cpu_ldub_data_ra)
70 DO_LD_PRIM_1(ld1bb
, H1
, uint8_t, uint8_t)
71 DO_LD_PRIM_1(ld1bhu
, H1_2
, uint16_t, uint8_t)
72 DO_LD_PRIM_1(ld1bhs
, H1_2
, uint16_t, int8_t)
73 DO_LD_PRIM_1(ld1bsu
, H1_4
, uint32_t, uint8_t)
74 DO_LD_PRIM_1(ld1bss
, H1_4
, uint32_t, int8_t)
75 DO_LD_PRIM_1(ld1bdu
, H1_8
, uint64_t, uint8_t)
76 DO_LD_PRIM_1(ld1bds
, H1_8
, uint64_t, int8_t)
78 #define DO_ST_PRIM_1(NAME, H, TE, TM) \
79 DO_ST_HOST(st1##NAME, H, TE, TM, stb_p) \
80 DO_ST_TLB(st1##NAME, H, TE, TM, cpu_stb_data_ra)
82 DO_ST_PRIM_1(bb
, H1
, uint8_t, uint8_t)
83 DO_ST_PRIM_1(bh
, H1_2
, uint16_t, uint8_t)
84 DO_ST_PRIM_1(bs
, H1_4
, uint32_t, uint8_t)
85 DO_ST_PRIM_1(bd
, H1_8
, uint64_t, uint8_t)
87 #define DO_LD_PRIM_2(NAME, H, TE, TM, LD) \
88 DO_LD_HOST(ld1##NAME##_be, H, TE, TM, LD##_be_p) \
89 DO_LD_HOST(ld1##NAME##_le, H, TE, TM, LD##_le_p) \
90 DO_LD_TLB(ld1##NAME##_be, H, TE, TM, cpu_##LD##_be_data_ra) \
91 DO_LD_TLB(ld1##NAME##_le, H, TE, TM, cpu_##LD##_le_data_ra)
93 #define DO_ST_PRIM_2(NAME, H, TE, TM, ST) \
94 DO_ST_HOST(st1##NAME##_be, H, TE, TM, ST##_be_p) \
95 DO_ST_HOST(st1##NAME##_le, H, TE, TM, ST##_le_p) \
96 DO_ST_TLB(st1##NAME##_be, H, TE, TM, cpu_##ST##_be_data_ra) \
97 DO_ST_TLB(st1##NAME##_le, H, TE, TM, cpu_##ST##_le_data_ra)
99 DO_LD_PRIM_2(hh
, H1_2
, uint16_t, uint16_t, lduw
)
100 DO_LD_PRIM_2(hsu
, H1_4
, uint32_t, uint16_t, lduw
)
101 DO_LD_PRIM_2(hss
, H1_4
, uint32_t, int16_t, lduw
)
102 DO_LD_PRIM_2(hdu
, H1_8
, uint64_t, uint16_t, lduw
)
103 DO_LD_PRIM_2(hds
, H1_8
, uint64_t, int16_t, lduw
)
105 DO_ST_PRIM_2(hh
, H1_2
, uint16_t, uint16_t, stw
)
106 DO_ST_PRIM_2(hs
, H1_4
, uint32_t, uint16_t, stw
)
107 DO_ST_PRIM_2(hd
, H1_8
, uint64_t, uint16_t, stw
)
109 DO_LD_PRIM_2(ss
, H1_4
, uint32_t, uint32_t, ldl
)
110 DO_LD_PRIM_2(sdu
, H1_8
, uint64_t, uint32_t, ldl
)
111 DO_LD_PRIM_2(sds
, H1_8
, uint64_t, int32_t, ldl
)
113 DO_ST_PRIM_2(ss
, H1_4
, uint32_t, uint32_t, stl
)
114 DO_ST_PRIM_2(sd
, H1_8
, uint64_t, uint32_t, stl
)
116 DO_LD_PRIM_2(dd
, H1_8
, uint64_t, uint64_t, ldq
)
117 DO_ST_PRIM_2(dd
, H1_8
, uint64_t, uint64_t, stq
)
128 * Resolve the guest virtual address to info->host and info->flags.
129 * If @nofault, return false if the page is invalid, otherwise
130 * exit via page fault exception.
140 bool sve_probe_page(SVEHostPage
*info
, bool nofault
, CPUARMState
*env
,
141 target_ulong addr
, int mem_off
, MMUAccessType access_type
,
142 int mmu_idx
, uintptr_t retaddr
);
145 * Analyse contiguous data, protected by a governing predicate.
156 * First and last element wholly contained within the two pages.
157 * mem_off_first[0] and reg_off_first[0] are always set >= 0.
158 * reg_off_last[0] may be < 0 if the first element crosses pages.
159 * All of mem_off_first[1], reg_off_first[1] and reg_off_last[1]
160 * are set >= 0 only if there are complete elements on a second page.
162 * The reg_off_* offsets are relative to the internal vector register.
163 * The mem_off_first offset is relative to the memory address; the
164 * two offsets are different when a load operation extends, a store
165 * operation truncates, or for multi-register operations.
167 int16_t mem_off_first
[2];
168 int16_t reg_off_first
[2];
169 int16_t reg_off_last
[2];
172 * One element that is misaligned and spans both pages,
173 * or -1 if there is no such active element.
175 int16_t mem_off_split
;
176 int16_t reg_off_split
;
179 * The byte offset at which the entire operation crosses a page boundary.
180 * Set >= 0 if and only if the entire operation spans two pages.
184 /* TLB data for the two pages. */
189 * Find first active element on each page, and a loose bound for the
190 * final element on each page. Identify any single element that spans
191 * the page boundary. Return true if there are any active elements.
193 bool sve_cont_ldst_elements(SVEContLdSt
*info
, target_ulong addr
, uint64_t *vg
,
194 intptr_t reg_max
, int esz
, int msize
);
197 * Resolve the guest virtual addresses to info->page[].
198 * Control the generation of page faults with @fault. Return false if
199 * there is no work to do, which can only happen with @fault == FAULT_NO.
201 bool sve_cont_ldst_pages(SVEContLdSt
*info
, SVEContFault fault
,
202 CPUARMState
*env
, target_ulong addr
,
203 MMUAccessType access_type
, uintptr_t retaddr
);
205 #ifdef CONFIG_USER_ONLY
207 sve_cont_ldst_watchpoints(SVEContLdSt
*info
, CPUARMState
*env
, uint64_t *vg
,
208 target_ulong addr
, int esize
, int msize
,
209 int wp_access
, uintptr_t retaddr
)
212 void sve_cont_ldst_watchpoints(SVEContLdSt
*info
, CPUARMState
*env
,
213 uint64_t *vg
, target_ulong addr
,
214 int esize
, int msize
, int wp_access
,
218 void sve_cont_ldst_mte_check(SVEContLdSt
*info
, CPUARMState
*env
, uint64_t *vg
,
219 target_ulong addr
, int esize
, int msize
,
220 uint32_t mtedesc
, uintptr_t ra
);
222 #endif /* TARGET_ARM_SVE_LDST_INTERNAL_H */