master
s 368 lines 8.19 KB
Raw
1 /*
2 * Test the Zicclsm extension (misaligned load/store support).
3 *
4 * This single source is assembled twice:
5 * - test-zicclsm : run on a CPU with zicclsm=true. Every misaligned
6 * scalar integer, floating-point and vector
7 * load/store must complete WITHOUT raising a trap.
8 * - test-zicclsm-off : built with -DZICCLSM_DISABLED and run on a CPU with
9 * zicclsm=false. Every misaligned access must raise a
10 * misaligned load/store exception, with the correct
11 * mcause and mtval.
12 *
13 * Zicclsm governs all regular scalar loads/stores (integer and F/D/Zfh
14 * floating-point) as well as vector element loads/stores. Floating-point
15 * loads/stores (flh/flw/fld, fsh/fsw/fsd) are therefore exercised here.
16 *
17 * Atomic (A/Zacas/...) accesses are intentionally excluded: they always
18 * require natural alignment regardless of Zicclsm. Likewise cm.push/cm.pop
19 * (Zcmp) are excluded, as they are not regular loads/stores.
20 *
21 * Register conventions (persist across the whole test; the trap handler only
22 * clobbers t0-t4):
23 * s1 = expected mcause for the pending misaligned access
24 * s2 = expected mtval (the misaligned address)
25 * s3 = trap counter (incremented by the handler)
26 * s4 = base address of the aligned data buffer
27 * s5 = snapshot of s3 taken before an access, used to check the delta
28 *
29 * SPDX-License-Identifier: GPL-2.0-or-later
30 */
31
32 .option norelax
33 .option norvc
34
35 /* RISC-V exception causes (see target/riscv/cpu_bits.h). */
36 #define CAUSE_LOAD_MISALIGNED 0x4
37 #define CAUSE_STORE_MISALIGNED 0x6
38
39 /*
40 * EXPECT sets up the expectation for the access that immediately follows and
41 * snapshots the trap counter.
42 * \cause = expected mcause if the access traps
43 * \off = byte offset from the buffer base; also the expected mtval
44 */
45 .macro EXPECT cause, off
46 li s1, \cause
47 addi s2, s4, \off
48 mv s5, s3
49 .endm
50
51 /*
52 * CHECK validates the outcome of the preceding access.
53 * - When Zicclsm is disabled, exactly one trap must have fired.
54 * - When Zicclsm is enabled, no trap must have fired.
55 */
56 .macro CHECK
57 #ifdef ZICCLSM_DISABLED
58 addi s5, s5, 1
59 bne s3, s5, fail
60 #else
61 bne s3, s5, fail
62 #endif
63 .endm
64
65 /* In the enabled case, also verify the value returned by scalar loads. */
66 .macro CHECK_VALUE value
67 #ifndef ZICCLSM_DISABLED
68 li t0, \value
69 bne a2, t0, fail
70 #endif
71 .endm
72
73 /* Verify bytes written by an enabled scalar store. */
74 .macro CHECK_BYTE off, value
75 #ifndef ZICCLSM_DISABLED
76 lbu t0, \off(s4)
77 li t1, \value
78 bne t0, t1, fail
79 #endif
80 .endm
81
82 .text
83 .global _start
84 _start:
85 /* Install the trap handler. */
86 lla t0, trap
87 csrw mtvec, t0
88
89 /* Enable the FP (FS) and Vector (VS) unit state so F/D/V instructions
90 * do not trap as illegal. 0x6600 = FS[14:13]=11 | VS[10:9]=11. */
91 li t0, 0x6600
92 csrs mstatus, t0
93
94 /* Initialise persistent state. */
95 li s3, 0 /* trap counter */
96 lla s4, buf /* aligned buffer base */
97
98 /*
99 * ---- Scalar integer loads ----
100 * lh/lhu need 2-byte alignment; lw/lwu 4-byte; ld 8-byte.
101 */
102 EXPECT CAUSE_LOAD_MISALIGNED, 1
103 lh a2, 1(s4)
104 CHECK
105 CHECK_VALUE 0x2211
106 EXPECT CAUSE_LOAD_MISALIGNED, 1
107 lhu a2, 1(s4)
108 CHECK
109 CHECK_VALUE 0x2211
110
111 EXPECT CAUSE_LOAD_MISALIGNED, 1
112 lw a2, 1(s4)
113 CHECK
114 CHECK_VALUE 0x44332211
115 EXPECT CAUSE_LOAD_MISALIGNED, 3
116 lw a2, 3(s4)
117 CHECK
118 CHECK_VALUE 0x66554433
119 EXPECT CAUSE_LOAD_MISALIGNED, 1
120 lwu a2, 1(s4)
121 CHECK
122 CHECK_VALUE 0x44332211
123
124 EXPECT CAUSE_LOAD_MISALIGNED, 1
125 ld a2, 1(s4)
126 CHECK
127 CHECK_VALUE 0x8877665544332211
128 EXPECT CAUSE_LOAD_MISALIGNED, 3
129 ld a2, 3(s4)
130 CHECK
131 CHECK_VALUE 0xaa99887766554433
132 EXPECT CAUSE_LOAD_MISALIGNED, 7
133 ld a2, 7(s4)
134 CHECK
135 CHECK_VALUE 0xeeddccbbaa998877
136
137 /*
138 * ---- Scalar integer stores ----
139 */
140 li t6, 0x1122334455667788
141 EXPECT CAUSE_STORE_MISALIGNED, 1
142 sh t6, 1(s4)
143 CHECK
144 CHECK_BYTE 1, 0x88
145 CHECK_BYTE 2, 0x77
146
147 EXPECT CAUSE_STORE_MISALIGNED, 1
148 sw t6, 1(s4)
149 CHECK
150 CHECK_BYTE 1, 0x88
151 CHECK_BYTE 2, 0x77
152 CHECK_BYTE 3, 0x66
153 CHECK_BYTE 4, 0x55
154 EXPECT CAUSE_STORE_MISALIGNED, 3
155 sw t6, 3(s4)
156 CHECK
157 CHECK_BYTE 3, 0x88
158 CHECK_BYTE 4, 0x77
159 CHECK_BYTE 5, 0x66
160 CHECK_BYTE 6, 0x55
161
162 EXPECT CAUSE_STORE_MISALIGNED, 1
163 sd t6, 1(s4)
164 CHECK
165 CHECK_BYTE 1, 0x88
166 CHECK_BYTE 2, 0x77
167 CHECK_BYTE 3, 0x66
168 CHECK_BYTE 4, 0x55
169 CHECK_BYTE 5, 0x44
170 CHECK_BYTE 6, 0x33
171 CHECK_BYTE 7, 0x22
172 CHECK_BYTE 8, 0x11
173 EXPECT CAUSE_STORE_MISALIGNED, 7
174 sd t6, 7(s4)
175 CHECK
176 CHECK_BYTE 7, 0x88
177 CHECK_BYTE 8, 0x77
178 CHECK_BYTE 9, 0x66
179 CHECK_BYTE 10, 0x55
180 CHECK_BYTE 11, 0x44
181 CHECK_BYTE 12, 0x33
182 CHECK_BYTE 13, 0x22
183 CHECK_BYTE 14, 0x11
184
185 /*
186 * ---- Floating-point loads ----
187 * flh needs 2-byte alignment; flw 4-byte; fld 8-byte. Their alignment
188 * is governed by Zicclsm just like the scalar integer forms.
189 */
190 EXPECT CAUSE_LOAD_MISALIGNED, 1
191 flh fa0, 1(s4)
192 CHECK
193
194 EXPECT CAUSE_LOAD_MISALIGNED, 1
195 flw fa0, 1(s4)
196 CHECK
197 EXPECT CAUSE_LOAD_MISALIGNED, 3
198 flw fa0, 3(s4)
199 CHECK
200
201 EXPECT CAUSE_LOAD_MISALIGNED, 1
202 fld fa0, 1(s4)
203 CHECK
204 EXPECT CAUSE_LOAD_MISALIGNED, 7
205 fld fa0, 7(s4)
206 CHECK
207
208 /*
209 * ---- Floating-point stores ----
210 */
211 EXPECT CAUSE_STORE_MISALIGNED, 1
212 fsh fa0, 1(s4)
213 CHECK
214
215 EXPECT CAUSE_STORE_MISALIGNED, 1
216 fsw fa0, 1(s4)
217 CHECK
218 EXPECT CAUSE_STORE_MISALIGNED, 3
219 fsw fa0, 3(s4)
220 CHECK
221
222 EXPECT CAUSE_STORE_MISALIGNED, 1
223 fsd fa0, 1(s4)
224 CHECK
225 EXPECT CAUSE_STORE_MISALIGNED, 7
226 fsd fa0, 7(s4)
227 CHECK
228
229 /*
230 * ---- Vector unit-stride loads / stores ----
231 * A base address that is not aligned to the element size (SEW) is
232 * misaligned for the first element access.
233 */
234 vsetvli t1, x0, e16, m1, ta, ma
235 EXPECT CAUSE_LOAD_MISALIGNED, 1
236 addi a0, s4, 1
237 vle16.v v0, (a0)
238 CHECK
239 EXPECT CAUSE_STORE_MISALIGNED, 1
240 addi a0, s4, 1
241 vse16.v v0, (a0)
242 CHECK
243
244 vsetvli t1, x0, e32, m1, ta, ma
245 EXPECT CAUSE_LOAD_MISALIGNED, 1
246 addi a0, s4, 1
247 vle32.v v0, (a0)
248 CHECK
249 EXPECT CAUSE_STORE_MISALIGNED, 3
250 addi a0, s4, 3
251 vse32.v v0, (a0)
252 CHECK
253
254 vsetvli t1, x0, e64, m1, ta, ma
255 EXPECT CAUSE_LOAD_MISALIGNED, 1
256 addi a0, s4, 1
257 vle64.v v0, (a0)
258 CHECK
259 EXPECT CAUSE_STORE_MISALIGNED, 7
260 addi a0, s4, 7
261 vse64.v v0, (a0)
262 CHECK
263
264 /*
265 * ---- Vector strided loads / stores ----
266 */
267 vsetvli t1, x0, e32, m1, ta, ma
268 li a1, 8 /* stride in bytes */
269 EXPECT CAUSE_LOAD_MISALIGNED, 1
270 addi a0, s4, 1
271 vlse32.v v0, (a0), a1
272 CHECK
273 EXPECT CAUSE_STORE_MISALIGNED, 1
274 addi a0, s4, 1
275 vsse32.v v0, (a0), a1
276 CHECK
277
278 /* ---- Vector indexed loads / stores ---- */
279 /*
280 * Zero indices keep the first element at the deliberately misaligned base.
281 */
282 vmv.v.i v1, 0
283 EXPECT CAUSE_LOAD_MISALIGNED, 1
284 addi a0, s4, 1
285 vluxei32.v v0, (a0), v1
286 CHECK
287 EXPECT CAUSE_STORE_MISALIGNED, 1
288 addi a0, s4, 1
289 vsuxei32.v v0, (a0), v1
290 CHECK
291
292 /* ---- Vector segmented loads / stores ---- */
293 EXPECT CAUSE_LOAD_MISALIGNED, 1
294 addi a0, s4, 1
295 vlseg2e32.v v0, (a0)
296 CHECK
297 EXPECT CAUSE_STORE_MISALIGNED, 1
298 addi a0, s4, 1
299 vsseg2e32.v v0, (a0)
300 CHECK
301
302 /*
303 * ---- Vector whole-register load ----
304 * Only the whole-register *load* forms carry an element width
305 * (vl1re32.v => EEW=32), so only they enforce alignment when Zicclsm is
306 * off. The whole-register store form (vs1r.v) is defined as EEW=8
307 * (byte granular) and therefore never faults on misalignment, so it is
308 * not exercised here.
309 */
310 EXPECT CAUSE_LOAD_MISALIGNED, 1
311 addi a0, s4, 1
312 vl1re32.v v1, (a0)
313 CHECK
314
315 /* Success. */
316 li a0, 0
317 j _exit
318
319 /*
320 * Trap handler: validate mcause and mtval against the expectation, bump
321 * the trap counter, then skip past the faulting instruction. The
322 * instruction length is decoded from its low two bits (0b11 => 4 bytes,
323 * otherwise a 2-byte compressed instruction).
324 */
325 .balign 4
326 trap:
327 csrr t0, mcause
328 bne t0, s1, fail
329 csrr t1, mtval
330 bne t1, s2, fail
331 addi s3, s3, 1
332
333 csrr t0, mepc
334 lhu t2, 0(t0)
335 andi t3, t2, 3
336 li t4, 3
337 bne t3, t4, 1f
338 addi t0, t0, 4 /* 32-bit instruction */
339 j 2f
340 1:
341 addi t0, t0, 2 /* 16-bit compressed instruction */
342 2:
343 csrw mepc, t0
344 mret
345
346 fail:
347 li a0, 1
348 _exit:
349 lla a1, semiargs
350 li t0, 0x20026 /* ADP_Stopped_ApplicationExit */
351 sd t0, 0(a1)
352 sd a0, 8(a1)
353 li a0, 0x20 /* TARGET_SYS_EXIT_EXTENDED */
354 .balign 16
355 slli zero, zero, 0x1f
356 ebreak
357 srai zero, zero, 0x7
358 j .
359
360 .data
361 .balign 16
362 semiargs:
363 .space 16
364 .balign 64
365 buf:
366 .byte 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77
367 .byte 0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff
368 .space 240