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