1/* $NetBSD: divsi3.S,v 1.4 2003/04/05 23:27:15 bjh21 Exp $ */ 2 3/*- 4 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 5 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 6 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 7 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 8 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 9 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 10 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 11 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 12 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 13 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 14 * SUCH DAMAGE. 15 */ 16 17#include <machine/asm.h> 18__FBSDID("$FreeBSD$"); 19 20/* 21 * stack is aligned as there's a possibility of branching to L_overflow 22 * which makes a C call 23 */ 24 25ENTRY_NP(__umodsi3) 26 stmfd sp!, {lr} 27 sub sp, sp, #4 /* align stack */ 28 bl .L_udivide 29 add sp, sp, #4 /* unalign stack */ 30 mov r0, r1 31 ldmfd sp!, {pc} 32END(__umodsi3) 33 34ENTRY_NP(__modsi3) 35 stmfd sp!, {lr} 36 sub sp, sp, #4 /* align stack */ 37 bl .L_divide 38 add sp, sp, #4 /* unalign stack */ 39 mov r0, r1 40 ldmfd sp!, {pc} 41 42.L_overflow: 43#if !defined(_KERNEL) && !defined(_STANDALONE) 44 mov r0, #8 /* SIGFPE */ 45 bl PIC_SYM(_C_LABEL(raise), PLT) /* raise it */ 46 mov r0, #0 47#else 48 /* XXX should cause a fatal error */ 49 mvn r0, #0 50#endif 51 RET 52END(__modsi3) 53 54#ifdef __ARM_EABI__ 55ENTRY_NP(__aeabi_uidiv) 56ENTRY_NP(__aeabi_uidivmod) 57#endif 58ENTRY_NP(__udivsi3) 59.L_udivide: /* r0 = r0 / r1; r1 = r0 % r1 */ 60 eor r0, r1, r0 61 eor r1, r0, r1 62 eor r0, r1, r0 63 /* r0 = r1 / r0; r1 = r1 % r0 */ 64 cmp r0, #1 65 bcc .L_overflow 66 beq .L_divide_l0 67 mov ip, #0 68 movs r1, r1 69 bpl .L_divide_l1 70 orr ip, ip, #0x20000000 /* ip bit 0x20000000 = -ve r1 */ 71 movs r1, r1, lsr #1 72 orrcs ip, ip, #0x10000000 /* ip bit 0x10000000 = bit 0 of r1 */ 73 b .L_divide_l1 74 75.L_divide_l0: /* r0 == 1 */ 76 mov r0, r1 77 mov r1, #0 78 RET 79#ifdef __ARM_EABI__ 80END(__aeabi_uidiv) 81END(__aeabi_uidivmod) 82#endif 83END(__udivsi3) 84 85#ifdef __ARM_EABI__ 86ENTRY_NP(__aeabi_idiv) 87ENTRY_NP(__aeabi_idivmod) 88#endif 89ENTRY_NP(__divsi3) 90.L_divide: /* r0 = r0 / r1; r1 = r0 % r1 */ 91 eor r0, r1, r0 92 eor r1, r0, r1 93 eor r0, r1, r0 94 /* r0 = r1 / r0; r1 = r1 % r0 */ 95 cmp r0, #1 96 bcc .L_overflow 97 beq .L_divide_l0 98 ands ip, r0, #0x80000000 99 rsbmi r0, r0, #0 100 ands r2, r1, #0x80000000 101 eor ip, ip, r2 102 rsbmi r1, r1, #0 103 orr ip, r2, ip, lsr #1 /* ip bit 0x40000000 = -ve division */ 104 /* ip bit 0x80000000 = -ve remainder */ 105 106.L_divide_l1: 107 mov r2, #1 108 mov r3, #0 109 110 /* 111 * If the highest bit of the dividend is set, we have to be 112 * careful when shifting the divisor. Test this. 113 */ 114 movs r1,r1 115 bpl .L_old_code 116 117 /* 118 * At this point, the highest bit of r1 is known to be set. 119 * We abuse this below in the tst instructions. 120 */ 121 tst r1, r0 /*, lsl #0 */ 122 bmi .L_divide_b1 123 tst r1, r0, lsl #1 124 bmi .L_divide_b2 125 tst r1, r0, lsl #2 126 bmi .L_divide_b3 127 tst r1, r0, lsl #3 128 bmi .L_divide_b4 129 tst r1, r0, lsl #4 130 bmi .L_divide_b5 131 tst r1, r0, lsl #5 132 bmi .L_divide_b6 133 tst r1, r0, lsl #6 134 bmi .L_divide_b7 135 tst r1, r0, lsl #7 136 bmi .L_divide_b8 137 tst r1, r0, lsl #8 138 bmi .L_divide_b9 139 tst r1, r0, lsl #9 140 bmi .L_divide_b10 141 tst r1, r0, lsl #10 142 bmi .L_divide_b11 143 tst r1, r0, lsl #11 144 bmi .L_divide_b12 145 tst r1, r0, lsl #12 146 bmi .L_divide_b13 147 tst r1, r0, lsl #13 148 bmi .L_divide_b14 149 tst r1, r0, lsl #14 150 bmi .L_divide_b15 151 tst r1, r0, lsl #15 152 bmi .L_divide_b16 153 tst r1, r0, lsl #16 154 bmi .L_divide_b17 155 tst r1, r0, lsl #17 156 bmi .L_divide_b18 157 tst r1, r0, lsl #18 158 bmi .L_divide_b19 159 tst r1, r0, lsl #19 160 bmi .L_divide_b20 161 tst r1, r0, lsl #20 162 bmi .L_divide_b21 163 tst r1, r0, lsl #21 164 bmi .L_divide_b22 165 tst r1, r0, lsl #22 166 bmi .L_divide_b23 167 tst r1, r0, lsl #23 168 bmi .L_divide_b24 169 tst r1, r0, lsl #24 170 bmi .L_divide_b25 171 tst r1, r0, lsl #25 172 bmi .L_divide_b26 173 tst r1, r0, lsl #26 174 bmi .L_divide_b27 175 tst r1, r0, lsl #27 176 bmi .L_divide_b28 177 tst r1, r0, lsl #28 178 bmi .L_divide_b29 179 tst r1, r0, lsl #29 180 bmi .L_divide_b30 181 tst r1, r0, lsl #30 182 bmi .L_divide_b31 183/* 184 * instead of: 185 * tst r1, r0, lsl #31 186 * bmi .L_divide_b32 187 */ 188 b .L_divide_b32 189 190.L_old_code: 191 cmp r1, r0 192 bcc .L_divide_b0 193 cmp r1, r0, lsl #1 194 bcc .L_divide_b1 195 cmp r1, r0, lsl #2 196 bcc .L_divide_b2 197 cmp r1, r0, lsl #3 198 bcc .L_divide_b3 199 cmp r1, r0, lsl #4 200 bcc .L_divide_b4 201 cmp r1, r0, lsl #5 202 bcc .L_divide_b5 203 cmp r1, r0, lsl #6 204 bcc .L_divide_b6 205 cmp r1, r0, lsl #7 206 bcc .L_divide_b7 207 cmp r1, r0, lsl #8 208 bcc .L_divide_b8 209 cmp r1, r0, lsl #9 210 bcc .L_divide_b9 211 cmp r1, r0, lsl #10 212 bcc .L_divide_b10 213 cmp r1, r0, lsl #11 214 bcc .L_divide_b11 215 cmp r1, r0, lsl #12 216 bcc .L_divide_b12 217 cmp r1, r0, lsl #13 218 bcc .L_divide_b13 219 cmp r1, r0, lsl #14 220 bcc .L_divide_b14 221 cmp r1, r0, lsl #15 222 bcc .L_divide_b15 223 cmp r1, r0, lsl #16 224 bcc .L_divide_b16 225 cmp r1, r0, lsl #17 226 bcc .L_divide_b17 227 cmp r1, r0, lsl #18 228 bcc .L_divide_b18 229 cmp r1, r0, lsl #19 230 bcc .L_divide_b19 231 cmp r1, r0, lsl #20 232 bcc .L_divide_b20 233 cmp r1, r0, lsl #21 234 bcc .L_divide_b21 235 cmp r1, r0, lsl #22 236 bcc .L_divide_b22 237 cmp r1, r0, lsl #23 238 bcc .L_divide_b23 239 cmp r1, r0, lsl #24 240 bcc .L_divide_b24 241 cmp r1, r0, lsl #25 242 bcc .L_divide_b25 243 cmp r1, r0, lsl #26 244 bcc .L_divide_b26 245 cmp r1, r0, lsl #27 246 bcc .L_divide_b27 247 cmp r1, r0, lsl #28 248 bcc .L_divide_b28 249 cmp r1, r0, lsl #29 250 bcc .L_divide_b29 251 cmp r1, r0, lsl #30 252 bcc .L_divide_b30 253.L_divide_b32: 254 cmp r1, r0, lsl #31 255 subhs r1, r1,r0, lsl #31 256 addhs r3, r3,r2, lsl #31 257.L_divide_b31: 258 cmp r1, r0, lsl #30 259 subhs r1, r1,r0, lsl #30 260 addhs r3, r3,r2, lsl #30 261.L_divide_b30: 262 cmp r1, r0, lsl #29 263 subhs r1, r1,r0, lsl #29 264 addhs r3, r3,r2, lsl #29 265.L_divide_b29: 266 cmp r1, r0, lsl #28 267 subhs r1, r1,r0, lsl #28 268 addhs r3, r3,r2, lsl #28 269.L_divide_b28: 270 cmp r1, r0, lsl #27 271 subhs r1, r1,r0, lsl #27 272 addhs r3, r3,r2, lsl #27 273.L_divide_b27: 274 cmp r1, r0, lsl #26 275 subhs r1, r1,r0, lsl #26 276 addhs r3, r3,r2, lsl #26 277.L_divide_b26: 278 cmp r1, r0, lsl #25 279 subhs r1, r1,r0, lsl #25 280 addhs r3, r3,r2, lsl #25 281.L_divide_b25: 282 cmp r1, r0, lsl #24 283 subhs r1, r1,r0, lsl #24 284 addhs r3, r3,r2, lsl #24 285.L_divide_b24: 286 cmp r1, r0, lsl #23 287 subhs r1, r1,r0, lsl #23 288 addhs r3, r3,r2, lsl #23 289.L_divide_b23: 290 cmp r1, r0, lsl #22 291 subhs r1, r1,r0, lsl #22 292 addhs r3, r3,r2, lsl #22 293.L_divide_b22: 294 cmp r1, r0, lsl #21 295 subhs r1, r1,r0, lsl #21 296 addhs r3, r3,r2, lsl #21 297.L_divide_b21: 298 cmp r1, r0, lsl #20 299 subhs r1, r1,r0, lsl #20 300 addhs r3, r3,r2, lsl #20 301.L_divide_b20: 302 cmp r1, r0, lsl #19 303 subhs r1, r1,r0, lsl #19 304 addhs r3, r3,r2, lsl #19 305.L_divide_b19: 306 cmp r1, r0, lsl #18 307 subhs r1, r1,r0, lsl #18 308 addhs r3, r3,r2, lsl #18 309.L_divide_b18: 310 cmp r1, r0, lsl #17 311 subhs r1, r1,r0, lsl #17 312 addhs r3, r3,r2, lsl #17 313.L_divide_b17: 314 cmp r1, r0, lsl #16 315 subhs r1, r1,r0, lsl #16 316 addhs r3, r3,r2, lsl #16 317.L_divide_b16: 318 cmp r1, r0, lsl #15 319 subhs r1, r1,r0, lsl #15 320 addhs r3, r3,r2, lsl #15 321.L_divide_b15: 322 cmp r1, r0, lsl #14 323 subhs r1, r1,r0, lsl #14 324 addhs r3, r3,r2, lsl #14 325.L_divide_b14: 326 cmp r1, r0, lsl #13 327 subhs r1, r1,r0, lsl #13 328 addhs r3, r3,r2, lsl #13 329.L_divide_b13: 330 cmp r1, r0, lsl #12 331 subhs r1, r1,r0, lsl #12 332 addhs r3, r3,r2, lsl #12 333.L_divide_b12: 334 cmp r1, r0, lsl #11 335 subhs r1, r1,r0, lsl #11 336 addhs r3, r3,r2, lsl #11 337.L_divide_b11: 338 cmp r1, r0, lsl #10 339 subhs r1, r1,r0, lsl #10 340 addhs r3, r3,r2, lsl #10 341.L_divide_b10: 342 cmp r1, r0, lsl #9 343 subhs r1, r1,r0, lsl #9 344 addhs r3, r3,r2, lsl #9 345.L_divide_b9: 346 cmp r1, r0, lsl #8 347 subhs r1, r1,r0, lsl #8 348 addhs r3, r3,r2, lsl #8 349.L_divide_b8: 350 cmp r1, r0, lsl #7 351 subhs r1, r1,r0, lsl #7 352 addhs r3, r3,r2, lsl #7 353.L_divide_b7: 354 cmp r1, r0, lsl #6 355 subhs r1, r1,r0, lsl #6 356 addhs r3, r3,r2, lsl #6 357.L_divide_b6: 358 cmp r1, r0, lsl #5 359 subhs r1, r1,r0, lsl #5 360 addhs r3, r3,r2, lsl #5 361.L_divide_b5: 362 cmp r1, r0, lsl #4 363 subhs r1, r1,r0, lsl #4 364 addhs r3, r3,r2, lsl #4 365.L_divide_b4: 366 cmp r1, r0, lsl #3 367 subhs r1, r1,r0, lsl #3 368 addhs r3, r3,r2, lsl #3 369.L_divide_b3: 370 cmp r1, r0, lsl #2 371 subhs r1, r1,r0, lsl #2 372 addhs r3, r3,r2, lsl #2 373.L_divide_b2: 374 cmp r1, r0, lsl #1 375 subhs r1, r1,r0, lsl #1 376 addhs r3, r3,r2, lsl #1 377.L_divide_b1: 378 cmp r1, r0 379 subhs r1, r1, r0 380 addhs r3, r3, r2 381.L_divide_b0: 382 383 tst ip, #0x20000000 384 bne .L_udivide_l1 385 mov r0, r3 386 cmp ip, #0 387 rsbmi r1, r1, #0 388 movs ip, ip, lsl #1 389 bicmi r0, r0, #0x80000000 /* Fix incase we divided 0x80000000 */ 390 rsbmi r0, r0, #0 391 RET 392 393.L_udivide_l1: 394 tst ip, #0x10000000 395 mov r1, r1, lsl #1 396 orrne r1, r1, #1 397 mov r3, r3, lsl #1 398 cmp r1, r0 399 subhs r1, r1, r0 400 addhs r3, r3, r2 401 mov r0, r3 402 RET 403#ifdef __ARM_EABI__ 404END(__aeabi_idiv) 405END(__aeabi_idivmod) 406#endif 407END(__divsi3) 408 409