 5a0585359d
			
		
	
	
		5a0585359d
		
	
	
	
	
		
			
			. raise(SIGFPE) for modulo-0/divide-0 operations in internal int division functions . gcc: do not link with -lgcc anywhere so these internal functions are always used from libc instead of (sometimes) masked by -lgcc . together fixes test53 on ARM Change-Id: I31ec19dfdd68b8a92695595da901874e63106f9d
		
			
				
	
	
		
			375 lines
		
	
	
		
			8.0 KiB
		
	
	
	
		
			ArmAsm
		
	
	
	
	
	
			
		
		
	
	
			375 lines
		
	
	
		
			8.0 KiB
		
	
	
	
		
			ArmAsm
		
	
	
	
	
	
| /*	$NetBSD: divsi3.S,v 1.3 2012/10/10 02:16:54 christos Exp $	*/
 | |
| 
 | |
| /*
 | |
|  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
 | |
|  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 | |
|  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 | |
|  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
 | |
|  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
 | |
|  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
 | |
|  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
 | |
|  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 | |
|  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
 | |
|  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 | |
|  * SUCH DAMAGE.
 | |
|  */
 | |
| 
 | |
| #include <machine/asm.h>
 | |
| 
 | |
| /* 
 | |
|  * stack is aligned as there's a possibility of branching to .L_overflow
 | |
|  * which makes a C call
 | |
|  */
 | |
| 
 | |
| .L_overflow:
 | |
| #if !defined(_KERNEL) && !defined(_STANDALONE) && !defined(_LIBMINC)
 | |
| 	mov	r0, #8			/* SIGFPE */
 | |
| 	bl	PIC_SYM(_C_LABEL(raise), PLT)	/* raise it */
 | |
| 	mov	r0, #0
 | |
| #else
 | |
| 	/* XXX should cause a fatal error */
 | |
| 	mvn	r0, #0
 | |
| #endif
 | |
| 	RET
 | |
| 
 | |
| ENTRY_NP(__aeabi_uidivmod)
 | |
| ENTRY_NP(__aeabi_uidiv)
 | |
| ENTRY(__udivsi3)
 | |
| .L_udivide:				/* r0 = r0 / r1; r1 = r0 % r1 */
 | |
| 	eor     r0, r1, r0 
 | |
| 	eor     r1, r0, r1 
 | |
| 	eor     r0, r1, r0 
 | |
| 					/* r0 = r1 / r0; r1 = r1 % r0 */
 | |
| 	cmp	r0, #1
 | |
| 	bcc	.L_overflow
 | |
| 	beq	.L_divide_l0
 | |
| 	mov	ip, #0
 | |
| 	movs	r1, r1
 | |
| 	bpl	.L_divide_l1
 | |
| 	orr	ip, ip, #0x20000000	/* ip bit 0x20000000 = -ve r1 */
 | |
| 	movs	r1, r1, lsr #1
 | |
| 	orrcs	ip, ip, #0x10000000	/* ip bit 0x10000000 = bit 0 of r1 */
 | |
| 	b	.L_divide_l1
 | |
| 
 | |
| .L_divide_l0:				/* r0 == 1 */
 | |
| 	mov	r0, r1
 | |
| 	mov	r1, #0
 | |
| 	RET
 | |
| 
 | |
| ENTRY_NP(__aeabi_idivmod)
 | |
| ENTRY_NP(__aeabi_idiv)
 | |
| ENTRY(__divsi3)
 | |
| .L_divide:				/* r0 = r0 / r1; r1 = r0 % r1 */
 | |
| 	eor     r0, r1, r0 
 | |
| 	eor     r1, r0, r1 
 | |
| 	eor     r0, r1, r0 
 | |
| 					/* r0 = r1 / r0; r1 = r1 % r0 */
 | |
| 	cmp	r0, #1
 | |
| 	bcc	.L_overflow
 | |
| 	beq	.L_divide_l0
 | |
| 	ands	ip, r0, #0x80000000
 | |
| 	rsbmi	r0, r0, #0
 | |
