1/* 2 * OpenRISC string.S 3 * 4 * Linux architectural port borrowing liberally from similar works of 5 * others. All original copyrights apply as per the original source 6 * declaration. 7 * 8 * Modifications for the OpenRISC architecture: 9 * Copyright (C) 2003 Matjaz Breskvar <phoenix@bsemi.com> 10 * Copyright (C) 2010-2011 Jonas Bonn <jonas@southpole.se> 11 * 12 * This program is free software; you can redistribute it and/or 13 * modify it under the terms of the GNU General Public License 14 * as published by the Free Software Foundation; either version 15 * 2 of the License, or (at your option) any later version. 16 */ 17 18#include <linux/linkage.h> 19#include <asm/errno.h> 20 21 /* 22 * this can be optimized by doing gcc inline assemlby with 23 * proper constraints (no need to save args registers...) 24 * 25 */ 26 27 28/* 29 * 30 * int __copy_tofrom_user(void *to, const void *from, unsigned long size); 31 * 32 * NOTE: it returns number of bytes NOT copied !!! 33 * 34 */ 35 .global __copy_tofrom_user 36__copy_tofrom_user: 37 l.addi r1,r1,-12 38 l.sw 0(r1),r6 39 l.sw 4(r1),r4 40 l.sw 8(r1),r3 41 42 l.addi r11,r5,0 432: l.sfeq r11,r0 44 l.bf 1f 45 l.addi r11,r11,-1 468: l.lbz r6,0(r4) 479: l.sb 0(r3),r6 48 l.addi r3,r3,1 49 l.j 2b 50 l.addi r4,r4,1 511: 52 l.addi r11,r11,1 // r11 holds the return value 53 54 l.lwz r6,0(r1) 55 l.lwz r4,4(r1) 56 l.lwz r3,8(r1) 57 l.jr r9 58 l.addi r1,r1,12 59 60 .section .fixup, "ax" 6199: 62 l.j 1b 63 l.nop 64 .previous 65 66 .section __ex_table, "a" 67 .long 8b, 99b // read fault 68 .long 9b, 99b // write fault 69 .previous 70 71/* 72 * unsigned long clear_user(void *addr, unsigned long size) ; 73 * 74 * NOTE: it returns number of bytes NOT cleared !!! 75 */ 76 .global __clear_user 77__clear_user: 78 l.addi r1,r1,-8 79 l.sw 0(r1),r4 80 l.sw 4(r1),r3 81 822: l.sfeq r4,r0 83 l.bf 1f 84 l.addi r4,r4,-1 859: l.sb 0(r3),r0 86 l.j 2b 87 l.addi r3,r3,1 88 891: 90 l.addi r11,r4,1 91 92 l.lwz r4,0(r1) 93 l.lwz r3,4(r1) 94 l.jr r9 95 l.addi r1,r1,8 96 97 .section .fixup, "ax" 9899: 99 l.j 1b 100 l.nop 101 .previous 102 103 .section __ex_table, "a" 104 .long 9b, 99b // write fault 105 .previous 106 107/* 108 * long strncpy_from_user(char *dst, const char *src, long count) 109 * 110 * 111 */ 112 .global __strncpy_from_user 113__strncpy_from_user: 114 l.addi r1,r1,-16 115 l.sw 0(r1),r6 116 l.sw 4(r1),r5 117 l.sw 8(r1),r4 118 l.sw 12(r1),r3 119 120 l.addi r11,r5,0 1212: l.sfeq r5,r0 122 l.bf 1f 123 l.addi r5,r5,-1 1248: l.lbz r6,0(r4) 125 l.sfeq r6,r0 126 l.bf 1f 1279: l.sb 0(r3),r6 128 l.addi r3,r3,1 129 l.j 2b 130 l.addi r4,r4,1 1311: 132 l.lwz r6,0(r1) 133 l.addi r5,r5,1 134 l.sub r11,r11,r5 // r11 holds the return value 135 136 l.lwz r6,0(r1) 137 l.lwz r5,4(r1) 138 l.lwz r4,8(r1) 139 l.lwz r3,12(r1) 140 l.jr r9 141 l.addi r1,r1,16 142 143 .section .fixup, "ax" 14499: 145 l.movhi r11,hi(-EFAULT) 146 l.ori r11,r11,lo(-EFAULT) 147 148 l.lwz r6,0(r1) 149 l.lwz r5,4(r1) 150 l.lwz r4,8(r1) 151 l.lwz r3,12(r1) 152 l.jr r9 153 l.addi r1,r1,16 154 .previous 155 156 .section __ex_table, "a" 157 .long 8b, 99b // read fault 158 .previous 159 160/* 161 * extern int __strnlen_user(const char *str, long len, unsigned long top); 162 * 163 * 164 * RTRN: - length of a string including NUL termination character 165 * - on page fault 0 166 */ 167 168 .global __strnlen_user 169__strnlen_user: 170 l.addi r1,r1,-8 171 l.sw 0(r1),r6 172 l.sw 4(r1),r3 173 174 l.addi r11,r0,0 1752: l.sfeq r11,r4 176 l.bf 1f 177 l.addi r11,r11,1 1788: l.lbz r6,0(r3) 179 l.sfeq r6,r0 180 l.bf 1f 181 l.sfgeu r3,r5 // are we over the top ? 182 l.bf 99f 183 l.j 2b 184 l.addi r3,r3,1 185 1861: 187 l.lwz r6,0(r1) 188 l.lwz r3,4(r1) 189 l.jr r9 190 l.addi r1,r1,8 191 192 .section .fixup, "ax" 19399: 194 l.addi r11,r0,0 195 196 l.lwz r6,0(r1) 197 l.lwz r3,4(r1) 198 l.jr r9 199 l.addi r1,r1,8 200 .previous 201 202 .section __ex_table, "a" 203 .long 8b, 99b // read fault 204 .previous 205