xref: /netbsd-src/sys/arch/arm/arm/bus_space_asm_generic.S (revision 177f3da6cef31437fb2633c769259d4051a68268)
1/*	$NetBSD: bus_space_asm_generic.S,v 1.12 2020/09/24 11:02:02 skrll Exp $	*/
2
3/*
4 * Copyright (c) 1997 Causality Limited.
5 * Copyright (c) 1997 Mark Brinicombe.
6 * All rights reserved.
7 *
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
10 * are met:
11 * 1. Redistributions of source code must retain the above copyright
12 *    notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright
14 *    notice, this list of conditions and the following disclaimer in the
15 *    documentation and/or other materials provided with the distribution.
16 * 3. All advertising materials mentioning features or use of this software
17 *    must display the following acknowledgement:
18 *	This product includes software developed by Mark Brinicombe
19 *	for the NetBSD Project.
20 * 4. The name of the company nor the name of the author may be used to
21 *    endorse or promote products derived from this software without specific
22 *    prior written permission.
23 *
24 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
25 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
26 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
27 * IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
28 * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
29 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
30 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
31 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
32 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
33 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
34 * SUCH DAMAGE.
35 */
36
37#include <arm/asm.h>
38#include <arm/cpuconf.h>
39#include <arm/byte_swap.h>
40
41#ifdef _ARM_ARCH_7
42#define	DSB	dsb
43#elif defined(_ARM_ARCH_6)
44#define	DSB	mcr p15, 0, r0, c7, c10, 4
45#else
46#define	DSB
47#endif
48
49#if defined(__thumb__) && defined(_ARM_ARCH_T2)
50#define CHECK_LENGTH(r, l)	cbz r, l
51#elif defined(__thumb__)
52#define CHECK_LENGTH(r, l)	cmp r, #0; beq l
53#else
54#define CHECK_LENGTH(r, l)	cmp r, #0; RETc(eq)
55#endif
56/*
57 * Generic bus_space functions.
58 */
59
60/*
61 * read single
62 */
63
64ENTRY_NP(generic_bs_r_1)
65	DSB
66	ldrb	r0, [r1, r2]
67	RET
68END(generic_bs_r_1)
69
70#if (ARM_ARCH_4 + ARM_ARCH_5 + ARM_ARCH_6 + ARM_ARCH_7) > 0
71ENTRY_NP(generic_armv4_bs_r_2)
72	DSB
73	ldrh	r0, [r1, r2]
74	RET
75END(generic_armv4_bs_r_2)
76
77ENTRY_NP(generic_armv4_bs_r_2_swap)
78	DSB
79	ldrh	r0, [r1, r2]
80	BSWAP16(r0, r0, r1)
81	RET
82END(generic_armv4_bs_r_2_swap)
83#endif
84
85ENTRY_NP(generic_bs_r_4)
86	DSB
87	ldr	r0, [r1, r2]
88	RET
89END(generic_bs_r_4)
90
91ENTRY_NP(generic_bs_r_4_swap)
92	DSB
93	ldr	r0, [r1, r2]
94	BSWAP32(r0, r0, r1)
95	RET
96END(generic_bs_r_4_swap)
97
98/*
99 * write single
100 */
101
102ENTRY_NP(generic_bs_w_1)
103	strb	r3, [r1, r2]
104	DSB
105	RET
106END(generic_bs_w_1)
107
108#if (ARM_ARCH_4 + ARM_ARCH_5 + ARM_ARCH_6 + ARM_ARCH_7) > 0
109ENTRY_NP(generic_armv4_bs_w_2_swap)
110	BSWAP16(r3, r3, r0)		/* swap and fallthrough */
111ENTRY_NP(generic_armv4_bs_w_2)
112	strh	r3, [r1, r2]
113	DSB
114	RET
115END(generic_armv4_bs_w_2)
116END(generic_armv4_bs_w_2_swap)
117#endif
118
119ENTRY_NP(generic_bs_w_4_swap)
120	BSWAP32(r3, r3, r0)
121ENTRY_NP(generic_bs_w_4)
122	str	r3, [r1, r2]
123	DSB
124	RET
125END(generic_bs_w_4)
126END(generic_bs_w_4_swap)
127
128/*
129 * read multiple
130 */
131
132ENTRY_NP(generic_bs_rm_1)
133	adds	r0, r1, r2
134	mov	r1, r3
135	ldr	r2, [sp, #0]
136	CHECK_LENGTH(r2, 99f)
137	DSB
138
1391:	ldrb	r3, [r0]
140	strb	r3, [r1], #1
141	subs	r2, r2, #1
142	bne	1b
143
14499:	RET
145END(generic_bs_rm_1)
146
147#if (ARM_ARCH_4 + ARM_ARCH_5 + ARM_ARCH_6 + ARM_ARCH_7) > 0
148ENTRY_NP(generic_armv4_bs_rm_2)
149	adds	r0, r1, r2
150	mov	r1, r3
151	ldr	r2, [sp, #0]
152	CHECK_LENGTH(r2, 99f)
153	DSB
154
1551:	ldrh	r3, [r0]
156	strh	r3, [r1], #2
157	subs	r2, r2, #1
158	bne	1b
159
16099:	RET
161END(generic_armv4_bs_rm_2)
162
163ENTRY_NP(generic_armv4_bs_rm_2_swap)
164	DSB
165	adds	r0, r1, r2
166	mov	r1, r3
167	ldr	r2, [sp, #0]
168	CHECK_LENGTH(r2, 99f)
169	DSB
170
1711:	ldrh	r3, [r0]
172	BSWAP16(r3, r3, ip)
173	strh	r3, [r1], #2
174	subs	r2, r2, #1
175	bne	1b
176
17799:	RET
178END(generic_armv4_bs_rm_2_swap)
179#endif
180
181ENTRY_NP(generic_bs_rm_4)
182	adds	r0, r1, r2
183	mov	r1, r3
184	ldr	r2, [sp, #0]
185	CHECK_LENGTH(r2, 99f)
186	DSB
187
1881:	ldr	r3, [r0]
189	str	r3, [r1], #4
190	subs	r2, r2, #1
191	bne	1b
192
19399:	RET
194END(generic_bs_rm_4)
195
196ENTRY_NP(generic_bs_rm_4_swap)
197	adds	r0, r1, r2
198	mov	r1, r3
199	ldr	r2, [sp, #0]
200	CHECK_LENGTH(r2, 99f)
201	DSB
202
2031:	ldr	r3, [r0]
204	BSWAP32(r3, r3, ip)
205	str	r3, [r1], #4
206	subs	r2, r2, #1
207	bne	1b
208
20999:	RET
210END(generic_bs_rm_4_swap)
211
212/*
213 * write multiple
214 */
215
216ENTRY_NP(generic_bs_wm_1)
217	adds	r0, r1, r2
218	mov	r1, r3
219	ldr	r2, [sp, #0]
220	CHECK_LENGTH(r2, 99f)
221
2221:	ldrb	r3, [r1], #1
223	strb	r3, [r0]
224	subs	r2, r2, #1
225	bne	1b
226
227	DSB
22899:	RET
229END(generic_bs_wm_1)
230
231#if (ARM_ARCH_4 + ARM_ARCH_5 + ARM_ARCH_6 + ARM_ARCH_7) > 0
232ENTRY_NP(generic_armv4_bs_wm_2)
233	adds	r0, r1, r2
234	mov	r1, r3
235	ldr	r2, [sp, #0]
236	CHECK_LENGTH(r2, 99f)
237
2381:	ldrh	r3, [r1], #2
239	strh	r3, [r0]
240	subs	r2, r2, #1
241	bne	1b
242
243	DSB
24499:	RET
245END(generic_armv4_bs_wm_2)
246
247ENTRY_NP(generic_armv4_bs_wm_2_swap)
248	adds	r0, r1, r2
249	mov	r1, r3
250	ldr	r2, [sp, #0]
251
2521:	ldrh	r3, [r1], #2
253	BSWAP16(r3, r3, ip)
254	strh	r3, [r0]
255	subs	r2, r2, #1
256	bne	1b
257
258	DSB
25999:	RET
260END(generic_armv4_bs_wm_2_swap)
261#endif
262
263ENTRY_NP(generic_bs_wm_4)
264	adds	r0, r1, r2
265	mov	r1, r3
266	ldr	r2, [sp, #0]
267	CHECK_LENGTH(r2, 99f)
268
2691:	ldr	r3, [r1], #4
270	str	r3, [r0]
271	subs	r2, r2, #1
272	bne	1b
273
274	DSB
27599:	RET
276END(generic_bs_wm_4)
277
278ENTRY_NP(generic_bs_wm_4_swap)
279	adds	r0, r1, r2
280	mov	r1, r3
281	ldr	r2, [sp, #0]
282	CHECK_LENGTH(r2, 99f)
283
2841:	ldr	r3, [r1], #4
285	BSWAP32(r3, r3, ip)
286	str	r3, [r0]
287	subs	r2, r2, #1
288	bne	1b
289
290	DSB
29199:	RET
292END(generic_bs_wm_4_swap)
293
294/*
295 * read region
296 */
297
298ENTRY_NP(generic_bs_rr_1)
299	adds	r0, r1, r2
300	mov	r1, r3
301	ldr	r2, [sp, #0]
302	CHECK_LENGTH(r2, 99f)
303	DSB
304
3051:	ldrb	r3, [r0], #1
306	strb	r3, [r1], #1
307	subs	r2, r2, #1
308	bne	1b
309
31099:	RET
311END(generic_bs_rr_1)
312
313#if (ARM_ARCH_4 + ARM_ARCH_5 + ARM_ARCH_6 + ARM_ARCH_7) > 0
314ENTRY_NP(generic_armv4_bs_rr_2)
315	adds	r0, r1, r2
316	mov	r1, r3
317	ldr	r2, [sp, #0]
318	CHECK_LENGTH(r2, 99f)
319	DSB
320
3211:	ldrh	r3, [r0], #2
322	strh	r3, [r1], #2
323	subs	r2, r2, #1
324	bne	1b
325
32699:	RET
327END(generic_armv4_bs_rr_2)
328
329ENTRY_NP(generic_armv4_bs_rr_2_swap)
330	adds	r0, r1, r2
331	mov	r1, r3
332	ldr	r2, [sp, #0]
333	CHECK_LENGTH(r2, 99f)
334	DSB
335
3361:	ldrh	r3, [r0], #2
337	BSWAP16(r3, r3, ip)
338	strh	r3, [r1], #2
339	subs	r2, r2, #1
340	bne	1b
341
34299:	RET
343END(generic_armv4_bs_rr_2_swap)
344#endif
345
346ENTRY_NP(generic_bs_rr_4)
347	adds	r0, r1, r2
348	mov	r1, r3
349	ldr	r2, [sp, #0]
350	CHECK_LENGTH(r2, 99f)
351
3521:	ldr	r3, [r0], #4
353	str	r3, [r1], #4
354	subs	r2, r2, #1
355	bne	1b
356
35799:	RET
358END(generic_bs_rr_4)
359
360ENTRY_NP(generic_bs_rr_4_swap)
361	adds	r0, r1, r2
362	mov	r1, r3
363	ldr	r2, [sp, #0]
364	CHECK_LENGTH(r2, 99f)
365	DSB
366
3671:	ldr	r3, [r0], #4
368	BSWAP32(r3, r3, ip)
369	str	r3, [r1], #4
370	subs	r2, r2, #1
371	bne	1b
372
37399:	RET
374END(generic_bs_rr_4_swap)
375
376/*
377 * write region.
378 */
379
380ENTRY_NP(generic_bs_wr_1)
381	adds	r0, r1, r2
382	mov	r1, r3
383	ldr	r2, [sp, #0]
384	CHECK_LENGTH(r2, 99f)
385
3861:	ldrb	r3, [r1], #1
387	strb	r3, [r0], #1
388	subs	r2, r2, #1
389	bne	1b
390
391	DSB
39299:	RET
393END(generic_bs_wr_1)
394
395#if (ARM_ARCH_4 + ARM_ARCH_5 + ARM_ARCH_6 + ARM_ARCH_7) > 0
396ENTRY_NP(generic_armv4_bs_wr_2)
397	adds	r0, r1, r2
398	mov	r1, r3
399	ldr	r2, [sp, #0]
400	CHECK_LENGTH(r2, 99f)
401
4021:	ldrh	r3, [r1], #2
403	strh	r3, [r0], #2
404	subs	r2, r2, #1
405	bne	1b
406
407	DSB
40899:	RET
409END(generic_armv4_bs_wr_2)
410
411ENTRY_NP(generic_armv4_bs_wr_2_swap)
412	adds	r0, r1, r2
413	mov	r1, r3
414	ldr	r2, [sp, #0]
415	CHECK_LENGTH(r2, 99f)
416
4171:	ldrh	r3, [r1], #2
418	BSWAP16(r3, r3, ip)
419	strh	r3, [r0], #2
420	subs	r2, r2, #1
421	bne	1b
422
423	DSB
42499:	RET
425END(generic_armv4_bs_wr_2_swap)
426#endif
427
428ENTRY_NP(generic_bs_wr_4)
429	adds	r0, r1, r2
430	mov	r1, r3
431	ldr	r2, [sp, #0]
432	CHECK_LENGTH(r2, 99f)
433
4341:	ldr	r3, [r1], #4
435	str	r3, [r0], #4
436	subs	r2, r2, #1
437	bne	1b
438
439	DSB
44099:	RET
441END(generic_bs_wr_4)
442
443ENTRY_NP(generic_bs_wr_4_swap)
444	adds	r0, r1, r2
445	mov	r1, r3
446	ldr	r2, [sp, #0]
447	CHECK_LENGTH(r2, 99f)
448
4491:	ldr	r3, [r1], #4
450	BSWAP32(r3, r3, ip)
451	str	r3, [r0], #4
452	subs	r2, r2, #1
453	bne	1b
454
455	DSB
45699:	RET
457END(generic_bs_wr_4_swap)
458
459/*
460 * set region
461 */
462
463ENTRY_NP(generic_bs_sr_1)
464	adds	r0, r1, r2
465	mov	r1, r3
466	ldr	r2, [sp, #0]
467	CHECK_LENGTH(r2, 99f)
468
4691:	strb	r1, [r0], #1
470	subs	r2, r2, #1
471	bne	1b
472
473	DSB
47499:	RET
475END(generic_bs_sr_1)
476
477#if (ARM_ARCH_4 + ARM_ARCH_5 + ARM_ARCH_6 + ARM_ARCH_7) > 0
478ENTRY_NP(generic_armv4_bs_sr_2_swap)
479	BSWAP16(r3, r3, r0)	/* swap and fallthrough */
480ENTRY_NP(generic_armv4_bs_sr_2)
481	adds	r0, r1, r2
482	mov	r1, r3
483	ldr	r2, [sp, #0]
484	CHECK_LENGTH(r2, 99f)
485
4861:	strh	r1, [r0], #2
487	subs	r2, r2, #1
488	bne	1b
489
490	DSB
49199:	RET
492END(generic_armv4_bs_sr_2)
493END(generic_armv4_bs_sr_2_swap)
494#endif
495
496ENTRY_NP(generic_bs_sr_4_swap)
497	BSWAP32(r3, r3, r0)	/* swap and fallthrough */
498ENTRY_NP(generic_bs_sr_4)
499	adds	r0, r1, r2
500	mov	r1, r3
501	ldr	r2, [sp, #0]
502	CHECK_LENGTH(r2, 99f)
503
5041:	str	r1, [r0], #4
505	subs	r2, r2, #1
506	bne	1b
507
508	DSB
50999:	RET
510END(generic_bs_sr_4)
511END(generic_bs_sr_4_swap)
512
513/*
514 * copy region
515 */
516
517#if (ARM_ARCH_4 + ARM_ARCH_5 + ARM_ARCH_6 + ARM_ARCH_7) > 0
518ENTRY_NP(generic_armv4_bs_c_2)
519	adds	r0, r1, r2
520	ldr	r2, [sp, #0]
521	adds	r1, r2, r3
522	ldr	r2, [sp, #4]
523	CHECK_LENGTH(r2, 99f)
524
525	lsls	r2, r2, #1
526
527	cmp	r0, r1
528	blt	2f
529
530	adds	r0, r0, r2
531	adds	r1, r1, r2
532	negs	r2, r2
533
5341:	ldrh	r3, [r0, r2]
535	strh	r3, [r1, r2]
536	adds	r2, r2, #2
537	bne	1b
538
539	DSB
540	RET
541
5422:	subs	r2, r2, #2
543	ldrh	r3, [r0, r2]
544	strh	r3, [r1, r2]
545	bne	2b
546
547	DSB
54899:	RET
549END(generic_armv4_bs_c_2)
550#endif
551