| 	ands	r2, r1, #0x80000000
 | |
| 	eor	ip, ip, r2
 | |
| 	rsbmi	r1, r1, #0
 | |
| 	orr	ip, r2, ip, lsr #1	/* ip bit 0x40000000 = -ve division */
 | |
| 					/* ip bit 0x80000000 = -ve remainder */
 | |
| 
 | |
| .L_divide_l1:
 | |
| 	mov	r2, #1
 | |
| 	mov	r3, #0
 | |
| 
 | |
| 	/*
 | |
| 	 * If the highest bit of the dividend is set, we have to be
 | |
| 	 * careful when shifting the divisor. Test this. 
 | |
| 	 */
 | |
| 	movs	r1,r1
 | |
| 	bpl	.L_old_code
 | |
| 
 | |
| 	/*
 | |
| 	 * At this point, the highest bit of r1 is known to be set.
 | |
| 	 * We abuse this below in the tst instructions.
 | |
| 	 */
 | |
| 	tst	r1, r0 /*, lsl #0 */
 | |
| 	bmi	.L_divide_b1
 | |
| 	tst	r1, r0, lsl #1
 | |
| 	bmi	.L_divide_b2
 | |
| 	tst	r1, r0, lsl #2
 | |
| 	bmi	.L_divide_b3
 | |
| 	tst	r1, r0, lsl #3
 | |
| 	bmi	.L_divide_b4
 | |
| 	tst	r1, r0, lsl #4
 | |
| 	bmi	.L_divide_b5
 | |
| 	tst	r1, r0, lsl #5
 | |
| 	bmi	.L_divide_b6
 | |
| 	tst	r1, r0, lsl #6
 | |
| 	bmi	.L_divide_b7
 | |
| 	tst	r1, r0, lsl #7
 | |
| 	bmi	.L_divide_b8
 | |
| 	tst	r1, r0, lsl #8
 | |
| 	bmi	.L_divide_b9
 | |
| 	tst	r1, r0, lsl #9
 | |
| 	bmi	.L_divide_b10
 | |
| 	tst	r1, r0, lsl #10
 | |
| 	bmi	.L_divide_b11
 | |
| 	tst	r1, r0, lsl #11
 | |
| 	bmi	.L_divide_b12
 | |
| 	tst	r1, r0, lsl #12
 | |
| 	bmi	.L_divide_b13
 | |
| 	tst	r1, r0, lsl #13
 | |
| 	bmi	.L_divide_b14
 | |
| 	tst	r1, r0, lsl #14
 | |
| 	bmi	.L_divide_b15
 | |
| 	tst	r1, r0, lsl #15
 | |
| 	bmi	.L_divide_b16
 | |
| 	tst	r1, r0, lsl #16
 | |
| 	bmi	.L_divide_b17
 | |
| 	tst	r1, r0, lsl #17
 | |
| 	bmi	.L_divide_b18
 | |
| 	tst	r1, r0, lsl #18
 | |
| 	bmi	.L_divide_b19
 | |
| 	tst	r1, r0, lsl #19
 | |
| 	bmi	.L_divide_b20
 | |
| 	tst	r1, r0, lsl #20
 | |
| 	bmi	.L_divide_b21
 | |
| 	tst	r1, r0, lsl #21
 | |
| 	bmi	.L_divide_b22
 | |
| 	tst	r1, r0, lsl #22
 | |
| 	bmi	.L_divide_b23
 | |
| 	tst	r1, r0, lsl #23
 | |
| 	bmi	.L_divide_b24
 | |
| 	tst	r1, r0, lsl #24
 | |
| 	bmi	.L_divide_b25
 | |
| 	tst	r1, r0, lsl #25
 | |
| 	bmi	.L_divide_b26
 | |
| 	tst	r1, r0, lsl #26
 | |
| 	bmi	.L_divide_b27
 | |
| 	tst	r1, r0, lsl #27
 | |
| 	bmi	.L_divide_b28
 | |
| 	tst	r1, r0, lsl #28
 | |
