divsi3.S revision 136031
1129210Scognet/* $NetBSD: divsi3.S,v 1.4 2003/04/05 23:27:15 bjh21 Exp $ */ 2129210Scognet 3129210Scognet/* 4129210Scognet * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 5129210Scognet * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 6129210Scognet * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 7129210Scognet * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 8129210Scognet * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 9129210Scognet * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 10129210Scognet * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 11129210Scognet * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 12129210Scognet * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 13129210Scognet * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 14129210Scognet * SUCH DAMAGE. 15129210Scognet */ 16129210Scognet 17129210Scognet#include <machine/asm.h> 18129210Scognet__FBSDID("$FreeBSD: head/sys/libkern/arm/divsi3.S 136031 2004-10-01 16:44:08Z cognet $"); 19129210Scognet 20129210Scognet/* 21129210Scognet * stack is aligned as there's a possibility of branching to L_overflow 22129210Scognet * which makes a C call 23129210Scognet */ 24129210Scognet 25136031ScognetENTRY_NP(__umodsi3) 26129210Scognet stmfd sp!, {lr} 27129210Scognet sub sp, sp, #4 /* align stack */ 28129210Scognet bl .L_udivide 29129210Scognet add sp, sp, #4 /* unalign stack */ 30129210Scognet mov r0, r1 31129210Scognet ldmfd sp!, {pc} 32129210Scognet 33136031ScognetENTRY_NP(__modsi3) 34129210Scognet stmfd sp!, {lr} 35129210Scognet sub sp, sp, #4 /* align stack */ 36129210Scognet bl .L_divide 37129210Scognet add sp, sp, #4 /* unalign stack */ 38129210Scognet mov r0, r1 39129210Scognet ldmfd sp!, {pc} 40129210Scognet 41129210Scognet.L_overflow: 42129210Scognet#if !defined(_KERNEL) && !defined(_STANDALONE) 43129210Scognet mov r0, #8 /* SIGFPE */ 44129210Scognet bl PIC_SYM(_C_LABEL(raise), PLT) /* raise it */ 45129210Scognet mov r0, #0 46129210Scognet#else 47129210Scognet /* XXX should cause a fatal error */ 48129210Scognet mvn r0, #0 49129210Scognet#endif 50129210Scognet mov pc, lr 51129210Scognet 52136031ScognetENTRY_NP(__udivsi3) 53129210Scognet.L_udivide: /* r0 = r0 / r1; r1 = r0 % r1 */ 54129210Scognet eor r0, r1, r0 55129210Scognet eor r1, r0, r1 56129210Scognet eor r0, r1, r0 57129210Scognet /* r0 = r1 / r0; r1 = r1 % r0 */ 58129210Scognet cmp r0, #1 59129210Scognet bcc .L_overflow 60129210Scognet beq .L_divide_l0 61129210Scognet mov ip, #0 62129210Scognet movs r1, r1 63129210Scognet bpl .L_divide_l1 64129210Scognet orr ip, ip, #0x20000000 /* ip bit 0x20000000 = -ve r1 */ 65129210Scognet movs r1, r1, lsr #1 66129210Scognet orrcs ip, ip, #0x10000000 /* ip bit 0x10000000 = bit 0 of r1 */ 67129210Scognet b .L_divide_l1 68129210Scognet 69129210Scognet.L_divide_l0: /* r0 == 1 */ 70129210Scognet mov r0, r1 71129210Scognet mov r1, #0 72129210Scognet mov pc, lr 73129210Scognet 74136031ScognetENTRY_NP(__divsi3) 75129210Scognet.L_divide: /* r0 = r0 / r1; r1 = r0 % r1 */ 76129210Scognet eor r0, r1, r0 77129210Scognet eor r1, r0, r1 78129210Scognet eor r0, r1, r0 79129210Scognet /* r0 = r1 / r0; r1 = r1 % r0 */ 80129210Scognet cmp r0, #1 81129210Scognet bcc .L_overflow 82129210Scognet beq .L_divide_l0 83129210Scognet ands ip, r0, #0x80000000 84129210Scognet rsbmi r0, r0, #0 85129210Scognet ands r2, r1, #0x80000000 86129210Scognet eor ip, ip, r2 87129210Scognet rsbmi r1, r1, #0 88129210Scognet orr ip, r2, ip, lsr #1 /* ip bit 0x40000000 = -ve division */ 89129210Scognet /* ip bit 0x80000000 = -ve remainder */ 90129210Scognet 91129210Scognet.L_divide_l1: 92129210Scognet mov r2, #1 93129210Scognet mov r3, #0 94129210Scognet 95129210Scognet /* 96129210Scognet * If the highest bit of the dividend is set, we have to be 97129210Scognet * careful when shifting the divisor. Test this. 98129210Scognet */ 99129210Scognet movs r1,r1 100129210Scognet bpl .L_old_code 101129210Scognet 102129210Scognet /* 103129210Scognet * At this point, the highest bit of r1 is known to be set. 104129210Scognet * We abuse this below in the tst instructions. 105129210Scognet */ 106129210Scognet tst r1, r0 /*, lsl #0 */ 107129210Scognet bmi .L_divide_b1 108129210Scognet tst r1, r0, lsl #1 109129210Scognet bmi .L_divide_b2 110129210Scognet tst r1, r0, lsl #2 111129210Scognet bmi .L_divide_b3 112129210Scognet tst r1, r0, lsl #3 113129210Scognet bmi .L_divide_b4 114129210Scognet tst r1, r0, lsl #4 115129210Scognet bmi .L_divide_b5 116129210Scognet tst r1, r0, lsl #5 117129210Scognet bmi .L_divide_b6 118129210Scognet tst r1, r0, lsl #6 119129210Scognet bmi .L_divide_b7 120129210Scognet tst r1, r0, lsl #7 121129210Scognet bmi .L_divide_b8 122129210Scognet tst r1, r0, lsl #8 123129210Scognet bmi .L_divide_b9 124129210Scognet tst r1, r0, lsl #9 125129210Scognet bmi .L_divide_b10 126129210Scognet tst r1, r0, lsl #10 127129210Scognet bmi .L_divide_b11 128129210Scognet tst r1, r0, lsl #11 129129210Scognet bmi .L_divide_b12 130129210Scognet tst r1, r0, lsl #12 131129210Scognet bmi .L_divide_b13 132129210Scognet tst r1, r0, lsl #13 133129210Scognet bmi .L_divide_b14 134129210Scognet tst r1, r0, lsl #14 135129210Scognet bmi .L_divide_b15 136129210Scognet tst r1, r0, lsl #15 137129210Scognet bmi .L_divide_b16 138129210Scognet tst r1, r0, lsl #16 139129210Scognet bmi .L_divide_b17 140129210Scognet tst r1, r0, lsl #17 141129210Scognet bmi .L_divide_b18 142129210Scognet tst r1, r0, lsl #18 143129210Scognet bmi .L_divide_b19 144129210Scognet tst r1, r0, lsl #19 145129210Scognet bmi .L_divide_b20 146129210Scognet tst r1, r0, lsl #20 147129210Scognet bmi .L_divide_b21 148129210Scognet tst r1, r0, lsl #21 149129210Scognet bmi .L_divide_b22 150129210Scognet tst r1, r0, lsl #22 151129210Scognet bmi .L_divide_b23 152129210Scognet tst r1, r0, lsl #23 153129210Scognet bmi .L_divide_b24 154129210Scognet tst r1, r0, lsl #24 155129210Scognet bmi .L_divide_b25 156129210Scognet tst r1, r0, lsl #25 157129210Scognet bmi .L_divide_b26 158129210Scognet tst r1, r0, lsl #26 159129210Scognet bmi .L_divide_b27 160129210Scognet tst r1, r0, lsl #27 161129210Scognet bmi .L_divide_b28 162129210Scognet tst r1, r0, lsl #28 163129210Scognet bmi .L_divide_b29 164129210Scognet tst r1, r0, lsl #29 165129210Scognet bmi .L_divide_b30 166129210Scognet tst r1, r0, lsl #30 167129210Scognet bmi .L_divide_b31 168129210Scognet/* 169129210Scognet * instead of: 170129210Scognet * tst r1, r0, lsl #31 171129210Scognet * bmi .L_divide_b32 172129210Scognet */ 173129210Scognet b .L_divide_b32 174129210Scognet 175129210Scognet.L_old_code: 176129210Scognet cmp r1, r0 177129210Scognet bcc .L_divide_b0 178129210Scognet cmp r1, r0, lsl #1 179129210Scognet bcc .L_divide_b1 180129210Scognet cmp r1, r0, lsl #2 181129210Scognet bcc .L_divide_b2 182129210Scognet cmp r1, r0, lsl #3 183129210Scognet bcc .L_divide_b3 184129210Scognet cmp r1, r0, lsl #4 185129210Scognet bcc .L_divide_b4 186129210Scognet cmp r1, r0, lsl #5 187129210Scognet bcc .L_divide_b5 188129210Scognet cmp r1, r0, lsl #6 189129210Scognet bcc .L_divide_b6 190129210Scognet cmp r1, r0, lsl #7 191129210Scognet bcc .L_divide_b7 192129210Scognet cmp r1, r0, lsl #8 193129210Scognet bcc .L_divide_b8 194129210Scognet cmp r1, r0, lsl #9 195129210Scognet bcc .L_divide_b9 196129210Scognet cmp r1, r0, lsl #10 197129210Scognet bcc .L_divide_b10 198129210Scognet cmp r1, r0, lsl #11 199129210Scognet bcc .L_divide_b11 200129210Scognet cmp r1, r0, lsl #12 201129210Scognet bcc .L_divide_b12 202129210Scognet cmp r1, r0, lsl #13 203129210Scognet bcc .L_divide_b13 204129210Scognet cmp r1, r0, lsl #14 205129210Scognet bcc .L_divide_b14 206129210Scognet cmp r1, r0, lsl #15 207129210Scognet bcc .L_divide_b15 208129210Scognet cmp r1, r0, lsl #16 209129210Scognet bcc .L_divide_b16 210129210Scognet cmp r1, r0, lsl #17 211129210Scognet bcc .L_divide_b17 212129210Scognet cmp r1, r0, lsl #18 213129210Scognet bcc .L_divide_b18 214129210Scognet cmp r1, r0, lsl #19 215129210Scognet bcc .L_divide_b19 216129210Scognet cmp r1, r0, lsl #20 217129210Scognet bcc .L_divide_b20 218129210Scognet cmp r1, r0, lsl #21 219129210Scognet bcc .L_divide_b21 220129210Scognet cmp r1, r0, lsl #22 221129210Scognet bcc .L_divide_b22 222129210Scognet cmp r1, r0, lsl #23 223129210Scognet bcc .L_divide_b23 224129210Scognet cmp r1, r0, lsl #24 225129210Scognet bcc .L_divide_b24 226129210Scognet cmp r1, r0, lsl #25 227129210Scognet bcc .L_divide_b25 228129210Scognet cmp r1, r0, lsl #26 229129210Scognet bcc .L_divide_b26 230129210Scognet cmp r1, r0, lsl #27 231129210Scognet bcc .L_divide_b27 232129210Scognet cmp r1, r0, lsl #28 233129210Scognet bcc .L_divide_b28 234129210Scognet cmp r1, r0, lsl #29 235129210Scognet bcc .L_divide_b29 236129210Scognet cmp r1, r0, lsl #30 237129210Scognet bcc .L_divide_b30 238129210Scognet.L_divide_b32: 239129210Scognet cmp r1, r0, lsl #31 240129210Scognet subhs r1, r1,r0, lsl #31 241129210Scognet addhs r3, r3,r2, lsl #31 242129210Scognet.L_divide_b31: 243129210Scognet cmp r1, r0, lsl #30 244129210Scognet subhs r1, r1,r0, lsl #30 245129210Scognet addhs r3, r3,r2, lsl #30 246129210Scognet.L_divide_b30: 247129210Scognet cmp r1, r0, lsl #29 248129210Scognet subhs r1, r1,r0, lsl #29 249129210Scognet addhs r3, r3,r2, lsl #29 250129210Scognet.L_divide_b29: 251129210Scognet cmp r1, r0, lsl #28 252129210Scognet subhs r1, r1,r0, lsl #28 253129210Scognet addhs r3, r3,r2, lsl #28 254129210Scognet.L_divide_b28: 255129210Scognet cmp r1, r0, lsl #27 256129210Scognet subhs r1, r1,r0, lsl #27 257129210Scognet addhs r3, r3,r2, lsl #27 258129210Scognet.L_divide_b27: 259129210Scognet cmp r1, r0, lsl #26 260129210Scognet subhs r1, r1,r0, lsl #26 261129210Scognet addhs r3, r3,r2, lsl #26 262129210Scognet.L_divide_b26: 263129210Scognet cmp r1, r0, lsl #25 264129210Scognet subhs r1, r1,r0, lsl #25 265129210Scognet addhs r3, r3,r2, lsl #25 266129210Scognet.L_divide_b25: 267129210Scognet cmp r1, r0, lsl #24 268129210Scognet subhs r1, r1,r0, lsl #24 269129210Scognet addhs r3, r3,r2, lsl #24 270129210Scognet.L_divide_b24: 271129210Scognet cmp r1, r0, lsl #23 272129210Scognet subhs r1, r1,r0, lsl #23 273129210Scognet addhs r3, r3,r2, lsl #23 274129210Scognet.L_divide_b23: 275129210Scognet cmp r1, r0, lsl #22 276129210Scognet subhs r1, r1,r0, lsl #22 277129210Scognet addhs r3, r3,r2, lsl #22 278129210Scognet.L_divide_b22: 279129210Scognet cmp r1, r0, lsl #21 280129210Scognet subhs r1, r1,r0, lsl #21 281129210Scognet addhs r3, r3,r2, lsl #21 282129210Scognet.L_divide_b21: 283129210Scognet cmp r1, r0, lsl #20 284129210Scognet subhs r1, r1,r0, lsl #20 285129210Scognet addhs r3, r3,r2, lsl #20 286129210Scognet.L_divide_b20: 287129210Scognet cmp r1, r0, lsl #19 288129210Scognet subhs r1, r1,r0, lsl #19 289129210Scognet addhs r3, r3,r2, lsl #19 290129210Scognet.L_divide_b19: 291129210Scognet cmp r1, r0, lsl #18 292129210Scognet subhs r1, r1,r0, lsl #18 293129210Scognet addhs r3, r3,r2, lsl #18 294129210Scognet.L_divide_b18: 295129210Scognet cmp r1, r0, lsl #17 296129210Scognet subhs r1, r1,r0, lsl #17 297129210Scognet addhs r3, r3,r2, lsl #17 298129210Scognet.L_divide_b17: 299129210Scognet cmp r1, r0, lsl #16 300129210Scognet subhs r1, r1,r0, lsl #16 301129210Scognet addhs r3, r3,r2, lsl #16 302129210Scognet.L_divide_b16: 303129210Scognet cmp r1, r0, lsl #15 304129210Scognet subhs r1, r1,r0, lsl #15 305129210Scognet addhs r3, r3,r2, lsl #15 306129210Scognet.L_divide_b15: 307129210Scognet cmp r1, r0, lsl #14 308129210Scognet subhs r1, r1,r0, lsl #14 309129210Scognet addhs r3, r3,r2, lsl #14 310129210Scognet.L_divide_b14: 311129210Scognet cmp r1, r0, lsl #13 312129210Scognet subhs r1, r1,r0, lsl #13 313129210Scognet addhs r3, r3,r2, lsl #13 314129210Scognet.L_divide_b13: 315129210Scognet cmp r1, r0, lsl #12 316129210Scognet subhs r1, r1,r0, lsl #12 317129210Scognet addhs r3, r3,r2, lsl #12 318129210Scognet.L_divide_b12: 319129210Scognet cmp r1, r0, lsl #11 320129210Scognet subhs r1, r1,r0, lsl #11 321129210Scognet addhs r3, r3,r2, lsl #11 322129210Scognet.L_divide_b11: 323129210Scognet cmp r1, r0, lsl #10 324129210Scognet subhs r1, r1,r0, lsl #10 325129210Scognet addhs r3, r3,r2, lsl #10 326129210Scognet.L_divide_b10: 327129210Scognet cmp r1, r0, lsl #9 328129210Scognet subhs r1, r1,r0, lsl #9 329129210Scognet addhs r3, r3,r2, lsl #9 330129210Scognet.L_divide_b9: 331129210Scognet cmp r1, r0, lsl #8 332129210Scognet subhs r1, r1,r0, lsl #8 333129210Scognet addhs r3, r3,r2, lsl #8 334129210Scognet.L_divide_b8: 335129210Scognet cmp r1, r0, lsl #7 336129210Scognet subhs r1, r1,r0, lsl #7 337129210Scognet addhs r3, r3,r2, lsl #7 338129210Scognet.L_divide_b7: 339129210Scognet cmp r1, r0, lsl #6 340129210Scognet subhs r1, r1,r0, lsl #6 341129210Scognet addhs r3, r3,r2, lsl #6 342129210Scognet.L_divide_b6: 343129210Scognet cmp r1, r0, lsl #5 344129210Scognet subhs r1, r1,r0, lsl #5 345129210Scognet addhs r3, r3,r2, lsl #5 346129210Scognet.L_divide_b5: 347129210Scognet cmp r1, r0, lsl #4 348129210Scognet subhs r1, r1,r0, lsl #4 349129210Scognet addhs r3, r3,r2, lsl #4 350129210Scognet.L_divide_b4: 351129210Scognet cmp r1, r0, lsl #3 352129210Scognet subhs r1, r1,r0, lsl #3 353129210Scognet addhs r3, r3,r2, lsl #3 354129210Scognet.L_divide_b3: 355129210Scognet cmp r1, r0, lsl #2 356129210Scognet subhs r1, r1,r0, lsl #2 357129210Scognet addhs r3, r3,r2, lsl #2 358129210Scognet.L_divide_b2: 359129210Scognet cmp r1, r0, lsl #1 360129210Scognet subhs r1, r1,r0, lsl #1 361129210Scognet addhs r3, r3,r2, lsl #1 362129210Scognet.L_divide_b1: 363129210Scognet cmp r1, r0 364129210Scognet subhs r1, r1, r0 365129210Scognet addhs r3, r3, r2 366129210Scognet.L_divide_b0: 367129210Scognet 368129210Scognet tst ip, #0x20000000 369129210Scognet bne .L_udivide_l1 370129210Scognet mov r0, r3 371129210Scognet cmp ip, #0 372129210Scognet rsbmi r1, r1, #0 373129210Scognet movs ip, ip, lsl #1 374129210Scognet bicmi r0, r0, #0x80000000 /* Fix incase we divided 0x80000000 */ 375129210Scognet rsbmi r0, r0, #0 376129210Scognet mov pc, lr 377129210Scognet 378129210Scognet.L_udivide_l1: 379129210Scognet tst ip, #0x10000000 380129210Scognet mov r1, r1, lsl #1 381129210Scognet orrne r1, r1, #1 382129210Scognet mov r3, r3, lsl #1 383129210Scognet cmp r1, r0 384129210Scognet subhs r1, r1, r0 385129210Scognet addhs r3, r3, r2 386129210Scognet mov r0, r3 387129210Scognet mov pc, lr 388