1 /* SPDX-License-Identifier: GPL-2.0-only */ 2 /* 3 * linux/arch/arm/lib/div64.S 4 * 5 * Optimized computation of 64-bit dividend / 6 * 7 * Author: Nicolas Pitre 8 * Created: Oct 5, 2003 9 * Copyright: Monta Vista Software, Inc. 10 */ 11 12 #include <linux/linkage.h> 13 #include <asm/assembler.h> 14 #include <asm/unwind.h> 15 16 #ifdef __ARMEB__ 17 #define xh r0 18 #define xl r1 19 #define yh r2 20 #define yl r3 21 #else 22 #define xl r0 23 #define xh r1 24 #define yl r2 25 #define yh r3 26 #endif 27 28 /* 29 * __do_div64: perform a division with 64-bit 30 * 31 * Note: Calling convention is totally non sta 32 * This is meant to be used by do_div() 33 * 34 * Input parameters: 35 * xh-xl = dividend (clobbered) 36 * r4 = divisor (preserved) 37 * 38 * Output values: 39 * yh-yl = result 40 * xh = remainder 41 * 42 * Clobbered regs: xl, ip 43 */ 44 45 ENTRY(__do_div64) 46 UNWIND(.fnstart) 47 48 @ Test for easy paths first. 49 subs ip, r4, #1 50 bls 9f @ divi 51 tst ip, r4 52 beq 8f @ divi 53 54 @ See if we need to handle upper 32-bi 55 cmp xh, r4 56 mov yh, #0 57 blo 3f 58 59 @ Align divisor with upper part of div 60 @ The aligned divisor is stored in yl 61 @ The bit position is stored in ip. 62 63 #if __LINUX_ARM_ARCH__ >= 5 64 65 clz yl, r4 66 clz ip, xh 67 sub yl, yl, ip 68 mov ip, #1 69 mov ip, ip, lsl yl 70 mov yl, r4, lsl yl 71 72 #else 73 74 mov yl, r4 75 mov ip, #1 76 1: cmp yl, #0x80000000 77 cmpcc yl, xh 78 movcc yl, yl, lsl #1 79 movcc ip, ip, lsl #1 80 bcc 1b 81 82 #endif 83 84 @ The division loop for needed upper b 85 @ Break out early if dividend reaches 86 2: cmp xh, yl 87 orrcs yh, yh, ip 88 subscs xh, xh, yl 89 movsne ip, ip, lsr #1 90 mov yl, yl, lsr #1 91 bne 2b 92 93 @ See if we need to handle lower 32-bi 94 3: cmp xh, #0 95 mov yl, #0 96 cmpeq xl, r4 97 movlo xh, xl 98 retlo lr 99 100 @ The division loop for lower bit posi 101 @ Here we shift remainer bits leftward 102 @ divisor for comparisons, considering 103 mov ip, #0x80000000 104 4: movs xl, xl, lsl #1 105 adcs xh, xh, xh 106 beq 6f 107 cmpcc xh, r4 108 5: orrcs yl, yl, ip 109 subcs xh, xh, r4 110 movs ip, ip, lsr #1 111 bne 4b 112 ret lr 113 114 @ The top part of remainder became zer 115 @ (the 33th bit) this is a false posit 116 @ Otherwise, if lower part is also nul 117 6: bcs 5b 118 cmp xl, #0 119 reteq lr 120 121 @ We still have remainer bits in the l 122 123 #if __LINUX_ARM_ARCH__ >= 5 124 125 clz xh, xl @ we k 126 add xh, xh, #1 127 mov xl, xl, lsl xh 128 mov ip, ip, lsr xh 129 130 #else 131 132 7: movs xl, xl, lsl #1 133 mov ip, ip, lsr #1 134 bcc 7b 135 136 #endif 137 138 @ Current remainder is now 1. It is w 139 @ divisor at this point since divisor 140 @ If possible, branch for another shif 141 @ If no bit position left then we are 142 movs ip, ip, lsr #1 143 mov xh, #1 144 bne 4b 145 ret lr 146 147 8: @ Division by a power of 2: determine 148 @ then simply shift values around 149 150 #if __LINUX_ARM_ARCH__ >= 5 151 152 clz ip, r4 153 rsb ip, ip, #31 154 155 #else 156 157 mov yl, r4 158 cmp r4, #(1 << 16) 159 mov ip, #0 160 movhs yl, yl, lsr #16 161 movhs ip, #16 162 163 cmp yl, #(1 << 8) 164 movhs yl, yl, lsr #8 165 addhs ip, ip, #8 166 167 cmp yl, #(1 << 4) 168 movhs yl, yl, lsr #4 169 addhs ip, ip, #4 170 171 cmp yl, #(1 << 2) 172 addhi ip, ip, #3 173 addls ip, ip, yl, lsr #1 174 175 #endif 176 177 mov yh, xh, lsr ip 178 mov yl, xl, lsr ip 179 rsb ip, ip, #32 180 ARM( orr yl, yl, xh, lsl ip ) 181 THUMB( lsl xh, xh, ip ) 182 THUMB( orr yl, yl, xh ) 183 mov xh, xl, lsl ip 184 mov xh, xh, lsr ip 185 ret lr 186 187 @ eq -> division by 1: obvious enough. 188 9: moveq yl, xl 189 moveq yh, xh 190 moveq xh, #0 191 reteq lr 192 UNWIND(.fnend) 193 194 UNWIND(.fnstart) 195 UNWIND(.pad #4) 196 UNWIND(.save {lr}) 197 Ldiv0_64: 198 @ Division by 0: 199 str lr, [sp, #-8]! 200 bl __div0 201 202 @ as wrong as it could be... 203 mov yl, #0 204 mov yh, #0 205 mov xh, #0 206 ldr pc, [sp], #8 207 208 UNWIND(.fnend) 209 ENDPROC(__do_div64)
Linux® is a registered trademark of Linus Torvalds in the United States and other countries.
TOMOYO® is a registered trademark of NTT DATA CORPORATION.