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