1 # 1 "lib/lib1funcs.S" 1 /* 0 0 2 * linux/arch/arm/lib/lib1funcs.S: Optimized ARM division routines 3 * 4 * Author: Nicolas Pitre 5 * - contributed to gcc-3.4 on Sep 30, 2003 6 * - adapted for the Linux kernel on Oct 2, 2003 7 */ 8 9 /* Copyright 1995, 1996, 1998, 1999, 2000, 2003 Free Software Foundation, Inc. 10 11 This file is free software; you can redistribute it and/or modify it 12 under the terms of the GNU General Public License as published by the 13 Free Software Foundation; either version 2, or (at your option) any 14 later version. 15 16 In addition to the permissions in the GNU General Public License, the 17 Free Software Foundation gives you unlimited permission to link the 18 compiled version of this file into combinations with other programs, 19 and to distribute those combinations without any restriction coming 20 from the use of this file. (The General Public License restrictions 21 do apply in other respects; for example, they cover modification of 22 the file, and distribution when not linked into a combine 23 executable.) 24 25 This file is distributed in the hope that it will be useful, but 26 WITHOUT ANY WARRANTY; without even the implied warranty of 27 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 28 General Public License for more details. 29 30 You should have received a copy of the GNU General Public License 31 along with this program; see the file COPYING. If not, write to 32 the Free Software Foundation, 59 Temple Place - Suite 330, 33 Boston, MA 02111-1307, USA. */ 34 35 36 #include 1 #ifndef __ASM_LINKAGE_H 37 #include 1 /* 2 * linux/include/asm-arm/assembler.h 3 * 4 * Copyright (C) 1996-2000 Russell King 5 * 6 * This program is free software; you can redistribute it and/or modify 7 * it under the terms of the GNU General Public License version 2 as 8 * published by the Free Software Foundation. 9 * 10 * This file contains arm architecture specific defines 11 * for the different processors. 12 * 13 * Do not include any C declarations in this file - it is included by 14 * assembler source. 15 */ 16 #ifndef __ASSEMBLY__ 17 #error "Only include this from assembly code" 18 #endif 19 20 #include 1 /* 21 22 #define pull lsl 23 #define push lsr 24 #define get_byte_0 lsr #24 25 #define get_byte_1 lsr #16 26 #define get_byte_2 lsr #8 27 #define get_byte_3 lsl #0 28 #define put_byte_0 lsl #24 29 #define put_byte_1 lsl #16 30 #define put_byte_2 lsl #8 31 #define put_byte_3 lsl #0 32 33 #define PLD(code...) 34 35 #define MODE_USR USR_MODE 36 #define MODE_FIQ FIQ_MODE 37 #define MODE_IRQ IRQ_MODE 38 #define MODE_SVC SVC_MODE 39 40 #define DEFAULT_FIQ MODE_FIQ 41 42 /* 43 * LOADREGS - ldm with PC in register list (eg, ldmfd sp!, {pc}) 44 */ 45 #ifdef __STDC__ 46 #define LOADREGS(cond, base, reglist...)\ 47 ldm##cond base,reglist 48 #else 49 #define LOADREGS(cond, base, reglist...)\ 50 ldm/**/cond base,reglist 51 #endif 52 53 /* 54 * Build a return instruction for this processor type. 55 */ 56 #define RETINSTR(instr, regs...)\ 57 instr regs 58 59 /* 60 * Enable and disable interrupts 61 */ 62 .macro disable_irq 63 msr cpsr_c, #PSR_I_BIT | SVC_MODE 64 .endm 65 66 .macro enable_irq 67 msr cpsr_c, #SVC_MODE 68 .endm 69 70 /* 71 * Save the current IRQ state and disable IRQs. Note that this macro 72 * assumes FIQs are enabled, and that the processor is in SVC mode. 73 */ 74 .macro save_and_disable_irqs, oldcpsr 75 mrs \oldcpsr, cpsr 76 disable_irq 77 .endm 78 79 /* 80 * Restore interrupt state previously stored in a register. We don't 81 * guarantee that this will preserve the flags. 82 */ 83 .macro restore_irqs, oldcpsr 84 msr cpsr_c, \oldcpsr 85 .endm 86 87 /* 88 * These two are used to save LR/restore PC over a user-based access. 89 * The old 26-bit architecture requires that we do. On 32-bit 90 * architecture, we can safely ignore this requirement. 91 */ 92 .macro save_lr 93 .endm 94 95 .macro restore_pc 96 mov pc, lr 97 .endm 98 ... 38 39 40 .macro ARM_DIV_BODY dividend, divisor, result, curbit 41 42 #if __LINUX_ARM_ARCH__ >= 5 43 44 clz \curbit, \divisor 45 clz \result, \dividend 46 sub \result, \curbit, \result 47 mov \curbit, #1 48 mov \divisor, \divisor, lsl \result 49 mov \curbit, \curbit, lsl \result 50 mov \result, #0 51 52 #else 53 54 @ Initially shift the divisor left 3 bits if possible, 55 @ set curbit accordingly. This allows for curbit to be located 56 @ at the left end of each 4 bit nibbles in the division loop 57 @ to save one loop in most cases. 58 tst \divisor, #0xe0000000 59 moveq \divisor, \divisor, lsl #3 60 moveq \curbit, #8 61 movne \curbit, #1 62 63 @ Unless the divisor is very big, shift it up in multiples of 64 @ four bits, since this is the amount of unwinding in the main 65 @ division loop. Continue shifting until the divisor is 66 @ larger than the dividend. 67 1: cmp \divisor, #0x10000000 68 cmplo \divisor, \dividend 69 movlo \divisor, \divisor, lsl #4 70 movlo \curbit, \curbit, lsl #4 71 blo 1b 72 73 @ For very big divisors, we must shift it a bit at a time, or 74 @ we will be in danger of overflowing. 75 1: cmp \divisor, #0x80000000 76 cmplo \divisor, \dividend 77 movlo \divisor, \divisor, lsl #1 78 movlo \curbit, \curbit, lsl #1 79 blo 1b 80 81 mov \result, #0 82 83 #endif 84 85 @ Division loop 86 1: cmp \dividend, \divisor 87 subhs \dividend, \dividend, \divisor 88 orrhs \result, \result, \curbit 89 cmp \dividend, \divisor, lsr #1 90 subhs \dividend, \dividend, \divisor, lsr #1 91 orrhs \result, \result, \curbit, lsr #1 92 cmp \dividend, \divisor, lsr #2 93 subhs \dividend, \dividend, \divisor, lsr #2 94 orrhs \result, \result, \curbit, lsr #2 95 cmp \dividend, \divisor, lsr #3 96 subhs \dividend, \dividend, \divisor, lsr #3 97 orrhs \result, \result, \curbit, lsr #3 98 cmp \dividend, #0 @ Early termination? 99 movnes \curbit, \curbit, lsr #4 @ No, any more bits to do? 100 movne \divisor, \divisor, lsr #4 101 bne 1b 102 103 .endm 104 105 106 .macro ARM_DIV2_ORDER divisor, order 107 108 #if __LINUX_ARM_ARCH__ >= 5 109 110 clz \order, \divisor 111 rsb \order, \order, #31 112 113 #else 114 115 cmp \divisor, #(1 << 16) 116 movhs \divisor, \divisor, lsr #16 117 movhs \order, #16 118 movlo \order, #0 119 120 cmp \divisor, #(1 << 8) 121 movhs \divisor, \divisor, lsr #8 122 addhs \order, \order, #8 123 124 cmp \divisor, #(1 << 4) 125 movhs \divisor, \divisor, lsr #4 126 addhs \order, \order, #4 127 128 cmp \divisor, #(1 << 2) 129 addhi \order, \order, #3 130 addls \order, \order, \divisor, lsr #1 131 132 #endif 133 134 .endm 135 136 137 .macro ARM_MOD_BODY dividend, divisor, order, spare 138 139 #if __LINUX_ARM_ARCH__ >= 5 140 141 clz \order, \divisor 142 clz \spare, \dividend 143 sub \order, \order, \spare 144 mov \divisor, \divisor, lsl \order 145 146 #else 147 148 mov \order, #0 149 150 @ Unless the divisor is very big, shift it up in multiples of 151 @ four bits, since this is the amount of unwinding in the main 152 @ division loop. Continue shifting until the divisor is 153 @ larger than the dividend. 154 1: cmp \divisor, #0x10000000 155 cmplo \divisor, \dividend 156 movlo \divisor, \divisor, lsl #4 157 addlo \order, \order, #4 158 blo 1b 159 160 @ For very big divisors, we must shift it a bit at a time, or 161 @ we will be in danger of overflowing. 162 1: cmp \divisor, #0x80000000 163 cmplo \divisor, \dividend 164 movlo \divisor, \divisor, lsl #1 165 addlo \order, \order, #1 166 blo 1b 167 168 #endif 169 170 @ Perform all needed substractions to keep only the reminder. 171 @ Do comparisons in batch of 4 first. 172 subs \order, \order, #3 @ yes, 3 is intended here 173 blt 2f 174 175 1: cmp \dividend, \divisor 176 subhs \dividend, \dividend, \divisor 177 cmp \dividend, \divisor, lsr #1 178 subhs \dividend, \dividend, \divisor, lsr #1 179 cmp \dividend, \divisor, lsr #2 180 subhs \dividend, \dividend, \divisor, lsr #2 181 cmp \dividend, \divisor, lsr #3 182 subhs \dividend, \dividend, \divisor, lsr #3 183 cmp \dividend, #1 184 mov \divisor, \divisor, lsr #4 185 subges \order, \order, #4 186 bge 1b 187 188 tst \order, #3 189 teqne \dividend, #0 190 beq 5f 191 192 @ Either 1, 2 or 3 comparison/substractions are left. 193 2: cmn \order, #2 194 blt 4f 195 beq 3f 196 cmp \dividend, \divisor 197 subhs \dividend, \dividend, \divisor 198 mov \divisor, \divisor, lsr #1 199 3: cmp \dividend, \divisor 200 subhs \dividend, \dividend, \divisor 201 mov \divisor, \divisor, lsr #1 202 4: cmp \dividend, \divisor 203 subhs \dividend, \dividend, \divisor 204 5: 205 .endm 206 207 208 /*ENTRY(__udivsi3) 209 ENTRY(__aeabi_uidiv) 210 211 subs r2, r1, #1 212 moveq pc, lr 213 bcc Ldiv0 214 cmp r0, r1 215 bls 11f 216 tst r1, r2 217 beq 12f 218 219 ARM_DIV_BODY r0, r1, r2, r3 220 221 mov r0, r2 222 mov pc, lr 223 224 11: moveq r0, #1 225 movne r0, #0 226 mov pc, lr 227 228 12: ARM_DIV2_ORDER r1, r2 229 230 mov r0, r0, lsr r2 231 mov pc, lr 232 */ 233 234 ENTRY(__umodsi3) 235 236 0000 012051E2 subs r2, r1, #1 @ compare divisor with 1 237 0004 A700003A bcc Ldiv0 238 0008 01005011 cmpne r0, r1 @ compare dividend with divisor 239 000c 0000A003 moveq r0, #0 240 0010 02001181 tsthi r1, r2 @ see if divisor is power of 2 241 0014 02000000 andeq r0, r0, r2 242 0018 0EF0A091 movls pc, lr 243 244 ARM_MOD_BODY r0, r1, r2, r3 245 246 00b8 0EF0A0E1 mov pc, lr 247 248 249 ENTRY(__divsi3) 250 ENTRY(__aeabi_idiv) 251 252 00bc 000051E3 cmp r1, #0 253 00c0 01C020E0 eor ip, r0, r1 @ save the sign of the result. 254 00c4 7700000A beq Ldiv0 255 00c8 00106142 rsbmi r1, r1, #0 @ loops below use unsigned. 256 00cc 012051E2 subs r2, r1, #1 @ division by 1 or -1 ? 257 00d0 2700000A beq 10f 258 00d4 0030B0E1 movs r3, r0 259 00d8 00306042 rsbmi r3, r0, #0 @ positive dividend value 260 00dc 010053E1 cmp r3, r1 261 00e0 2600009A bls 11f 262 00e4 020011E1 tst r1, r2 @ divisor is power of 2 ? 263 00e8 2800000A beq 12f 264 265 ARM_DIV_BODY r3, r1, r0, r2 266 267 0168 00005CE3 cmp ip, #0 268 016c 00006042 rsbmi r0, r0, #0 269 0170 0EF0A0E1 mov pc, lr 270 271 0174 00003CE1 10: teq ip, r0 @ same sign ? 272 0178 00006042 rsbmi r0, r0, #0 273 017c 0EF0A0E1 mov pc, lr 274 275 0180 0000A033 11: movlo r0, #0 276 0184 CC0FA001 moveq r0, ip, asr #31 277 0188 01008003 orreq r0, r0, #1 278 018c 0EF0A0E1 mov pc, lr 279 280 12: ARM_DIV2_ORDER r1, r2 281 282 01c4 00005CE3 cmp ip, #0 283 01c8 3302A0E1 mov r0, r3, lsr r2 284 01cc 00006042 rsbmi r0, r0, #0 285 01d0 0EF0A0E1 mov pc, lr 286 287 288 ENTRY(__modsi3) 289 290 01d4 000051E3 cmp r1, #0 291 01d8 3200000A beq Ldiv0 292 01dc 00106142 rsbmi r1, r1, #0 @ loops below use unsigned. 293 01e0 00C0B0E1 movs ip, r0 @ preserve sign of dividend 294 01e4 00006042 rsbmi r0, r0, #0 @ if negative make positive 295 01e8 012051E2 subs r2, r1, #1 @ compare divisor with 1 296 01ec 01005011 cmpne r0, r1 @ compare dividend with divisor 297 01f0 0000A003 moveq r0, #0 298 01f4 02001181 tsthi r1, r2 @ see if divisor is power of 2 299 01f8 02000000 andeq r0, r0, r2 300 01fc 2600009A bls 10f 301 302 ARM_MOD_BODY r0, r1, r2, r3 303 304 029c 00005CE3 10: cmp ip, #0 305 02a0 00006042 rsbmi r0, r0, #0 306 02a4 0EF0A0E1 mov pc, lr 307 308 #ifdef CONFIG_AEABI 309 310 ENTRY(__aeabi_uidivmod) 311 312 stmfd sp!, {r0, r1, ip, lr} 313 bl __aeabi_uidiv 314 ldmfd sp!, {r1, r2, ip, lr} 315 mul r3, r0, r2 316 sub r1, r1, r3 317 mov pc, lr 318 319 ENTRY(__aeabi_idivmod) 320 321 stmfd sp!, {r0, r1, ip, lr} 322 bl __aeabi_idiv 323 ldmfd sp!, {r1, r2, ip, lr} 324 mul r3, r0, r2 325 sub r1, r1, r3 326 mov pc, lr 327 328 #endif 329 330 Ldiv0: 331 332 02a8 08E02DE5 str lr, [sp, #-8]! 333 02ac FEFFFFEB bl __div0 334 02b0 0000A0E3 mov r0, #0 @ About as wrong as it could be. 335 02b4 08F09DE4 ldr pc, [sp], #8 336 337 ENTRY(__div0) 338 02b8 0EF0A0E1 mov pc, lr DEFINED SYMBOLS lib/lib1funcs.S:234 .text:00000000 __umodsi3 lib/lib1funcs.S:234 .text:00000000 $a lib/lib1funcs.S:330 .text:000002a8 Ldiv0 lib/lib1funcs.S:249 .text:000000bc __divsi3 lib/lib1funcs.S:250 .text:000000bc __aeabi_idiv lib/lib1funcs.S:288 .text:000001d4 __modsi3 lib/lib1funcs.S:337 .text:000002b8 __div0 .debug_aranges:0000000c $d NO UNDEFINED SYMBOLS