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