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: releng/10.3/lib/libc/arm/gen/divsi3.S 271337 2014-09-09 22:24:01Z ian $"); 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} 32271337SianEND(__umodsi3) 33129202Scognet 34129202ScognetENTRY(__modsi3) 35129202Scognet stmfd sp!, {lr} 36129202Scognet sub sp, sp, #4 /* align stack */ 37129202Scognet bl .L_divide 38129202Scognet add sp, sp, #4 /* unalign stack */ 39129202Scognet mov r0, r1 40129202Scognet ldmfd sp!, {pc} 41129202Scognet 42129202Scognet.L_overflow: 43129202Scognet#if !defined(_KERNEL) && !defined(_STANDALONE) 44129202Scognet mov r0, #8 /* SIGFPE */ 45129202Scognet bl PIC_SYM(_C_LABEL(raise), PLT) /* raise it */ 46129202Scognet mov r0, #0 47129202Scognet#else 48129202Scognet /* XXX should cause a fatal error */ 49129202Scognet mvn r0, #0 50129202Scognet#endif 51137464Scognet RET 52271337SianEND(__modsi3) 53129202Scognet 54129202ScognetENTRY(__udivsi3) 55129202Scognet.L_udivide: /* r0 = r0 / r1; r1 = r0 % r1 */ 56129202Scognet eor r0, r1, r0 57129202Scognet eor r1, r0, r1 58129202Scognet eor r0, r1, r0 59129202Scognet /* r0 = r1 / r0; r1 = r1 % r0 */ 60129202Scognet cmp r0, #1 61129202Scognet bcc .L_overflow 62129202Scognet beq .L_divide_l0 63129202Scognet mov ip, #0 64129202Scognet movs r1, r1 65129202Scognet bpl .L_divide_l1 66129202Scognet orr ip, ip, #0x20000000 /* ip bit 0x20000000 = -ve r1 */ 67129202Scognet movs r1, r1, lsr #1 68129202Scognet orrcs ip, ip, #0x10000000 /* ip bit 0x10000000 = bit 0 of r1 */ 69129202Scognet b .L_divide_l1 70129202Scognet 71129202Scognet.L_divide_l0: /* r0 == 1 */ 72129202Scognet mov r0, r1 73129202Scognet mov r1, #0 74137464Scognet RET 75271337SianEND(__udivsi3) 76129202Scognet 77129202ScognetENTRY(__divsi3) 78129202Scognet.L_divide: /* r0 = r0 / r1; r1 = r0 % r1 */ 79129202Scognet eor r0, r1, r0 80129202Scognet eor r1, r0, r1 81129202Scognet eor r0, r1, r0 82129202Scognet /* r0 = r1 / r0; r1 = r1 % r0 */ 83129202Scognet cmp r0, #1 84129202Scognet bcc .L_overflow 85129202Scognet beq .L_divide_l0 86129202Scognet ands ip, r0, #0x80000000 87129202Scognet rsbmi r0, r0, #0 88129202Scognet ands r2, r1, #0x80000000 89129202Scognet eor ip, ip, r2 90129202Scognet rsbmi r1, r1, #0 91129202Scognet orr ip, r2, ip, lsr #1 /* ip bit 0x40000000 = -ve division */ 92129202Scognet /* ip bit 0x80000000 = -ve remainder */ 93129202Scognet 94129202Scognet.L_divide_l1: 95129202Scognet mov r2, #1 96129202Scognet mov r3, #0 97129202Scognet 98129202Scognet /* 99129202Scognet * If the highest bit of the dividend is set, we have to be 100129202Scognet * careful when shifting the divisor. Test this. 101129202Scognet */ 102129202Scognet movs r1,r1 103129202Scognet bpl .L_old_code 104129202Scognet 105129202Scognet /* 106129202Scognet * At this point, the highest bit of r1 is known to be set. 107129202Scognet * We abuse this below in the tst instructions. 108129202Scognet */ 109129202Scognet tst r1, r0 /*, lsl #0 */ 110129202Scognet bmi .L_divide_b1 111129202Scognet tst r1, r0, lsl #1 112129202Scognet bmi .L_divide_b2 113129202Scognet tst r1, r0, lsl #2 114129202Scognet bmi .L_divide_b3 115129202Scognet tst r1, r0, lsl #3 116129202Scognet bmi .L_divide_b4 117129202Scognet tst r1, r0, lsl #4 118129202Scognet bmi .L_divide_b5 119129202Scognet tst r1, r0, lsl #5 120129202Scognet bmi .L_divide_b6 121129202Scognet tst r1, r0, lsl #6 122129202Scognet bmi .L_divide_b7 123129202Scognet tst r1, r0, lsl #7 124129202Scognet bmi .L_divide_b8 125129202Scognet tst r1, r0, lsl #8 126129202Scognet bmi .L_divide_b9 127129202Scognet tst r1, r0, lsl #9 128129202Scognet bmi .L_divide_b10 129129202Scognet tst r1, r0, lsl #10 130129202Scognet bmi .L_divide_b11 131129202Scognet tst r1, r0, lsl #11 132129202Scognet bmi .L_divide_b12 133129202Scognet tst r1, r0, lsl #12 134129202Scognet bmi .L_divide_b13 135129202Scognet tst r1, r0, lsl #13 136129202Scognet bmi .L_divide_b14 137129202Scognet tst r1, r0, lsl #14 138129202Scognet bmi .L_divide_b15 139129202Scognet tst r1, r0, lsl #15 140129202Scognet bmi .L_divide_b16 141129202Scognet tst r1, r0, lsl #16 142129202Scognet bmi .L_divide_b17 143129202Scognet tst r1, r0, lsl #17 144129202Scognet bmi .L_divide_b18 145129202Scognet tst r1, r0, lsl #18 146129202Scognet bmi .L_divide_b19 147129202Scognet tst r1, r0, lsl #19 148129202Scognet bmi .L_divide_b20 149129202Scognet tst r1, r0, lsl #20 150129202Scognet bmi .L_divide_b21 151129202Scognet tst r1, r0, lsl #21 152129202Scognet bmi .L_divide_b22 153129202Scognet tst r1, r0, lsl #22 154129202Scognet bmi .L_divide_b23 155129202Scognet tst r1, r0, lsl #23 156129202Scognet bmi .L_divide_b24 157129202Scognet tst r1, r0, lsl #24 158129202Scognet bmi .L_divide_b25 159129202Scognet tst r1, r0, lsl #25 160129202Scognet bmi .L_divide_b26 161129202Scognet tst r1, r0, lsl #26 162129202Scognet bmi .L_divide_b27 163129202Scognet tst r1, r0, lsl #27 164129202Scognet bmi .L_divide_b28 165129202Scognet tst r1, r0, lsl #28 166129202Scognet bmi .L_divide_b29 167129202Scognet tst r1, r0, lsl #29 168129202Scognet bmi .L_divide_b30 169129202Scognet tst r1, r0, lsl #30 170129202Scognet bmi .L_divide_b31 171129202Scognet/* 172129202Scognet * instead of: 173129202Scognet * tst r1, r0, lsl #31 174129202Scognet * bmi .L_divide_b32 175129202Scognet */ 176129202Scognet b .L_divide_b32 177129202Scognet 178129202Scognet.L_old_code: 179129202Scognet cmp r1, r0 180129202Scognet bcc .L_divide_b0 181129202Scognet cmp r1, r0, lsl #1 182129202Scognet bcc .L_divide_b1 183129202Scognet cmp r1, r0, lsl #2 184129202Scognet bcc .L_divide_b2 185129202Scognet cmp r1, r0, lsl #3 186129202Scognet bcc .L_divide_b3 187129202Scognet cmp r1, r0, lsl #4 188129202Scognet bcc .L_divide_b4 189129202Scognet cmp r1, r0, lsl #5 190129202Scognet bcc .L_divide_b5 191129202Scognet cmp r1, r0, lsl #6 192129202Scognet bcc .L_divide_b6 193129202Scognet cmp r1, r0, lsl #7 194129202Scognet bcc .L_divide_b7 195129202Scognet cmp r1, r0, lsl #8 196129202Scognet bcc .L_divide_b8 197129202Scognet cmp r1, r0, lsl #9 198129202Scognet bcc .L_divide_b9 199129202Scognet cmp r1, r0, lsl #10 200129202Scognet bcc .L_divide_b10 201129202Scognet cmp r1, r0, lsl #11 202129202Scognet bcc .L_divide_b11 203129202Scognet cmp r1, r0, lsl #12 204129202Scognet bcc .L_divide_b12 205129202Scognet cmp r1, r0, lsl #13 206129202Scognet bcc .L_divide_b13 207129202Scognet cmp r1, r0, lsl #14 208129202Scognet bcc .L_divide_b14 209129202Scognet cmp r1, r0, lsl #15 210129202Scognet bcc .L_divide_b15 211129202Scognet cmp r1, r0, lsl #16 212129202Scognet bcc .L_divide_b16 213129202Scognet cmp r1, r0, lsl #17 214129202Scognet bcc .L_divide_b17 215129202Scognet cmp r1, r0, lsl #18 216129202Scognet bcc .L_divide_b18 217129202Scognet cmp r1, r0, lsl #19 218129202Scognet bcc .L_divide_b19 219129202Scognet cmp r1, r0, lsl #20 220129202Scognet bcc .L_divide_b20 221129202Scognet cmp r1, r0, lsl #21 222129202Scognet bcc .L_divide_b21 223129202Scognet cmp r1, r0, lsl #22 224129202Scognet bcc .L_divide_b22 225129202Scognet cmp r1, r0, lsl #23 226129202Scognet bcc .L_divide_b23 227129202Scognet cmp r1, r0, lsl #24 228129202Scognet bcc .L_divide_b24 229129202Scognet cmp r1, r0, lsl #25 230129202Scognet bcc .L_divide_b25 231129202Scognet cmp r1, r0, lsl #26 232129202Scognet bcc .L_divide_b26 233129202Scognet cmp r1, r0, lsl #27 234129202Scognet bcc .L_divide_b27 235129202Scognet cmp r1, r0, lsl #28 236129202Scognet bcc .L_divide_b28 237129202Scognet cmp r1, r0, lsl #29 238129202Scognet bcc .L_divide_b29 239129202Scognet cmp r1, r0, lsl #30 240129202Scognet bcc .L_divide_b30 241129202Scognet.L_divide_b32: 242129202Scognet cmp r1, r0, lsl #31 243129202Scognet subhs r1, r1,r0, lsl #31 244129202Scognet addhs r3, r3,r2, lsl #31 245129202Scognet.L_divide_b31: 246129202Scognet cmp r1, r0, lsl #30 247129202Scognet subhs r1, r1,r0, lsl #30 248129202Scognet addhs r3, r3,r2, lsl #30 249129202Scognet.L_divide_b30: 250129202Scognet cmp r1, r0, lsl #29 251129202Scognet subhs r1, r1,r0, lsl #29 252129202Scognet addhs r3, r3,r2, lsl #29 253129202Scognet.L_divide_b29: 254129202Scognet cmp r1, r0, lsl #28 255129202Scognet subhs r1, r1,r0, lsl #28 256129202Scognet addhs r3, r3,r2, lsl #28 257129202Scognet.L_divide_b28: 258129202Scognet cmp r1, r0, lsl #27 259129202Scognet subhs r1, r1,r0, lsl #27 260129202Scognet addhs r3, r3,r2, lsl #27 261129202Scognet.L_divide_b27: 262129202Scognet cmp r1, r0, lsl #26 263129202Scognet subhs r1, r1,r0, lsl #26 264129202Scognet addhs r3, r3,r2, lsl #26 265129202Scognet.L_divide_b26: 266129202Scognet cmp r1, r0, lsl #25 267129202Scognet subhs r1, r1,r0, lsl #25 268129202Scognet addhs r3, r3,r2, lsl #25 269129202Scognet.L_divide_b25: 270129202Scognet cmp r1, r0, lsl #24 271129202Scognet subhs r1, r1,r0, lsl #24 272129202Scognet addhs r3, r3,r2, lsl #24 273129202Scognet.L_divide_b24: 274129202Scognet cmp r1, r0, lsl #23 275129202Scognet subhs r1, r1,r0, lsl #23 276129202Scognet addhs r3, r3,r2, lsl #23 277129202Scognet.L_divide_b23: 278129202Scognet cmp r1, r0, lsl #22 279129202Scognet subhs r1, r1,r0, lsl #22 280129202Scognet addhs r3, r3,r2, lsl #22 281129202Scognet.L_divide_b22: 282129202Scognet cmp r1, r0, lsl #21 283129202Scognet subhs r1, r1,r0, lsl #21 284129202Scognet addhs r3, r3,r2, lsl #21 285129202Scognet.L_divide_b21: 286129202Scognet cmp r1, r0, lsl #20 287129202Scognet subhs r1, r1,r0, lsl #20 288129202Scognet addhs r3, r3,r2, lsl #20 289129202Scognet.L_divide_b20: 290129202Scognet cmp r1, r0, lsl #19 291129202Scognet subhs r1, r1,r0, lsl #19 292129202Scognet addhs r3, r3,r2, lsl #19 293129202Scognet.L_divide_b19: 294129202Scognet cmp r1, r0, lsl #18 295129202Scognet subhs r1, r1,r0, lsl #18 296129202Scognet addhs r3, r3,r2, lsl #18 297129202Scognet.L_divide_b18: 298129202Scognet cmp r1, r0, lsl #17 299129202Scognet subhs r1, r1,r0, lsl #17 300129202Scognet addhs r3, r3,r2, lsl #17 301129202Scognet.L_divide_b17: 302129202Scognet cmp r1, r0, lsl #16 303129202Scognet subhs r1, r1,r0, lsl #16 304129202Scognet addhs r3, r3,r2, lsl #16 305129202Scognet.L_divide_b16: 306129202Scognet cmp r1, r0, lsl #15 307129202Scognet subhs r1, r1,r0, lsl #15 308129202Scognet addhs r3, r3,r2, lsl #15 309129202Scognet.L_divide_b15: 310129202Scognet cmp r1, r0, lsl #14 311129202Scognet subhs r1, r1,r0, lsl #14 312129202Scognet addhs r3, r3,r2, lsl #14 313129202Scognet.L_divide_b14: 314129202Scognet cmp r1, r0, lsl #13 315129202Scognet subhs r1, r1,r0, lsl #13 316129202Scognet addhs r3, r3,r2, lsl #13 317129202Scognet.L_divide_b13: 318129202Scognet cmp r1, r0, lsl #12 319129202Scognet subhs r1, r1,r0, lsl #12 320129202Scognet addhs r3, r3,r2, lsl #12 321129202Scognet.L_divide_b12: 322129202Scognet cmp r1, r0, lsl #11 323129202Scognet subhs r1, r1,r0, lsl #11 324129202Scognet addhs r3, r3,r2, lsl #11 325129202Scognet.L_divide_b11: 326129202Scognet cmp r1, r0, lsl #10 327129202Scognet subhs r1, r1,r0, lsl #10 328129202Scognet addhs r3, r3,r2, lsl #10 329129202Scognet.L_divide_b10: 330129202Scognet cmp r1, r0, lsl #9 331129202Scognet subhs r1, r1,r0, lsl #9 332129202Scognet addhs r3, r3,r2, lsl #9 333129202Scognet.L_divide_b9: 334129202Scognet cmp r1, r0, lsl #8 335129202Scognet subhs r1, r1,r0, lsl #8 336129202Scognet addhs r3, r3,r2, lsl #8 337129202Scognet.L_divide_b8: 338129202Scognet cmp r1, r0, lsl #7 339129202Scognet subhs r1, r1,r0, lsl #7 340129202Scognet addhs r3, r3,r2, lsl #7 341129202Scognet.L_divide_b7: 342129202Scognet cmp r1, r0, lsl #6 343129202Scognet subhs r1, r1,r0, lsl #6 344129202Scognet addhs r3, r3,r2, lsl #6 345129202Scognet.L_divide_b6: 346129202Scognet cmp r1, r0, lsl #5 347129202Scognet subhs r1, r1,r0, lsl #5 348129202Scognet addhs r3, r3,r2, lsl #5 349129202Scognet.L_divide_b5: 350129202Scognet cmp r1, r0, lsl #4 351129202Scognet subhs r1, r1,r0, lsl #4 352129202Scognet addhs r3, r3,r2, lsl #4 353129202Scognet.L_divide_b4: 354129202Scognet cmp r1, r0, lsl #3 355129202Scognet subhs r1, r1,r0, lsl #3 356129202Scognet addhs r3, r3,r2, lsl #3 357129202Scognet.L_divide_b3: 358129202Scognet cmp r1, r0, lsl #2 359129202Scognet subhs r1, r1,r0, lsl #2 360129202Scognet addhs r3, r3,r2, lsl #2 361129202Scognet.L_divide_b2: 362129202Scognet cmp r1, r0, lsl #1 363129202Scognet subhs r1, r1,r0, lsl #1 364129202Scognet addhs r3, r3,r2, lsl #1 365129202Scognet.L_divide_b1: 366129202Scognet cmp r1, r0 367129202Scognet subhs r1, r1, r0 368129202Scognet addhs r3, r3, r2 369129202Scognet.L_divide_b0: 370129202Scognet 371129202Scognet tst ip, #0x20000000 372129202Scognet bne .L_udivide_l1 373129202Scognet mov r0, r3 374129202Scognet cmp ip, #0 375129202Scognet rsbmi r1, r1, #0 376129202Scognet movs ip, ip, lsl #1 377129202Scognet bicmi r0, r0, #0x80000000 /* Fix incase we divided 0x80000000 */ 378129202Scognet rsbmi r0, r0, #0 379137464Scognet RET 380129202Scognet 381129202Scognet.L_udivide_l1: 382129202Scognet tst ip, #0x10000000 383129202Scognet mov r1, r1, lsl #1 384129202Scognet orrne r1, r1, #1 385129202Scognet mov r3, r3, lsl #1 386129202Scognet cmp r1, r0 387129202Scognet subhs r1, r1, r0 388129202Scognet addhs r3, r3, r2 389129202Scognet mov r0, r3 390137464Scognet RET 391271337SianEND(__divsi3) 392