Annotation of sys/arch/arm/arm/bcopyinout.S, Revision 1.1
1.1 ! nbrk 1: /* $OpenBSD: bcopyinout.S,v 1.1 2004/02/01 05:09:48 drahn Exp $ */
! 2: /* $NetBSD: bcopyinout.S,v 1.13 2003/10/31 16:54:05 scw Exp $ */
! 3:
! 4: /*
! 5: * Copyright (c) 2002 Wasabi Systems, Inc.
! 6: * All rights reserved.
! 7: *
! 8: * Written by Allen Briggs for Wasabi Systems, Inc.
! 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: * 3. All advertising materials mentioning features or use of this software
! 19: * must display the following acknowledgement:
! 20: * This product includes software developed for the NetBSD Project by
! 21: * Wasabi Systems, Inc.
! 22: * 4. The name of Wasabi Systems, Inc. may not be used to endorse
! 23: * or promote products derived from this software without specific prior
! 24: * written permission.
! 25: *
! 26: * THIS SOFTWARE IS PROVIDED BY WASABI SYSTEMS, INC. ``AS IS'' AND
! 27: * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
! 28: * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
! 29: * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL WASABI SYSTEMS, INC
! 30: * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
! 31: * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
! 32: * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
! 33: * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
! 34: * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
! 35: * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
! 36: * POSSIBILITY OF SUCH DAMAGE.
! 37: */
! 38:
! 39: #include "assym.h"
! 40:
! 41: #include <machine/asm.h>
! 42:
! 43: #ifdef __XSCALE__
! 44: #include "bcopyinout_xscale.S"
! 45: #else
! 46:
! 47: .text
! 48: .align 0
! 49:
! 50: #ifdef MULTIPROCESSOR
! 51: .Lcpu_info:
! 52: .word _C_LABEL(cpu_info)
! 53: #else
! 54: .Lcurpcb:
! 55: .word _C_LABEL(curpcb)
! 56: #endif
! 57:
! 58: #ifdef __PROG32
! 59: #define SAVE_REGS stmfd sp!, {r4-r11}
! 60: #define RESTORE_REGS ldmfd sp!, {r4-r11}
! 61: #else
! 62: /* Need to save R14_svc because it'll get trampled if we take a page fault. */
! 63: #define SAVE_REGS stmfd sp!, {r4-r11, r14}
! 64: #define RESTORE_REGS ldmfd sp!, {r4-r11, r14}
! 65: #endif
! 66:
! 67: #if defined(__XSCALE__)
! 68: #define HELLOCPP #
! 69: #define PREFETCH(rx,o) pld [ rx , HELLOCPP (o) ]
! 70: #else
! 71: #define PREFETCH(rx,o)
! 72: #endif
! 73:
! 74: /*
! 75: * r0 = user space address
! 76: * r1 = kernel space address
! 77: * r2 = length
! 78: *
! 79: * Copies bytes from user space to kernel space
! 80: *
! 81: * We save/restore r4-r11:
! 82: * r4-r11 are scratch
! 83: */
! 84: ENTRY(copyin)
! 85: /* Quick exit if length is zero */
! 86: teq r2, #0
! 87: moveq r0, #0
! 88: moveq pc, lr
! 89:
! 90: SAVE_REGS
! 91: #ifdef MULTIPROCESSOR
! 92: /* XXX Probably not appropriate for non-Hydra SMPs */
! 93: stmfd sp!, {r0-r2, r14}
! 94: bl _C_LABEL(cpu_number)
! 95: ldr r4, .Lcpu_info
! 96: ldr r4, [r4, r0, lsl #2]
! 97: ldr r4, [r4, #CI_CURPCB]
! 98: ldmfd sp!, {r0-r2, r14}
! 99: #else
! 100: ldr r4, .Lcurpcb
! 101: ldr r4, [r4]
! 102: #endif
! 103:
! 104: ldr r5, [r4, #PCB_ONFAULT]
! 105: adr r3, .Lcopyfault
! 106: str r3, [r4, #PCB_ONFAULT]
! 107:
! 108: PREFETCH(r0, 0)
! 109: PREFETCH(r1, 0)
! 110:
! 111: /*
! 112: * If not too many bytes, take the slow path.
! 113: */
! 114: cmp r2, #0x08
! 115: blt .Licleanup
! 116:
! 117: /*
! 118: * Align destination to word boundary.
! 119: */
! 120: and r6, r1, #0x3
! 121: ldr pc, [pc, r6, lsl #2]
! 122: b .Lialend
! 123: .word .Lialend
! 124: .word .Lial3
! 125: .word .Lial2
! 126: .word .Lial1
! 127: .Lial3: ldrbt r6, [r0], #1
! 128: sub r2, r2, #1
! 129: strb r6, [r1], #1
! 130: .Lial2: ldrbt r7, [r0], #1
! 131: sub r2, r2, #1
! 132: strb r7, [r1], #1
! 133: .Lial1: ldrbt r6, [r0], #1
! 134: sub r2, r2, #1
! 135: strb r6, [r1], #1
! 136: .Lialend:
! 137:
! 138: /*
! 139: * If few bytes left, finish slow.
! 140: */
! 141: cmp r2, #0x08
! 142: blt .Licleanup
! 143:
! 144: /*
! 145: * If source is not aligned, finish slow.
! 146: */
! 147: ands r3, r0, #0x03
! 148: bne .Licleanup
! 149:
! 150: cmp r2, #0x60 /* Must be > 0x5f for unrolled cacheline */
! 151: blt .Licleanup8
! 152:
! 153: /*
! 154: * Align destination to cacheline boundary.
! 155: * If source and destination are nicely aligned, this can be a big
! 156: * win. If not, it's still cheaper to copy in groups of 32 even if
! 157: * we don't get the nice cacheline alignment.
! 158: */
! 159: and r6, r1, #0x1f
! 160: ldr pc, [pc, r6]
! 161: b .Licaligned
! 162: .word .Licaligned
! 163: .word .Lical28
! 164: .word .Lical24
! 165: .word .Lical20
! 166: .word .Lical16
! 167: .word .Lical12
! 168: .word .Lical8
! 169: .word .Lical4
! 170: .Lical28:ldrt r6, [r0], #4
! 171: sub r2, r2, #4
! 172: str r6, [r1], #4
! 173: .Lical24:ldrt r7, [r0], #4
! 174: sub r2, r2, #4
! 175: str r7, [r1], #4
! 176: .Lical20:ldrt r6, [r0], #4
! 177: sub r2, r2, #4
! 178: str r6, [r1], #4
! 179: .Lical16:ldrt r7, [r0], #4
! 180: sub r2, r2, #4
! 181: str r7, [r1], #4
! 182: .Lical12:ldrt r6, [r0], #4
! 183: sub r2, r2, #4
! 184: str r6, [r1], #4
! 185: .Lical8:ldrt r7, [r0], #4
! 186: sub r2, r2, #4
! 187: str r7, [r1], #4
! 188: .Lical4:ldrt r6, [r0], #4
! 189: sub r2, r2, #4
! 190: str r6, [r1], #4
! 191:
! 192: /*
! 193: * We start with > 0x40 bytes to copy (>= 0x60 got us into this
! 194: * part of the code, and we may have knocked that down by as much
! 195: * as 0x1c getting aligned).
! 196: *
! 197: * This loop basically works out to:
! 198: * do {
! 199: * prefetch-next-cacheline(s)
! 200: * bytes -= 0x20;
! 201: * copy cacheline
! 202: * } while (bytes >= 0x40);
! 203: * bytes -= 0x20;
! 204: * copy cacheline
! 205: */
! 206: .Licaligned:
! 207: PREFETCH(r0, 32)
! 208: PREFETCH(r1, 32)
! 209:
! 210: sub r2, r2, #0x20
! 211:
! 212: /* Copy a cacheline */
! 213: ldrt r10, [r0], #4
! 214: ldrt r11, [r0], #4
! 215: ldrt r6, [r0], #4
! 216: ldrt r7, [r0], #4
! 217: ldrt r8, [r0], #4
! 218: ldrt r9, [r0], #4
! 219: stmia r1!, {r10-r11}
! 220: ldrt r10, [r0], #4
! 221: ldrt r11, [r0], #4
! 222: stmia r1!, {r6-r11}
! 223:
! 224: cmp r2, #0x40
! 225: bge .Licaligned
! 226:
! 227: sub r2, r2, #0x20
! 228:
! 229: /* Copy a cacheline */
! 230: ldrt r10, [r0], #4
! 231: ldrt r11, [r0], #4
! 232: ldrt r6, [r0], #4
! 233: ldrt r7, [r0], #4
! 234: ldrt r8, [r0], #4
! 235: ldrt r9, [r0], #4
! 236: stmia r1!, {r10-r11}
! 237: ldrt r10, [r0], #4
! 238: ldrt r11, [r0], #4
! 239: stmia r1!, {r6-r11}
! 240:
! 241: cmp r2, #0x08
! 242: blt .Liprecleanup
! 243:
! 244: .Licleanup8:
! 245: ldrt r8, [r0], #4
! 246: ldrt r9, [r0], #4
! 247: sub r2, r2, #8
! 248: stmia r1!, {r8, r9}
! 249: cmp r2, #8
! 250: bge .Licleanup8
! 251:
! 252: .Liprecleanup:
! 253: /*
! 254: * If we're done, bail.
! 255: */
! 256: cmp r2, #0
! 257: beq .Lout
! 258:
! 259: .Licleanup:
! 260: and r6, r2, #0x3
! 261: ldr pc, [pc, r6, lsl #2]
! 262: b .Licend
! 263: .word .Lic4
! 264: .word .Lic1
! 265: .word .Lic2
! 266: .word .Lic3
! 267: .Lic4: ldrbt r6, [r0], #1
! 268: sub r2, r2, #1
! 269: strb r6, [r1], #1
! 270: .Lic3: ldrbt r7, [r0], #1
! 271: sub r2, r2, #1
! 272: strb r7, [r1], #1
! 273: .Lic2: ldrbt r6, [r0], #1
! 274: sub r2, r2, #1
! 275: strb r6, [r1], #1
! 276: .Lic1: ldrbt r7, [r0], #1
! 277: subs r2, r2, #1
! 278: strb r7, [r1], #1
! 279: .Licend:
! 280: bne .Licleanup
! 281:
! 282: .Liout:
! 283: mov r0, #0
! 284:
! 285: str r5, [r4, #PCB_ONFAULT]
! 286: RESTORE_REGS
! 287:
! 288: mov pc, lr
! 289:
! 290: .Lcopyfault:
! 291: str r5, [r4, #PCB_ONFAULT]
! 292: RESTORE_REGS
! 293:
! 294: mov pc, lr
! 295:
! 296: /*
! 297: * r0 = kernel space address
! 298: * r1 = user space address
! 299: * r2 = length
! 300: *
! 301: * Copies bytes from kernel space to user space
! 302: *
! 303: * We save/restore r4-r11:
! 304: * r4-r11 are scratch
! 305: */
! 306:
! 307: ENTRY(copyout)
! 308: /* Quick exit if length is zero */
! 309: teq r2, #0
! 310: moveq r0, #0
! 311: moveq pc, lr
! 312:
! 313: SAVE_REGS
! 314: #ifdef MULTIPROCESSOR
! 315: /* XXX Probably not appropriate for non-Hydra SMPs */
! 316: stmfd sp!, {r0-r2, r14}
! 317: bl _C_LABEL(cpu_number)
! 318: ldr r4, .Lcpu_info
! 319: ldr r4, [r4, r0, lsl #2]
! 320: ldr r4, [r4, #CI_CURPCB]
! 321: ldmfd sp!, {r0-r2, r14}
! 322: #else
! 323: ldr r4, .Lcurpcb
! 324: ldr r4, [r4]
! 325: #endif
! 326:
! 327: ldr r5, [r4, #PCB_ONFAULT]
! 328: adr r3, .Lcopyfault
! 329: str r3, [r4, #PCB_ONFAULT]
! 330:
! 331: PREFETCH(r0, 0)
! 332: PREFETCH(r1, 0)
! 333:
! 334: /*
! 335: * If not too many bytes, take the slow path.
! 336: */
! 337: cmp r2, #0x08
! 338: blt .Lcleanup
! 339:
! 340: /*
! 341: * Align destination to word boundary.
! 342: */
! 343: and r6, r1, #0x3
! 344: ldr pc, [pc, r6, lsl #2]
! 345: b .Lalend
! 346: .word .Lalend
! 347: .word .Lal3
! 348: .word .Lal2
! 349: .word .Lal1
! 350: .Lal3: ldrb r6, [r0], #1
! 351: sub r2, r2, #1
! 352: strbt r6, [r1], #1
! 353: .Lal2: ldrb r7, [r0], #1
! 354: sub r2, r2, #1
! 355: strbt r7, [r1], #1
! 356: .Lal1: ldrb r6, [r0], #1
! 357: sub r2, r2, #1
! 358: strbt r6, [r1], #1
! 359: .Lalend:
! 360:
! 361: /*
! 362: * If few bytes left, finish slow.
! 363: */
! 364: cmp r2, #0x08
! 365: blt .Lcleanup
! 366:
! 367: /*
! 368: * If source is not aligned, finish slow.
! 369: */
! 370: ands r3, r0, #0x03
! 371: bne .Lcleanup
! 372:
! 373: cmp r2, #0x60 /* Must be > 0x5f for unrolled cacheline */
! 374: blt .Lcleanup8
! 375:
! 376: /*
! 377: * Align source & destination to cacheline boundary.
! 378: */
! 379: and r6, r1, #0x1f
! 380: ldr pc, [pc, r6]
! 381: b .Lcaligned
! 382: .word .Lcaligned
! 383: .word .Lcal28
! 384: .word .Lcal24
! 385: .word .Lcal20
! 386: .word .Lcal16
! 387: .word .Lcal12
! 388: .word .Lcal8
! 389: .word .Lcal4
! 390: .Lcal28:ldr r6, [r0], #4
! 391: sub r2, r2, #4
! 392: strt r6, [r1], #4
! 393: .Lcal24:ldr r7, [r0], #4
! 394: sub r2, r2, #4
! 395: strt r7, [r1], #4
! 396: .Lcal20:ldr r6, [r0], #4
! 397: sub r2, r2, #4
! 398: strt r6, [r1], #4
! 399: .Lcal16:ldr r7, [r0], #4
! 400: sub r2, r2, #4
! 401: strt r7, [r1], #4
! 402: .Lcal12:ldr r6, [r0], #4
! 403: sub r2, r2, #4
! 404: strt r6, [r1], #4
! 405: .Lcal8: ldr r7, [r0], #4
! 406: sub r2, r2, #4
! 407: strt r7, [r1], #4
! 408: .Lcal4: ldr r6, [r0], #4
! 409: sub r2, r2, #4
! 410: strt r6, [r1], #4
! 411:
! 412: /*
! 413: * We start with > 0x40 bytes to copy (>= 0x60 got us into this
! 414: * part of the code, and we may have knocked that down by as much
! 415: * as 0x1c getting aligned).
! 416: *
! 417: * This loop basically works out to:
! 418: * do {
! 419: * prefetch-next-cacheline(s)
! 420: * bytes -= 0x20;
! 421: * copy cacheline
! 422: * } while (bytes >= 0x40);
! 423: * bytes -= 0x20;
! 424: * copy cacheline
! 425: */
! 426: .Lcaligned:
! 427: PREFETCH(r0, 32)
! 428: PREFETCH(r1, 32)
! 429:
! 430: sub r2, r2, #0x20
! 431:
! 432: /* Copy a cacheline */
! 433: ldmia r0!, {r6-r11}
! 434: strt r6, [r1], #4
! 435: strt r7, [r1], #4
! 436: ldmia r0!, {r6-r7}
! 437: strt r8, [r1], #4
! 438: strt r9, [r1], #4
! 439: strt r10, [r1], #4
! 440: strt r11, [r1], #4
! 441: strt r6, [r1], #4
! 442: strt r7, [r1], #4
! 443:
! 444: cmp r2, #0x40
! 445: bge .Lcaligned
! 446:
! 447: sub r2, r2, #0x20
! 448:
! 449: /* Copy a cacheline */
! 450: ldmia r0!, {r6-r11}
! 451: strt r6, [r1], #4
! 452: strt r7, [r1], #4
! 453: ldmia r0!, {r6-r7}
! 454: strt r8, [r1], #4
! 455: strt r9, [r1], #4
! 456: strt r10, [r1], #4
! 457: strt r11, [r1], #4
! 458: strt r6, [r1], #4
! 459: strt r7, [r1], #4
! 460:
! 461: cmp r2, #0x08
! 462: blt .Lprecleanup
! 463:
! 464: .Lcleanup8:
! 465: ldmia r0!, {r8-r9}
! 466: sub r2, r2, #8
! 467: strt r8, [r1], #4
! 468: strt r9, [r1], #4
! 469: cmp r2, #8
! 470: bge .Lcleanup8
! 471:
! 472: .Lprecleanup:
! 473: /*
! 474: * If we're done, bail.
! 475: */
! 476: cmp r2, #0
! 477: beq .Lout
! 478:
! 479: .Lcleanup:
! 480: and r6, r2, #0x3
! 481: ldr pc, [pc, r6, lsl #2]
! 482: b .Lcend
! 483: .word .Lc4
! 484: .word .Lc1
! 485: .word .Lc2
! 486: .word .Lc3
! 487: .Lc4: ldrb r6, [r0], #1
! 488: sub r2, r2, #1
! 489: strbt r6, [r1], #1
! 490: .Lc3: ldrb r7, [r0], #1
! 491: sub r2, r2, #1
! 492: strbt r7, [r1], #1
! 493: .Lc2: ldrb r6, [r0], #1
! 494: sub r2, r2, #1
! 495: strbt r6, [r1], #1
! 496: .Lc1: ldrb r7, [r0], #1
! 497: subs r2, r2, #1
! 498: strbt r7, [r1], #1
! 499: .Lcend:
! 500: bne .Lcleanup
! 501:
! 502: .Lout:
! 503: mov r0, #0
! 504:
! 505: str r5, [r4, #PCB_ONFAULT]
! 506: RESTORE_REGS
! 507:
! 508: mov pc, lr
! 509:
! 510: /*
! 511: * r0 = kernel space source address
! 512: * r1 = kernel space destination address
! 513: * r2 = length
! 514: *
! 515: * Copies bytes from kernel space to kernel space, aborting on page fault
! 516: *
! 517: * Copy of copyout, but without the ldrt/strt instructions.
! 518: */
! 519:
! 520: ENTRY(kcopy)
! 521: /* Quick exit if length is zero */
! 522: teq r2, #0
! 523: moveq r0, #0
! 524: moveq pc, lr
! 525:
! 526: SAVE_REGS
! 527: #ifdef MULTIPROCESSOR
! 528: /* XXX Probably not appropriate for non-Hydra SMPs */
! 529: stmfd sp!, {r0-r2, r14}
! 530: bl _C_LABEL(cpu_number)
! 531: ldr r4, .Lcpu_info
! 532: ldr r4, [r4, r0, lsl #2]
! 533: ldr r4, [r4, #CI_CURPCB]
! 534: ldmfd sp!, {r0-r2, r14}
! 535: #else
! 536: ldr r4, .Lcurpcb
! 537: ldr r4, [r4]
! 538: #endif
! 539:
! 540: ldr r5, [r4, #PCB_ONFAULT]
! 541: adr r3, .Lcopyfault
! 542: str r3, [r4, #PCB_ONFAULT]
! 543:
! 544: PREFETCH(r0, 0)
! 545: PREFETCH(r1, 0)
! 546:
! 547: /*
! 548: * If not too many bytes, take the slow path.
! 549: */
! 550: cmp r2, #0x08
! 551: blt .Lkcleanup
! 552:
! 553: /*
! 554: * Align destination to word boundary.
! 555: */
! 556: and r6, r1, #0x3
! 557: ldr pc, [pc, r6, lsl #2]
! 558: b .Lkalend
! 559: .word .Lkalend
! 560: .word .Lkal3
! 561: .word .Lkal2
! 562: .word .Lkal1
! 563: .Lkal3: ldrb r6, [r0], #1
! 564: sub r2, r2, #1
! 565: strb r6, [r1], #1
! 566: .Lkal2: ldrb r7, [r0], #1
! 567: sub r2, r2, #1
! 568: strb r7, [r1], #1
! 569: .Lkal1: ldrb r6, [r0], #1
! 570: sub r2, r2, #1
! 571: strb r6, [r1], #1
! 572: .Lkalend:
! 573:
! 574: /*
! 575: * If few bytes left, finish slow.
! 576: */
! 577: cmp r2, #0x08
! 578: blt .Lkcleanup
! 579:
! 580: /*
! 581: * If source is not aligned, finish slow.
! 582: */
! 583: ands r3, r0, #0x03
! 584: bne .Lkcleanup
! 585:
! 586: cmp r2, #0x60 /* Must be > 0x5f for unrolled cacheline */
! 587: blt .Lkcleanup8
! 588:
! 589: /*
! 590: * Align source & destination to cacheline boundary.
! 591: */
! 592: and r6, r1, #0x1f
! 593: ldr pc, [pc, r6]
! 594: b .Lkcaligned
! 595: .word .Lkcaligned
! 596: .word .Lkcal28
! 597: .word .Lkcal24
! 598: .word .Lkcal20
! 599: .word .Lkcal16
! 600: .word .Lkcal12
! 601: .word .Lkcal8
! 602: .word .Lkcal4
! 603: .Lkcal28:ldr r6, [r0], #4
! 604: sub r2, r2, #4
! 605: str r6, [r1], #4
! 606: .Lkcal24:ldr r7, [r0], #4
! 607: sub r2, r2, #4
! 608: str r7, [r1], #4
! 609: .Lkcal20:ldr r6, [r0], #4
! 610: sub r2, r2, #4
! 611: str r6, [r1], #4
! 612: .Lkcal16:ldr r7, [r0], #4
! 613: sub r2, r2, #4
! 614: str r7, [r1], #4
! 615: .Lkcal12:ldr r6, [r0], #4
! 616: sub r2, r2, #4
! 617: str r6, [r1], #4
! 618: .Lkcal8:ldr r7, [r0], #4
! 619: sub r2, r2, #4
! 620: str r7, [r1], #4
! 621: .Lkcal4:ldr r6, [r0], #4
! 622: sub r2, r2, #4
! 623: str r6, [r1], #4
! 624:
! 625: /*
! 626: * We start with > 0x40 bytes to copy (>= 0x60 got us into this
! 627: * part of the code, and we may have knocked that down by as much
! 628: * as 0x1c getting aligned).
! 629: *
! 630: * This loop basically works out to:
! 631: * do {
! 632: * prefetch-next-cacheline(s)
! 633: * bytes -= 0x20;
! 634: * copy cacheline
! 635: * } while (bytes >= 0x40);
! 636: * bytes -= 0x20;
! 637: * copy cacheline
! 638: */
! 639: .Lkcaligned:
! 640: PREFETCH(r0, 32)
! 641: PREFETCH(r1, 32)
! 642:
! 643: sub r2, r2, #0x20
! 644:
! 645: /* Copy a cacheline */
! 646: ldmia r0!, {r6-r11}
! 647: stmia r1!, {r6, r7}
! 648: ldmia r0!, {r6, r7}
! 649: stmia r1!, {r8-r11}
! 650: stmia r1!, {r6, r7}
! 651:
! 652: cmp r2, #0x40
! 653: bge .Lkcaligned
! 654:
! 655: sub r2, r2, #0x20
! 656:
! 657: /* Copy a cacheline */
! 658: ldmia r0!, {r6-r11}
! 659: stmia r1!, {r6-r7}
! 660: ldmia r0!, {r6-r7}
! 661: stmia r1!, {r8-r11}
! 662: stmia r1!, {r6-r7}
! 663:
! 664: cmp r2, #0x08
! 665: blt .Lkprecleanup
! 666:
! 667: .Lkcleanup8:
! 668: ldmia r0!, {r8-r9}
! 669: sub r2, r2, #8
! 670: stmia r1!, {r8-r9}
! 671: cmp r2, #8
! 672: bge .Lkcleanup8
! 673:
! 674: .Lkprecleanup:
! 675: /*
! 676: * If we're done, bail.
! 677: */
! 678: cmp r2, #0
! 679: beq .Lkout
! 680:
! 681: .Lkcleanup:
! 682: and r6, r2, #0x3
! 683: ldr pc, [pc, r6, lsl #2]
! 684: b .Lkcend
! 685: .word .Lkc4
! 686: .word .Lkc1
! 687: .word .Lkc2
! 688: .word .Lkc3
! 689: .Lkc4: ldrb r6, [r0], #1
! 690: sub r2, r2, #1
! 691: strb r6, [r1], #1
! 692: .Lkc3: ldrb r7, [r0], #1
! 693: sub r2, r2, #1
! 694: strb r7, [r1], #1
! 695: .Lkc2: ldrb r6, [r0], #1
! 696: sub r2, r2, #1
! 697: strb r6, [r1], #1
! 698: .Lkc1: ldrb r7, [r0], #1
! 699: subs r2, r2, #1
! 700: strb r7, [r1], #1
! 701: .Lkcend:
! 702: bne .Lkcleanup
! 703:
! 704: .Lkout:
! 705: mov r0, #0
! 706:
! 707: str r5, [r4, #PCB_ONFAULT]
! 708: RESTORE_REGS
! 709:
! 710: mov pc, lr
! 711: #endif /* !__XSCALE__ */
! 712:
! 713: #ifdef __PROG32
! 714: /*
! 715: * int badaddr_read_1(const uint8_t *src, uint8_t *dest)
! 716: *
! 717: * Copies a single 8-bit value from src to dest, returning 0 on success,
! 718: * else EFAULT if a page fault occurred.
! 719: */
! 720: ENTRY(badaddr_read_1)
! 721: #ifdef MULTIPROCESSOR
! 722: /* XXX Probably not appropriate for non-Hydra SMPs */
! 723: stmfd sp!, {r0-r1, r14}
! 724: bl _C_LABEL(cpu_number)
! 725: ldr r2, .Lcpu_info
! 726: ldr r2, [r2, r0, lsl #2]
! 727: ldr r2, [r2, #CI_CURPCB]
! 728: ldmfd sp!, {r0-r1, r14}
! 729: #else
! 730: ldr r2, .Lcurpcb
! 731: ldr r2, [r2]
! 732: #endif
! 733: ldr ip, [r2, #PCB_ONFAULT]
! 734: adr r3, 1f
! 735: str r3, [r2, #PCB_ONFAULT]
! 736: nop
! 737: nop
! 738: nop
! 739: ldrb r3, [r0]
! 740: nop
! 741: nop
! 742: nop
! 743: strb r3, [r1]
! 744: mov r0, #0 /* No fault */
! 745: 1: str ip, [r2, #PCB_ONFAULT]
! 746: mov pc, lr
! 747:
! 748: /*
! 749: * int badaddr_read_2(const uint16_t *src, uint16_t *dest)
! 750: *
! 751: * Copies a single 16-bit value from src to dest, returning 0 on success,
! 752: * else EFAULT if a page fault occurred.
! 753: */
! 754: ENTRY(badaddr_read_2)
! 755: #ifdef MULTIPROCESSOR
! 756: /* XXX Probably not appropriate for non-Hydra SMPs */
! 757: stmfd sp!, {r0-r1, r14}
! 758: bl _C_LABEL(cpu_number)
! 759: ldr r2, .Lcpu_info
! 760: ldr r2, [r2, r0, lsl #2]
! 761: ldr r2, [r2, #CI_CURPCB]
! 762: ldmfd sp!, {r0-r1, r14}
! 763: #else
! 764: ldr r2, .Lcurpcb
! 765: ldr r2, [r2]
! 766: #endif
! 767: ldr ip, [r2, #PCB_ONFAULT]
! 768: adr r3, 1f
! 769: str r3, [r2, #PCB_ONFAULT]
! 770: nop
! 771: nop
! 772: nop
! 773: ldrh r3, [r0]
! 774: nop
! 775: nop
! 776: nop
! 777: strh r3, [r1]
! 778: mov r0, #0 /* No fault */
! 779: 1: str ip, [r2, #PCB_ONFAULT]
! 780: mov pc, lr
! 781:
! 782: /*
! 783: * int badaddr_read_4(const uint32_t *src, uint32_t *dest)
! 784: *
! 785: * Copies a single 32-bit value from src to dest, returning 0 on success,
! 786: * else EFAULT if a page fault occurred.
! 787: */
! 788: ENTRY(badaddr_read_4)
! 789: #ifdef MULTIPROCESSOR
! 790: /* XXX Probably not appropriate for non-Hydra SMPs */
! 791: stmfd sp!, {r0-r1, r14}
! 792: bl _C_LABEL(cpu_number)
! 793: ldr r2, .Lcpu_info
! 794: ldr r2, [r2, r0, lsl #2]
! 795: ldr r2, [r2, #CI_CURPCB]
! 796: ldmfd sp!, {r0-r1, r14}
! 797: #else
! 798: ldr r2, .Lcurpcb
! 799: ldr r2, [r2]
! 800: #endif
! 801: ldr ip, [r2, #PCB_ONFAULT]
! 802: adr r3, 1f
! 803: str r3, [r2, #PCB_ONFAULT]
! 804: nop
! 805: nop
! 806: nop
! 807: ldr r3, [r0]
! 808: nop
! 809: nop
! 810: nop
! 811: str r3, [r1]
! 812: mov r0, #0 /* No fault */
! 813: 1: str ip, [r2, #PCB_ONFAULT]
! 814: mov pc, lr
! 815: #endif /* __PROG32 */
CVSweb