divsi3.S revision 245548
1129210Scognet/* $NetBSD: divsi3.S,v 1.4 2003/04/05 23:27:15 bjh21 Exp $ */ 2129210Scognet 3139815Simp/*- 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 245548 2013-01-17 09:37:42Z andrew $"); 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 50137463Scognet RET 51129210Scognet 52245548Sandrew#ifdef __ARM_EABI__ 53245548SandrewENTRY_NP(__aeabi_uidiv) 54245548SandrewENTRY_NP(__aeabi_uidivmod) 55245548Sandrew#endif 56136031ScognetENTRY_NP(__udivsi3) 57129210Scognet.L_udivide: /* r0 = r0 / r1; r1 = r0 % r1 */ 58129210Scognet eor r0, r1, r0 59129210Scognet eor r1, r0, r1 60129210Scognet eor r0, r1, r0 61129210Scognet /* r0 = r1 / r0; r1 = r1 % r0 */ 62129210Scognet cmp r0, #1 63129210Scognet bcc .L_overflow 64129210Scognet beq .L_divide_l0 65129210Scognet mov ip, #0 66129210Scognet movs r1, r1 67129210Scognet bpl .L_divide_l1 68129210Scognet orr ip, ip, #0x20000000 /* ip bit 0x20000000 = -ve r1 */ 69129210Scognet movs r1, r1, lsr #1 70129210Scognet orrcs ip, ip, #0x10000000 /* ip bit 0x10000000 = bit 0 of r1 */ 71129210Scognet b .L_divide_l1 72129210Scognet 73129210Scognet.L_divide_l0: /* r0 == 1 */ 74129210Scognet mov r0, r1 75129210Scognet mov r1, #0 76137463Scognet RET 77129210Scognet 78245548Sandrew#ifdef __ARM_EABI__ 79245548SandrewENTRY_NP(__aeabi_idiv) 80245548SandrewENTRY_NP(__aeabi_idivmod) 81245548Sandrew#endif 82136031ScognetENTRY_NP(__divsi3) 83129210Scognet.L_divide: /* r0 = r0 / r1; r1 = r0 % r1 */ 84129210Scognet eor r0, r1, r0 85129210Scognet eor r1, r0, r1 86129210Scognet eor r0, r1, r0 87129210Scognet /* r0 = r1 / r0; r1 = r1 % r0 */ 88129210Scognet cmp r0, #1 89129210Scognet bcc .L_overflow 90129210Scognet beq .L_divide_l0 91129210Scognet ands ip, r0, #0x80000000 92129210Scognet rsbmi r0, r0, #0 93129210Scognet ands r2, r1, #0x80000000 94129210Scognet eor ip, ip, r2 95129210Scognet rsbmi r1, r1, #0 96129210Scognet orr ip, r2, ip, lsr #1 /* ip bit 0x40000000 = -ve division */ 97129210Scognet /* ip bit 0x80000000 = -ve remainder */ 98129210Scognet 99129210Scognet.L_divide_l1: 100129210Scognet mov r2, #1 101129210Scognet mov r3, #0 102129210Scognet 103129210Scognet /* 104129210Scognet * If the highest bit of the dividend is set, we have to be 105129210Scognet * careful when shifting the divisor. Test this. 106129210Scognet */ 107129210Scognet movs r1,r1 108129210Scognet bpl .L_old_code 109129210Scognet 110129210Scognet /* 111129210Scognet * At this point, the highest bit of r1 is known to be set. 112129210Scognet * We abuse this below in the tst instructions. 113129210Scognet */ 114129210Scognet tst r1, r0 /*, lsl #0 */ 115129210Scognet bmi .L_divide_b1 116129210Scognet tst r1, r0, lsl #1 117129210Scognet bmi .L_divide_b2 118129210Scognet tst r1, r0, lsl #2 119129210Scognet bmi .L_divide_b3 120129210Scognet tst r1, r0, lsl #3 121129210Scognet bmi .L_divide_b4 122129210Scognet tst r1, r0, lsl #4 123129210Scognet bmi .L_divide_b5 124129210Scognet tst r1, r0, lsl #5 125129210Scognet bmi .L_divide_b6 126129210Scognet tst r1, r0, lsl #6 127129210Scognet bmi .L_divide_b7 128129210Scognet tst r1, r0, lsl #7 129129210Scognet bmi .L_divide_b8 130129210Scognet tst r1, r0, lsl #8 131129210Scognet bmi .L_divide_b9 132129210Scognet tst r1, r0, lsl #9 133129210Scognet bmi .L_divide_b10 134129210Scognet tst r1, r0, lsl #10 135129210Scognet bmi .L_divide_b11 136129210Scognet tst r1, r0, lsl #11 137129210Scognet bmi .L_divide_b12 138129210Scognet tst r1, r0, lsl #12 139129210Scognet bmi .L_divide_b13 140129210Scognet tst r1, r0, lsl #13 141129210Scognet bmi .L_divide_b14 142129210Scognet tst r1, r0, lsl #14 143129210Scognet bmi .L_divide_b15 144129210Scognet tst r1, r0, lsl #15 145129210Scognet bmi .L_divide_b16 146129210Scognet tst r1, r0, lsl #16 147129210Scognet bmi .L_divide_b17 148129210Scognet tst r1, r0, lsl #17 149129210Scognet bmi .L_divide_b18 150129210Scognet tst r1, r0, lsl #18 151129210Scognet bmi .L_divide_b19 152129210Scognet tst r1, r0, lsl #19 153129210Scognet bmi .L_divide_b20 154129210Scognet tst r1, r0, lsl #20 155129210Scognet bmi .L_divide_b21 156129210Scognet tst r1, r0, lsl #21 157129210Scognet bmi .L_divide_b22 158129210Scognet tst r1, r0, lsl #22 159129210Scognet bmi .L_divide_b23 160129210Scognet tst r1, r0, lsl #23 161129210Scognet bmi .L_divide_b24 162129210Scognet tst r1, r0, lsl #24 163129210Scognet bmi .L_divide_b25 164129210Scognet tst r1, r0, lsl #25 165129210Scognet bmi .L_divide_b26 166129210Scognet tst r1, r0, lsl #26 167129210Scognet bmi .L_divide_b27 168129210Scognet tst r1, r0, lsl #27 169129210Scognet bmi .L_divide_b28 170129210Scognet tst r1, r0, lsl #28 171129210Scognet bmi .L_divide_b29 172129210Scognet tst r1, r0, lsl #29 173129210Scognet bmi .L_divide_b30 174129210Scognet tst r1, r0, lsl #30 175129210Scognet bmi .L_divide_b31 176129210Scognet/* 177129210Scognet * instead of: 178129210Scognet * tst r1, r0, lsl #31 179129210Scognet * bmi .L_divide_b32 180129210Scognet */ 181129210Scognet b .L_divide_b32 182129210Scognet 183129210Scognet.L_old_code: 184129210Scognet cmp r1, r0 185129210Scognet bcc .L_divide_b0 186129210Scognet cmp r1, r0, lsl #1 187129210Scognet bcc .L_divide_b1 188129210Scognet cmp r1, r0, lsl #2 189129210Scognet bcc .L_divide_b2 190129210Scognet cmp r1, r0, lsl #3 191129210Scognet bcc .L_divide_b3 192129210Scognet cmp r1, r0, lsl #4 193129210Scognet bcc .L_divide_b4 194129210Scognet cmp r1, r0, lsl #5 195129210Scognet bcc .L_divide_b5 196129210Scognet cmp r1, r0, lsl #6 197129210Scognet bcc .L_divide_b6 198129210Scognet cmp r1, r0, lsl #7 199129210Scognet bcc .L_divide_b7 200129210Scognet cmp r1, r0, lsl #8 201129210Scognet bcc .L_divide_b8 202129210Scognet cmp r1, r0, lsl #9 203129210Scognet bcc .L_divide_b9 204129210Scognet cmp r1, r0, lsl #10 205129210Scognet bcc .L_divide_b10 206129210Scognet cmp r1, r0, lsl #11 207129210Scognet bcc .L_divide_b11 208129210Scognet cmp r1, r0, lsl #12 209129210Scognet bcc .L_divide_b12 210129210Scognet cmp r1, r0, lsl #13 211129210Scognet bcc .L_divide_b13 212129210Scognet cmp r1, r0, lsl #14 213129210Scognet bcc .L_divide_b14 214129210Scognet cmp r1, r0, lsl #15 215129210Scognet bcc .L_divide_b15 216129210Scognet cmp r1, r0, lsl #16 217129210Scognet bcc .L_divide_b16 218129210Scognet cmp r1, r0, lsl #17 219129210Scognet bcc .L_divide_b17 220129210Scognet cmp r1, r0, lsl #18 221129210Scognet bcc .L_divide_b18 222129210Scognet cmp r1, r0, lsl #19 223129210Scognet bcc .L_divide_b19 224129210Scognet cmp r1, r0, lsl #20 225129210Scognet bcc .L_divide_b20 226129210Scognet cmp r1, r0, lsl #21 227129210Scognet bcc .L_divide_b21 228129210Scognet cmp r1, r0, lsl #22 229129210Scognet bcc .L_divide_b22 230129210Scognet cmp r1, r0, lsl #23 231129210Scognet bcc .L_divide_b23 232129210Scognet cmp r1, r0, lsl #24 233129210Scognet bcc .L_divide_b24 234129210Scognet cmp r1, r0, lsl #25 235129210Scognet bcc .L_divide_b25 236129210Scognet cmp r1, r0, lsl #26 237129210Scognet bcc .L_divide_b26 238129210Scognet cmp r1, r0, lsl #27 239129210Scognet bcc .L_divide_b27 240129210Scognet cmp r1, r0, lsl #28 241129210Scognet bcc .L_divide_b28 242129210Scognet cmp r1, r0, lsl #29 243129210Scognet bcc .L_divide_b29 244129210Scognet cmp r1, r0, lsl #30 245129210Scognet bcc .L_divide_b30 246129210Scognet.L_divide_b32: 247129210Scognet cmp r1, r0, lsl #31 248129210Scognet subhs r1, r1,r0, lsl #31 249129210Scognet addhs r3, r3,r2, lsl #31 250129210Scognet.L_divide_b31: 251129210Scognet cmp r1, r0, lsl #30 252129210Scognet subhs r1, r1,r0, lsl #30 253129210Scognet addhs r3, r3,r2, lsl #30 254129210Scognet.L_divide_b30: 255129210Scognet cmp r1, r0, lsl #29 256129210Scognet subhs r1, r1,r0, lsl #29 257129210Scognet addhs r3, r3,r2, lsl #29 258129210Scognet.L_divide_b29: 259129210Scognet cmp r1, r0, lsl #28 260129210Scognet subhs r1, r1,r0, lsl #28 261129210Scognet addhs r3, r3,r2, lsl #28 262129210Scognet.L_divide_b28: 263129210Scognet cmp r1, r0, lsl #27 264129210Scognet subhs r1, r1,r0, lsl #27 265129210Scognet addhs r3, r3,r2, lsl #27 266129210Scognet.L_divide_b27: 267129210Scognet cmp r1, r0, lsl #26 268129210Scognet subhs r1, r1,r0, lsl #26 269129210Scognet addhs r3, r3,r2, lsl #26 270129210Scognet.L_divide_b26: 271129210Scognet cmp r1, r0, lsl #25 272129210Scognet subhs r1, r1,r0, lsl #25 273129210Scognet addhs r3, r3,r2, lsl #25 274129210Scognet.L_divide_b25: 275129210Scognet cmp r1, r0, lsl #24 276129210Scognet subhs r1, r1,r0, lsl #24 277129210Scognet addhs r3, r3,r2, lsl #24 278129210Scognet.L_divide_b24: 279129210Scognet cmp r1, r0, lsl #23 280129210Scognet subhs r1, r1,r0, lsl #23 281129210Scognet addhs r3, r3,r2, lsl #23 282129210Scognet.L_divide_b23: 283129210Scognet cmp r1, r0, lsl #22 284129210Scognet subhs r1, r1,r0, lsl #22 285129210Scognet addhs r3, r3,r2, lsl #22 286129210Scognet.L_divide_b22: 287129210Scognet cmp r1, r0, lsl #21 288129210Scognet subhs r1, r1,r0, lsl #21 289129210Scognet addhs r3, r3,r2, lsl #21 290129210Scognet.L_divide_b21: 291129210Scognet cmp r1, r0, lsl #20 292129210Scognet subhs r1, r1,r0, lsl #20 293129210Scognet addhs r3, r3,r2, lsl #20 294129210Scognet.L_divide_b20: 295129210Scognet cmp r1, r0, lsl #19 296129210Scognet subhs r1, r1,r0, lsl #19 297129210Scognet addhs r3, r3,r2, lsl #19 298129210Scognet.L_divide_b19: 299129210Scognet cmp r1, r0, lsl #18 300129210Scognet subhs r1, r1,r0, lsl #18 301129210Scognet addhs r3, r3,r2, lsl #18 302129210Scognet.L_divide_b18: 303129210Scognet cmp r1, r0, lsl #17 304129210Scognet subhs r1, r1,r0, lsl #17 305129210Scognet addhs r3, r3,r2, lsl #17 306129210Scognet.L_divide_b17: 307129210Scognet cmp r1, r0, lsl #16 308129210Scognet subhs r1, r1,r0, lsl #16 309129210Scognet addhs r3, r3,r2, lsl #16 310129210Scognet.L_divide_b16: 311129210Scognet cmp r1, r0, lsl #15 312129210Scognet subhs r1, r1,r0, lsl #15 313129210Scognet addhs r3, r3,r2, lsl #15 314129210Scognet.L_divide_b15: 315129210Scognet cmp r1, r0, lsl #14 316129210Scognet subhs r1, r1,r0, lsl #14 317129210Scognet addhs r3, r3,r2, lsl #14 318129210Scognet.L_divide_b14: 319129210Scognet cmp r1, r0, lsl #13 320129210Scognet subhs r1, r1,r0, lsl #13 321129210Scognet addhs r3, r3,r2, lsl #13 322129210Scognet.L_divide_b13: 323129210Scognet cmp r1, r0, lsl #12 324129210Scognet subhs r1, r1,r0, lsl #12 325129210Scognet addhs r3, r3,r2, lsl #12 326129210Scognet.L_divide_b12: 327129210Scognet cmp r1, r0, lsl #11 328129210Scognet subhs r1, r1,r0, lsl #11 329129210Scognet addhs r3, r3,r2, lsl #11 330129210Scognet.L_divide_b11: 331129210Scognet cmp r1, r0, lsl #10 332129210Scognet subhs r1, r1,r0, lsl #10 333129210Scognet addhs r3, r3,r2, lsl #10 334129210Scognet.L_divide_b10: 335129210Scognet cmp r1, r0, lsl #9 336129210Scognet subhs r1, r1,r0, lsl #9 337129210Scognet addhs r3, r3,r2, lsl #9 338129210Scognet.L_divide_b9: 339129210Scognet cmp r1, r0, lsl #8 340129210Scognet subhs r1, r1,r0, lsl #8 341129210Scognet addhs r3, r3,r2, lsl #8 342129210Scognet.L_divide_b8: 343129210Scognet cmp r1, r0, lsl #7 344129210Scognet subhs r1, r1,r0, lsl #7 345129210Scognet addhs r3, r3,r2, lsl #7 346129210Scognet.L_divide_b7: 347129210Scognet cmp r1, r0, lsl #6 348129210Scognet subhs r1, r1,r0, lsl #6 349129210Scognet addhs r3, r3,r2, lsl #6 350129210Scognet.L_divide_b6: 351129210Scognet cmp r1, r0, lsl #5 352129210Scognet subhs r1, r1,r0, lsl #5 353129210Scognet addhs r3, r3,r2, lsl #5 354129210Scognet.L_divide_b5: 355129210Scognet cmp r1, r0, lsl #4 356129210Scognet subhs r1, r1,r0, lsl #4 357129210Scognet addhs r3, r3,r2, lsl #4 358129210Scognet.L_divide_b4: 359129210Scognet cmp r1, r0, lsl #3 360129210Scognet subhs r1, r1,r0, lsl #3 361129210Scognet addhs r3, r3,r2, lsl #3 362129210Scognet.L_divide_b3: 363129210Scognet cmp r1, r0, lsl #2 364129210Scognet subhs r1, r1,r0, lsl #2 365129210Scognet addhs r3, r3,r2, lsl #2 366129210Scognet.L_divide_b2: 367129210Scognet cmp r1, r0, lsl #1 368129210Scognet subhs r1, r1,r0, lsl #1 369129210Scognet addhs r3, r3,r2, lsl #1 370129210Scognet.L_divide_b1: 371129210Scognet cmp r1, r0 372129210Scognet subhs r1, r1, r0 373129210Scognet addhs r3, r3, r2 374129210Scognet.L_divide_b0: 375129210Scognet 376129210Scognet tst ip, #0x20000000 377129210Scognet bne .L_udivide_l1 378129210Scognet mov r0, r3 379129210Scognet cmp ip, #0 380129210Scognet rsbmi r1, r1, #0 381129210Scognet movs ip, ip, lsl #1 382129210Scognet bicmi r0, r0, #0x80000000 /* Fix incase we divided 0x80000000 */ 383129210Scognet rsbmi r0, r0, #0 384137463Scognet RET 385129210Scognet 386129210Scognet.L_udivide_l1: 387129210Scognet tst ip, #0x10000000 388129210Scognet mov r1, r1, lsl #1 389129210Scognet orrne r1, r1, #1 390129210Scognet mov r3, r3, lsl #1 391129210Scognet cmp r1, r0 392129210Scognet subhs r1, r1, r0 393129210Scognet addhs r3, r3, r2 394129210Scognet mov r0, r3 395137463Scognet RET 396