divsi3.S revision 248367
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 248367 2013-03-16 04:08:01Z 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} 32248367SandrewEND(__umodsi3) 33129210Scognet 34136031ScognetENTRY_NP(__modsi3) 35129210Scognet stmfd sp!, {lr} 36129210Scognet sub sp, sp, #4 /* align stack */ 37129210Scognet bl .L_divide 38129210Scognet add sp, sp, #4 /* unalign stack */ 39129210Scognet mov r0, r1 40129210Scognet ldmfd sp!, {pc} 41129210Scognet 42129210Scognet.L_overflow: 43129210Scognet#if !defined(_KERNEL) && !defined(_STANDALONE) 44129210Scognet mov r0, #8 /* SIGFPE */ 45129210Scognet bl PIC_SYM(_C_LABEL(raise), PLT) /* raise it */ 46129210Scognet mov r0, #0 47129210Scognet#else 48129210Scognet /* XXX should cause a fatal error */ 49129210Scognet mvn r0, #0 50129210Scognet#endif 51137463Scognet RET 52248367SandrewEND(__modsi3) 53129210Scognet 54245548Sandrew#ifdef __ARM_EABI__ 55245548SandrewENTRY_NP(__aeabi_uidiv) 56245548SandrewENTRY_NP(__aeabi_uidivmod) 57245548Sandrew#endif 58136031ScognetENTRY_NP(__udivsi3) 59129210Scognet.L_udivide: /* r0 = r0 / r1; r1 = r0 % r1 */ 60129210Scognet eor r0, r1, r0 61129210Scognet eor r1, r0, r1 62129210Scognet eor r0, r1, r0 63129210Scognet /* r0 = r1 / r0; r1 = r1 % r0 */ 64129210Scognet cmp r0, #1 65129210Scognet bcc .L_overflow 66129210Scognet beq .L_divide_l0 67129210Scognet mov ip, #0 68129210Scognet movs r1, r1 69129210Scognet bpl .L_divide_l1 70129210Scognet orr ip, ip, #0x20000000 /* ip bit 0x20000000 = -ve r1 */ 71129210Scognet movs r1, r1, lsr #1 72129210Scognet orrcs ip, ip, #0x10000000 /* ip bit 0x10000000 = bit 0 of r1 */ 73129210Scognet b .L_divide_l1 74129210Scognet 75129210Scognet.L_divide_l0: /* r0 == 1 */ 76129210Scognet mov r0, r1 77129210Scognet mov r1, #0 78137463Scognet RET 79248367Sandrew#ifdef __ARM_EABI__ 80248367SandrewEND(__aeabi_uidiv) 81248367SandrewEND(__aeabi_uidivmod) 82248367Sandrew#endif 83248367SandrewEND(__udivsi3) 84129210Scognet 85245548Sandrew#ifdef __ARM_EABI__ 86245548SandrewENTRY_NP(__aeabi_idiv) 87245548SandrewENTRY_NP(__aeabi_idivmod) 88245548Sandrew#endif 89136031ScognetENTRY_NP(__divsi3) 90129210Scognet.L_divide: /* r0 = r0 / r1; r1 = r0 % r1 */ 91129210Scognet eor r0, r1, r0 92129210Scognet eor r1, r0, r1 93129210Scognet eor r0, r1, r0 94129210Scognet /* r0 = r1 / r0; r1 = r1 % r0 */ 95129210Scognet cmp r0, #1 96129210Scognet bcc .L_overflow 97129210Scognet beq .L_divide_l0 98129210Scognet ands ip, r0, #0x80000000 99129210Scognet rsbmi r0, r0, #0 100129210Scognet ands r2, r1, #0x80000000 101129210Scognet eor ip, ip, r2 102129210Scognet rsbmi r1, r1, #0 103129210Scognet orr ip, r2, ip, lsr #1 /* ip bit 0x40000000 = -ve division */ 104129210Scognet /* ip bit 0x80000000 = -ve remainder */ 105129210Scognet 106129210Scognet.L_divide_l1: 107129210Scognet mov r2, #1 108129210Scognet mov r3, #0 109129210Scognet 110129210Scognet /* 111129210Scognet * If the highest bit of the dividend is set, we have to be 112129210Scognet * careful when shifting the divisor. Test this. 113129210Scognet */ 114129210Scognet movs r1,r1 115129210Scognet bpl .L_old_code 116129210Scognet 117129210Scognet /* 118129210Scognet * At this point, the highest bit of r1 is known to be set. 119129210Scognet * We abuse this below in the tst instructions. 120129210Scognet */ 121129210Scognet tst r1, r0 /*, lsl #0 */ 122129210Scognet bmi .L_divide_b1 123129210Scognet tst r1, r0, lsl #1 124129210Scognet bmi .L_divide_b2 125129210Scognet tst r1, r0, lsl #2 126129210Scognet bmi .L_divide_b3 127129210Scognet tst r1, r0, lsl #3 128129210Scognet bmi .L_divide_b4 129129210Scognet tst r1, r0, lsl #4 130129210Scognet bmi .L_divide_b5 131129210Scognet tst r1, r0, lsl #5 132129210Scognet bmi .L_divide_b6 133129210Scognet tst r1, r0, lsl #6 134129210Scognet bmi .L_divide_b7 135129210Scognet tst r1, r0, lsl #7 136129210Scognet bmi .L_divide_b8 137129210Scognet tst r1, r0, lsl #8 138129210Scognet bmi .L_divide_b9 139129210Scognet tst r1, r0, lsl #9 140129210Scognet bmi .L_divide_b10 141129210Scognet tst r1, r0, lsl #10 142129210Scognet bmi .L_divide_b11 143129210Scognet tst r1, r0, lsl #11 144129210Scognet bmi .L_divide_b12 145129210Scognet tst r1, r0, lsl #12 146129210Scognet bmi .L_divide_b13 147129210Scognet tst r1, r0, lsl #13 148129210Scognet bmi .L_divide_b14 149129210Scognet tst r1, r0, lsl #14 150129210Scognet bmi .L_divide_b15 151129210Scognet tst r1, r0, lsl #15 152129210Scognet bmi .L_divide_b16 153129210Scognet tst r1, r0, lsl #16 154129210Scognet bmi .L_divide_b17 155129210Scognet tst r1, r0, lsl #17 156129210Scognet bmi .L_divide_b18 157129210Scognet tst r1, r0, lsl #18 158129210Scognet bmi .L_divide_b19 159129210Scognet tst r1, r0, lsl #19 160129210Scognet bmi .L_divide_b20 161129210Scognet tst r1, r0, lsl #20 162129210Scognet bmi .L_divide_b21 163129210Scognet tst r1, r0, lsl #21 164129210Scognet bmi .L_divide_b22 165129210Scognet tst r1, r0, lsl #22 166129210Scognet bmi .L_divide_b23 167129210Scognet tst r1, r0, lsl #23 168129210Scognet bmi .L_divide_b24 169129210Scognet tst r1, r0, lsl #24 170129210Scognet bmi .L_divide_b25 171129210Scognet tst r1, r0, lsl #25 172129210Scognet bmi .L_divide_b26 173129210Scognet tst r1, r0, lsl #26 174129210Scognet bmi .L_divide_b27 175129210Scognet tst r1, r0, lsl #27 176129210Scognet bmi .L_divide_b28 177129210Scognet tst r1, r0, lsl #28 178129210Scognet bmi .L_divide_b29 179129210Scognet tst r1, r0, lsl #29 180129210Scognet bmi .L_divide_b30 181129210Scognet tst r1, r0, lsl #30 182129210Scognet bmi .L_divide_b31 183129210Scognet/* 184129210Scognet * instead of: 185129210Scognet * tst r1, r0, lsl #31 186129210Scognet * bmi .L_divide_b32 187129210Scognet */ 188129210Scognet b .L_divide_b32 189129210Scognet 190129210Scognet.L_old_code: 191129210Scognet cmp r1, r0 192129210Scognet bcc .L_divide_b0 193129210Scognet cmp r1, r0, lsl #1 194129210Scognet bcc .L_divide_b1 195129210Scognet cmp r1, r0, lsl #2 196129210Scognet bcc .L_divide_b2 197129210Scognet cmp r1, r0, lsl #3 198129210Scognet bcc .L_divide_b3 199129210Scognet cmp r1, r0, lsl #4 200129210Scognet bcc .L_divide_b4 201129210Scognet cmp r1, r0, lsl #5 202129210Scognet bcc .L_divide_b5 203129210Scognet cmp r1, r0, lsl #6 204129210Scognet bcc .L_divide_b6 205129210Scognet cmp r1, r0, lsl #7 206129210Scognet bcc .L_divide_b7 207129210Scognet cmp r1, r0, lsl #8 208129210Scognet bcc .L_divide_b8 209129210Scognet cmp r1, r0, lsl #9 210129210Scognet bcc .L_divide_b9 211129210Scognet cmp r1, r0, lsl #10 212129210Scognet bcc .L_divide_b10 213129210Scognet cmp r1, r0, lsl #11 214129210Scognet bcc .L_divide_b11 215129210Scognet cmp r1, r0, lsl #12 216129210Scognet bcc .L_divide_b12 217129210Scognet cmp r1, r0, lsl #13 218129210Scognet bcc .L_divide_b13 219129210Scognet cmp r1, r0, lsl #14 220129210Scognet bcc .L_divide_b14 221129210Scognet cmp r1, r0, lsl #15 222129210Scognet bcc .L_divide_b15 223129210Scognet cmp r1, r0, lsl #16 224129210Scognet bcc .L_divide_b16 225129210Scognet cmp r1, r0, lsl #17 226129210Scognet bcc .L_divide_b17 227129210Scognet cmp r1, r0, lsl #18 228129210Scognet bcc .L_divide_b18 229129210Scognet cmp r1, r0, lsl #19 230129210Scognet bcc .L_divide_b19 231129210Scognet cmp r1, r0, lsl #20 232129210Scognet bcc .L_divide_b20 233129210Scognet cmp r1, r0, lsl #21 234129210Scognet bcc .L_divide_b21 235129210Scognet cmp r1, r0, lsl #22 236129210Scognet bcc .L_divide_b22 237129210Scognet cmp r1, r0, lsl #23 238129210Scognet bcc .L_divide_b23 239129210Scognet cmp r1, r0, lsl #24 240129210Scognet bcc .L_divide_b24 241129210Scognet cmp r1, r0, lsl #25 242129210Scognet bcc .L_divide_b25 243129210Scognet cmp r1, r0, lsl #26 244129210Scognet bcc .L_divide_b26 245129210Scognet cmp r1, r0, lsl #27 246129210Scognet bcc .L_divide_b27 247129210Scognet cmp r1, r0, lsl #28 248129210Scognet bcc .L_divide_b28 249129210Scognet cmp r1, r0, lsl #29 250129210Scognet bcc .L_divide_b29 251129210Scognet cmp r1, r0, lsl #30 252129210Scognet bcc .L_divide_b30 253129210Scognet.L_divide_b32: 254129210Scognet cmp r1, r0, lsl #31 255129210Scognet subhs r1, r1,r0, lsl #31 256129210Scognet addhs r3, r3,r2, lsl #31 257129210Scognet.L_divide_b31: 258129210Scognet cmp r1, r0, lsl #30 259129210Scognet subhs r1, r1,r0, lsl #30 260129210Scognet addhs r3, r3,r2, lsl #30 261129210Scognet.L_divide_b30: 262129210Scognet cmp r1, r0, lsl #29 263129210Scognet subhs r1, r1,r0, lsl #29 264129210Scognet addhs r3, r3,r2, lsl #29 265129210Scognet.L_divide_b29: 266129210Scognet cmp r1, r0, lsl #28 267129210Scognet subhs r1, r1,r0, lsl #28 268129210Scognet addhs r3, r3,r2, lsl #28 269129210Scognet.L_divide_b28: 270129210Scognet cmp r1, r0, lsl #27 271129210Scognet subhs r1, r1,r0, lsl #27 272129210Scognet addhs r3, r3,r2, lsl #27 273129210Scognet.L_divide_b27: 274129210Scognet cmp r1, r0, lsl #26 275129210Scognet subhs r1, r1,r0, lsl #26 276129210Scognet addhs r3, r3,r2, lsl #26 277129210Scognet.L_divide_b26: 278129210Scognet cmp r1, r0, lsl #25 279129210Scognet subhs r1, r1,r0, lsl #25 280129210Scognet addhs r3, r3,r2, lsl #25 281129210Scognet.L_divide_b25: 282129210Scognet cmp r1, r0, lsl #24 283129210Scognet subhs r1, r1,r0, lsl #24 284129210Scognet addhs r3, r3,r2, lsl #24 285129210Scognet.L_divide_b24: 286129210Scognet cmp r1, r0, lsl #23 287129210Scognet subhs r1, r1,r0, lsl #23 288129210Scognet addhs r3, r3,r2, lsl #23 289129210Scognet.L_divide_b23: 290129210Scognet cmp r1, r0, lsl #22 291129210Scognet subhs r1, r1,r0, lsl #22 292129210Scognet addhs r3, r3,r2, lsl #22 293129210Scognet.L_divide_b22: 294129210Scognet cmp r1, r0, lsl #21 295129210Scognet subhs r1, r1,r0, lsl #21 296129210Scognet addhs r3, r3,r2, lsl #21 297129210Scognet.L_divide_b21: 298129210Scognet cmp r1, r0, lsl #20 299129210Scognet subhs r1, r1,r0, lsl #20 300129210Scognet addhs r3, r3,r2, lsl #20 301129210Scognet.L_divide_b20: 302129210Scognet cmp r1, r0, lsl #19 303129210Scognet subhs r1, r1,r0, lsl #19 304129210Scognet addhs r3, r3,r2, lsl #19 305129210Scognet.L_divide_b19: 306129210Scognet cmp r1, r0, lsl #18 307129210Scognet subhs r1, r1,r0, lsl #18 308129210Scognet addhs r3, r3,r2, lsl #18 309129210Scognet.L_divide_b18: 310129210Scognet cmp r1, r0, lsl #17 311129210Scognet subhs r1, r1,r0, lsl #17 312129210Scognet addhs r3, r3,r2, lsl #17 313129210Scognet.L_divide_b17: 314129210Scognet cmp r1, r0, lsl #16 315129210Scognet subhs r1, r1,r0, lsl #16 316129210Scognet addhs r3, r3,r2, lsl #16 317129210Scognet.L_divide_b16: 318129210Scognet cmp r1, r0, lsl #15 319129210Scognet subhs r1, r1,r0, lsl #15 320129210Scognet addhs r3, r3,r2, lsl #15 321129210Scognet.L_divide_b15: 322129210Scognet cmp r1, r0, lsl #14 323129210Scognet subhs r1, r1,r0, lsl #14 324129210Scognet addhs r3, r3,r2, lsl #14 325129210Scognet.L_divide_b14: 326129210Scognet cmp r1, r0, lsl #13 327129210Scognet subhs r1, r1,r0, lsl #13 328129210Scognet addhs r3, r3,r2, lsl #13 329129210Scognet.L_divide_b13: 330129210Scognet cmp r1, r0, lsl #12 331129210Scognet subhs r1, r1,r0, lsl #12 332129210Scognet addhs r3, r3,r2, lsl #12 333129210Scognet.L_divide_b12: 334129210Scognet cmp r1, r0, lsl #11 335129210Scognet subhs r1, r1,r0, lsl #11 336129210Scognet addhs r3, r3,r2, lsl #11 337129210Scognet.L_divide_b11: 338129210Scognet cmp r1, r0, lsl #10 339129210Scognet subhs r1, r1,r0, lsl #10 340129210Scognet addhs r3, r3,r2, lsl #10 341129210Scognet.L_divide_b10: 342129210Scognet cmp r1, r0, lsl #9 343129210Scognet subhs r1, r1,r0, lsl #9 344129210Scognet addhs r3, r3,r2, lsl #9 345129210Scognet.L_divide_b9: 346129210Scognet cmp r1, r0, lsl #8 347129210Scognet subhs r1, r1,r0, lsl #8 348129210Scognet addhs r3, r3,r2, lsl #8 349129210Scognet.L_divide_b8: 350129210Scognet cmp r1, r0, lsl #7 351129210Scognet subhs r1, r1,r0, lsl #7 352129210Scognet addhs r3, r3,r2, lsl #7 353129210Scognet.L_divide_b7: 354129210Scognet cmp r1, r0, lsl #6 355129210Scognet subhs r1, r1,r0, lsl #6 356129210Scognet addhs r3, r3,r2, lsl #6 357129210Scognet.L_divide_b6: 358129210Scognet cmp r1, r0, lsl #5 359129210Scognet subhs r1, r1,r0, lsl #5 360129210Scognet addhs r3, r3,r2, lsl #5 361129210Scognet.L_divide_b5: 362129210Scognet cmp r1, r0, lsl #4 363129210Scognet subhs r1, r1,r0, lsl #4 364129210Scognet addhs r3, r3,r2, lsl #4 365129210Scognet.L_divide_b4: 366129210Scognet cmp r1, r0, lsl #3 367129210Scognet subhs r1, r1,r0, lsl #3 368129210Scognet addhs r3, r3,r2, lsl #3 369129210Scognet.L_divide_b3: 370129210Scognet cmp r1, r0, lsl #2 371129210Scognet subhs r1, r1,r0, lsl #2 372129210Scognet addhs r3, r3,r2, lsl #2 373129210Scognet.L_divide_b2: 374129210Scognet cmp r1, r0, lsl #1 375129210Scognet subhs r1, r1,r0, lsl #1 376129210Scognet addhs r3, r3,r2, lsl #1 377129210Scognet.L_divide_b1: 378129210Scognet cmp r1, r0 379129210Scognet subhs r1, r1, r0 380129210Scognet addhs r3, r3, r2 381129210Scognet.L_divide_b0: 382129210Scognet 383129210Scognet tst ip, #0x20000000 384129210Scognet bne .L_udivide_l1 385129210Scognet mov r0, r3 386129210Scognet cmp ip, #0 387129210Scognet rsbmi r1, r1, #0 388129210Scognet movs ip, ip, lsl #1 389129210Scognet bicmi r0, r0, #0x80000000 /* Fix incase we divided 0x80000000 */ 390129210Scognet rsbmi r0, r0, #0 391137463Scognet RET 392129210Scognet 393129210Scognet.L_udivide_l1: 394129210Scognet tst ip, #0x10000000 395129210Scognet mov r1, r1, lsl #1 396129210Scognet orrne r1, r1, #1 397129210Scognet mov r3, r3, lsl #1 398129210Scognet cmp r1, r0 399129210Scognet subhs r1, r1, r0 400129210Scognet addhs r3, r3, r2 401129210Scognet mov r0, r3 402137463Scognet RET 403248367Sandrew#ifdef __ARM_EABI__ 404248367SandrewEND(__aeabi_idiv) 405248367SandrewEND(__aeabi_idivmod) 406248367Sandrew#endif 407248367SandrewEND(__divsi3) 408248367Sandrew 409