xref: /netbsd-src/sys/arch/amd64/amd64/busfunc.S (revision 10c5b0232091c5643fb7fcc69b901d4009c696a7)
1/*	$NetBSD: busfunc.S,v 1.12 2019/11/14 16:23:52 maxv 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#include <machine/frameasm.h>
34
35#include "assym.h"
36
37.Ldopanic:
38	movq	$.Lpstr, %rdi
39	call	_C_LABEL(panic)
40.Lpstr:	.string	"bus_space: 8-byte access to I/O space\0"
41
42/*
43 * uint8_t bus_space_read_1(bus_space_tag_t tag, bus_space_handle_t bsh,
44 *    bus_size_t offset);
45 */
46ENTRY(bus_space_read_1)
47	addq	%rsi, %rdx
48	cmpl	$X86_BUS_SPACE_IO, BST_TYPE(%rdi)
49	je	1f
50	movzbl	(%rdx), %eax
51	KMSAN_INIT_RET(1)
52	ret
531:
54	xorl	%eax, %eax
55	inb	%dx, %al
56	KMSAN_INIT_RET(1)
57	ret
58END(bus_space_read_1)
59
60/*
61 * uint16_t bus_space_read_2(bus_space_tag_t tag, bus_space_handle_t bsh,
62 *    bus_size_t offset);
63 */
64ENTRY(bus_space_read_2)
65	addq	%rsi, %rdx
66	cmpl	$X86_BUS_SPACE_IO, BST_TYPE(%rdi)
67	je	1f
68	movzwl	(%rdx), %eax
69	KMSAN_INIT_RET(2)
70	ret
711:
72	xorl	%eax, %eax
73	inw	%dx, %ax
74	KMSAN_INIT_RET(2)
75	ret
76END(bus_space_read_2)
77
78/*
79 * uint32_t bus_space_read_4(bus_space_tag_t tag, bus_space_handle_t bsh,
80 *    bus_size_t offset);
81 */
82ENTRY(bus_space_read_4)
83	addq	%rsi, %rdx
84	cmpl	$X86_BUS_SPACE_IO, BST_TYPE(%rdi)
85	je	1f
86	movl	(%rdx), %eax
87	KMSAN_INIT_RET(4)
88	ret
891:
90	inl	%dx, %eax
91	KMSAN_INIT_RET(4)
92	ret
93END(bus_space_read_4)
94
95/*
96 * uint64_t bus_space_read_8(bus_space_tag_t tag, bus_space_handle_t bsh,
97 *    bus_size_t offset);
98 */
99ENTRY(bus_space_read_8)
100	addq	%rsi, %rdx
101	cmpl	$X86_BUS_SPACE_IO, BST_TYPE(%rdi)
102	je	.Ldopanic
103	movq	(%rdx), %rax
104	KMSAN_INIT_RET(8)
105	ret
106END(bus_space_read_8)
107
108STRONG_ALIAS(bus_space_read_stream_1,bus_space_read_1)
109STRONG_ALIAS(bus_space_read_stream_2,bus_space_read_2)
110STRONG_ALIAS(bus_space_read_stream_4,bus_space_read_4)
111STRONG_ALIAS(bus_space_read_stream_8,bus_space_read_8)
112
113/*
114 * void bus_space_write_1(bus_space_tag_t tag, bus_space_handle_t bsh,
115 *    bus_size_t offset, uint8_t value);
116 */
117ENTRY(bus_space_write_1)
118	addq	%rsi, %rdx
119	cmpl	$X86_BUS_SPACE_IO, BST_TYPE(%rdi)
120	je	1f
121	movb	%cl, (%rdx)
122	ret
1231:
124	movl	%ecx, %eax
125	outb	%al, %dx
126	ret
127END(bus_space_write_1)
128
129/*
130 * void bus_space_write_2(bus_space_tag_t tag, bus_space_handle_t bsh,
131 *    bus_size_t offset, uint16_t value);
132 */
133ENTRY(bus_space_write_2)
134	addq	%rsi, %rdx
135	cmpl	$X86_BUS_SPACE_IO, BST_TYPE(%rdi)
136	je	1f
137	movw	%cx, (%rdx)
138	ret
1391:
140	movl	%ecx, %eax
141	outw	%ax, %dx
142	ret
143END(bus_space_write_2)
144
145/*
146 * void bus_space_write_4(bus_space_tag_t tag, bus_space_handle_t bsh,
147 *     bus_size_t offset, uint32_t value);
148 */
149ENTRY(bus_space_write_4)
150	addq	%rsi, %rdx
151	cmpl	$X86_BUS_SPACE_IO, BST_TYPE(%rdi)
152	je	1f
153	movl	%ecx, (%rdx)
154	ret
1551:
156	movl	%ecx, %eax
157	outl	%eax, %dx
158	ret
159END(bus_space_write_4)
160
161/*
162 * void bus_space_write_8(bus_space_tag_t tag, bus_space_handle_t bsh,
163 *     bus_size_t offset, uint64_t value);
164 */
165ENTRY(bus_space_write_8)
166	addq	%rsi, %rdx
167	cmpl	$X86_BUS_SPACE_IO, BST_TYPE(%rdi)
168	je	.Ldopanic
169	movq	%rcx, (%rdx)
170	ret
171END(bus_space_write_8)
172
173STRONG_ALIAS(bus_space_write_stream_1,bus_space_write_1)
174STRONG_ALIAS(bus_space_write_stream_2,bus_space_write_2)
175STRONG_ALIAS(bus_space_write_stream_4,bus_space_write_4)
176STRONG_ALIAS(bus_space_write_stream_8,bus_space_write_8)
177
178/*
179 * void bus_space_read_multi_1(bus_space_tag_t tag, bus_space_handle_t bsh,
180 *    bus_size_t offset, uint8_t *addr, size_t count);
181 */
182ENTRY(bus_space_read_multi_1)
183	leaq	(%rsi,%rdx,1), %rdx
184	cmpl	$X86_BUS_SPACE_IO, BST_TYPE(%rdi)
185	jne	1f
186	movq	%rcx, %rdi
187	movq	%r8, %rcx
188	rep
189	insb	%dx, %es:(%rdi)
190	ret
191	.align	16
1921:
193	movb	(%rdx), %al
194	movb	%al, (%rcx)
195	leaq	1(%rcx), %rcx
196	decq	%r8
197	jnz	1b
198	ret
199END(bus_space_read_multi_1)
200
201/*
202 * void bus_space_read_multi_2(bus_space_tag_t tag, bus_space_handle_t bsh,
203 *    bus_size_t offset, uint16_t *addr, size_t count);
204 */
205ENTRY(bus_space_read_multi_2)
206	leaq	(%rsi,%rdx,1), %rdx
207	cmpl	$X86_BUS_SPACE_IO, BST_TYPE(%rdi)
208	jne	1f
209	movq	%rcx, %rdi
210	movq	%r8, %rcx
211	rep
212	insw	%dx, %es:(%rdi)
213	ret
214	.align	16
2151:
216	movw	(%rdx), %ax
217	movw	%ax, (%rcx)
218	leaq	2(%rcx), %rcx
219	decq	%r8
220	jnz	1b
221	ret
222END(bus_space_read_multi_2)
223
224/*
225 * void bus_space_read_multi_4(bus_space_tag_t tag, bus_space_handle_t bsh,
226 *    bus_size_t offset, uint32_t *addr, size_t count);
227 */
228ENTRY(bus_space_read_multi_4)
229	leaq	(%rsi,%rdx,1), %rdx
230	cmpl	$X86_BUS_SPACE_IO, BST_TYPE(%rdi)
231	jne	1f
232	movq	%rcx, %rdi
233	movq	%r8, %rcx
234	rep
235	insl	%dx, %es:(%rdi)
236	ret
237	.align	16
2381:
239	movl	(%rdx), %eax
240	movl	%eax, (%rcx)
241	leaq	4(%rcx), %rcx
242	decq	%r8
243	jnz	1b
244	ret
245END(bus_space_read_multi_4)
246
247/*
248 * void bus_space_read_multi_8(bus_space_tag_t tag, bus_space_handle_t bsh,
249 *    bus_size_t offset, uint64_t *addr, size_t count);
250 */
251ENTRY(bus_space_read_multi_8)
252	leaq	(%rsi,%rdx,1), %rdx
253	cmpl	$X86_BUS_SPACE_IO, BST_TYPE(%rdi)
254	je	.Ldopanic
255	.align	16
2561:
257	movq	(%rdx), %rax
258	movq	%rax, (%rcx)
259	leaq	8(%rcx), %rcx
260	decq	%r8
261	jnz	1b
262	ret
263END(bus_space_read_multi_8)
264
265STRONG_ALIAS(bus_space_read_multi_stream_1,bus_space_read_multi_1)
266STRONG_ALIAS(bus_space_read_multi_stream_2,bus_space_read_multi_2)
267STRONG_ALIAS(bus_space_read_multi_stream_4,bus_space_read_multi_4)
268STRONG_ALIAS(bus_space_read_multi_stream_8,bus_space_read_multi_8)
269
270/*
271 * void bus_space_write_multi_1(bus_space_tag_t tag, bus_space_handle_t bsh,
272 *    bus_size_t offset, const uint8_t *addr, size_t count);
273 */
274ENTRY(bus_space_write_multi_1)
275	leaq	(%rsi,%rdx,1), %rdx
276	cmpl	$X86_BUS_SPACE_IO, BST_TYPE(%rdi)
277	jne	1f
278	movq	%rcx, %rsi
279	movq	%r8, %rcx
280	rep
281	outsb	%ds:(%rsi), %dx
282	ret
283	.align	16
2841:
285	movb	(%rcx), %al
286	movb	%al, (%rdx)
287	leaq	1(%rcx), %rcx
288	decq	%r8
289	jnz	1b
290	ret
291END(bus_space_write_multi_1)
292
293/*
294 * void bus_space_write_multi_2(bus_space_tag_t tag, bus_space_handle_t bsh,
295 *    bus_size_t offset, const uint16_t *addr, size_t count);
296 */
297ENTRY(bus_space_write_multi_2)
298	leaq	(%rsi,%rdx,1), %rdx
299	cmpl	$X86_BUS_SPACE_IO, BST_TYPE(%rdi)
300	jne	1f
301	movq	%rcx, %rsi
302	movq	%r8, %rcx
303	rep
304	outsw	%ds:(%rsi), %dx
305	ret
306	.align	16
3071:
308	movw	(%rcx), %ax
309	movw	%ax, (%rdx)
310	leaq	2(%rcx), %rcx
311	decq	%r8
312	jnz	1b
313	ret
314END(bus_space_write_multi_2)
315
316/*
317 * void bus_space_write_multi_4(bus_space_tag_t tag, bus_space_handle_t bsh,
318 *    bus_size_t offset, const uint32_t *addr, size_t count);
319 */
320ENTRY(bus_space_write_multi_4)
321	leaq	(%rsi,%rdx,1), %rdx
322	cmpl	$X86_BUS_SPACE_IO, BST_TYPE(%rdi)
323	jne	1f
324	movq	%rcx, %rsi
325	movq	%r8, %rcx
326	rep
327	outsl	%ds:(%rsi), %dx
328	ret
329	.align	16
3301:
331	movl	(%rcx), %eax
332	movl	%eax, (%rdx)
333	leaq	4(%rcx), %rcx
334	decq	%r8
335	jnz	1b
336	ret
337END(bus_space_write_multi_4)
338
339/*
340 * void bus_space_write_multi_8(bus_space_tag_t tag, bus_space_handle_t bsh,
341 *    bus_size_t offset, const uint64_t *addr, size_t count);
342 */
343ENTRY(bus_space_write_multi_8)
344	leaq	(%rsi,%rdx,1), %rdx
345	cmpl	$X86_BUS_SPACE_IO, BST_TYPE(%rdi)
346	je	.Ldopanic
347	.align	16
3481:
349	movq	(%rcx), %rax
350	movq	%rax, (%rdx)
351	leaq	8(%rcx), %rcx
352	decq	%r8
353	jnz	1b
354	ret
355END(bus_space_write_multi_8)
356
357STRONG_ALIAS(bus_space_write_multi_stream_1,bus_space_write_multi_1)
358STRONG_ALIAS(bus_space_write_multi_stream_2,bus_space_write_multi_2)
359STRONG_ALIAS(bus_space_write_multi_stream_4,bus_space_write_multi_4)
360STRONG_ALIAS(bus_space_write_multi_stream_8,bus_space_write_multi_8)
361
362/*
363 * void bus_space_read_region_1(bus_space_tag_t tag, bus_space_handle_t bsh,
364 *    bus_size_t offset, uint8_t *addr, size_t count);
365 */
366ENTRY(bus_space_read_region_1)
367	cmpl	$X86_BUS_SPACE_IO, BST_TYPE(%rdi)
368	je	2f
369	addq	%rdx, %rsi
370	movq	%rcx, %rdi
371	movq	%r8, %rcx
372	rep
373	movsb	%ds:(%rsi), %es:(%rdi)
374	ret
3752:
376	addl	%esi, %edx
3773:
378	inb	%dx, %al
379	incl	%edx
380	decq	%r8
381	movb	%al, (%rcx)
382	leaq	1(%rcx), %rcx
383	jnz	3b
384	ret
385END(bus_space_read_region_1)
386
387/*
388 * void bus_space_read_region_2(bus_space_tag_t tag, bus_space_handle_t bsh,
389 *    bus_size_t offset, uint16_t *addr, size_t count);
390 */
391ENTRY(bus_space_read_region_2)
392	cmpl	$X86_BUS_SPACE_IO, BST_TYPE(%rdi)
393	je	2f
394	addq	%rdx, %rsi
395	movq	%rcx, %rdi
396	movq	%r8, %rcx
397	rep
398	movsw	%ds:(%rsi), %es:(%rdi)
399	ret
4002:
401	addl	%esi, %edx
4023:
403	inw	%dx, %ax
404	addl	$2, %edx
405	decq	%r8
406	movw	%ax, (%rcx)
407	leaq	2(%rcx), %rcx
408	jnz	3b
409	ret
410END(bus_space_read_region_2)
411
412/*
413 * void bus_space_read_region_4(bus_space_tag_t tag, bus_space_handle_t bsh,
414 *    bus_size_t offset, uint32_t *addr, size_t count);
415 */
416ENTRY(bus_space_read_region_4)
417	cmpl	$X86_BUS_SPACE_IO, BST_TYPE(%rdi)
418	je	2f
419	addq	%rdx, %rsi
420	movq	%rcx, %rdi
421	movq	%r8, %rcx
422	rep
423	movsl	%ds:(%rsi), %es:(%rdi)
424	ret
4252:
426	addl	%esi, %edx
4273:
428	inl	%dx, %eax
429	addl	$4, %edx
430	decq	%r8
431	movl	%eax, (%rcx)
432	leaq	4(%rcx), %rcx
433	jnz	3b
434	ret
435END(bus_space_read_region_4)
436
437/*
438 * void bus_space_read_region_8(bus_space_tag_t tag, bus_space_handle_t bsh,
439 *    bus_size_t offset, uint64_t *addr, size_t count);
440 */
441ENTRY(bus_space_read_region_8)
442	cmpl	$X86_BUS_SPACE_IO, BST_TYPE(%rdi)
443	je	.Ldopanic
444	addq	%rdx, %rsi
445	movq	%rcx, %rdi
446	movq	%r8, %rcx
447	rep
448	movsq	%ds:(%rsi), %es:(%rdi)
449	ret
450END(bus_space_read_region_8)
451
452STRONG_ALIAS(bus_space_read_region_stream_1,bus_space_read_region_1)
453STRONG_ALIAS(bus_space_read_region_stream_2,bus_space_read_region_2)
454STRONG_ALIAS(bus_space_read_region_stream_4,bus_space_read_region_4)
455STRONG_ALIAS(bus_space_read_region_stream_8,bus_space_read_region_8)
456
457/*
458 * void bus_space_write_region_1(bus_space_tag_t tag, bus_space_handle_t bsh,
459 *    bus_size_t offset, const uint8_t *addr, size_t count);
460 */
461ENTRY(bus_space_write_region_1)
462	cmpl	$X86_BUS_SPACE_IO, BST_TYPE(%rdi)
463	je	2f
464	leaq	(%rdx,%rsi,1), %rdi
465	movq	%rcx, %rsi
466	movq	%r8, %rcx
467	rep
468	movsb	%ds:(%rsi), %es:(%rdi)
469	ret
4702:
471	addl	%esi, %edx
4723:
473	movb	(%rcx), %al
474	incq	%rcx
475	decq	%r8
476	outb	%al, %dx
477	leaq	1(%rdx), %rdx
478	jnz	3b
479	ret
480END(bus_space_write_region_1)
481
482/*
483 * void bus_space_write_region_2(bus_space_tag_t tag, bus_space_handle_t bsh,
484 *    bus_size_t offset, const uint16_t *addr, size_t count);
485 */
486ENTRY(bus_space_write_region_2)
487	cmpl	$X86_BUS_SPACE_IO, BST_TYPE(%rdi)
488	je	2f
489	leaq	(%rdx,%rsi,1), %rdi
490	movq	%rcx, %rsi
491	movq	%r8, %rcx
492	rep
493	movsw	%ds:(%rsi), %es:(%rdi)
494	ret
4952:
496	addl	%esi, %edx
4973:
498	movw	(%rcx), %ax
499	addq	$2, %rcx
500	decq	%r8
501	outw	%ax, %dx
502	leaq	2(%rdx), %rdx
503	jnz	3b
504	ret
505END(bus_space_write_region_2)
506
507/*
508 * void bus_space_write_region_4(bus_space_tag_t tag, bus_space_handle_t bsh,
509 *    bus_size_t offset, const uint32_t *addr, size_t count);
510 */
511ENTRY(bus_space_write_region_4)
512	cmpl	$X86_BUS_SPACE_IO, BST_TYPE(%rdi)
513	je	2f
514	leaq	(%rdx,%rsi,1), %rdi
515	movq	%rcx, %rsi
516	movq	%r8, %rcx
517	rep
518	movsl	%ds:(%rsi), %es:(%rdi)
519	ret
5202:
521	addl	%esi, %edx
5223:
523	movl	(%rcx), %eax
524	addq	$4, %rcx
525	decq	%r8
526	outl	%eax, %dx
527	leaq	4(%rdx), %rdx
528	jnz	3b
529	ret
530END(bus_space_write_region_4)
531
532/*
533 * void bus_space_write_region_8(bus_space_tag_t tag, bus_space_handle_t bsh,
534 *    bus_size_t offset, const uint64_t *addr, size_t count);
535 */
536ENTRY(bus_space_write_region_8)
537	cmpl	$X86_BUS_SPACE_IO, BST_TYPE(%rdi)
538	je	.Ldopanic
539	leaq	(%rdx,%rsi,1), %rdi
540	movq	%rcx, %rsi
541	movq	%r8, %rcx
542	rep
543	movsq	%ds:(%rsi), %es:(%rdi)
544	ret
545END(bus_space_write_region_8)
546
547STRONG_ALIAS(bus_space_write_region_stream_1,bus_space_write_region_1)
548STRONG_ALIAS(bus_space_write_region_stream_2,bus_space_write_region_2)
549STRONG_ALIAS(bus_space_write_region_stream_4,bus_space_write_region_4)
550STRONG_ALIAS(bus_space_write_region_stream_8,bus_space_write_region_8)
551