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