| 	bmi	.L_divide_b29
 | |
| 	tst	r1, r0, lsl #29
 | |
| 	bmi	.L_divide_b30
 | |
| 	tst	r1, r0, lsl #30
 | |
| 	bmi	.L_divide_b31
 | |
| /*
 | |
|  * instead of:
 | |
|  *	tst	r1, r0, lsl #31
 | |
|  *	bmi	.L_divide_b32
 | |
|  */
 | |
| 	b	.L_divide_b32
 | |
| 
 | |
| .L_old_code:
 | |
| 	cmp	r1, r0
 | |
| 	bcc	.L_divide_b0
 | |
| 	cmp	r1, r0, lsl #1
 | |
| 	bcc	.L_divide_b1
 | |
| 	cmp	r1, r0, lsl #2
 | |
| 	bcc	.L_divide_b2
 | |
| 	cmp	r1, r0, lsl #3
 | |
| 	bcc	.L_divide_b3
 | |
| 	cmp	r1, r0, lsl #4
 | |
| 	bcc	.L_divide_b4
 | |
| 	cmp	r1, r0, lsl #5
 | |
| 	bcc	.L_divide_b5
 | |
| 	cmp	r1, r0, lsl #6
 | |
| 	bcc	.L_divide_b6
 | |
| 	cmp	r1, r0, lsl #7
 | |
| 	bcc	.L_divide_b7
 | |
| 	cmp	r1, r0, lsl #8
 | |
| 	bcc	.L_divide_b8
 | |
| 	cmp	r1, r0, lsl #9
 | |
| 	bcc	.L_divide_b9
 | |
| 	cmp	r1, r0, lsl #10
 | |
| 	bcc	.L_divide_b10
 | |
| 	cmp	r1, r0, lsl #11
 | |
| 	bcc	.L_divide_b11
 | |
| 	cmp	r1, r0, lsl #12
 | |
| 	bcc	.L_divide_b12
 | |
| 	cmp	r1, r0, lsl #13
 | |
| 	bcc	.L_divide_b13
 | |
| 	cmp	r1, r0, lsl #14
 | |
| 	bcc	.L_divide_b14
 | |
| 	cmp	r1, r0, lsl #15
 | |
| 	bcc	.L_divide_b15
 | |
| 	cmp	r1, r0, lsl #16
 | |
| 	bcc	.L_divide_b16
 | |
| 	cmp	r1, r0, lsl #17
 | |
| 	bcc	.L_divide_b17
 | |
| 	cmp	r1, r0, lsl #18
 | |
| 	bcc	.L_divide_b18
 | |
| 	cmp	r1, r0, lsl #19
 | |
| 	bcc	.L_divide_b19
 | |
| 	cmp	r1, r0, lsl #20
 | |
| 	bcc	.L_divide_b20
 | |
| 	cmp	r1, r0, lsl #21
 | |
| 	bcc	.L_divide_b21
 | |
| 	cmp	r1, r0, lsl #22
 | |
| 	bcc	.L_divide_b22
 | |
| 	cmp	r1, r0, lsl #23
 | |
| 	bcc	.L_divide_b23
 | |
| 	cmp	r1, r0, lsl #24
 | |
| 	bcc	.L_divide_b24
 | |
| 	cmp	r1, r0, lsl #25
 | |
| 	bcc	.L_divide_b25
 | |
| 	cmp	r1, r0, lsl #26
 | |
| 	bcc	.L_divide_b26
 | |
| 	cmp	r1, r0, lsl #27
 | |
| 	bcc	.L_divide_b27
 | |
| 	cmp	r1, r0, lsl #28
 | |
| 	bcc	.L_divide_b28
 | |
| 	cmp	r1, r0, lsl #29
 | |
| 	bcc	.L_divide_b29
 | |
| 	cmp	r1, r0, lsl #30
 | |
| 	bcc	.L_divide_b30
 | |
| .L_divide_b32:
 | |
| 	cmp	r1, r0, lsl #31
 | |
| 	subhs	r1, r1,r0, lsl #31
 | |
