1/*
2 * SPDX-License-Identifier: BSD-2-Clause
3 *
4 * Copyright (c) 2021 Warner Losh
5 * Copyright (c) 2023 Stormshield
6 * Copyright (c) 2023 Klara, Inc.
7 */
8
9#include <sys/syscall.h>
10
11#define	STDOUT_FILENO	1
12#define	SWP_MAGIC	0xffc0
13#define	SWPB_MAGIC	0xc0c0
14
15	.text
16	.file "swp_test.S"
17	.syntax unified
18	.globl main
19	.p2align 2
20	.type main,%function
21	.code 32
22
23main:
24	sub sp, #0x04
25	/* r4 is our failed test counter */
26	mov r4, #0
27	/* r6 is our current teset counter */
28	mov r6, #1
29
30	movw r0, :lower16:.L.testheader
31	movt r0, :upper16:.L.testheader
32	ldr r1, =(.L.testheaderEnd - .L.testheader - 1)
33	bl print
34
35	/* eq */
36	bl reset
37	mov r1, #SWP_MAGIC
38	cmp r1, r1
39	swpeq r0, r1, [r0]
40	bl expect_success
41
42	/* Returned 0 (bad) or 1 (ok) */
43	cmp r0, #0
44	beq 1f
45
46	/* !eq */
47	bl reset
48	mov r1, #SWP_MAGIC
49	mov r2, #0
50	cmp r1, r2
51	swpeq r0, r1, [r0]
52	bl expect_fail
53
54	/* Don't care about the return of the second one, just print */
551:
56	movw r0, :lower16:.L.eq
57	movt r0, :upper16:.L.eq
58	ldr r1, =(.L.eqEnd - .L.eq - 1)
59	bl print_result
60	add r6, r6, #1	/* Next test */
61
62	/* cs */
63	bl reset
64	mov r1, #SWP_MAGIC
65	movw r3, #0xffff
66	movt r3, #0xffff
67	/* Overflow */
68	adds r2, r3, r3
69	swpcs r0, r1, [r0]
70	bl expect_success
71
72	/* Returned 0 (bad) or 1 (ok) */
73	cmp r0, #0
74	beq 2f
75
76	/* !cs */
77	bl reset
78	mov r1, #SWP_MAGIC
79	mov r3, #0x00
80	adds r2, r3, #0x08
81	swpcs r0, r1, [r0]
82	bl expect_fail
83
84	/* Don't care about the return of the second one, just print */
852:
86	movw r0, :lower16:.L.cs
87	movt r0, :upper16:.L.cs
88	ldr r1, =(.L.csEnd - .L.cs - 1)
89	bl print_result
90	add r6, r6, #1	/* Next test */
91
92	/* mi */
93	bl reset
94	mov r1, #SWP_MAGIC
95	mov r2, #0
96	/* Underflow */
97	subs r2, r2, #0x05
98	swpmi r0, r1, [r0]
99	bl expect_success
100
101	/* Returned 0 (bad) or 1 (ok) */
102	cmp r0, #0
103	beq 3f
104
105	/* !mi */
106	bl reset
107	mov r1, #SWP_MAGIC
108	mov r2, #0x10
109	subs r2, r2, #0x08
110	swpmi r0, r1, [r0]
111	bl expect_fail
112
113	/* Don't care about the return of the second one, just print */
1143:
115	movw r0, :lower16:.L.mi
116	movt r0, :upper16:.L.mi
117	ldr r1, =(.L.miEnd - .L.mi - 1)
118	bl print_result
119	add r6, r6, #1	/* Next test */
120
121	/* vs */
122	bl reset
123	mov r1, #SWP_MAGIC
124	movw r3, #0xffff
125	movt r3, #0x7fff
126	/* Overflow */
127	adds r2, r3, #0x10
128	swpvs r0, r1, [r0]
129	bl expect_success
130
131	/* Returned 0 (bad) or 1 (ok) */
132	cmp r0, #0
133	beq 4f
134
135	/* !vs */
136	bl reset
137	mov r1, #SWP_MAGIC
138	mov r3, #0x00
139	adds r2, r3, #0x08
140	swpvs r0, r1, [r0]
141	bl expect_fail
142
143	/* Don't care about the return of the second one, just print */
1444:
145	movw r0, :lower16:.L.vs
146	movt r0, :upper16:.L.vs
147	ldr r1, =(.L.vsEnd - .L.vs - 1)
148	bl print_result
149	add r6, r6, #1	/* Next test */
150
151	/* hi */
152	bl reset
153	mov r1, #SWP_MAGIC
154	mov r2, #0x00
155	mov r3, #0x01
156	cmp r3, r2
157	swphi r0, r1, [r0]
158	bl expect_success
159
160	/* Returned 0 (bad) or 1 (ok) */
161	cmp r0, #0
162	beq 5f
163
164	/* !hi */
165	bl reset
166	mov r1, #SWP_MAGIC
167	mov r2, #0x00
168	mov r3, #0x01
169	cmp r2, r3
170	swphi r0, r1, [r0]
171	bl expect_fail
172
173	/* Don't care about the return of the second one, just print */
1745:
175	movw r0, :lower16:.L.hi
176	movt r0, :upper16:.L.hi
177	ldr r1, =(.L.hiEnd - .L.hi - 1)
178	bl print_result
179	add r6, r6, #1	/* Next test */
180
181	/* ge */
182	bl reset
183	mov r1, #SWP_MAGIC
184	mov r2, #0x01
185	cmp r2, r2
186	swpge r0, r1, [r0]
187	bl expect_success
188
189	/* Returned 0 (bad) or 1 (ok) */
190	cmp r0, #0
191	beq 6f
192
193	/* !ge */
194	bl reset
195	mov r1, #SWP_MAGIC
196	mov r2, #0x00
197	mov r3, #0x01
198	cmp r2, r3
199	swpge r0, r1, [r0]
200	bl expect_fail
201
202	/* Don't care about the return of the second one, just print */
2036:
204	movw r0, :lower16:.L.ge
205	movt r0, :upper16:.L.ge
206	ldr r1, =(.L.geEnd - .L.ge - 1)
207	bl print_result
208	add r6, r6, #1	/* Next test */
209
210	/* gt */
211	bl reset
212	mov r1, #SWP_MAGIC
213	mov r2, #0x00
214	mov r3, #0x01
215	cmp r3, r2
216	swpgt r0, r1, [r0]
217	bl expect_success
218
219	/* Returned 0 (bad) or 1 (ok) */
220	cmp r0, #0
221	beq 7f
222
223	/* !ge */
224	bl reset
225	mov r1, #SWP_MAGIC
226	mov r2, #0x00
227	mov r3, #0x01
228	cmp r2, r3
229	swpgt r0, r1, [r0]
230	bl expect_fail
231
232	/* Don't care about the return of the second one, just print */
2337:
234	movw r0, :lower16:.L.gt
235	movt r0, :upper16:.L.gt
236	ldr r1, =(.L.gtEnd - .L.gt - 1)
237	bl print_result
238	add r6, r6, #1	/* Next test */
239
240	mov r0, r4	/* retval */
241	ldr r7, =SYS_exit
242	swi 0
243
244	.p2align 2
245	.type print_result,%function
246	.code 32
247print_result:
248	push {r4, r5, lr}
249	/* Save the label, size for our result */
250	mov r4, r0
251	mov r5, r1
252
253	movw r0, :lower16:.L.ok
254	movt r0, :upper16:.L.ok
255	ldr r1, =(.L.okEnd - .L.ok - 1)
256	bl print
257	mov r0, r6
258	add r0, #0x30 /* "0" + test number */
259	mov r1, #0x01
260	str r0, [sp]
261	mov r0, sp
262	bl print
263	movw r0, :lower16:.L.swp
264	movt r0, :upper16:.L.swp
265	ldr r1, =(.L.swpEnd - .L.swp - 1)
266	bl print
267	mov r0, r4
268	mov r1, r5
269	bl print
270	movw r0, :lower16:.L.term
271	movt r0, :upper16:.L.term
272	ldr r1, =(.L.termEnd - .L.term - 1)
273	bl print
274
275	pop {r4, r5, lr}
276	bx lr
277
278	.p2align 2
279	.type reset,%function
280	.code 32
281reset:
282	/* Reset sp[0] and return the address used */
283	mov r0, #0x03
284	str r0, [sp]
285	mov r0, sp
286	bx lr
287
288	.p2align 2
289	.type expect_fail,%function
290	.code 32
291expect_fail:
292	/* Just check the stack value */
293	ldr r0, [sp]
294	mov r1, #0x03
295	cmp r0,  r1
296	bne 1f
297
298	/* Success (not swapped) */
299	mov r0, #1
300	bx lr
301
3021:
303	/* Fail (swapped) */
304	/* Print the "not" part */
305	movw r0, :lower16:.L.not
306	movt r0, :upper16:.L.not
307	ldr r1, =(.L.notEnd - .L.not - 1)
308	push {lr}
309	bl print
310	pop {lr}
311
312	/* Failed */
313	add r4, r4, #1
314	mov r0, #0
315	bx lr
316
317	.p2align 2
318	.type expect_success,%function
319	.code 32
320expect_success:
321	/* Old value should be 3 */
322	cmp r0, #0x03
323	beq 1f
324	b 3f
325
3261:
327	/* Check stack value */
328	ldr r0, [sp]
329	mov r1, #SWP_MAGIC
330	cmp r0, r1
331	beq 2f
332	b 3f
333
3342:
335	mov r0, #1
336	bx lr
337
3383:
339	/* Print the "not" part */
340	movw r0, :lower16:.L.not
341	movt r0, :upper16:.L.not
342	ldr r1, =(.L.notEnd - .L.not - 1)
343	push {lr}
344	bl print
345	pop {lr}
346
347	/* Failed */
348	add r4, r4, #1
349	mov r0, #0
350	bx lr
351
352	.p2align 2
353	.type print,%function
354	.code 32
355print:
356	/* r0 - string, r1 = size */
357	mov r2, r1
358	mov r1, r0
359	ldr r0, =STDOUT_FILENO
360	ldr r7, =SYS_write
361	swi 0
362
363	bx lr
364
365.L.testheader:
366	.asciz "1..7\n"
367.L.testheaderEnd:
368	.size .L.testheader, .L.testheaderEnd - .L.testheader
369
370.L.not:
371	.asciz "not "
372.L.notEnd:
373	.size .L.not, .L.notEnd - .L.not
374.L.ok:
375	.asciz "ok "
376.L.okEnd:
377	.size .L.ok, .L.okEnd - .L.ok
378.L.swp:
379	.asciz " - swp"
380.L.swpEnd:
381	.size .L.swp, .L.swpEnd - .L.swp
382.L.eq:
383	.asciz "eq"
384.L.eqEnd:
385	.size .L.eq, .L.eqEnd - .L.eq
386.L.cs:
387	.asciz "cs"
388.L.csEnd:
389	.size .L.cs, .L.csEnd - .L.cs
390.L.mi:
391	.asciz "mi"
392.L.miEnd:
393	.size .L.mi, .L.miEnd - .L.mi
394.L.vs:
395	.asciz "vs"
396.L.vsEnd:
397	.size .L.vs, .L.vsEnd - .L.vs
398.L.hi:
399	.asciz "hi"
400.L.hiEnd:
401	.size .L.hi, .L.hiEnd - .L.hi
402.L.ge:
403	.asciz "ge"
404.L.geEnd:
405	.size .L.ge, .L.geEnd - .L.ge
406.L.gt:
407	.asciz "gt"
408.L.gtEnd:
409	.size .L.gt, .L.gtEnd - .L.gt
410.L.term:
411	.asciz "\n"
412.L.termEnd:
413	.size .L.term, .L.termEnd - .L.term
414