1129198Scognet/* $NetBSD: bcopyinout_xscale.S,v 1.3 2003/12/15 09:27:18 scw Exp $ */ 2129198Scognet 3139735Simp/*- 4129198Scognet * Copyright 2003 Wasabi Systems, Inc. 5129198Scognet * All rights reserved. 6129198Scognet * 7129198Scognet * Written by Steve C. Woodford for Wasabi Systems, Inc. 8129198Scognet * 9129198Scognet * Redistribution and use in source and binary forms, with or without 10129198Scognet * modification, are permitted provided that the following conditions 11129198Scognet * are met: 12129198Scognet * 1. Redistributions of source code must retain the above copyright 13129198Scognet * notice, this list of conditions and the following disclaimer. 14129198Scognet * 2. Redistributions in binary form must reproduce the above copyright 15129198Scognet * notice, this list of conditions and the following disclaimer in the 16129198Scognet * documentation and/or other materials provided with the distribution. 17129198Scognet * 3. All advertising materials mentioning features or use of this software 18129198Scognet * must display the following acknowledgement: 19129198Scognet * This product includes software developed for the NetBSD Project by 20129198Scognet * Wasabi Systems, Inc. 21129198Scognet * 4. The name of Wasabi Systems, Inc. may not be used to endorse 22129198Scognet * or promote products derived from this software without specific prior 23129198Scognet * written permission. 24129198Scognet * 25129198Scognet * THIS SOFTWARE IS PROVIDED BY WASABI SYSTEMS, INC. ``AS IS'' AND 26129198Scognet * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 27129198Scognet * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 28129198Scognet * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL WASABI SYSTEMS, INC 29129198Scognet * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 30129198Scognet * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 31129198Scognet * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 32129198Scognet * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 33129198Scognet * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 34129198Scognet * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 35129198Scognet * POSSIBILITY OF SUCH DAMAGE. 36129198Scognet */ 37129198Scognet 38129198Scognet#include <machine/asm.h> 39129198Scognet__FBSDID("$FreeBSD$"); 40129198Scognet 41129198Scognet .text 42129198Scognet .align 0 43129198Scognet 44239268Sgonzo#ifdef _ARM_ARCH_6 45239268Sgonzo#define GET_PCB(tmp) \ 46239268Sgonzo mrc p15, 0, tmp, c13, c0, 4; \ 47266159Sian add tmp, tmp, #(TD_PCB) 48129198Scognet#else 49129198Scognet.Lcurpcb: 50129198Scognet .word _C_LABEL(__pcpu) + PC_CURPCB 51239268Sgonzo#define GET_PCB(tmp) \ 52239268Sgonzo ldr tmp, .Lcurpcb 53129198Scognet#endif 54129198Scognet 55129198Scognet/* 56129198Scognet * r0 = user space address 57129198Scognet * r1 = kernel space address 58129198Scognet * r2 = length 59129198Scognet * 60129198Scognet * Copies bytes from user space to kernel space 61129198Scognet */ 62129198ScognetENTRY(copyin) 63129198Scognet cmp r2, #0x00 64129198Scognet movle r0, #0x00 65129198Scognet movle pc, lr /* Bail early if length is <= 0 */ 66129198Scognet 67150864Scognet ldr r3, .L_arm_memcpy 68150864Scognet ldr r3, [r3] 69150864Scognet cmp r3, #0 70150864Scognet beq .Lnormal 71150864Scognet ldr r3, .L_min_memcpy_size 72150864Scognet ldr r3, [r3] 73150864Scognet cmp r2, r3 74150864Scognet blt .Lnormal 75150864Scognet stmfd sp!, {r0-r2, r4, lr} 76150864Scognet mov r3, r0 77150864Scognet mov r0, r1 78150864Scognet mov r1, r3 79150864Scognet mov r3, #2 /* SRC_IS_USER */ 80150864Scognet ldr r4, .L_arm_memcpy 81150864Scognet mov lr, pc 82150864Scognet ldr pc, [r4] 83150864Scognet cmp r0, #0 84150864Scognet ldmfd sp!, {r0-r2, r4, lr} 85150864Scognet moveq r0, #0 86150864Scognet RETeq 87150864Scognet 88150864Scognet.Lnormal: 89129198Scognet stmfd sp!, {r10-r11, lr} 90129198Scognet 91239268Sgonzo GET_PCB(r10) 92129198Scognet ldr r10, [r10] 93129198Scognet 94129198Scognet mov r3, #0x00 95129198Scognet adr ip, .Lcopyin_fault 96129198Scognet ldr r11, [r10, #PCB_ONFAULT] 97129198Scognet str ip, [r10, #PCB_ONFAULT] 98129198Scognet bl .Lcopyin_guts 99129198Scognet str r11, [r10, #PCB_ONFAULT] 100129198Scognet mov r0, #0x00 101129198Scognet ldmfd sp!, {r10-r11, pc} 102129198Scognet 103129198Scognet.Lcopyin_fault: 104239033Sandrew ldr r0, =EFAULT 105129198Scognet str r11, [r10, #PCB_ONFAULT] 106129198Scognet cmp r3, #0x00 107129198Scognet ldmgtfd sp!, {r4-r7} /* r3 > 0 Restore r4-r7 */ 108129198Scognet ldmltfd sp!, {r4-r9} /* r3 < 0 Restore r4-r9 */ 109129198Scognet ldmfd sp!, {r10-r11, pc} 110129198Scognet 111129198Scognet.Lcopyin_guts: 112129198Scognet pld [r0] 113129198Scognet /* Word-align the destination buffer */ 114129198Scognet ands ip, r1, #0x03 /* Already word aligned? */ 115129198Scognet beq .Lcopyin_wordaligned /* Yup */ 116129198Scognet rsb ip, ip, #0x04 117129198Scognet cmp r2, ip /* Enough bytes left to align it? */ 118129198Scognet blt .Lcopyin_l4_2 /* Nope. Just copy bytewise */ 119129198Scognet sub r2, r2, ip 120129198Scognet rsbs ip, ip, #0x03 121129198Scognet addne pc, pc, ip, lsl #3 122129198Scognet nop 123129198Scognet ldrbt ip, [r0], #0x01 124129198Scognet strb ip, [r1], #0x01 125129198Scognet ldrbt ip, [r0], #0x01 126129198Scognet strb ip, [r1], #0x01 127129198Scognet ldrbt ip, [r0], #0x01 128129198Scognet strb ip, [r1], #0x01 129129198Scognet cmp r2, #0x00 /* All done? */ 130137463Scognet RETeq 131129198Scognet 132129198Scognet /* Destination buffer is now word aligned */ 133129198Scognet.Lcopyin_wordaligned: 134129198Scognet ands ip, r0, #0x03 /* Is src also word-aligned? */ 135129198Scognet bne .Lcopyin_bad_align /* Nope. Things just got bad */ 136129198Scognet cmp r2, #0x08 /* Less than 8 bytes remaining? */ 137129198Scognet blt .Lcopyin_w_less_than8 138129198Scognet 139129198Scognet /* Quad-align the destination buffer */ 140129198Scognet tst r1, #0x07 /* Already quad aligned? */ 141129198Scognet ldrnet ip, [r0], #0x04 142153273Scognet strne ip, [r1], #0x04 143153273Scognet subne r2, r2, #0x04 144129198Scognet stmfd sp!, {r4-r9} /* Free up some registers */ 145129198Scognet mov r3, #-1 /* Signal restore r4-r9 */ 146129198Scognet 147129198Scognet /* Destination buffer quad aligned, source is word aligned */ 148129198Scognet subs r2, r2, #0x80 149129198Scognet blt .Lcopyin_w_lessthan128 150129198Scognet 151129198Scognet /* Copy 128 bytes at a time */ 152129198Scognet.Lcopyin_w_loop128: 153129198Scognet ldrt r4, [r0], #0x04 /* LD:00-03 */ 154129198Scognet ldrt r5, [r0], #0x04 /* LD:04-07 */ 155129198Scognet pld [r0, #0x18] /* Prefetch 0x20 */ 156129198Scognet ldrt r6, [r0], #0x04 /* LD:08-0b */ 157129198Scognet ldrt r7, [r0], #0x04 /* LD:0c-0f */ 158129198Scognet ldrt r8, [r0], #0x04 /* LD:10-13 */ 159129198Scognet ldrt r9, [r0], #0x04 /* LD:14-17 */ 160129198Scognet strd r4, [r1], #0x08 /* ST:00-07 */ 161129198Scognet ldrt r4, [r0], #0x04 /* LD:18-1b */ 162129198Scognet ldrt r5, [r0], #0x04 /* LD:1c-1f */ 163129198Scognet strd r6, [r1], #0x08 /* ST:08-0f */ 164129198Scognet ldrt r6, [r0], #0x04 /* LD:20-23 */ 165129198Scognet ldrt r7, [r0], #0x04 /* LD:24-27 */ 166129198Scognet pld [r0, #0x18] /* Prefetch 0x40 */ 167129198Scognet strd r8, [r1], #0x08 /* ST:10-17 */ 168129198Scognet ldrt r8, [r0], #0x04 /* LD:28-2b */ 169129198Scognet ldrt r9, [r0], #0x04 /* LD:2c-2f */ 170129198Scognet strd r4, [r1], #0x08 /* ST:18-1f */ 171129198Scognet ldrt r4, [r0], #0x04 /* LD:30-33 */ 172129198Scognet ldrt r5, [r0], #0x04 /* LD:34-37 */ 173129198Scognet strd r6, [r1], #0x08 /* ST:20-27 */ 174129198Scognet ldrt r6, [r0], #0x04 /* LD:38-3b */ 175129198Scognet ldrt r7, [r0], #0x04 /* LD:3c-3f */ 176129198Scognet strd r8, [r1], #0x08 /* ST:28-2f */ 177129198Scognet ldrt r8, [r0], #0x04 /* LD:40-43 */ 178129198Scognet ldrt r9, [r0], #0x04 /* LD:44-47 */ 179129198Scognet pld [r0, #0x18] /* Prefetch 0x60 */ 180129198Scognet strd r4, [r1], #0x08 /* ST:30-37 */ 181129198Scognet ldrt r4, [r0], #0x04 /* LD:48-4b */ 182129198Scognet ldrt r5, [r0], #0x04 /* LD:4c-4f */ 183129198Scognet strd r6, [r1], #0x08 /* ST:38-3f */ 184129198Scognet ldrt r6, [r0], #0x04 /* LD:50-53 */ 185129198Scognet ldrt r7, [r0], #0x04 /* LD:54-57 */ 186129198Scognet strd r8, [r1], #0x08 /* ST:40-47 */ 187129198Scognet ldrt r8, [r0], #0x04 /* LD:58-5b */ 188129198Scognet ldrt r9, [r0], #0x04 /* LD:5c-5f */ 189129198Scognet strd r4, [r1], #0x08 /* ST:48-4f */ 190129198Scognet ldrt r4, [r0], #0x04 /* LD:60-63 */ 191129198Scognet ldrt r5, [r0], #0x04 /* LD:64-67 */ 192129198Scognet pld [r0, #0x18] /* Prefetch 0x80 */ 193129198Scognet strd r6, [r1], #0x08 /* ST:50-57 */ 194129198Scognet ldrt r6, [r0], #0x04 /* LD:68-6b */ 195129198Scognet ldrt r7, [r0], #0x04 /* LD:6c-6f */ 196129198Scognet strd r8, [r1], #0x08 /* ST:58-5f */ 197129198Scognet ldrt r8, [r0], #0x04 /* LD:70-73 */ 198129198Scognet ldrt r9, [r0], #0x04 /* LD:74-77 */ 199129198Scognet strd r4, [r1], #0x08 /* ST:60-67 */ 200129198Scognet ldrt r4, [r0], #0x04 /* LD:78-7b */ 201129198Scognet ldrt r5, [r0], #0x04 /* LD:7c-7f */ 202129198Scognet strd r6, [r1], #0x08 /* ST:68-6f */ 203129198Scognet strd r8, [r1], #0x08 /* ST:70-77 */ 204129198Scognet subs r2, r2, #0x80 205129198Scognet strd r4, [r1], #0x08 /* ST:78-7f */ 206129198Scognet bge .Lcopyin_w_loop128 207129198Scognet 208129198Scognet.Lcopyin_w_lessthan128: 209129198Scognet adds r2, r2, #0x80 /* Adjust for extra sub */ 210129198Scognet ldmeqfd sp!, {r4-r9} 211137463Scognet RETeq 212129198Scognet subs r2, r2, #0x20 213129198Scognet blt .Lcopyin_w_lessthan32 214129198Scognet 215129198Scognet /* Copy 32 bytes at a time */ 216129198Scognet.Lcopyin_w_loop32: 217129198Scognet ldrt r4, [r0], #0x04 218129198Scognet ldrt r5, [r0], #0x04 219129198Scognet pld [r0, #0x18] 220129198Scognet ldrt r6, [r0], #0x04 221129198Scognet ldrt r7, [r0], #0x04 222129198Scognet ldrt r8, [r0], #0x04 223129198Scognet ldrt r9, [r0], #0x04 224129198Scognet strd r4, [r1], #0x08 225129198Scognet ldrt r4, [r0], #0x04 226129198Scognet ldrt r5, [r0], #0x04 227129198Scognet strd r6, [r1], #0x08 228129198Scognet strd r8, [r1], #0x08 229129198Scognet subs r2, r2, #0x20 230129198Scognet strd r4, [r1], #0x08 231129198Scognet bge .Lcopyin_w_loop32 232129198Scognet 233129198Scognet.Lcopyin_w_lessthan32: 234129198Scognet adds r2, r2, #0x20 /* Adjust for extra sub */ 235129198Scognet ldmeqfd sp!, {r4-r9} 236137463Scognet RETeq /* Return now if done */ 237129198Scognet 238129198Scognet and r4, r2, #0x18 239129198Scognet rsb r5, r4, #0x18 240129198Scognet subs r2, r2, r4 241129198Scognet add pc, pc, r5, lsl #1 242129198Scognet nop 243129198Scognet 244129198Scognet /* At least 24 bytes remaining */ 245129198Scognet ldrt r4, [r0], #0x04 246129198Scognet ldrt r5, [r0], #0x04 247129198Scognet nop 248129198Scognet strd r4, [r1], #0x08 249129198Scognet 250129198Scognet /* At least 16 bytes remaining */ 251129198Scognet ldrt r4, [r0], #0x04 252129198Scognet ldrt r5, [r0], #0x04 253129198Scognet nop 254129198Scognet strd r4, [r1], #0x08 255129198Scognet 256129198Scognet /* At least 8 bytes remaining */ 257129198Scognet ldrt r4, [r0], #0x04 258129198Scognet ldrt r5, [r0], #0x04 259129198Scognet nop 260129198Scognet strd r4, [r1], #0x08 261129198Scognet 262129198Scognet /* Less than 8 bytes remaining */ 263129198Scognet ldmfd sp!, {r4-r9} 264137463Scognet RETeq /* Return now if done */ 265129198Scognet mov r3, #0x00 266129198Scognet 267129198Scognet.Lcopyin_w_less_than8: 268129198Scognet subs r2, r2, #0x04 269129198Scognet ldrget ip, [r0], #0x04 270129198Scognet strge ip, [r1], #0x04 271137463Scognet RETeq /* Return now if done */ 272129198Scognet addlt r2, r2, #0x04 273129198Scognet ldrbt ip, [r0], #0x01 274129198Scognet cmp r2, #0x02 275129198Scognet ldrgebt r2, [r0], #0x01 276129198Scognet strb ip, [r1], #0x01 277129198Scognet ldrgtbt ip, [r0] 278129198Scognet strgeb r2, [r1], #0x01 279129198Scognet strgtb ip, [r1] 280137463Scognet RET 281129198Scognet 282129198Scognet/* 283129198Scognet * At this point, it has not been possible to word align both buffers. 284129198Scognet * The destination buffer (r1) is word aligned, but the source buffer 285129198Scognet * (r0) is not. 286129198Scognet */ 287129198Scognet.Lcopyin_bad_align: 288129198Scognet stmfd sp!, {r4-r7} 289129198Scognet mov r3, #0x01 290129198Scognet bic r0, r0, #0x03 291129198Scognet cmp ip, #2 292129198Scognet ldrt ip, [r0], #0x04 293129198Scognet bgt .Lcopyin_bad3 294129198Scognet beq .Lcopyin_bad2 295129198Scognet b .Lcopyin_bad1 296129198Scognet 297129198Scognet.Lcopyin_bad1_loop16: 298129198Scognet#ifdef __ARMEB__ 299129198Scognet mov r4, ip, lsl #8 300129198Scognet#else 301129198Scognet mov r4, ip, lsr #8 302129198Scognet#endif 303129198Scognet ldrt r5, [r0], #0x04 304129198Scognet pld [r0, #0x018] 305129198Scognet ldrt r6, [r0], #0x04 306129198Scognet ldrt r7, [r0], #0x04 307129198Scognet ldrt ip, [r0], #0x04 308129198Scognet#ifdef __ARMEB__ 309129198Scognet orr r4, r4, r5, lsr #24 310129198Scognet mov r5, r5, lsl #8 311129198Scognet orr r5, r5, r6, lsr #24 312129198Scognet mov r6, r6, lsl #8 313129198Scognet orr r6, r6, r7, lsr #24 314129198Scognet mov r7, r7, lsl #8 315129198Scognet orr r7, r7, ip, lsr #24 316129198Scognet#else 317129198Scognet orr r4, r4, r5, lsl #24 318129198Scognet mov r5, r5, lsr #8 319129198Scognet orr r5, r5, r6, lsl #24 320129198Scognet mov r6, r6, lsr #8 321129198Scognet orr r6, r6, r7, lsl #24 322129198Scognet mov r7, r7, lsr #8 323129198Scognet orr r7, r7, ip, lsl #24 324129198Scognet#endif 325129198Scognet str r4, [r1], #0x04 326129198Scognet str r5, [r1], #0x04 327129198Scognet str r6, [r1], #0x04 328129198Scognet str r7, [r1], #0x04 329129198Scognet.Lcopyin_bad1: 330236991Simp subs r2, r2, #0x10 331129198Scognet bge .Lcopyin_bad1_loop16 332129198Scognet 333236991Simp adds r2, r2, #0x10 334129198Scognet ldmeqfd sp!, {r4-r7} 335137463Scognet RETeq /* Return now if done */ 336129198Scognet subs r2, r2, #0x04 337129198Scognet sublt r0, r0, #0x03 338129198Scognet blt .Lcopyin_l4 339129198Scognet 340129198Scognet.Lcopyin_bad1_loop4: 341129198Scognet#ifdef __ARMEB__ 342129198Scognet mov r4, ip, lsl #8 343129198Scognet#else 344129198Scognet mov r4, ip, lsr #8 345129198Scognet#endif 346129198Scognet ldrt ip, [r0], #0x04 347129198Scognet subs r2, r2, #0x04 348129198Scognet#ifdef __ARMEB__ 349129198Scognet orr r4, r4, ip, lsr #24 350129198Scognet#else 351129198Scognet orr r4, r4, ip, lsl #24 352129198Scognet#endif 353129198Scognet str r4, [r1], #0x04 354129198Scognet bge .Lcopyin_bad1_loop4 355129198Scognet sub r0, r0, #0x03 356129198Scognet b .Lcopyin_l4 357129198Scognet 358129198Scognet.Lcopyin_bad2_loop16: 359129198Scognet#ifdef __ARMEB__ 360129198Scognet mov r4, ip, lsl #16 361129198Scognet#else 362129198Scognet mov r4, ip, lsr #16 363129198Scognet#endif 364129198Scognet ldrt r5, [r0], #0x04 365129198Scognet pld [r0, #0x018] 366129198Scognet ldrt r6, [r0], #0x04 367129198Scognet ldrt r7, [r0], #0x04 368129198Scognet ldrt ip, [r0], #0x04 369129198Scognet#ifdef __ARMEB__ 370129198Scognet orr r4, r4, r5, lsr #16 371129198Scognet mov r5, r5, lsl #16 372129198Scognet orr r5, r5, r6, lsr #16 373129198Scognet mov r6, r6, lsl #16 374129198Scognet orr r6, r6, r7, lsr #16 375129198Scognet mov r7, r7, lsl #16 376129198Scognet orr r7, r7, ip, lsr #16 377129198Scognet#else 378129198Scognet orr r4, r4, r5, lsl #16 379129198Scognet mov r5, r5, lsr #16 380129198Scognet orr r5, r5, r6, lsl #16 381129198Scognet mov r6, r6, lsr #16 382129198Scognet orr r6, r6, r7, lsl #16 383129198Scognet mov r7, r7, lsr #16 384129198Scognet orr r7, r7, ip, lsl #16 385129198Scognet#endif 386129198Scognet str r4, [r1], #0x04 387129198Scognet str r5, [r1], #0x04 388129198Scognet str r6, [r1], #0x04 389129198Scognet str r7, [r1], #0x04 390129198Scognet.Lcopyin_bad2: 391236991Simp subs r2, r2, #0x10 392129198Scognet bge .Lcopyin_bad2_loop16 393129198Scognet 394236991Simp adds r2, r2, #0x10 395129198Scognet ldmeqfd sp!, {r4-r7} 396137463Scognet RETeq /* Return now if done */ 397129198Scognet subs r2, r2, #0x04 398129198Scognet sublt r0, r0, #0x02 399129198Scognet blt .Lcopyin_l4 400129198Scognet 401129198Scognet.Lcopyin_bad2_loop4: 402129198Scognet#ifdef __ARMEB__ 403129198Scognet mov r4, ip, lsl #16 404129198Scognet#else 405129198Scognet mov r4, ip, lsr #16 406129198Scognet#endif 407129198Scognet ldrt ip, [r0], #0x04 408129198Scognet subs r2, r2, #0x04 409129198Scognet#ifdef __ARMEB__ 410129198Scognet orr r4, r4, ip, lsr #16 411129198Scognet#else 412129198Scognet orr r4, r4, ip, lsl #16 413129198Scognet#endif 414129198Scognet str r4, [r1], #0x04 415129198Scognet bge .Lcopyin_bad2_loop4 416129198Scognet sub r0, r0, #0x02 417129198Scognet b .Lcopyin_l4 418129198Scognet 419129198Scognet.Lcopyin_bad3_loop16: 420129198Scognet#ifdef __ARMEB__ 421129198Scognet mov r4, ip, lsl #24 422129198Scognet#else 423129198Scognet mov r4, ip, lsr #24 424129198Scognet#endif 425129198Scognet ldrt r5, [r0], #0x04 426129198Scognet pld [r0, #0x018] 427129198Scognet ldrt r6, [r0], #0x04 428129198Scognet ldrt r7, [r0], #0x04 429129198Scognet ldrt ip, [r0], #0x04 430129198Scognet#ifdef __ARMEB__ 431129198Scognet orr r4, r4, r5, lsr #8 432129198Scognet mov r5, r5, lsl #24 433129198Scognet orr r5, r5, r6, lsr #8 434129198Scognet mov r6, r6, lsl #24 435129198Scognet orr r6, r6, r7, lsr #8 436129198Scognet mov r7, r7, lsl #24 437129198Scognet orr r7, r7, ip, lsr #8 438129198Scognet#else 439129198Scognet orr r4, r4, r5, lsl #8 440129198Scognet mov r5, r5, lsr #24 441129198Scognet orr r5, r5, r6, lsl #8 442129198Scognet mov r6, r6, lsr #24 443129198Scognet orr r6, r6, r7, lsl #8 444129198Scognet mov r7, r7, lsr #24 445129198Scognet orr r7, r7, ip, lsl #8 446129198Scognet#endif 447129198Scognet str r4, [r1], #0x04 448129198Scognet str r5, [r1], #0x04 449129198Scognet str r6, [r1], #0x04 450129198Scognet str r7, [r1], #0x04 451129198Scognet.Lcopyin_bad3: 452236991Simp subs r2, r2, #0x10 453129198Scognet bge .Lcopyin_bad3_loop16 454129198Scognet 455236991Simp adds r2, r2, #0x10 456129198Scognet ldmeqfd sp!, {r4-r7} 457137463Scognet RETeq /* Return now if done */ 458129198Scognet subs r2, r2, #0x04 459129198Scognet sublt r0, r0, #0x01 460129198Scognet blt .Lcopyin_l4 461129198Scognet 462129198Scognet.Lcopyin_bad3_loop4: 463129198Scognet#ifdef __ARMEB__ 464129198Scognet mov r4, ip, lsl #24 465129198Scognet#else 466129198Scognet mov r4, ip, lsr #24 467129198Scognet#endif 468129198Scognet ldrt ip, [r0], #0x04 469129198Scognet subs r2, r2, #0x04 470129198Scognet#ifdef __ARMEB__ 471129198Scognet orr r4, r4, ip, lsr #8 472129198Scognet#else 473129198Scognet orr r4, r4, ip, lsl #8 474129198Scognet#endif 475129198Scognet str r4, [r1], #0x04 476129198Scognet bge .Lcopyin_bad3_loop4 477129198Scognet sub r0, r0, #0x01 478129198Scognet 479129198Scognet.Lcopyin_l4: 480129198Scognet ldmfd sp!, {r4-r7} 481129198Scognet mov r3, #0x00 482129198Scognet adds r2, r2, #0x04 483137463Scognet RETeq 484129198Scognet.Lcopyin_l4_2: 485129198Scognet rsbs r2, r2, #0x03 486129198Scognet addne pc, pc, r2, lsl #3 487129198Scognet nop 488129198Scognet ldrbt ip, [r0], #0x01 489129198Scognet strb ip, [r1], #0x01 490129198Scognet ldrbt ip, [r0], #0x01 491129198Scognet strb ip, [r1], #0x01 492129198Scognet ldrbt ip, [r0] 493129198Scognet strb ip, [r1] 494137463Scognet RET 495248361SandrewEND(copyin) 496129198Scognet 497129198Scognet/* 498129198Scognet * r0 = kernel space address 499129198Scognet * r1 = user space address 500129198Scognet * r2 = length 501129198Scognet * 502129198Scognet * Copies bytes from kernel space to user space 503129198Scognet */ 504129198ScognetENTRY(copyout) 505129198Scognet cmp r2, #0x00 506129198Scognet movle r0, #0x00 507129198Scognet movle pc, lr /* Bail early if length is <= 0 */ 508129198Scognet 509150864Scognet ldr r3, .L_arm_memcpy 510150864Scognet ldr r3, [r3] 511150864Scognet cmp r3, #0 512150864Scognet beq .Lnormale 513150864Scognet ldr r3, .L_min_memcpy_size 514150864Scognet ldr r3, [r3] 515150864Scognet cmp r2, r3 516150864Scognet blt .Lnormale 517150864Scognet stmfd sp!, {r0-r2, r4, lr} 518150864Scognet mov r3, r0 519150864Scognet mov r0, r1 520150864Scognet mov r1, r3 521150864Scognet mov r3, #1 /* DST_IS_USER */ 522150864Scognet ldr r4, .L_arm_memcpy 523150864Scognet mov lr, pc 524150864Scognet ldr pc, [r4] 525150864Scognet cmp r0, #0 526150864Scognet ldmfd sp!, {r0-r2, r4, lr} 527150864Scognet moveq r0, #0 528150864Scognet RETeq 529150864Scognet 530150864Scognet.Lnormale: 531129198Scognet stmfd sp!, {r10-r11, lr} 532129198Scognet 533239268Sgonzo GET_PCB(r10) 534129198Scognet ldr r10, [r10] 535129198Scognet 536129198Scognet mov r3, #0x00 537129198Scognet adr ip, .Lcopyout_fault 538129198Scognet ldr r11, [r10, #PCB_ONFAULT] 539129198Scognet str ip, [r10, #PCB_ONFAULT] 540129198Scognet bl .Lcopyout_guts 541129198Scognet str r11, [r10, #PCB_ONFAULT] 542129198Scognet mov r0, #0x00 543129198Scognet ldmfd sp!, {r10-r11, pc} 544129198Scognet 545129198Scognet.Lcopyout_fault: 546239033Sandrew ldr r0, =EFAULT 547129198Scognet str r11, [r10, #PCB_ONFAULT] 548129198Scognet cmp r3, #0x00 549129198Scognet ldmgtfd sp!, {r4-r7} /* r3 > 0 Restore r4-r7 */ 550129198Scognet ldmltfd sp!, {r4-r9} /* r3 < 0 Restore r4-r9 */ 551129198Scognet ldmfd sp!, {r10-r11, pc} 552129198Scognet 553129198Scognet.Lcopyout_guts: 554129198Scognet pld [r0] 555129198Scognet /* Word-align the destination buffer */ 556129198Scognet ands ip, r1, #0x03 /* Already word aligned? */ 557129198Scognet beq .Lcopyout_wordaligned /* Yup */ 558129198Scognet rsb ip, ip, #0x04 559129198Scognet cmp r2, ip /* Enough bytes left to align it? */ 560129198Scognet blt .Lcopyout_l4_2 /* Nope. Just copy bytewise */ 561129198Scognet sub r2, r2, ip 562129198Scognet rsbs ip, ip, #0x03 563129198Scognet addne pc, pc, ip, lsl #3 564129198Scognet nop 565129198Scognet ldrb ip, [r0], #0x01 566129198Scognet strbt ip, [r1], #0x01 567129198Scognet ldrb ip, [r0], #0x01 568129198Scognet strbt ip, [r1], #0x01 569129198Scognet ldrb ip, [r0], #0x01 570129198Scognet strbt ip, [r1], #0x01 571129198Scognet cmp r2, #0x00 /* All done? */ 572137463Scognet RETeq 573129198Scognet 574129198Scognet /* Destination buffer is now word aligned */ 575129198Scognet.Lcopyout_wordaligned: 576129198Scognet ands ip, r0, #0x03 /* Is src also word-aligned? */ 577129198Scognet bne .Lcopyout_bad_align /* Nope. Things just got bad */ 578129198Scognet cmp r2, #0x08 /* Less than 8 bytes remaining? */ 579129198Scognet blt .Lcopyout_w_less_than8 580129198Scognet 581129198Scognet /* Quad-align the destination buffer */ 582153273Scognet tst r0, #0x07 /* Already quad aligned? */ 583129198Scognet ldrne ip, [r0], #0x04 584153273Scognet subne r2, r2, #0x04 585153273Scognet strnet ip, [r1], #0x04 586153273Scognet 587129198Scognet stmfd sp!, {r4-r9} /* Free up some registers */ 588129198Scognet mov r3, #-1 /* Signal restore r4-r9 */ 589129198Scognet 590153273Scognet /* Destination buffer word aligned, source is quad aligned */ 591129198Scognet subs r2, r2, #0x80 592129198Scognet blt .Lcopyout_w_lessthan128 593129198Scognet 594129198Scognet /* Copy 128 bytes at a time */ 595129198Scognet.Lcopyout_w_loop128: 596153273Scognet ldrd r4, [r0], #0x08 /* LD:00-07 */ 597129198Scognet pld [r0, #0x18] /* Prefetch 0x20 */ 598153273Scognet ldrd r6, [r0], #0x08 /* LD:08-0f */ 599153273Scognet ldrd r8, [r0], #0x08 /* LD:10-17 */ 600129198Scognet strt r4, [r1], #0x04 /* ST:00-03 */ 601129198Scognet strt r5, [r1], #0x04 /* ST:04-07 */ 602153273Scognet ldrd r4, [r0], #0x08 /* LD:18-1f */ 603129198Scognet strt r6, [r1], #0x04 /* ST:08-0b */ 604129198Scognet strt r7, [r1], #0x04 /* ST:0c-0f */ 605153273Scognet ldrd r6, [r0], #0x08 /* LD:20-27 */ 606129198Scognet pld [r0, #0x18] /* Prefetch 0x40 */ 607129198Scognet strt r8, [r1], #0x04 /* ST:10-13 */ 608129198Scognet strt r9, [r1], #0x04 /* ST:14-17 */ 609153273Scognet ldrd r8, [r0], #0x08 /* LD:28-2f */ 610129198Scognet strt r4, [r1], #0x04 /* ST:18-1b */ 611129198Scognet strt r5, [r1], #0x04 /* ST:1c-1f */ 612153273Scognet ldrd r4, [r0], #0x08 /* LD:30-37 */ 613129198Scognet strt r6, [r1], #0x04 /* ST:20-23 */ 614129198Scognet strt r7, [r1], #0x04 /* ST:24-27 */ 615153273Scognet ldrd r6, [r0], #0x08 /* LD:38-3f */ 616129198Scognet strt r8, [r1], #0x04 /* ST:28-2b */ 617129198Scognet strt r9, [r1], #0x04 /* ST:2c-2f */ 618153273Scognet ldrd r8, [r0], #0x08 /* LD:40-47 */ 619129198Scognet pld [r0, #0x18] /* Prefetch 0x60 */ 620129198Scognet strt r4, [r1], #0x04 /* ST:30-33 */ 621129198Scognet strt r5, [r1], #0x04 /* ST:34-37 */ 622153273Scognet ldrd r4, [r0], #0x08 /* LD:48-4f */ 623129198Scognet strt r6, [r1], #0x04 /* ST:38-3b */ 624129198Scognet strt r7, [r1], #0x04 /* ST:3c-3f */ 625153273Scognet ldrd r6, [r0], #0x08 /* LD:50-57 */ 626129198Scognet strt r8, [r1], #0x04 /* ST:40-43 */ 627129198Scognet strt r9, [r1], #0x04 /* ST:44-47 */ 628153273Scognet ldrd r8, [r0], #0x08 /* LD:58-4f */ 629129198Scognet strt r4, [r1], #0x04 /* ST:48-4b */ 630129198Scognet strt r5, [r1], #0x04 /* ST:4c-4f */ 631153273Scognet ldrd r4, [r0], #0x08 /* LD:60-67 */ 632129198Scognet pld [r0, #0x18] /* Prefetch 0x80 */ 633129198Scognet strt r6, [r1], #0x04 /* ST:50-53 */ 634129198Scognet strt r7, [r1], #0x04 /* ST:54-57 */ 635153273Scognet ldrd r6, [r0], #0x08 /* LD:68-6f */ 636129198Scognet strt r8, [r1], #0x04 /* ST:58-5b */ 637129198Scognet strt r9, [r1], #0x04 /* ST:5c-5f */ 638153273Scognet ldrd r8, [r0], #0x08 /* LD:70-77 */ 639129198Scognet strt r4, [r1], #0x04 /* ST:60-63 */ 640129198Scognet strt r5, [r1], #0x04 /* ST:64-67 */ 641153273Scognet ldrd r4, [r0], #0x08 /* LD:78-7f */ 642129198Scognet strt r6, [r1], #0x04 /* ST:68-6b */ 643129198Scognet strt r7, [r1], #0x04 /* ST:6c-6f */ 644129198Scognet strt r8, [r1], #0x04 /* ST:70-73 */ 645129198Scognet strt r9, [r1], #0x04 /* ST:74-77 */ 646129198Scognet subs r2, r2, #0x80 647129198Scognet strt r4, [r1], #0x04 /* ST:78-7b */ 648129198Scognet strt r5, [r1], #0x04 /* ST:7c-7f */ 649129198Scognet bge .Lcopyout_w_loop128 650129198Scognet 651129198Scognet.Lcopyout_w_lessthan128: 652129198Scognet adds r2, r2, #0x80 /* Adjust for extra sub */ 653129198Scognet ldmeqfd sp!, {r4-r9} 654137463Scognet RETeq /* Return now if done */ 655129198Scognet subs r2, r2, #0x20 656129198Scognet blt .Lcopyout_w_lessthan32 657129198Scognet 658129198Scognet /* Copy 32 bytes at a time */ 659129198Scognet.Lcopyout_w_loop32: 660153273Scognet ldrd r4, [r0], #0x08 661129198Scognet pld [r0, #0x18] 662153273Scognet ldrd r6, [r0], #0x08 663153273Scognet ldrd r8, [r0], #0x08 664129198Scognet strt r4, [r1], #0x04 665129198Scognet strt r5, [r1], #0x04 666153273Scognet ldrd r4, [r0], #0x08 667129198Scognet strt r6, [r1], #0x04 668129198Scognet strt r7, [r1], #0x04 669129198Scognet strt r8, [r1], #0x04 670129198Scognet strt r9, [r1], #0x04 671129198Scognet subs r2, r2, #0x20 672129198Scognet strt r4, [r1], #0x04 673129198Scognet strt r5, [r1], #0x04 674129198Scognet bge .Lcopyout_w_loop32 675129198Scognet 676129198Scognet.Lcopyout_w_lessthan32: 677129198Scognet adds r2, r2, #0x20 /* Adjust for extra sub */ 678129198Scognet ldmeqfd sp!, {r4-r9} 679137463Scognet RETeq /* Return now if done */ 680129198Scognet 681129198Scognet and r4, r2, #0x18 682129198Scognet rsb r5, r4, #0x18 683129198Scognet subs r2, r2, r4 684129198Scognet add pc, pc, r5, lsl #1 685129198Scognet nop 686129198Scognet 687129198Scognet /* At least 24 bytes remaining */ 688153273Scognet ldrd r4, [r0], #0x08 689129198Scognet strt r4, [r1], #0x04 690129198Scognet strt r5, [r1], #0x04 691153273Scognet nop 692129198Scognet 693129198Scognet /* At least 16 bytes remaining */ 694153273Scognet ldrd r4, [r0], #0x08 695129198Scognet strt r4, [r1], #0x04 696129198Scognet strt r5, [r1], #0x04 697153273Scognet nop 698129198Scognet 699129198Scognet /* At least 8 bytes remaining */ 700153273Scognet ldrd r4, [r0], #0x08 701129198Scognet strt r4, [r1], #0x04 702129198Scognet strt r5, [r1], #0x04 703153273Scognet nop 704129198Scognet 705129198Scognet /* Less than 8 bytes remaining */ 706129198Scognet ldmfd sp!, {r4-r9} 707137463Scognet RETeq /* Return now if done */ 708129198Scognet mov r3, #0x00 709129198Scognet 710129198Scognet.Lcopyout_w_less_than8: 711129198Scognet subs r2, r2, #0x04 712129198Scognet ldrge ip, [r0], #0x04 713129198Scognet strget ip, [r1], #0x04 714137463Scognet RETeq /* Return now if done */ 715129198Scognet addlt r2, r2, #0x04 716129198Scognet ldrb ip, [r0], #0x01 717129198Scognet cmp r2, #0x02 718129198Scognet ldrgeb r2, [r0], #0x01 719129198Scognet strbt ip, [r1], #0x01 720129198Scognet ldrgtb ip, [r0] 721129198Scognet strgebt r2, [r1], #0x01 722129198Scognet strgtbt ip, [r1] 723137463Scognet RET 724129198Scognet 725129198Scognet/* 726129198Scognet * At this point, it has not been possible to word align both buffers. 727129198Scognet * The destination buffer (r1) is word aligned, but the source buffer 728129198Scognet * (r0) is not. 729129198Scognet */ 730129198Scognet.Lcopyout_bad_align: 731129198Scognet stmfd sp!, {r4-r7} 732129198Scognet mov r3, #0x01 733129198Scognet bic r0, r0, #0x03 734129198Scognet cmp ip, #2 735129198Scognet ldr ip, [r0], #0x04 736129198Scognet bgt .Lcopyout_bad3 737129198Scognet beq .Lcopyout_bad2 738129198Scognet b .Lcopyout_bad1 739129198Scognet 740129198Scognet.Lcopyout_bad1_loop16: 741129198Scognet#ifdef __ARMEB__ 742129198Scognet mov r4, ip, lsl #8 743129198Scognet#else 744129198Scognet mov r4, ip, lsr #8 745129198Scognet#endif 746129198Scognet ldr r5, [r0], #0x04 747129198Scognet pld [r0, #0x018] 748129198Scognet ldr r6, [r0], #0x04 749129198Scognet ldr r7, [r0], #0x04 750129198Scognet ldr ip, [r0], #0x04 751129198Scognet#ifdef __ARMEB__ 752129198Scognet orr r4, r4, r5, lsr #24 753129198Scognet mov r5, r5, lsl #8 754129198Scognet orr r5, r5, r6, lsr #24 755129198Scognet mov r6, r6, lsl #8 756129198Scognet orr r6, r6, r7, lsr #24 757129198Scognet mov r7, r7, lsl #8 758129198Scognet orr r7, r7, ip, lsr #24 759129198Scognet#else 760129198Scognet orr r4, r4, r5, lsl #24 761129198Scognet mov r5, r5, lsr #8 762129198Scognet orr r5, r5, r6, lsl #24 763129198Scognet mov r6, r6, lsr #8 764129198Scognet orr r6, r6, r7, lsl #24 765129198Scognet mov r7, r7, lsr #8 766129198Scognet orr r7, r7, ip, lsl #24 767129198Scognet#endif 768129198Scognet strt r4, [r1], #0x04 769129198Scognet strt r5, [r1], #0x04 770129198Scognet strt r6, [r1], #0x04 771129198Scognet strt r7, [r1], #0x04 772129198Scognet.Lcopyout_bad1: 773236991Simp subs r2, r2, #0x10 774129198Scognet bge .Lcopyout_bad1_loop16 775129198Scognet 776236991Simp adds r2, r2, #0x10 777129198Scognet ldmeqfd sp!, {r4-r7} 778137463Scognet RETeq /* Return now if done */ 779129198Scognet subs r2, r2, #0x04 780129198Scognet sublt r0, r0, #0x03 781129198Scognet blt .Lcopyout_l4 782129198Scognet 783129198Scognet.Lcopyout_bad1_loop4: 784129198Scognet#ifdef __ARMEB__ 785129198Scognet mov r4, ip, lsl #8 786129198Scognet#else 787129198Scognet mov r4, ip, lsr #8 788129198Scognet#endif 789129198Scognet ldr ip, [r0], #0x04 790129198Scognet subs r2, r2, #0x04 791129198Scognet#ifdef __ARMEB__ 792129198Scognet orr r4, r4, ip, lsr #24 793129198Scognet#else 794129198Scognet orr r4, r4, ip, lsl #24 795129198Scognet#endif 796129198Scognet strt r4, [r1], #0x04 797129198Scognet bge .Lcopyout_bad1_loop4 798129198Scognet sub r0, r0, #0x03 799129198Scognet b .Lcopyout_l4 800129198Scognet 801129198Scognet.Lcopyout_bad2_loop16: 802129198Scognet#ifdef __ARMEB__ 803129198Scognet mov r4, ip, lsl #16 804129198Scognet#else 805129198Scognet mov r4, ip, lsr #16 806129198Scognet#endif 807129198Scognet ldr r5, [r0], #0x04 808129198Scognet pld [r0, #0x018] 809129198Scognet ldr r6, [r0], #0x04 810129198Scognet ldr r7, [r0], #0x04 811129198Scognet ldr ip, [r0], #0x04 812129198Scognet#ifdef __ARMEB__ 813129198Scognet orr r4, r4, r5, lsr #16 814129198Scognet mov r5, r5, lsl #16 815129198Scognet orr r5, r5, r6, lsr #16 816129198Scognet mov r6, r6, lsl #16 817129198Scognet orr r6, r6, r7, lsr #16 818129198Scognet mov r7, r7, lsl #16 819129198Scognet orr r7, r7, ip, lsr #16 820129198Scognet#else 821129198Scognet orr r4, r4, r5, lsl #16 822129198Scognet mov r5, r5, lsr #16 823129198Scognet orr r5, r5, r6, lsl #16 824129198Scognet mov r6, r6, lsr #16 825129198Scognet orr r6, r6, r7, lsl #16 826129198Scognet mov r7, r7, lsr #16 827129198Scognet orr r7, r7, ip, lsl #16 828129198Scognet#endif 829129198Scognet strt r4, [r1], #0x04 830129198Scognet strt r5, [r1], #0x04 831129198Scognet strt r6, [r1], #0x04 832129198Scognet strt r7, [r1], #0x04 833129198Scognet.Lcopyout_bad2: 834236991Simp subs r2, r2, #0x10 835129198Scognet bge .Lcopyout_bad2_loop16 836129198Scognet 837236991Simp adds r2, r2, #0x10 838129198Scognet ldmeqfd sp!, {r4-r7} 839137463Scognet RETeq /* Return now if done */ 840129198Scognet subs r2, r2, #0x04 841129198Scognet sublt r0, r0, #0x02 842129198Scognet blt .Lcopyout_l4 843129198Scognet 844129198Scognet.Lcopyout_bad2_loop4: 845129198Scognet#ifdef __ARMEB__ 846129198Scognet mov r4, ip, lsl #16 847129198Scognet#else 848129198Scognet mov r4, ip, lsr #16 849129198Scognet#endif 850129198Scognet ldr ip, [r0], #0x04 851129198Scognet subs r2, r2, #0x04 852129198Scognet#ifdef __ARMEB__ 853129198Scognet orr r4, r4, ip, lsr #16 854129198Scognet#else 855129198Scognet orr r4, r4, ip, lsl #16 856129198Scognet#endif 857129198Scognet strt r4, [r1], #0x04 858129198Scognet bge .Lcopyout_bad2_loop4 859129198Scognet sub r0, r0, #0x02 860129198Scognet b .Lcopyout_l4 861129198Scognet 862129198Scognet.Lcopyout_bad3_loop16: 863129198Scognet#ifdef __ARMEB__ 864129198Scognet mov r4, ip, lsl #24 865129198Scognet#else 866129198Scognet mov r4, ip, lsr #24 867129198Scognet#endif 868129198Scognet ldr r5, [r0], #0x04 869129198Scognet pld [r0, #0x018] 870129198Scognet ldr r6, [r0], #0x04 871129198Scognet ldr r7, [r0], #0x04 872129198Scognet ldr ip, [r0], #0x04 873129198Scognet#ifdef __ARMEB__ 874129198Scognet orr r4, r4, r5, lsr #8 875129198Scognet mov r5, r5, lsl #24 876129198Scognet orr r5, r5, r6, lsr #8 877129198Scognet mov r6, r6, lsl #24 878129198Scognet orr r6, r6, r7, lsr #8 879129198Scognet mov r7, r7, lsl #24 880129198Scognet orr r7, r7, ip, lsr #8 881129198Scognet#else 882129198Scognet orr r4, r4, r5, lsl #8 883129198Scognet mov r5, r5, lsr #24 884129198Scognet orr r5, r5, r6, lsl #8 885129198Scognet mov r6, r6, lsr #24 886129198Scognet orr r6, r6, r7, lsl #8 887129198Scognet mov r7, r7, lsr #24 888129198Scognet orr r7, r7, ip, lsl #8 889129198Scognet#endif 890129198Scognet strt r4, [r1], #0x04 891129198Scognet strt r5, [r1], #0x04 892129198Scognet strt r6, [r1], #0x04 893129198Scognet strt r7, [r1], #0x04 894129198Scognet.Lcopyout_bad3: 895236991Simp subs r2, r2, #0x10 896129198Scognet bge .Lcopyout_bad3_loop16 897129198Scognet 898236991Simp adds r2, r2, #0x10 899129198Scognet ldmeqfd sp!, {r4-r7} 900137463Scognet RETeq /* Return now if done */ 901129198Scognet subs r2, r2, #0x04 902129198Scognet sublt r0, r0, #0x01 903129198Scognet blt .Lcopyout_l4 904129198Scognet 905129198Scognet.Lcopyout_bad3_loop4: 906129198Scognet#ifdef __ARMEB__ 907129198Scognet mov r4, ip, lsl #24 908129198Scognet#else 909129198Scognet mov r4, ip, lsr #24 910129198Scognet#endif 911129198Scognet ldr ip, [r0], #0x04 912129198Scognet subs r2, r2, #0x04 913129198Scognet#ifdef __ARMEB__ 914129198Scognet orr r4, r4, ip, lsr #8 915129198Scognet#else 916129198Scognet orr r4, r4, ip, lsl #8 917129198Scognet#endif 918129198Scognet strt r4, [r1], #0x04 919129198Scognet bge .Lcopyout_bad3_loop4 920129198Scognet sub r0, r0, #0x01 921129198Scognet 922129198Scognet.Lcopyout_l4: 923129198Scognet ldmfd sp!, {r4-r7} 924129198Scognet mov r3, #0x00 925129198Scognet adds r2, r2, #0x04 926137463Scognet RETeq 927129198Scognet.Lcopyout_l4_2: 928129198Scognet rsbs r2, r2, #0x03 929129198Scognet addne pc, pc, r2, lsl #3 930129198Scognet nop 931129198Scognet ldrb ip, [r0], #0x01 932129198Scognet strbt ip, [r1], #0x01 933129198Scognet ldrb ip, [r0], #0x01 934129198Scognet strbt ip, [r1], #0x01 935129198Scognet ldrb ip, [r0] 936129198Scognet strbt ip, [r1] 937137463Scognet RET 938248361SandrewEND(copyout) 939248361Sandrew 940