| 	addhs	r3, r3,r2, lsl #31
 | |
| .L_divide_b31:
 | |
| 	cmp	r1, r0, lsl #30
 | |
| 	subhs	r1, r1,r0, lsl #30
 | |
| 	addhs	r3, r3,r2, lsl #30
 | |
| .L_divide_b30:
 | |
| 	cmp	r1, r0, lsl #29
 | |
| 	subhs	r1, r1,r0, lsl #29
 | |
| 	addhs	r3, r3,r2, lsl #29
 | |
| .L_divide_b29:
 | |
| 	cmp	r1, r0, lsl #28
 | |
| 	subhs	r1, r1,r0, lsl #28
 | |
| 	addhs	r3, r3,r2, lsl #28
 | |
| .L_divide_b28:
 | |
| 	cmp	r1, r0, lsl #27
 | |
| 	subhs	r1, r1,r0, lsl #27
 | |
| 	addhs	r3, r3,r2, lsl #27
 | |
| .L_divide_b27:
 | |
| 	cmp	r1, r0, lsl #26
 | |
| 	subhs	r1, r1,r0, lsl #26
 | |
| 	addhs	r3, r3,r2, lsl #26
 | |
| .L_divide_b26:
 | |
| 	cmp	r1, r0, lsl #25
 | |
| 	subhs	r1, r1,r0, lsl #25
 | |
| 	addhs	r3, r3,r2, lsl #25
 | |
| .L_divide_b25:
 | |
| 	cmp	r1, r0, lsl #24
 | |
| 	subhs	r1, r1,r0, lsl #24
 | |
| 	addhs	r3, r3,r2, lsl #24
 | |
| .L_divide_b24:
 | |
| 	cmp	r1, r0, lsl #23
 | |
| 	subhs	r1, r1,r0, lsl #23
 | |
| 	addhs	r3, r3,r2, lsl #23
 | |
| .L_divide_b23:
 | |
| 	cmp	r1, r0, lsl #22
 | |
| 	subhs	r1, r1,r0, lsl #22
 | |
| 	addhs	r3, r3,r2, lsl #22
 | |
| .L_divide_b22:
 | |
| 	cmp	r1, r0, lsl #21
 | |
| 	subhs	r1, r1,r0, lsl #21
 | |
| 	addhs	r3, r3,r2, lsl #21
 | |
| .L_divide_b21:
 | |
| 	cmp	r1, r0, lsl #20
 | |
| 	subhs	r1, r1,r0, lsl #20
 | |
| 	addhs	r3, r3,r2, lsl #20
 | |
| .L_divide_b20:
 | |
| 	cmp	r1, r0, lsl #19
 | |
| 	subhs	r1, r1,r0, lsl #19
 | |
| 	addhs	r3, r3,r2, lsl #19
 | |
| .L_divide_b19:
 | |
| 	cmp	r1, r0, lsl #18
 | |
| 	subhs	r1, r1,r0, lsl #18
 | |
| 	addhs	r3, r3,r2, lsl #18
 | |
| .L_divide_b18:
 | |
| 	cmp	r1, r0, lsl #17
 | |
| 	subhs	r1, r1,r0, lsl #17
 | |
| 	addhs	r3, r3,r2, lsl #17
 | |
| .L_divide_b17:
 | |
| 	cmp	r1, r0, lsl #16
 | |
| 	subhs	r1, r1,r0, lsl #16
 | |
| 	addhs	r3, r3,r2, lsl #16
 | |
| .L_divide_b16:
 | |
| 	cmp	r1, r0, lsl #15
 | |
| 	subhs	r1, r1,r0, lsl #15
 | |
| 	addhs	r3, r3,r2, lsl #15
 | |
| .L_divide_b15:
 | |
| 	cmp	r1, r0, lsl #14
 | |
| 	subhs	r1, r1,r0, lsl #14
 | |
| 	addhs	r3, r3,r2, lsl #14
 | |
| .L_divide_b14:
 | |
| 	cmp	r1, r0, lsl #13
 | |
