18c2ecf20Sopenharmony_ci/* 28c2ecf20Sopenharmony_ci * This file is subject to the terms and conditions of the GNU General Public 38c2ecf20Sopenharmony_ci * License. See the file "COPYING" in the main directory of this archive 48c2ecf20Sopenharmony_ci * for more details. 58c2ecf20Sopenharmony_ci * 68c2ecf20Sopenharmony_ci * Copyright (C) 2009, Wind River Systems Inc 78c2ecf20Sopenharmony_ci * Implemented by fredrik.markstrom@gmail.com and ivarholmqvist@gmail.com 88c2ecf20Sopenharmony_ci */ 98c2ecf20Sopenharmony_ci 108c2ecf20Sopenharmony_ci#include <linux/export.h> 118c2ecf20Sopenharmony_ci#include <linux/uaccess.h> 128c2ecf20Sopenharmony_ci 138c2ecf20Sopenharmony_ciasm(".global raw_copy_from_user\n" 148c2ecf20Sopenharmony_ci " .type raw_copy_from_user, @function\n" 158c2ecf20Sopenharmony_ci "raw_copy_from_user:\n" 168c2ecf20Sopenharmony_ci " movi r2,7\n" 178c2ecf20Sopenharmony_ci " mov r3,r4\n" 188c2ecf20Sopenharmony_ci " bge r2,r6,1f\n" 198c2ecf20Sopenharmony_ci " xor r2,r4,r5\n" 208c2ecf20Sopenharmony_ci " andi r2,r2,3\n" 218c2ecf20Sopenharmony_ci " movi r7,3\n" 228c2ecf20Sopenharmony_ci " beq r2,zero,4f\n" 238c2ecf20Sopenharmony_ci "1: addi r6,r6,-1\n" 248c2ecf20Sopenharmony_ci " movi r2,-1\n" 258c2ecf20Sopenharmony_ci " beq r6,r2,3f\n" 268c2ecf20Sopenharmony_ci " mov r7,r2\n" 278c2ecf20Sopenharmony_ci "2: ldbu r2,0(r5)\n" 288c2ecf20Sopenharmony_ci " addi r6,r6,-1\n" 298c2ecf20Sopenharmony_ci " addi r5,r5,1\n" 308c2ecf20Sopenharmony_ci " stb r2,0(r3)\n" 318c2ecf20Sopenharmony_ci " addi r3,r3,1\n" 328c2ecf20Sopenharmony_ci " bne r6,r7,2b\n" 338c2ecf20Sopenharmony_ci "3:\n" 348c2ecf20Sopenharmony_ci " addi r2,r6,1\n" 358c2ecf20Sopenharmony_ci " ret\n" 368c2ecf20Sopenharmony_ci "13:mov r2,r6\n" 378c2ecf20Sopenharmony_ci " ret\n" 388c2ecf20Sopenharmony_ci "4: andi r2,r4,1\n" 398c2ecf20Sopenharmony_ci " cmpeq r2,r2,zero\n" 408c2ecf20Sopenharmony_ci " beq r2,zero,7f\n" 418c2ecf20Sopenharmony_ci "5: andi r2,r3,2\n" 428c2ecf20Sopenharmony_ci " beq r2,zero,6f\n" 438c2ecf20Sopenharmony_ci "9: ldhu r2,0(r5)\n" 448c2ecf20Sopenharmony_ci " addi r6,r6,-2\n" 458c2ecf20Sopenharmony_ci " addi r5,r5,2\n" 468c2ecf20Sopenharmony_ci " sth r2,0(r3)\n" 478c2ecf20Sopenharmony_ci " addi r3,r3,2\n" 488c2ecf20Sopenharmony_ci "6: bge r7,r6,1b\n" 498c2ecf20Sopenharmony_ci "10:ldw r2,0(r5)\n" 508c2ecf20Sopenharmony_ci " addi r6,r6,-4\n" 518c2ecf20Sopenharmony_ci " addi r5,r5,4\n" 528c2ecf20Sopenharmony_ci " stw r2,0(r3)\n" 538c2ecf20Sopenharmony_ci " addi r3,r3,4\n" 548c2ecf20Sopenharmony_ci " br 6b\n" 558c2ecf20Sopenharmony_ci "7: ldbu r2,0(r5)\n" 568c2ecf20Sopenharmony_ci " addi r6,r6,-1\n" 578c2ecf20Sopenharmony_ci " addi r5,r5,1\n" 588c2ecf20Sopenharmony_ci " addi r3,r4,1\n" 598c2ecf20Sopenharmony_ci " stb r2,0(r4)\n" 608c2ecf20Sopenharmony_ci " br 5b\n" 618c2ecf20Sopenharmony_ci ".section __ex_table,\"a\"\n" 628c2ecf20Sopenharmony_ci ".word 2b,3b\n" 638c2ecf20Sopenharmony_ci ".word 9b,13b\n" 648c2ecf20Sopenharmony_ci ".word 10b,13b\n" 658c2ecf20Sopenharmony_ci ".word 7b,13b\n" 668c2ecf20Sopenharmony_ci ".previous\n" 678c2ecf20Sopenharmony_ci ); 688c2ecf20Sopenharmony_ciEXPORT_SYMBOL(raw_copy_from_user); 698c2ecf20Sopenharmony_ci 708c2ecf20Sopenharmony_ciasm( 718c2ecf20Sopenharmony_ci " .global raw_copy_to_user\n" 728c2ecf20Sopenharmony_ci " .type raw_copy_to_user, @function\n" 738c2ecf20Sopenharmony_ci "raw_copy_to_user:\n" 748c2ecf20Sopenharmony_ci " movi r2,7\n" 758c2ecf20Sopenharmony_ci " mov r3,r4\n" 768c2ecf20Sopenharmony_ci " bge r2,r6,1f\n" 778c2ecf20Sopenharmony_ci " xor r2,r4,r5\n" 788c2ecf20Sopenharmony_ci " andi r2,r2,3\n" 798c2ecf20Sopenharmony_ci " movi r7,3\n" 808c2ecf20Sopenharmony_ci " beq r2,zero,4f\n" 818c2ecf20Sopenharmony_ci /* Bail if we try to copy zero bytes */ 828c2ecf20Sopenharmony_ci "1: addi r6,r6,-1\n" 838c2ecf20Sopenharmony_ci " movi r2,-1\n" 848c2ecf20Sopenharmony_ci " beq r6,r2,3f\n" 858c2ecf20Sopenharmony_ci /* Copy byte by byte for small copies and if src^dst != 0 */ 868c2ecf20Sopenharmony_ci " mov r7,r2\n" 878c2ecf20Sopenharmony_ci "2: ldbu r2,0(r5)\n" 888c2ecf20Sopenharmony_ci " addi r5,r5,1\n" 898c2ecf20Sopenharmony_ci "9: stb r2,0(r3)\n" 908c2ecf20Sopenharmony_ci " addi r6,r6,-1\n" 918c2ecf20Sopenharmony_ci " addi r3,r3,1\n" 928c2ecf20Sopenharmony_ci " bne r6,r7,2b\n" 938c2ecf20Sopenharmony_ci "3: addi r2,r6,1\n" 948c2ecf20Sopenharmony_ci " ret\n" 958c2ecf20Sopenharmony_ci "13:mov r2,r6\n" 968c2ecf20Sopenharmony_ci " ret\n" 978c2ecf20Sopenharmony_ci /* If 'to' is an odd address byte copy */ 988c2ecf20Sopenharmony_ci "4: andi r2,r4,1\n" 998c2ecf20Sopenharmony_ci " cmpeq r2,r2,zero\n" 1008c2ecf20Sopenharmony_ci " beq r2,zero,7f\n" 1018c2ecf20Sopenharmony_ci /* If 'to' is not divideable by four copy halfwords */ 1028c2ecf20Sopenharmony_ci "5: andi r2,r3,2\n" 1038c2ecf20Sopenharmony_ci " beq r2,zero,6f\n" 1048c2ecf20Sopenharmony_ci " ldhu r2,0(r5)\n" 1058c2ecf20Sopenharmony_ci " addi r5,r5,2\n" 1068c2ecf20Sopenharmony_ci "10:sth r2,0(r3)\n" 1078c2ecf20Sopenharmony_ci " addi r6,r6,-2\n" 1088c2ecf20Sopenharmony_ci " addi r3,r3,2\n" 1098c2ecf20Sopenharmony_ci /* Copy words */ 1108c2ecf20Sopenharmony_ci "6: bge r7,r6,1b\n" 1118c2ecf20Sopenharmony_ci " ldw r2,0(r5)\n" 1128c2ecf20Sopenharmony_ci " addi r5,r5,4\n" 1138c2ecf20Sopenharmony_ci "11:stw r2,0(r3)\n" 1148c2ecf20Sopenharmony_ci " addi r6,r6,-4\n" 1158c2ecf20Sopenharmony_ci " addi r3,r3,4\n" 1168c2ecf20Sopenharmony_ci " br 6b\n" 1178c2ecf20Sopenharmony_ci /* Copy remaining bytes */ 1188c2ecf20Sopenharmony_ci "7: ldbu r2,0(r5)\n" 1198c2ecf20Sopenharmony_ci " addi r5,r5,1\n" 1208c2ecf20Sopenharmony_ci " addi r3,r4,1\n" 1218c2ecf20Sopenharmony_ci "12: stb r2,0(r4)\n" 1228c2ecf20Sopenharmony_ci " addi r6,r6,-1\n" 1238c2ecf20Sopenharmony_ci " br 5b\n" 1248c2ecf20Sopenharmony_ci ".section __ex_table,\"a\"\n" 1258c2ecf20Sopenharmony_ci ".word 9b,3b\n" 1268c2ecf20Sopenharmony_ci ".word 10b,13b\n" 1278c2ecf20Sopenharmony_ci ".word 11b,13b\n" 1288c2ecf20Sopenharmony_ci ".word 12b,13b\n" 1298c2ecf20Sopenharmony_ci ".previous\n"); 1308c2ecf20Sopenharmony_ciEXPORT_SYMBOL(raw_copy_to_user); 131