1/*	$NetBSD: busfunc.S,v 1.11 2013/06/22 05:20:57 uebayasi Exp $	*/
2
3/*-
4 * Copyright (c) 2007, 2008 The NetBSD Foundation, Inc.
5 * All rights reserved.
6 *
7 * This code is derived from software contributed to The NetBSD Foundation
8 * by Andrew Doran.
9 *
10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions
12 * are met:
13 * 1. Redistributions of source code must retain the above copyright
14 *    notice, this list of conditions and the following disclaimer.
15 * 2. Redistributions in binary form must reproduce the above copyright
16 *    notice, this list of conditions and the following disclaimer in the
17 *    documentation and/or other materials provided with the distribution.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
20 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
21 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
22 * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
23 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
24 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
25 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
26 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
27 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
28 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29 * POSSIBILITY OF SUCH DAMAGE.
30 */
31
32#include <machine/asm.h>
33
34#include "assym.h"
35
36.Ldopanic:
37	movq	$.Lpstr, %rdi
38	call	_C_LABEL(panic)
39.Lpstr:	.string	"bus_space: 8-byte access to I/O space\0"
40
41/*
42 * uint8_t bus_space_read_1(bus_space_tag_t tag, bus_space_handle_t bsh,
43 *    bus_size_t offset);
44 */
45ENTRY(bus_space_read_1)
46	addq	%rsi, %rdx
47	cmpl	$X86_BUS_SPACE_IO, BST_TYPE(%rdi)
48	je	1f
49	movzbl	(%rdx), %eax
50	ret
511:
52	xorl	%eax, %eax
53	inb	%dx, %al
54	ret
55END(bus_space_read_1)
56
57/*
58 * uint16_t bus_space_read_2(bus_space_tag_t tag, bus_space_handle_t bsh,
59 *    bus_size_t offset);
60 */
61ENTRY(bus_space_read_2)
62	addq	%rsi, %rdx
63	cmpl	$X86_BUS_SPACE_IO, BST_TYPE(%rdi)
64	je	1f
65	movzwl	(%rdx), %eax
66	ret
671:
68	xorl	%eax, %eax
69	inw	%dx, %ax
70	ret
71END(bus_space_read_2)
72
73/*
74 * uint32_t bus_space_read_4(bus_space_tag_t tag, bus_space_handle_t bsh,
75 *    bus_size_t offset);
76 */
77ENTRY(bus_space_read_4)
78	addq	%rsi, %rdx
79	cmpl	$X86_BUS_SPACE_IO, BST_TYPE(%rdi)
80	je	1f
81	movl	(%rdx), %eax
82	ret
831:
84	inl	%dx, %eax
85	ret
86END(bus_space_read_4)
87
88/*
89 * uint64_t bus_space_read_8(bus_space_tag_t tag, bus_space_handle_t bsh,
90 *    bus_size_t offset);
91 */
92ENTRY(bus_space_read_8)
93	addq	%rsi, %rdx
94	cmpl	$X86_BUS_SPACE_IO, BST_TYPE(%rdi)
95	je	.Ldopanic
96	movq	(%rdx), %rax
97	ret
98END(bus_space_read_8)
99
100STRONG_ALIAS(bus_space_read_stream_1,bus_space_read_1)
101STRONG_ALIAS(bus_space_read_stream_2,bus_space_read_2)
102STRONG_ALIAS(bus_space_read_stream_4,bus_space_read_4)
103STRONG_ALIAS(bus_space_read_stream_8,bus_space_read_8)
104
105/*
106 * void bus_space_write_1(bus_space_tag_t tag, bus_space_handle_t bsh,
107 *    bus_size_t offset, uint8_t value);
108 */
109ENTRY(bus_space_write_1)
110	addq	%rsi, %rdx
111	cmpl	$X86_BUS_SPACE_IO, BST_TYPE(%rdi)
112	je	1f
113	movb	%cl, (%rdx)
114	ret
1151:
116	movl	%ecx, %eax
117	outb	%al, %dx
118	ret
119END(bus_space_write_1)
120
121/*
122 * void bus_space_write_2(bus_space_tag_t tag, bus_space_handle_t bsh,
123 *    bus_size_t offset, uint16_t value);
124 */
125ENTRY(bus_space_write_2)
126	addq	%rsi, %rdx
127	cmpl	$X86_BUS_SPACE_IO, BST_TYPE(%rdi)
128	je	1f
129	movw	%cx, (%rdx)
130	ret
1311:
132	movl	%ecx, %eax
133	outw	%ax, %dx
134	ret
135END(bus_space_write_2)
136
137/*
138 * void bus_space_write_4(bus_space_tag_t tag, bus_space_handle_t bsh,
139 *     bus_size_t offset, uint32_t value);
140 */
141ENTRY(bus_space_write_4)
142	addq	%rsi, %rdx
143	cmpl	$X86_BUS_SPACE_IO, BST_TYPE(%rdi)
144	je	1f
145	movl	%ecx, (%rdx)
146	ret
1471:
148	movl	%ecx, %eax
149	outl	%eax, %dx
150	ret
151END(bus_space_write_4)
152
153/*
154 * void bus_space_write_8(bus_space_tag_t tag, bus_space_handle_t bsh,
155 *     bus_size_t offset, uint64_t value);
156 */
157ENTRY(bus_space_write_8)
158	addq	%rsi, %rdx
159	cmpl	$X86_BUS_SPACE_IO, BST_TYPE(%rdi)
160	je	.Ldopanic
161	movq	%rcx, (%rdx)
162	ret
163END(bus_space_write_8)
164
165STRONG_ALIAS(bus_space_write_stream_1,bus_space_write_1)
166STRONG_ALIAS(bus_space_write_stream_2,bus_space_write_2)
167STRONG_ALIAS(bus_space_write_stream_4,bus_space_write_4)
168STRONG_ALIAS(bus_space_write_stream_8,bus_space_write_8)
169
170/*
171 * void bus_space_read_multi_1(bus_space_tag_t tag, bus_space_handle_t bsh,
172 *    bus_size_t offset, uint8_t *addr, size_t count);
173 */
174ENTRY(bus_space_read_multi_1)
175	leaq	(%rsi,%rdx,1), %rdx
176	cmpl	$X86_BUS_SPACE_IO, BST_TYPE(%rdi)
177	jne	1f
178	movq	%rcx, %rdi
179	movq	%r8, %rcx
180	rep
181	insb	%dx, %es:(%rdi)
182	ret
183	.align	16
1841:
185	movb	(%rdx), %al
186	movb	%al, (%rcx)
187	leaq	1(%rcx), %rcx
188	decq	%r8
189	jnz	1b
190	ret
191END(bus_space_read_multi_1)
192
193/*
194 * void bus_space_read_multi_2(bus_space_tag_t tag, bus_space_handle_t bsh,
195 *    bus_size_t offset, uint16_t *addr, size_t count);
196 */
197ENTRY(bus_space_read_multi_2)
198	leaq	(%rsi,%rdx,1), %rdx
199	cmpl	$X86_BUS_SPACE_IO, BST_TYPE(%rdi)
200	jne	1f
201	movq	%rcx, %rdi
202	movq	%r8, %rcx
203	rep
204	insw	%dx, %es:(%rdi)
205	ret
206	.align	16
2071:
208	movw	(%rdx), %ax
209	movw	%ax, (%rcx)
210	leaq	2(%rcx), %rcx
211	decq	%r8
212	jnz	1b
213	ret
214END(bus_space_read_multi_2)
215
216/*
217 * void bus_space_read_multi_4(bus_space_tag_t tag, bus_space_handle_t bsh,
218 *    bus_size_t offset, uint32_t *addr, size_t count);
219 */
220ENTRY(bus_space_read_multi_4)
221	leaq	(%rsi,%rdx,1), %rdx
222	cmpl	$X86_BUS_SPACE_IO, BST_TYPE(%rdi)
223	jne	1f
224	movq	%rcx, %rdi
225	movq	%r8, %rcx
226	rep
227	insl	%dx, %es:(%rdi)
228	ret
229	.align	16
2301:
231	movl	(%rdx), %eax
232	movl	%eax, (%rcx)
233	leaq	4(%rcx), %rcx
234	decq	%r8
235	jnz	1b
236	ret
237END(bus_space_read_multi_4)
238
239/*
240 * void bus_space_read_multi_8(bus_space_tag_t tag, bus_space_handle_t bsh,
241 *    bus_size_t offset, uint64_t *addr, size_t count);
242 */
243ENTRY(bus_space_read_multi_8)
244	leaq	(%rsi,%rdx,1), %rdx
245	cmpl	$X86_BUS_SPACE_IO, BST_TYPE(%rdi)
246	je	.Ldopanic
247	.align	16
2481:
249	movq	(%rdx), %rax
250	movq	%rax, (%rcx)
251	leaq	8(%rcx), %rcx
252	decq	%r8
253	jnz	1b
254	ret
255END(bus_space_read_multi_8)
256
257STRONG_ALIAS(bus_space_read_multi_stream_1,bus_space_read_multi_1)
258STRONG_ALIAS(bus_space_read_multi_stream_2,bus_space_read_multi_2)
259STRONG_ALIAS(bus_space_read_multi_stream_4,bus_space_read_multi_4)
260STRONG_ALIAS(bus_space_read_multi_stream_8,bus_space_read_multi_8)
261
262/*
263 * void bus_space_write_multi_1(bus_space_tag_t tag, bus_space_handle_t bsh,
264 *    bus_size_t offset, const uint8_t *addr, size_t count);
265 */
266ENTRY(bus_space_write_multi_1)
267	leaq	(%rsi,%rdx,1), %rdx
268	cmpl	$X86_BUS_SPACE_IO, BST_TYPE(%rdi)
269	jne	1f
270	movq	%rcx, %rsi
271	movq	%r8, %rcx
272	rep
273	outsb	%ds:(%rsi), %dx
274	ret
275	.align	16
2761:
277	movb	(%rcx), %al
278	movb	%al, (%rdx)
279	leaq	1(%rcx), %rcx
280	decq	%r8
281	jnz	1b
282	ret
283END(bus_space_write_multi_1)
284
285/*
286 * void bus_space_write_multi_2(bus_space_tag_t tag, bus_space_handle_t bsh,
287 *    bus_size_t offset, const uint16_t *addr, size_t count);
288 */
289ENTRY(bus_space_write_multi_2)
290	leaq	(%rsi,%rdx,1), %rdx
291	cmpl	$X86_BUS_SPACE_IO, BST_TYPE(%rdi)
292	jne	1f
293	movq	%rcx, %rsi
294	movq	%r8, %rcx
295	rep
296	outsw	%ds:(%rsi), %dx
297	ret
298	.align	16
2991:
300	movw	(%rcx), %ax
301	movw	%ax, (%rdx)
302	leaq	2(%rcx), %rcx
303	decq	%r8
304	jnz	1b
305	ret
306END(bus_space_write_multi_2)
307
308/*
309 * void bus_space_write_multi_4(bus_space_tag_t tag, bus_space_handle_t bsh,
310 *    bus_size_t offset, const uint32_t *addr, size_t count);
311 */
312ENTRY(bus_space_write_multi_4)
313	leaq	(%rsi,%rdx,1), %rdx
314	cmpl	$X86_BUS_SPACE_IO, BST_TYPE(%rdi)
315	jne	1f
316	movq	%rcx, %rsi
317	movq	%r8, %rcx
318	rep
319	outsl	%ds:(%rsi), %dx
320	ret
321	.align	16
3221:
323	movl	(%rcx), %eax
324	movl	%eax, (%rdx)
325	leaq	4(%rcx), %rcx
326	decq	%r8
327	jnz	1b
328	ret
329END(bus_space_write_multi_4)
330
331/*
332 * void bus_space_write_multi_8(bus_space_tag_t tag, bus_space_handle_t bsh,
333 *    bus_size_t offset, const uint64_t *addr, size_t count);
334 */
335ENTRY(bus_space_write_multi_8)
336	leaq	(%rsi,%rdx,1), %rdx
337	cmpl	$X86_BUS_SPACE_IO, BST_TYPE(%rdi)
338	je	.Ldopanic
339	.align	16
3401:
341	movq	(%rcx), %rax
342	movq	%rax, (%rdx)
343	leaq	8(%rcx), %rcx
344	decq	%r8
345	jnz	1b
346	ret
347END(bus_space_write_multi_8)
348
349STRONG_ALIAS(bus_space_write_multi_stream_1,bus_space_write_multi_1)
350STRONG_ALIAS(bus_space_write_multi_stream_2,bus_space_write_multi_2)
351STRONG_ALIAS(bus_space_write_multi_stream_4,bus_space_write_multi_4)
352STRONG_ALIAS(bus_space_write_multi_stream_8,bus_space_write_multi_8)
353
354/*
355 * void bus_space_read_region_1(bus_space_tag_t tag, bus_space_handle_t bsh,
356 *    bus_size_t offset, uint8_t *addr, size_t count);
357 */
358ENTRY(bus_space_read_region_1)
359	cmpl	$X86_BUS_SPACE_IO, BST_TYPE(%rdi)
360	je	2f
361	addq	%rdx, %rsi
362	movq	%rcx, %rdi
363	movq	%r8, %rcx
364	rep
365	movsb	%ds:(%rsi), %es:(%rdi)
366	ret
3672:
368	addl	%esi, %edx
3693:
370	inb	%dx, %al
371	incl	%edx
372	decq	%r8
373	movb	%al, (%rcx)
374	leaq	1(%rcx), %rcx
375	jnz	3b
376	ret
377END(bus_space_read_region_1)
378
379/*
380 * void bus_space_read_region_2(bus_space_tag_t tag, bus_space_handle_t bsh,
381 *    bus_size_t offset, uint16_t *addr, size_t count);
382 */
383ENTRY(bus_space_read_region_2)
384	cmpl	$X86_BUS_SPACE_IO, BST_TYPE(%rdi)
385	je	2f
386	addq	%rdx, %rsi
387	movq	%rcx, %rdi
388	movq	%r8, %rcx
389	rep
390	movsw	%ds:(%rsi), %es:(%rdi)
391	ret
3922:
393	addl	%esi, %edx
3943:
395	inw	%dx, %ax
396	addl	$2, %edx
397	decq	%r8
398	movw	%ax, (%rcx)
399	leaq	2(%rcx), %rcx
400	jnz	3b
401	ret
402END(bus_space_read_region_2)
403
404/*
405 * void bus_space_read_region_4(bus_space_tag_t tag, bus_space_handle_t bsh,
406 *    bus_size_t offset, uint32_t *addr, size_t count);
407 */
408ENTRY(bus_space_read_region_4)
409	cmpl	$X86_BUS_SPACE_IO, BST_TYPE(%rdi)
410	je	2f
411	addq	%rdx, %rsi
412	movq	%rcx, %rdi
413	movq	%r8, %rcx
414	rep
415	movsl	%ds:(%rsi), %es:(%rdi)
416	ret
4172:
418	addl	%esi, %edx
4193:
420	inl	%dx, %eax
421	addl	$4, %edx
422	decq	%r8
423	movl	%eax, (%rcx)
424	leaq	4(%rcx), %rcx
425	jnz	3b
426	ret
427END(bus_space_read_region_4)
428
429/*
430 * void bus_space_read_region_8(bus_space_tag_t tag, bus_space_handle_t bsh,
431 *    bus_size_t offset, uint64_t *addr, size_t count);
432 */
433ENTRY(bus_space_read_region_8)
434	cmpl	$X86_BUS_SPACE_IO, BST_TYPE(%rdi)
435	je	.Ldopanic
436	addq	%rdx, %rsi
437	movq	%rcx, %rdi
438	movq	%r8, %rcx
439	rep
440	movsq	%ds:(%rsi), %es:(%rdi)
441	ret
442END(bus_space_read_region_8)
443
444STRONG_ALIAS(bus_space_read_region_stream_1,bus_space_read_region_1)
445STRONG_ALIAS(bus_space_read_region_stream_2,bus_space_read_region_2)
446STRONG_ALIAS(bus_space_read_region_stream_4,bus_space_read_region_4)
447STRONG_ALIAS(bus_space_read_region_stream_8,bus_space_read_region_8)
448
449/*
450 * void bus_space_write_region_1(bus_space_tag_t tag, bus_space_handle_t bsh,
451 *    bus_size_t offset, const uint8_t *addr, size_t count);
452 */
453ENTRY(bus_space_write_region_1)
454	cmpl	$X86_BUS_SPACE_IO, BST_TYPE(%rdi)
455	je	2f
456	leaq	(%rdx,%rsi,1), %rdi
457	movq	%rcx, %rsi
458	movq	%r8, %rcx
459	rep
460	movsb	%ds:(%rsi), %es:(%rdi)
461	ret
4622:
463	addl	%esi, %edx
4643:
465	movb	(%rcx), %al
466	incq	%rcx
467	decq	%r8
468	outb	%al, %dx
469	leaq	1(%rdx), %rdx
470	jnz	3b
471	ret
472END(bus_space_write_region_1)
473
474/*
475 * void bus_space_write_region_2(bus_space_tag_t tag, bus_space_handle_t bsh,
476 *    bus_size_t offset, const uint16_t *addr, size_t count);
477 */
478ENTRY(bus_space_write_region_2)
479	cmpl	$X86_BUS_SPACE_IO, BST_TYPE(%rdi)
480	je	2f
481	leaq	(%rdx,%rsi,1), %rdi
482	movq	%rcx, %rsi
483	movq	%r8, %rcx
484	rep
485	movsw	%ds:(%rsi), %es:(%rdi)
486	ret
4872:
488	addl	%esi, %edx
4893:
490	movw	(%rcx), %ax
491	addq	$2, %rcx
492	decq	%r8
493	outw	%ax, %dx
494	leaq	2(%rdx), %rdx
495	jnz	3b
496	ret
497END(bus_space_write_region_2)
498
499/*
500 * void bus_space_write_region_4(bus_space_tag_t tag, bus_space_handle_t bsh,
501 *    bus_size_t offset, const uint32_t *addr, size_t count);
502 */
503ENTRY(bus_space_write_region_4)
504	cmpl	$X86_BUS_SPACE_IO, BST_TYPE(%rdi)
505	je	2f
506	leaq	(%rdx,%rsi,1), %rdi
507	movq	%rcx, %rsi
508	movq	%r8, %rcx
509	rep
510	movsl	%ds:(%rsi), %es:(%rdi)
511	ret
5122:
513	addl	%esi, %edx
5143:
515	movl	(%rcx), %eax
516	addq	$4, %rcx
517	decq	%r8
518	outl	%eax, %dx
519	leaq	4(%rdx), %rdx
520	jnz	3b
521	ret
522END(bus_space_write_region_4)
523
524/*
525 * void bus_space_write_region_8(bus_space_tag_t tag, bus_space_handle_t bsh,
526 *    bus_size_t offset, const uint64_t *addr, size_t count);
527 */
528ENTRY(bus_space_write_region_8)
529	cmpl	$X86_BUS_SPACE_IO, BST_TYPE(%rdi)
530	je	.Ldopanic
531	leaq	(%rdx,%rsi,1), %rdi
532	movq	%rcx, %rsi
533	movq	%r8, %rcx
534	rep
535	movsq	%ds:(%rsi), %es:(%rdi)
536	ret
537END(bus_space_write_region_8)
538
539STRONG_ALIAS(bus_space_write_region_stream_1,bus_space_write_region_1)
540STRONG_ALIAS(bus_space_write_region_stream_2,bus_space_write_region_2)
541STRONG_ALIAS(bus_space_write_region_stream_4,bus_space_write_region_4)
542STRONG_ALIAS(bus_space_write_region_stream_8,bus_space_write_region_8)
543