| 	subhs	r1, r1,r0, lsl #13
 | |
| 	addhs	r3, r3,r2, lsl #13
 | |
| .L_divide_b13:
 | |
| 	cmp	r1, r0, lsl #12
 | |
| 	subhs	r1, r1,r0, lsl #12
 | |
| 	addhs	r3, r3,r2, lsl #12
 | |
| .L_divide_b12:
 | |
| 	cmp	r1, r0, lsl #11
 | |
| 	subhs	r1, r1,r0, lsl #11
 | |
| 	addhs	r3, r3,r2, lsl #11
 | |
| .L_divide_b11:
 | |
| 	cmp	r1, r0, lsl #10
 | |
| 	subhs	r1, r1,r0, lsl #10
 | |
| 	addhs	r3, r3,r2, lsl #10
 | |
| .L_divide_b10:
 | |
| 	cmp	r1, r0, lsl #9
 | |
| 	subhs	r1, r1,r0, lsl #9
 | |
| 	addhs	r3, r3,r2, lsl #9
 | |
| .L_divide_b9:
 | |
| 	cmp	r1, r0, lsl #8
 | |
| 	subhs	r1, r1,r0, lsl #8
 | |
| 	addhs	r3, r3,r2, lsl #8
 | |
| .L_divide_b8:
 | |
| 	cmp	r1, r0, lsl #7
 | |
| 	subhs	r1, r1,r0, lsl #7
 | |
| 	addhs	r3, r3,r2, lsl #7
 | |
| .L_divide_b7:
 | |
| 	cmp	r1, r0, lsl #6
 | |
| 	subhs	r1, r1,r0, lsl #6
 | |
| 	addhs	r3, r3,r2, lsl #6
 | |
| .L_divide_b6:
 | |
| 	cmp	r1, r0, lsl #5
 | |
| 	subhs	r1, r1,r0, lsl #5
 | |
| 	addhs	r3, r3,r2, lsl #5
 | |
| .L_divide_b5:
 | |
| 	cmp	r1, r0, lsl #4
 | |
| 	subhs	r1, r1,r0, lsl #4
 | |
| 	addhs	r3, r3,r2, lsl #4
 | |
| .L_divide_b4:
 | |
| 	cmp	r1, r0, lsl #3
 | |
| 	subhs	r1, r1,r0, lsl #3
 | |
| 	addhs	r3, r3,r2, lsl #3
 | |
| .L_divide_b3:
 | |
| 	cmp	r1, r0, lsl #2
 | |
| 	subhs	r1, r1,r0, lsl #2
 | |
| 	addhs	r3, r3,r2, lsl #2
 | |
| .L_divide_b2:
 | |
| 	cmp	r1, r0, lsl #1
 | |
| 	subhs	r1, r1,r0, lsl #1
 | |
| 	addhs	r3, r3,r2, lsl #1
 | |
| .L_divide_b1:
 | |
| 	cmp	r1, r0
 | |
| 	subhs	r1, r1, r0
 | |
| 	addhs	r3, r3, r2
 | |
| .L_divide_b0:
 | |
| 
 | |
| 	tst	ip, #0x20000000
 | |
| 	bne	.L_udivide_l1
 | |
| 	mov	r0, r3
 | |
| 	cmp	ip, #0
 | |
| 	rsbmi	r1, r1, #0
 | |
| 	movs	ip, ip, lsl #1
 | |
| 	bicmi	r0, r0, #0x80000000	/* Fix incase we divided 0x80000000 */
 | |
| 	rsbmi	r0, r0, #0
 | |
| 	RET
 | |
| 
 | |
| .L_udivide_l1:
 | |
| 	tst	ip, #0x10000000
 | |
| 	mov	r1, r1, lsl #1
 | |
| 	orrne	r1, r1, #1
 | |
| 	mov	r3, r3, lsl #1
 | |
| 	cmp	r1, r0
 | |
| 	subhs	r1, r1, r0
 | |
| 	addhs	r3, r3, r2
 | |
| 	mov	r0, r3
 | |
| 	RET
 |