Home | History | Annotate | Line # | Download | only in quad
      1   1.1   matt /*-
      2   1.1   matt  * Copyright (c) 2012 The NetBSD Foundation, Inc.
      3   1.1   matt  * All rights reserved.
      4   1.1   matt  *
      5   1.1   matt  * This code is derived from software contributed to The NetBSD Foundation
      6   1.1   matt  * by Matt Thomas of 3am Software Foundry.
      7   1.1   matt  *
      8   1.1   matt  * Redistribution and use in source and binary forms, with or without
      9   1.1   matt  * modification, are permitted provided that the following conditions
     10   1.1   matt  * are met:
     11   1.1   matt  * 1. Redistributions of source code must retain the above copyright
     12   1.1   matt  *    notice, this list of conditions and the following disclaimer.
     13   1.1   matt  * 2. Redistributions in binary form must reproduce the above copyright
     14   1.1   matt  *    notice, this list of conditions and the following disclaimer in the
     15   1.1   matt  *    documentation and/or other materials provided with the distribution.
     16   1.1   matt  *
     17   1.1   matt  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
     18   1.1   matt  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
     19   1.1   matt  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
     20   1.1   matt  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
     21   1.1   matt  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
     22   1.1   matt  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
     23   1.1   matt  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
     24   1.1   matt  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
     25   1.1   matt  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
     26   1.1   matt  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
     27   1.1   matt  * POSSIBILITY OF SUCH DAMAGE.
     28   1.1   matt  */
     29   1.1   matt 
     30   1.1   matt #include <machine/asm.h>
     31   1.1   matt 
     32  1.13  joerg RCSID("$NetBSD: __aeabi_ldivmod.S,v 1.13 2014/05/06 16:02:11 joerg Exp $")
     33   1.4  skrll 
     34   1.1   matt #ifdef __ARMEB__
     35   1.1   matt #define	ALO	r1	/* incoming numerator, outgoing quotient */
     36   1.1   matt #define	AHI	r0	/* incoming numerator, outgoing quotient */
     37   1.1   matt #define	BLO	r3	/* incoming denominator, outgoing remainder */
     38   1.1   matt #define	BHI	r2	/* incoming denominator, outgoing remainder */
     39   1.1   matt #else
     40   1.1   matt #define	ALO	r0	/* incoming numerator, outgoing quotient */
     41   1.1   matt #define	AHI	r1	/* incoming numerator, outgoing quotient */
     42   1.1   matt #define	BLO	r2	/* incoming denominator, outgoing remainder */
     43   1.1   matt #define	BHI	r3	/* incoming denominator, outgoing remainder */
     44   1.1   matt #endif
     45   1.1   matt 
     46  1.12   matt ENTRY(__aeabi_ldivmod)
     47  1.12   matt #ifdef __ARM_EABI__
     48  1.13  joerg # if !defined(__ARM_DWARF_EH__)
     49  1.12   matt 	.fnstart
     50  1.13  joerg # endif
     51  1.12   matt 	.cfi_startproc
     52  1.12   matt #endif
     53  1.12   matt #if !defined(_KERNEL) && !defined(_STANDALONE)
     54  1.12   matt #if !defined(__thumb__)
     55  1.12   matt 	orrs	ip, BLO, BHI
     56  1.12   matt 	beq	.Ldivbyzero
     57  1.12   matt #elif defined(_ARM_ARCH_T2)
     58  1.12   matt 	cbnz	BLO, 1f
     59  1.12   matt 	cbz	BHI, .Ldivbyzero
     60  1.12   matt #else
     61  1.12   matt 	cmp	BLO, #0
     62  1.12   matt 	bne	1f
     63  1.12   matt 	cmp	BHI, #0
     64  1.12   matt 	beq	.Ldivbyzero
     65  1.12   matt #endif
     66  1.12   matt 1:
     67  1.12   matt #endif
     68  1.12   matt 
     69  1.12   matt 	push	{r4-r6, lr}
     70  1.12   matt #ifdef __ARM_EABI__
     71  1.12   matt 	.cfi_def_cfa_offset 16
     72  1.12   matt 	.cfi_offset 14, -4
     73  1.12   matt 	.cfi_offset 6, -8
     74  1.12   matt 	.cfi_offset 5, -12
     75  1.12   matt 	.cfi_offset 4, -16
     76  1.12   matt #endif
     77  1.12   matt #define	NEG	r5
     78  1.12   matt 	movs	NEG, #0
     79  1.12   matt 
     80   1.1   matt 	cmp	BHI, #0
     81   1.1   matt 	bge	2f
     82  1.12   matt 	movs	NEG, #1		/* flip quotient sign */
     83   1.1   matt 	bl	.Lnegate_b
     84   1.1   matt 	bcs	.Lmaxdenom
     85   1.1   matt 
     86   1.1   matt 2:
     87   1.1   matt 	cmp	AHI, #0
     88  1.12   matt #ifdef __thumb__
     89  1.12   matt 	bge	3f
     90  1.12   matt 	movs	r4, #3
     91  1.12   matt 	eors	NEG, NEG, r4	/* flip quotient sign, flip remainder sign */
     92  1.12   matt 	bl	.Lnegate_a
     93  1.12   matt 3:
     94  1.12   matt #else
     95   1.1   matt 	eorlt	NEG, NEG, #3	/* flip quotient sign, flip remainder sign */
     96   1.1   matt 	bllt	.Lnegate_a
     97  1.12   matt #endif
     98  1.12   matt 
     99   1.1   matt 	/*
    100   1.1   matt 	 * Arguments are setup, allocate some stack for the remainder
    101   1.1   matt 	 * and call __qdivrem for the heavy lifting.
    102   1.1   matt 	 */
    103  1.12   matt #ifdef __ARM_EABI__
    104  1.12   matt 	.cfi_def_cfa_offset 32
    105  1.12   matt #endif
    106   1.2   matt 	sub	sp, sp, #16
    107  1.12   matt #if !defined(__thumb__) || defined(_ARM_ARCH_T2)
    108  1.12   matt 	adds	r4, sp, #8
    109  1.12   matt #else
    110  1.12   matt 	mov	r4, sp
    111  1.12   matt 	adds	r4, r4, #8
    112  1.12   matt #endif
    113  1.12   matt 	str	r4, [sp]
    114   1.1   matt 	bl	PLT_SYM(__qdivrem)
    115   1.2   matt 	add	sp, sp, #8
    116  1.12   matt #ifdef __ARM_EABI__
    117  1.12   matt 	.cfi_def_cfa_offset 24
    118  1.12   matt 	.cfi_offset 3, -20
    119  1.12   matt 	.cfi_offset 2, -24
    120  1.12   matt #endif
    121   1.1   matt 
    122   1.1   matt 	/*
    123   1.1   matt 	 * The quotient is already in the right place and neither value
    124   1.1   matt 	 * needs its sign flipped.
    125   1.1   matt 	 */
    126  1.12   matt #if defined(__thumb__) && defined(_ARM_ARCH_T2)
    127  1.12   matt 	cbz	NEG, .Lnegate_neither
    128  1.12   matt #else
    129  1.12   matt 	cmp	NEG, #0		/* any signs to flip? */
    130  1.12   matt 	beq	.Lnegate_neither
    131  1.12   matt #endif
    132   1.1   matt 
    133  1.12   matt 	cmp	NEG, #2		/* does remainder need to be negative? */
    134  1.12   matt 	beq	.Lnegate_b_only	/* 2 means b only */
    135  1.12   matt 	bgt	.Lnegate_both	/* 3 means both */
    136  1.12   matt .Lnegate_a_only:
    137  1.12   matt 	bl	.Lnegate_a	/* 1 means a only */
    138  1.12   matt .Lnegate_neither:
    139  1.12   matt 	pop	{r2-r6, pc}	/* grab b from stack */
    140  1.12   matt .Lnegate_both:
    141  1.12   matt 	bl	.Lnegate_a
    142  1.12   matt .Lnegate_b_only:
    143  1.12   matt 	pop	{r2-r3}		/* get remainder */
    144  1.12   matt #ifdef __ARM_EABI__
    145  1.12   matt 	.cfi_def_cfa_offset 16
    146  1.12   matt #endif
    147  1.12   matt 	bl	.Lnegate_b	/* negate it */
    148  1.12   matt 	pop	{r4-r6, pc}
    149   1.1   matt 
    150  1.12   matt 	.align	0
    151   1.1   matt .Lnegate_a:
    152  1.12   matt #ifdef __thumb__
    153  1.12   matt 	movs	r4, AHI
    154  1.12   matt 	movs	AHI, #0
    155  1.12   matt 	negs	ALO, ALO
    156  1.12   matt 	sbcs	AHI, AHI, r4
    157  1.12   matt #else
    158  1.12   matt 	negs	ALO, ALO
    159  1.12   matt 	rsc	AHI, AHI, #0
    160  1.12   matt #endif
    161   1.1   matt 	RET
    162   1.1   matt 
    163  1.12   matt 	.align	0
    164   1.1   matt .Lnegate_b:
    165  1.12   matt #ifdef __thumb__
    166  1.12   matt 	movs	r4, BHI
    167  1.12   matt 	movs	BHI, #0
    168  1.12   matt 	negs	BLO, BLO
    169  1.12   matt 	sbcs	BHI, BHI, r4
    170  1.12   matt #else
    171  1.12   matt 	negs	BLO, BLO
    172  1.12   matt 	rsc	BHI, BHI, #0
    173  1.12   matt #endif
    174   1.1   matt 	RET
    175   1.1   matt 
    176  1.12   matt 	.align	0
    177   1.1   matt .Lmaxdenom:
    178   1.1   matt 	/*
    179   1.1   matt 	 * We had a carry so the denominator must have INT64_MIN
    180   1.1   matt 	 * Also BLO and BHI never changed values so we can use
    181   1.1   matt 	 * them to see if the numerator has the same value.  We
    182   1.1   matt 	 * don't have to worry about sign.
    183   1.1   matt 	 */
    184  1.12   matt 	cmp	BHI, AHI
    185  1.12   matt #ifdef __thumb__
    186  1.12   matt 	bne	1f
    187  1.12   matt 	cmp	BLO, ALO
    188  1.12   matt #else
    189  1.12   matt 	cmpeq	BLO, ALO
    190  1.12   matt #endif
    191   1.1   matt 	bne	1f
    192   1.1   matt 
    193   1.1   matt 	/*
    194   1.1   matt 	 * They were equal, so we return a quotient of 1 and remainder of 0.
    195   1.1   matt 	 */
    196  1.12   matt 	movs	ALO, #1
    197  1.12   matt 	movs	AHI, #0
    198  1.12   matt 	movs	BLO, #0
    199  1.12   matt 	movs	BHI, #0
    200  1.12   matt 	pop	{r4-r6, pc}
    201   1.1   matt 
    202   1.1   matt 	/*
    203   1.1   matt 	 * Our remainder must be the numerator and our quotient is 0.
    204   1.1   matt 	 */
    205  1.12   matt 	.align	0
    206  1.12   matt 1:	movs	BLO, ALO
    207  1.12   matt 	movs	BHI, AHI
    208  1.12   matt 	movs	ALO, #0
    209  1.12   matt 	movs	AHI, #0
    210  1.12   matt 	pop	{r4-r6, pc}
    211   1.5   matt 
    212   1.7   matt #if !defined(_KERNEL) && !defined(_STANDALONE)
    213  1.12   matt 	.align	0
    214   1.5   matt .Ldivbyzero:
    215  1.12   matt 	push	{r0-r1,r4,lr}
    216  1.12   matt #ifdef __ARM_EABI__
    217  1.13  joerg # if !defined(__ARM_DWARF_EH__)
    218  1.12   matt 	.save	{r0-r1,r4,lr}
    219  1.13  joerg # endif
    220  1.12   matt 	.cfi_def_cfa_offset 16
    221  1.12   matt 	.cfi_offset 14, -4
    222  1.12   matt 	.cfi_offset  4, -8
    223  1.12   matt #endif
    224   1.6  skrll 	cmp	AHI, #0
    225  1.12   matt #if !defined(__thumb__) || defined(_ARM_ARCH_T2)
    226  1.12   matt #ifdef __thumb__
    227  1.12   matt 	ittee	ge
    228  1.12   matt #endif
    229   1.5   matt 	mvnge	ALO, #0
    230  1.12   matt 	mvnge	AHI, #0x80000000
    231   1.5   matt 	movlt	ALO, #0
    232  1.10   matt 	movlt	AHI, #0x80000000
    233  1.12   matt #else
    234  1.12   matt 	blt	1f
    235  1.12   matt 	movs	ALO, #0
    236  1.12   matt 	mvns	ALO, ALO
    237  1.12   matt 	mov	AHI, ALO
    238  1.12   matt 	lsrs	AHI, AHI, #1
    239  1.12   matt 	b	2f
    240  1.12   matt 1:
    241  1.12   matt 	movs	ALO, #0
    242  1.12   matt 	movs	AHI, #1
    243  1.12   matt 	lsls	AHI, AHI, #31
    244  1.12   matt 2:
    245  1.12   matt #endif /* __thumb__ && !_ARM_ARCH_T2 */
    246   1.5   matt 	bl	PLT_SYM(__aeabi_ldiv0)
    247  1.12   matt 	pop	{r2-r4, pc}
    248  1.12   matt #endif	/* !_KERNEL && !_STANDALONE */
    249  1.12   matt #ifdef __ARM_EABI__
    250  1.12   matt 	.cfi_endproc
    251  1.13  joerg # if !defined(__ARM_DWARF_EH__)
    252  1.12   matt 	.fnend
    253  1.13  joerg # endif
    254   1.7   matt #endif
    255   1.1   matt END(__aeabi_ldivmod)
    256