divsi3.S revision 129202
187866Ssheldonh/* $NetBSD: divsi3.S,v 1.4 2003/04/05 23:27:15 bjh21 Exp $ */ 287866Ssheldonh 387866Ssheldonh/* 487866Ssheldonh * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 587866Ssheldonh * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 687866Ssheldonh * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 787866Ssheldonh * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 887866Ssheldonh * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 987866Ssheldonh * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 1087866Ssheldonh * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 1187866Ssheldonh * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 1287866Ssheldonh * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 1387866Ssheldonh * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 1487866Ssheldonh * SUCH DAMAGE. 1587866Ssheldonh */ 1687866Ssheldonh 1787866Ssheldonh#include <machine/asm.h> 1887866Ssheldonh__FBSDID("$FreeBSD: head/lib/libc/arm/gen/divsi3.S 129202 2004-05-14 12:04:31Z cognet $"); 1987866Ssheldonh 2087866Ssheldonh/* 2187866Ssheldonh * stack is aligned as there's a possibility of branching to L_overflow 2287866Ssheldonh * which makes a C call 2387866Ssheldonh */ 2487866Ssheldonh 2587866SsheldonhENTRY(__umodsi3) 2687866Ssheldonh stmfd sp!, {lr} 2787866Ssheldonh sub sp, sp, #4 /* align stack */ 2887866Ssheldonh bl .L_udivide 2987866Ssheldonh add sp, sp, #4 /* unalign stack */ 3087866Ssheldonh mov r0, r1 3187866Ssheldonh ldmfd sp!, {pc} 3287866Ssheldonh 3387866SsheldonhENTRY(__modsi3) 34136700Sobrien stmfd sp!, {lr} 35136700Sobrien sub sp, sp, #4 /* align stack */ 36136700Sobrien bl .L_divide 37136700Sobrien add sp, sp, #4 /* unalign stack */ 3887866Ssheldonh mov r0, r1 3987866Ssheldonh ldmfd sp!, {pc} 4087866Ssheldonh 4187866Ssheldonh.L_overflow: 4287866Ssheldonh#if !defined(_KERNEL) && !defined(_STANDALONE) 4387866Ssheldonh mov r0, #8 /* SIGFPE */ 4487866Ssheldonh bl PIC_SYM(_C_LABEL(raise), PLT) /* raise it */ 4587866Ssheldonh mov r0, #0 4687866Ssheldonh#else 4787866Ssheldonh /* XXX should cause a fatal error */ 4887866Ssheldonh mvn r0, #0 4987866Ssheldonh#endif 5087866Ssheldonh mov pc, lr 5187866Ssheldonh 5287866SsheldonhENTRY(__udivsi3) 5387866Ssheldonh.L_udivide: /* r0 = r0 / r1; r1 = r0 % r1 */ 5487866Ssheldonh eor r0, r1, r0 5587866Ssheldonh eor r1, r0, r1 5687866Ssheldonh eor r0, r1, r0 5787866Ssheldonh /* r0 = r1 / r0; r1 = r1 % r0 */ 5887866Ssheldonh cmp r0, #1 5987866Ssheldonh bcc .L_overflow 6087866Ssheldonh beq .L_divide_l0 6187866Ssheldonh mov ip, #0 6287866Ssheldonh movs r1, r1 6387866Ssheldonh bpl .L_divide_l1 6487866Ssheldonh orr ip, ip, #0x20000000 /* ip bit 0x20000000 = -ve r1 */ 6587866Ssheldonh movs r1, r1, lsr #1 6687866Ssheldonh orrcs ip, ip, #0x10000000 /* ip bit 0x10000000 = bit 0 of r1 */ 6787866Ssheldonh b .L_divide_l1 6887866Ssheldonh 6987866Ssheldonh.L_divide_l0: /* r0 == 1 */ 7087866Ssheldonh mov r0, r1 7187866Ssheldonh mov r1, #0 7287866Ssheldonh mov pc, lr 7387866Ssheldonh 7487866SsheldonhENTRY(__divsi3) 7587866Ssheldonh.L_divide: /* r0 = r0 / r1; r1 = r0 % r1 */ 7687866Ssheldonh eor r0, r1, r0 7787866Ssheldonh eor r1, r0, r1 7887866Ssheldonh eor r0, r1, r0 7987866Ssheldonh /* r0 = r1 / r0; r1 = r1 % r0 */ 8087866Ssheldonh cmp r0, #1 8187866Ssheldonh bcc .L_overflow 8287866Ssheldonh beq .L_divide_l0 8387866Ssheldonh ands ip, r0, #0x80000000 8487866Ssheldonh rsbmi r0, r0, #0 8587866Ssheldonh ands r2, r1, #0x80000000 8687866Ssheldonh eor ip, ip, r2 8787866Ssheldonh rsbmi r1, r1, #0 8887866Ssheldonh orr ip, r2, ip, lsr #1 /* ip bit 0x40000000 = -ve division */ 8987866Ssheldonh /* ip bit 0x80000000 = -ve remainder */ 9087866Ssheldonh 9187866Ssheldonh.L_divide_l1: 9287866Ssheldonh mov r2, #1 9387866Ssheldonh mov r3, #0 9487866Ssheldonh 9587866Ssheldonh /* 9687866Ssheldonh * If the highest bit of the dividend is set, we have to be 9787866Ssheldonh * careful when shifting the divisor. Test this. 9887866Ssheldonh */ 9987866Ssheldonh movs r1,r1 10087866Ssheldonh bpl .L_old_code 10187866Ssheldonh 10287866Ssheldonh /* 10387866Ssheldonh * At this point, the highest bit of r1 is known to be set. 10487866Ssheldonh * We abuse this below in the tst instructions. 10587866Ssheldonh */ 10687866Ssheldonh tst r1, r0 /*, lsl #0 */ 10787866Ssheldonh bmi .L_divide_b1 10887866Ssheldonh tst r1, r0, lsl #1 10987866Ssheldonh bmi .L_divide_b2 11087866Ssheldonh tst r1, r0, lsl #2 11187866Ssheldonh bmi .L_divide_b3 11287866Ssheldonh tst r1, r0, lsl #3 11387866Ssheldonh bmi .L_divide_b4 11487866Ssheldonh tst r1, r0, lsl #4 11587866Ssheldonh bmi .L_divide_b5 11687866Ssheldonh tst r1, r0, lsl #5 11787866Ssheldonh bmi .L_divide_b6 11887866Ssheldonh tst r1, r0, lsl #6 11987866Ssheldonh bmi .L_divide_b7 12087866Ssheldonh tst r1, r0, lsl #7 12187866Ssheldonh bmi .L_divide_b8 12287866Ssheldonh tst r1, r0, lsl #8 12387866Ssheldonh bmi .L_divide_b9 12487866Ssheldonh tst r1, r0, lsl #9 12587866Ssheldonh bmi .L_divide_b10 12687866Ssheldonh tst r1, r0, lsl #10 12787866Ssheldonh bmi .L_divide_b11 12887866Ssheldonh tst r1, r0, lsl #11 12987866Ssheldonh bmi .L_divide_b12 13087866Ssheldonh tst r1, r0, lsl #12 13187866Ssheldonh bmi .L_divide_b13 13287866Ssheldonh tst r1, r0, lsl #13 13387866Ssheldonh bmi .L_divide_b14 13487866Ssheldonh tst r1, r0, lsl #14 13587866Ssheldonh bmi .L_divide_b15 13687866Ssheldonh tst r1, r0, lsl #15 13787866Ssheldonh bmi .L_divide_b16 13887866Ssheldonh tst r1, r0, lsl #16 13987866Ssheldonh bmi .L_divide_b17 14087866Ssheldonh tst r1, r0, lsl #17 14187866Ssheldonh bmi .L_divide_b18 14287866Ssheldonh tst r1, r0, lsl #18 14387866Ssheldonh bmi .L_divide_b19 14487866Ssheldonh tst r1, r0, lsl #19 14587866Ssheldonh bmi .L_divide_b20 14687866Ssheldonh tst r1, r0, lsl #20 14787866Ssheldonh bmi .L_divide_b21 14887866Ssheldonh tst r1, r0, lsl #21 14987866Ssheldonh bmi .L_divide_b22 15087866Ssheldonh tst r1, r0, lsl #22 15187866Ssheldonh bmi .L_divide_b23 15287866Ssheldonh tst r1, r0, lsl #23 15387866Ssheldonh bmi .L_divide_b24 15487866Ssheldonh tst r1, r0, lsl #24 15587866Ssheldonh bmi .L_divide_b25 15687866Ssheldonh tst r1, r0, lsl #25 15787866Ssheldonh bmi .L_divide_b26 15887866Ssheldonh tst r1, r0, lsl #26 15987866Ssheldonh bmi .L_divide_b27 16087866Ssheldonh tst r1, r0, lsl #27 16187866Ssheldonh bmi .L_divide_b28 16287866Ssheldonh tst r1, r0, lsl #28 16387866Ssheldonh bmi .L_divide_b29 16487866Ssheldonh tst r1, r0, lsl #29 16587866Ssheldonh bmi .L_divide_b30 16687866Ssheldonh tst r1, r0, lsl #30 16787866Ssheldonh bmi .L_divide_b31 16887866Ssheldonh/* 16987866Ssheldonh * instead of: 17087866Ssheldonh * tst r1, r0, lsl #31 17187866Ssheldonh * bmi .L_divide_b32 17287866Ssheldonh */ 17387866Ssheldonh b .L_divide_b32 17487866Ssheldonh 17587866Ssheldonh.L_old_code: 17687866Ssheldonh cmp r1, r0 17787866Ssheldonh bcc .L_divide_b0 17887866Ssheldonh cmp r1, r0, lsl #1 17987866Ssheldonh bcc .L_divide_b1 18087866Ssheldonh cmp r1, r0, lsl #2 18187866Ssheldonh bcc .L_divide_b2 18287866Ssheldonh cmp r1, r0, lsl #3 18387866Ssheldonh bcc .L_divide_b3 18487866Ssheldonh cmp r1, r0, lsl #4 18587866Ssheldonh bcc .L_divide_b4 18687866Ssheldonh cmp r1, r0, lsl #5 18787866Ssheldonh bcc .L_divide_b5 18887866Ssheldonh cmp r1, r0, lsl #6 18987866Ssheldonh bcc .L_divide_b6 19087866Ssheldonh cmp r1, r0, lsl #7 19187866Ssheldonh bcc .L_divide_b7 19287866Ssheldonh cmp r1, r0, lsl #8 19387866Ssheldonh bcc .L_divide_b8 19487866Ssheldonh cmp r1, r0, lsl #9 19587866Ssheldonh bcc .L_divide_b9 19687866Ssheldonh cmp r1, r0, lsl #10 19787866Ssheldonh bcc .L_divide_b10 19887866Ssheldonh cmp r1, r0, lsl #11 19987866Ssheldonh bcc .L_divide_b11 20087866Ssheldonh cmp r1, r0, lsl #12 20187866Ssheldonh bcc .L_divide_b12 20287866Ssheldonh cmp r1, r0, lsl #13 20387866Ssheldonh bcc .L_divide_b13 20487866Ssheldonh cmp r1, r0, lsl #14 20587866Ssheldonh bcc .L_divide_b14 20687866Ssheldonh cmp r1, r0, lsl #15 20787866Ssheldonh bcc .L_divide_b15 20887866Ssheldonh cmp r1, r0, lsl #16 20987866Ssheldonh bcc .L_divide_b16 21087866Ssheldonh cmp r1, r0, lsl #17 21187866Ssheldonh bcc .L_divide_b17 21287866Ssheldonh cmp r1, r0, lsl #18 21387866Ssheldonh bcc .L_divide_b18 21487866Ssheldonh cmp r1, r0, lsl #19 21587866Ssheldonh bcc .L_divide_b19 21687866Ssheldonh cmp r1, r0, lsl #20 21787866Ssheldonh bcc .L_divide_b20 21887866Ssheldonh cmp r1, r0, lsl #21 21987866Ssheldonh bcc .L_divide_b21 22087866Ssheldonh cmp r1, r0, lsl #22 22187866Ssheldonh bcc .L_divide_b22 22287866Ssheldonh cmp r1, r0, lsl #23 22387866Ssheldonh bcc .L_divide_b23 22487866Ssheldonh cmp r1, r0, lsl #24 22587866Ssheldonh bcc .L_divide_b24 22687866Ssheldonh cmp r1, r0, lsl #25 22787866Ssheldonh bcc .L_divide_b25 22887866Ssheldonh cmp r1, r0, lsl #26 22987866Ssheldonh bcc .L_divide_b26 23087866Ssheldonh cmp r1, r0, lsl #27 23187866Ssheldonh bcc .L_divide_b27 23287866Ssheldonh cmp r1, r0, lsl #28 23387866Ssheldonh bcc .L_divide_b28 23487866Ssheldonh cmp r1, r0, lsl #29 23587866Ssheldonh bcc .L_divide_b29 23687866Ssheldonh cmp r1, r0, lsl #30 23787866Ssheldonh bcc .L_divide_b30 23887866Ssheldonh.L_divide_b32: 23987866Ssheldonh cmp r1, r0, lsl #31 24087866Ssheldonh subhs r1, r1,r0, lsl #31 24187866Ssheldonh addhs r3, r3,r2, lsl #31 24287866Ssheldonh.L_divide_b31: 24387866Ssheldonh cmp r1, r0, lsl #30 24487866Ssheldonh subhs r1, r1,r0, lsl #30 24587866Ssheldonh addhs r3, r3,r2, lsl #30 24687866Ssheldonh.L_divide_b30: 24787866Ssheldonh cmp r1, r0, lsl #29 24887866Ssheldonh subhs r1, r1,r0, lsl #29 24987866Ssheldonh addhs r3, r3,r2, lsl #29 25087866Ssheldonh.L_divide_b29: 25187866Ssheldonh cmp r1, r0, lsl #28 25287866Ssheldonh subhs r1, r1,r0, lsl #28 25387866Ssheldonh addhs r3, r3,r2, lsl #28 25487866Ssheldonh.L_divide_b28: 25587866Ssheldonh cmp r1, r0, lsl #27 25687866Ssheldonh subhs r1, r1,r0, lsl #27 25787866Ssheldonh addhs r3, r3,r2, lsl #27 25887866Ssheldonh.L_divide_b27: 25987866Ssheldonh cmp r1, r0, lsl #26 26087866Ssheldonh subhs r1, r1,r0, lsl #26 26187866Ssheldonh addhs r3, r3,r2, lsl #26 26287866Ssheldonh.L_divide_b26: 26387866Ssheldonh cmp r1, r0, lsl #25 26487866Ssheldonh subhs r1, r1,r0, lsl #25 26587866Ssheldonh addhs r3, r3,r2, lsl #25 26687866Ssheldonh.L_divide_b25: 26787866Ssheldonh cmp r1, r0, lsl #24 26887866Ssheldonh subhs r1, r1,r0, lsl #24 26987866Ssheldonh addhs r3, r3,r2, lsl #24 27087866Ssheldonh.L_divide_b24: 27187866Ssheldonh cmp r1, r0, lsl #23 27287866Ssheldonh subhs r1, r1,r0, lsl #23 27387866Ssheldonh addhs r3, r3,r2, lsl #23 27487866Ssheldonh.L_divide_b23: 27587866Ssheldonh cmp r1, r0, lsl #22 27687866Ssheldonh subhs r1, r1,r0, lsl #22 27787866Ssheldonh addhs r3, r3,r2, lsl #22 27887866Ssheldonh.L_divide_b22: 27987866Ssheldonh cmp r1, r0, lsl #21 28087866Ssheldonh subhs r1, r1,r0, lsl #21 28187866Ssheldonh addhs r3, r3,r2, lsl #21 28287866Ssheldonh.L_divide_b21: 28387866Ssheldonh cmp r1, r0, lsl #20 28487866Ssheldonh subhs r1, r1,r0, lsl #20 28587866Ssheldonh addhs r3, r3,r2, lsl #20 28687866Ssheldonh.L_divide_b20: 28787866Ssheldonh cmp r1, r0, lsl #19 28887866Ssheldonh subhs r1, r1,r0, lsl #19 28987866Ssheldonh addhs r3, r3,r2, lsl #19 29087866Ssheldonh.L_divide_b19: 29187866Ssheldonh cmp r1, r0, lsl #18 29287866Ssheldonh subhs r1, r1,r0, lsl #18 29387866Ssheldonh addhs r3, r3,r2, lsl #18 29487866Ssheldonh.L_divide_b18: 29587866Ssheldonh cmp r1, r0, lsl #17 29687866Ssheldonh subhs r1, r1,r0, lsl #17 29787866Ssheldonh addhs r3, r3,r2, lsl #17 29887866Ssheldonh.L_divide_b17: 29987866Ssheldonh cmp r1, r0, lsl #16 30087866Ssheldonh subhs r1, r1,r0, lsl #16 30187866Ssheldonh addhs r3, r3,r2, lsl #16 30287866Ssheldonh.L_divide_b16: 30387866Ssheldonh cmp r1, r0, lsl #15 30487866Ssheldonh subhs r1, r1,r0, lsl #15 30587866Ssheldonh addhs r3, r3,r2, lsl #15 30687866Ssheldonh.L_divide_b15: 30787866Ssheldonh cmp r1, r0, lsl #14 30887866Ssheldonh subhs r1, r1,r0, lsl #14 30987866Ssheldonh addhs r3, r3,r2, lsl #14 31087866Ssheldonh.L_divide_b14: 31187866Ssheldonh cmp r1, r0, lsl #13 31287866Ssheldonh subhs r1, r1,r0, lsl #13 31387866Ssheldonh addhs r3, r3,r2, lsl #13 31487866Ssheldonh.L_divide_b13: 31587866Ssheldonh cmp r1, r0, lsl #12 31687866Ssheldonh subhs r1, r1,r0, lsl #12 31787866Ssheldonh addhs r3, r3,r2, lsl #12 31887866Ssheldonh.L_divide_b12: 31987866Ssheldonh cmp r1, r0, lsl #11 32087866Ssheldonh subhs r1, r1,r0, lsl #11 32187866Ssheldonh addhs r3, r3,r2, lsl #11 32287866Ssheldonh.L_divide_b11: 32387866Ssheldonh cmp r1, r0, lsl #10 32487866Ssheldonh subhs r1, r1,r0, lsl #10 32587866Ssheldonh addhs r3, r3,r2, lsl #10 32687866Ssheldonh.L_divide_b10: 32787866Ssheldonh cmp r1, r0, lsl #9 32887866Ssheldonh subhs r1, r1,r0, lsl #9 32987866Ssheldonh addhs r3, r3,r2, lsl #9 33087866Ssheldonh.L_divide_b9: 33187866Ssheldonh cmp r1, r0, lsl #8 33287866Ssheldonh subhs r1, r1,r0, lsl #8 33387866Ssheldonh addhs r3, r3,r2, lsl #8 33487866Ssheldonh.L_divide_b8: 33587866Ssheldonh cmp r1, r0, lsl #7 33687866Ssheldonh subhs r1, r1,r0, lsl #7 33787866Ssheldonh addhs r3, r3,r2, lsl #7 33887866Ssheldonh.L_divide_b7: 33987866Ssheldonh cmp r1, r0, lsl #6 34087866Ssheldonh subhs r1, r1,r0, lsl #6 34187866Ssheldonh addhs r3, r3,r2, lsl #6 34287866Ssheldonh.L_divide_b6: 34387866Ssheldonh cmp r1, r0, lsl #5 34487866Ssheldonh subhs r1, r1,r0, lsl #5 34587866Ssheldonh addhs r3, r3,r2, lsl #5 34687866Ssheldonh.L_divide_b5: 34787866Ssheldonh cmp r1, r0, lsl #4 34887866Ssheldonh subhs r1, r1,r0, lsl #4 34987866Ssheldonh addhs r3, r3,r2, lsl #4 35087866Ssheldonh.L_divide_b4: 351136700Sobrien cmp r1, r0, lsl #3 35287866Ssheldonh subhs r1, r1,r0, lsl #3 35387866Ssheldonh addhs r3, r3,r2, lsl #3 35487866Ssheldonh.L_divide_b3: 35587866Ssheldonh cmp r1, r0, lsl #2 35687866Ssheldonh subhs r1, r1,r0, lsl #2 35787866Ssheldonh addhs r3, r3,r2, lsl #2 35887866Ssheldonh.L_divide_b2: 35987866Ssheldonh cmp r1, r0, lsl #1 36087866Ssheldonh subhs r1, r1,r0, lsl #1 36187866Ssheldonh addhs r3, r3,r2, lsl #1 36287866Ssheldonh.L_divide_b1: 36387866Ssheldonh cmp r1, r0 36487866Ssheldonh subhs r1, r1, r0 36587866Ssheldonh addhs r3, r3, r2 36687866Ssheldonh.L_divide_b0: 36787866Ssheldonh 36887866Ssheldonh tst ip, #0x20000000 36987866Ssheldonh bne .L_udivide_l1 37087866Ssheldonh mov r0, r3 37187866Ssheldonh cmp ip, #0 37287866Ssheldonh rsbmi r1, r1, #0 37387866Ssheldonh movs ip, ip, lsl #1 37487866Ssheldonh bicmi r0, r0, #0x80000000 /* Fix incase we divided 0x80000000 */ 37587866Ssheldonh rsbmi r0, r0, #0 37687866Ssheldonh mov pc, lr 37787866Ssheldonh 37887866Ssheldonh.L_udivide_l1: 37987866Ssheldonh tst ip, #0x10000000 38087866Ssheldonh mov r1, r1, lsl #1 38187866Ssheldonh orrne r1, r1, #1 38287866Ssheldonh mov r3, r3, lsl #1 38387866Ssheldonh cmp r1, r0 38487866Ssheldonh subhs r1, r1, r0 38587866Ssheldonh addhs r3, r3, r2 38687866Ssheldonh mov r0, r3 38787866Ssheldonh mov pc, lr 38887866Ssheldonh