1129202Scognet/* $NetBSD: divsi3.S,v 1.4 2003/04/05 23:27:15 bjh21 Exp $ */ 2129202Scognet 3129202Scognet/* 4129202Scognet * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 5129202Scognet * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 6129202Scognet * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 7129202Scognet * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 8129202Scognet * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 9129202Scognet * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 10129202Scognet * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 11129202Scognet * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 12129202Scognet * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 13129202Scognet * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 14129202Scognet * SUCH DAMAGE. 15129202Scognet */ 16129202Scognet 17129202Scognet#include <machine/asm.h> 18129202Scognet__FBSDID("$FreeBSD$"); 19129202Scognet 20129202Scognet/* 21129202Scognet * stack is aligned as there's a possibility of branching to L_overflow 22129202Scognet * which makes a C call 23129202Scognet */ 24129202Scognet 25129202ScognetENTRY(__umodsi3) 26129202Scognet stmfd sp!, {lr} 27129202Scognet sub sp, sp, #4 /* align stack */ 28129202Scognet bl .L_udivide 29129202Scognet add sp, sp, #4 /* unalign stack */ 30129202Scognet mov r0, r1 31129202Scognet ldmfd sp!, {pc} 32129202Scognet 33129202ScognetENTRY(__modsi3) 34129202Scognet stmfd sp!, {lr} 35129202Scognet sub sp, sp, #4 /* align stack */ 36129202Scognet bl .L_divide 37129202Scognet add sp, sp, #4 /* unalign stack */ 38129202Scognet mov r0, r1 39129202Scognet ldmfd sp!, {pc} 40129202Scognet 41129202Scognet.L_overflow: 42129202Scognet#if !defined(_KERNEL) && !defined(_STANDALONE) 43129202Scognet mov r0, #8 /* SIGFPE */ 44129202Scognet bl PIC_SYM(_C_LABEL(raise), PLT) /* raise it */ 45129202Scognet mov r0, #0 46129202Scognet#else 47129202Scognet /* XXX should cause a fatal error */ 48129202Scognet mvn r0, #0 49129202Scognet#endif 50137464Scognet RET 51129202Scognet 52129202ScognetENTRY(__udivsi3) 53129202Scognet.L_udivide: /* r0 = r0 / r1; r1 = r0 % r1 */ 54129202Scognet eor r0, r1, r0 55129202Scognet eor r1, r0, r1 56129202Scognet eor r0, r1, r0 57129202Scognet /* r0 = r1 / r0; r1 = r1 % r0 */ 58129202Scognet cmp r0, #1 59129202Scognet bcc .L_overflow 60129202Scognet beq .L_divide_l0 61129202Scognet mov ip, #0 62129202Scognet movs r1, r1 63129202Scognet bpl .L_divide_l1 64129202Scognet orr ip, ip, #0x20000000 /* ip bit 0x20000000 = -ve r1 */ 65129202Scognet movs r1, r1, lsr #1 66129202Scognet orrcs ip, ip, #0x10000000 /* ip bit 0x10000000 = bit 0 of r1 */ 67129202Scognet b .L_divide_l1 68129202Scognet 69129202Scognet.L_divide_l0: /* r0 == 1 */ 70129202Scognet mov r0, r1 71129202Scognet mov r1, #0 72137464Scognet RET 73129202Scognet 74129202ScognetENTRY(__divsi3) 75129202Scognet.L_divide: /* r0 = r0 / r1; r1 = r0 % r1 */ 76129202Scognet eor r0, r1, r0 77129202Scognet eor r1, r0, r1 78129202Scognet eor r0, r1, r0 79129202Scognet /* r0 = r1 / r0; r1 = r1 % r0 */ 80129202Scognet cmp r0, #1 81129202Scognet bcc .L_overflow 82129202Scognet beq .L_divide_l0 83129202Scognet ands ip, r0, #0x80000000 84129202Scognet rsbmi r0, r0, #0 85129202Scognet ands r2, r1, #0x80000000 86129202Scognet eor ip, ip, r2 87129202Scognet rsbmi r1, r1, #0 88129202Scognet orr ip, r2, ip, lsr #1 /* ip bit 0x40000000 = -ve division */ 89129202Scognet /* ip bit 0x80000000 = -ve remainder */ 90129202Scognet 91129202Scognet.L_divide_l1: 92129202Scognet mov r2, #1 93129202Scognet mov r3, #0 94129202Scognet 95129202Scognet /* 96129202Scognet * If the highest bit of the dividend is set, we have to be 97129202Scognet * careful when shifting the divisor. Test this. 98129202Scognet */ 99129202Scognet movs r1,r1 100129202Scognet bpl .L_old_code 101129202Scognet 102129202Scognet /* 103129202Scognet * At this point, the highest bit of r1 is known to be set. 104129202Scognet * We abuse this below in the tst instructions. 105129202Scognet */ 106129202Scognet tst r1, r0 /*, lsl #0 */ 107129202Scognet bmi .L_divide_b1 108129202Scognet tst r1, r0, lsl #1 109129202Scognet bmi .L_divide_b2 110129202Scognet tst r1, r0, lsl #2 111129202Scognet bmi .L_divide_b3 112129202Scognet tst r1, r0, lsl #3 113129202Scognet bmi .L_divide_b4 114129202Scognet tst r1, r0, lsl #4 115129202Scognet bmi .L_divide_b5 116129202Scognet tst r1, r0, lsl #5 117129202Scognet bmi .L_divide_b6 118129202Scognet tst r1, r0, lsl #6 119129202Scognet bmi .L_divide_b7 120129202Scognet tst r1, r0, lsl #7 121129202Scognet bmi .L_divide_b8 122129202Scognet tst r1, r0, lsl #8 123129202Scognet bmi .L_divide_b9 124129202Scognet tst r1, r0, lsl #9 125129202Scognet bmi .L_divide_b10 126129202Scognet tst r1, r0, lsl #10 127129202Scognet bmi .L_divide_b11 128129202Scognet tst r1, r0, lsl #11 129129202Scognet bmi .L_divide_b12 130129202Scognet tst r1, r0, lsl #12 131129202Scognet bmi .L_divide_b13 132129202Scognet tst r1, r0, lsl #13 133129202Scognet bmi .L_divide_b14 134129202Scognet tst r1, r0, lsl #14 135129202Scognet bmi .L_divide_b15 136129202Scognet tst r1, r0, lsl #15 137129202Scognet bmi .L_divide_b16 138129202Scognet tst r1, r0, lsl #16 139129202Scognet bmi .L_divide_b17 140129202Scognet tst r1, r0, lsl #17 141129202Scognet bmi .L_divide_b18 142129202Scognet tst r1, r0, lsl #18 143129202Scognet bmi .L_divide_b19 144129202Scognet tst r1, r0, lsl #19 145129202Scognet bmi .L_divide_b20 146129202Scognet tst r1, r0, lsl #20 147129202Scognet bmi .L_divide_b21 148129202Scognet tst r1, r0, lsl #21 149129202Scognet bmi .L_divide_b22 150129202Scognet tst r1, r0, lsl #22 151129202Scognet bmi .L_divide_b23 152129202Scognet tst r1, r0, lsl #23 153129202Scognet bmi .L_divide_b24 154129202Scognet tst r1, r0, lsl #24 155129202Scognet bmi .L_divide_b25 156129202Scognet tst r1, r0, lsl #25 157129202Scognet bmi .L_divide_b26 158129202Scognet tst r1, r0, lsl #26 159129202Scognet bmi .L_divide_b27 160129202Scognet tst r1, r0, lsl #27 161129202Scognet bmi .L_divide_b28 162129202Scognet tst r1, r0, lsl #28 163129202Scognet bmi .L_divide_b29 164129202Scognet tst r1, r0, lsl #29 165129202Scognet bmi .L_divide_b30 166129202Scognet tst r1, r0, lsl #30 167129202Scognet bmi .L_divide_b31 168129202Scognet/* 169129202Scognet * instead of: 170129202Scognet * tst r1, r0, lsl #31 171129202Scognet * bmi .L_divide_b32 172129202Scognet */ 173129202Scognet b .L_divide_b32 174129202Scognet 175129202Scognet.L_old_code: 176129202Scognet cmp r1, r0 177129202Scognet bcc .L_divide_b0 178129202Scognet cmp r1, r0, lsl #1 179129202Scognet bcc .L_divide_b1 180129202Scognet cmp r1, r0, lsl #2 181129202Scognet bcc .L_divide_b2 182129202Scognet cmp r1, r0, lsl #3 183129202Scognet bcc .L_divide_b3 184129202Scognet cmp r1, r0, lsl #4 185129202Scognet bcc .L_divide_b4 186129202Scognet cmp r1, r0, lsl #5 187129202Scognet bcc .L_divide_b5 188129202Scognet cmp r1, r0, lsl #6 189129202Scognet bcc .L_divide_b6 190129202Scognet cmp r1, r0, lsl #7 191129202Scognet bcc .L_divide_b7 192129202Scognet cmp r1, r0, lsl #8 193129202Scognet bcc .L_divide_b8 194129202Scognet cmp r1, r0, lsl #9 195129202Scognet bcc .L_divide_b9 196129202Scognet cmp r1, r0, lsl #10 197129202Scognet bcc .L_divide_b10 198129202Scognet cmp r1, r0, lsl #11 199129202Scognet bcc .L_divide_b11 200129202Scognet cmp r1, r0, lsl #12 201129202Scognet bcc .L_divide_b12 202129202Scognet cmp r1, r0, lsl #13 203129202Scognet bcc .L_divide_b13 204129202Scognet cmp r1, r0, lsl #14 205129202Scognet bcc .L_divide_b14 206129202Scognet cmp r1, r0, lsl #15 207129202Scognet bcc .L_divide_b15 208129202Scognet cmp r1, r0, lsl #16 209129202Scognet bcc .L_divide_b16 210129202Scognet cmp r1, r0, lsl #17 211129202Scognet bcc .L_divide_b17 212129202Scognet cmp r1, r0, lsl #18 213129202Scognet bcc .L_divide_b18 214129202Scognet cmp r1, r0, lsl #19 215129202Scognet bcc .L_divide_b19 216129202Scognet cmp r1, r0, lsl #20 217129202Scognet bcc .L_divide_b20 218129202Scognet cmp r1, r0, lsl #21 219129202Scognet bcc .L_divide_b21 220129202Scognet cmp r1, r0, lsl #22 221129202Scognet bcc .L_divide_b22 222129202Scognet cmp r1, r0, lsl #23 223129202Scognet bcc .L_divide_b23 224129202Scognet cmp r1, r0, lsl #24 225129202Scognet bcc .L_divide_b24 226129202Scognet cmp r1, r0, lsl #25 227129202Scognet bcc .L_divide_b25 228129202Scognet cmp r1, r0, lsl #26 229129202Scognet bcc .L_divide_b26 230129202Scognet cmp r1, r0, lsl #27 231129202Scognet bcc .L_divide_b27 232129202Scognet cmp r1, r0, lsl #28 233129202Scognet bcc .L_divide_b28 234129202Scognet cmp r1, r0, lsl #29 235129202Scognet bcc .L_divide_b29 236129202Scognet cmp r1, r0, lsl #30 237129202Scognet bcc .L_divide_b30 238129202Scognet.L_divide_b32: 239129202Scognet cmp r1, r0, lsl #31 240129202Scognet subhs r1, r1,r0, lsl #31 241129202Scognet addhs r3, r3,r2, lsl #31 242129202Scognet.L_divide_b31: 243129202Scognet cmp r1, r0, lsl #30 244129202Scognet subhs r1, r1,r0, lsl #30 245129202Scognet addhs r3, r3,r2, lsl #30 246129202Scognet.L_divide_b30: 247129202Scognet cmp r1, r0, lsl #29 248129202Scognet subhs r1, r1,r0, lsl #29 249129202Scognet addhs r3, r3,r2, lsl #29 250129202Scognet.L_divide_b29: 251129202Scognet cmp r1, r0, lsl #28 252129202Scognet subhs r1, r1,r0, lsl #28 253129202Scognet addhs r3, r3,r2, lsl #28 254129202Scognet.L_divide_b28: 255129202Scognet cmp r1, r0, lsl #27 256129202Scognet subhs r1, r1,r0, lsl #27 257129202Scognet addhs r3, r3,r2, lsl #27 258129202Scognet.L_divide_b27: 259129202Scognet cmp r1, r0, lsl #26 260129202Scognet subhs r1, r1,r0, lsl #26 261129202Scognet addhs r3, r3,r2, lsl #26 262129202Scognet.L_divide_b26: 263129202Scognet cmp r1, r0, lsl #25 264129202Scognet subhs r1, r1,r0, lsl #25 265129202Scognet addhs r3, r3,r2, lsl #25 266129202Scognet.L_divide_b25: 267129202Scognet cmp r1, r0, lsl #24 268129202Scognet subhs r1, r1,r0, lsl #24 269129202Scognet addhs r3, r3,r2, lsl #24 270129202Scognet.L_divide_b24: 271129202Scognet cmp r1, r0, lsl #23 272129202Scognet subhs r1, r1,r0, lsl #23 273129202Scognet addhs r3, r3,r2, lsl #23 274129202Scognet.L_divide_b23: 275129202Scognet cmp r1, r0, lsl #22 276129202Scognet subhs r1, r1,r0, lsl #22 277129202Scognet addhs r3, r3,r2, lsl #22 278129202Scognet.L_divide_b22: 279129202Scognet cmp r1, r0, lsl #21 280129202Scognet subhs r1, r1,r0, lsl #21 281129202Scognet addhs r3, r3,r2, lsl #21 282129202Scognet.L_divide_b21: 283129202Scognet cmp r1, r0, lsl #20 284129202Scognet subhs r1, r1,r0, lsl #20 285129202Scognet addhs r3, r3,r2, lsl #20 286129202Scognet.L_divide_b20: 287129202Scognet cmp r1, r0, lsl #19 288129202Scognet subhs r1, r1,r0, lsl #19 289129202Scognet addhs r3, r3,r2, lsl #19 290129202Scognet.L_divide_b19: 291129202Scognet cmp r1, r0, lsl #18 292129202Scognet subhs r1, r1,r0, lsl #18 293129202Scognet addhs r3, r3,r2, lsl #18 294129202Scognet.L_divide_b18: 295129202Scognet cmp r1, r0, lsl #17 296129202Scognet subhs r1, r1,r0, lsl #17 297129202Scognet addhs r3, r3,r2, lsl #17 298129202Scognet.L_divide_b17: 299129202Scognet cmp r1, r0, lsl #16 300129202Scognet subhs r1, r1,r0, lsl #16 301129202Scognet addhs r3, r3,r2, lsl #16 302129202Scognet.L_divide_b16: 303129202Scognet cmp r1, r0, lsl #15 304129202Scognet subhs r1, r1,r0, lsl #15 305129202Scognet addhs r3, r3,r2, lsl #15 306129202Scognet.L_divide_b15: 307129202Scognet cmp r1, r0, lsl #14 308129202Scognet subhs r1, r1,r0, lsl #14 309129202Scognet addhs r3, r3,r2, lsl #14 310129202Scognet.L_divide_b14: 311129202Scognet cmp r1, r0, lsl #13 312129202Scognet subhs r1, r1,r0, lsl #13 313129202Scognet addhs r3, r3,r2, lsl #13 314129202Scognet.L_divide_b13: 315129202Scognet cmp r1, r0, lsl #12 316129202Scognet subhs r1, r1,r0, lsl #12 317129202Scognet addhs r3, r3,r2, lsl #12 318129202Scognet.L_divide_b12: 319129202Scognet cmp r1, r0, lsl #11 320129202Scognet subhs r1, r1,r0, lsl #11 321129202Scognet addhs r3, r3,r2, lsl #11 322129202Scognet.L_divide_b11: 323129202Scognet cmp r1, r0, lsl #10 324129202Scognet subhs r1, r1,r0, lsl #10 325129202Scognet addhs r3, r3,r2, lsl #10 326129202Scognet.L_divide_b10: 327129202Scognet cmp r1, r0, lsl #9 328129202Scognet subhs r1, r1,r0, lsl #9 329129202Scognet addhs r3, r3,r2, lsl #9 330129202Scognet.L_divide_b9: 331129202Scognet cmp r1, r0, lsl #8 332129202Scognet subhs r1, r1,r0, lsl #8 333129202Scognet addhs r3, r3,r2, lsl #8 334129202Scognet.L_divide_b8: 335129202Scognet cmp r1, r0, lsl #7 336129202Scognet subhs r1, r1,r0, lsl #7 337129202Scognet addhs r3, r3,r2, lsl #7 338129202Scognet.L_divide_b7: 339129202Scognet cmp r1, r0, lsl #6 340129202Scognet subhs r1, r1,r0, lsl #6 341129202Scognet addhs r3, r3,r2, lsl #6 342129202Scognet.L_divide_b6: 343129202Scognet cmp r1, r0, lsl #5 344129202Scognet subhs r1, r1,r0, lsl #5 345129202Scognet addhs r3, r3,r2, lsl #5 346129202Scognet.L_divide_b5: 347129202Scognet cmp r1, r0, lsl #4 348129202Scognet subhs r1, r1,r0, lsl #4 349129202Scognet addhs r3, r3,r2, lsl #4 350129202Scognet.L_divide_b4: 351129202Scognet cmp r1, r0, lsl #3 352129202Scognet subhs r1, r1,r0, lsl #3 353129202Scognet addhs r3, r3,r2, lsl #3 354129202Scognet.L_divide_b3: 355129202Scognet cmp r1, r0, lsl #2 356129202Scognet subhs r1, r1,r0, lsl #2 357129202Scognet addhs r3, r3,r2, lsl #2 358129202Scognet.L_divide_b2: 359129202Scognet cmp r1, r0, lsl #1 360129202Scognet subhs r1, r1,r0, lsl #1 361129202Scognet addhs r3, r3,r2, lsl #1 362129202Scognet.L_divide_b1: 363129202Scognet cmp r1, r0 364129202Scognet subhs r1, r1, r0 365129202Scognet addhs r3, r3, r2 366129202Scognet.L_divide_b0: 367129202Scognet 368129202Scognet tst ip, #0x20000000 369129202Scognet bne .L_udivide_l1 370129202Scognet mov r0, r3 371129202Scognet cmp ip, #0 372129202Scognet rsbmi r1, r1, #0 373129202Scognet movs ip, ip, lsl #1 374129202Scognet bicmi r0, r0, #0x80000000 /* Fix incase we divided 0x80000000 */ 375129202Scognet rsbmi r0, r0, #0 376137464Scognet RET 377129202Scognet 378129202Scognet.L_udivide_l1: 379129202Scognet tst ip, #0x10000000 380129202Scognet mov r1, r1, lsl #1 381129202Scognet orrne r1, r1, #1 382129202Scognet mov r3, r3, lsl #1 383129202Scognet cmp r1, r0 384129202Scognet subhs r1, r1, r0 385129202Scognet addhs r3, r3, r2 386129202Scognet mov r0, r3 387137464Scognet RET 388