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