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