Home | History | Annotate | Line # | Download | only in mcore
      1 /* libgcc routines for the MCore.
      2    Copyright (C) 1993-2024 Free Software Foundation, Inc.
      3 
      4 This file is part of GCC.
      5 
      6 GCC is free software; you can redistribute it and/or modify it
      7 under the terms of the GNU General Public License as published by the
      8 Free Software Foundation; either version 3, or (at your option) any
      9 later version.
     10 
     11 This file is distributed in the hope that it will be useful, but
     12 WITHOUT ANY WARRANTY; without even the implied warranty of
     13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
     14 General Public License for more details.
     15 
     16 Under Section 7 of GPL version 3, you are granted additional
     17 permissions described in the GCC Runtime Library Exception, version
     18 3.1, as published by the Free Software Foundation.
     19 
     20 You should have received a copy of the GNU General Public License and
     21 a copy of the GCC Runtime Library Exception along with this program;
     22 see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
     23 <http://www.gnu.org/licenses/>.  */
     24 
     25 #define CONCAT1(a, b) CONCAT2(a, b)
     26 #define CONCAT2(a, b) a ## b
     27 
     28 /* Use the right prefix for global labels.  */
     29 
     30 #define SYM(x) CONCAT1 (__, x)
     31 
     32 #ifdef __ELF__
     33 #define TYPE(x) .type SYM (x),@function
     34 #define SIZE(x) .size SYM (x), . - SYM (x)
     35 #else
     36 #define TYPE(x)
     37 #define SIZE(x)
     38 #endif
     39 
     40 .macro FUNC_START name
     41 	.text
     42 	.globl SYM (\name)
     43 	TYPE (\name)
     44 SYM (\name):
     45 .endm
     46 
     47 .macro FUNC_END name
     48 	SIZE (\name)
     49 .endm
     50 
     51 #ifdef	L_udivsi3
     52 FUNC_START udiv32
     53 FUNC_START udivsi32
     54 
     55 	movi	r1,0		// r1-r2 form 64 bit dividend
     56 	movi	r4,1		// r4 is quotient (1 for a sentinel)
     57 
     58 	cmpnei	r3,0		// look for 0 divisor
     59 	bt	9f
     60 	trap	3		// divide by 0
     61 9:
     62 	// control iterations; skip across high order 0 bits in dividend
     63 	mov	r7,r2
     64 	cmpnei	r7,0
     65 	bt	8f
     66 	movi	r2,0		// 0 dividend
     67 	jmp	r15		// quick return
     68 8:
     69 	ff1	r7		// figure distance to skip
     70 	lsl	r4,r7		// move the sentinel along (with 0's behind)
     71 	lsl	r2,r7		// and the low 32 bits of numerator
     72 
     73 // appears to be wrong...
     74 // tested out incorrectly in our OS work...
     75 //	mov	r7,r3		// looking at divisor
     76 //	ff1	r7		// I can move 32-r7 more bits to left.
     77 //	addi	r7,1		// ok, one short of that...
     78 //	mov	r1,r2
     79 //	lsr	r1,r7		// bits that came from low order...
     80 //	rsubi	r7,31		// r7 == "32-n" == LEFT distance
     81 //	addi	r7,1		// this is (32-n)
     82 //	lsl	r4,r7		// fixes the high 32 (quotient)
     83 //	lsl	r2,r7
     84 //	cmpnei	r4,0
     85 //	bf	4f		// the sentinel went away...
     86 
     87 	// run the remaining bits
     88 
     89 1:	lslc	r2,1		// 1 bit left shift of r1-r2
     90 	addc	r1,r1
     91 	cmphs	r1,r3		// upper 32 of dividend >= divisor?
     92 	bf	2f
     93 	sub	r1,r3		// if yes, subtract divisor
     94 2:	addc	r4,r4		// shift by 1 and count subtracts
     95 	bf	1b		// if sentinel falls out of quotient, stop
     96 
     97 4:	mov	r2,r4		// return quotient
     98 	mov	r3,r1		// and piggyback the remainder
     99 	jmp	r15
    100 FUNC_END udiv32
    101 FUNC_END udivsi32
    102 #endif
    103 
    104 #ifdef	L_umodsi3
    105 FUNC_START urem32
    106 FUNC_START umodsi3
    107 	movi	r1,0		// r1-r2 form 64 bit dividend
    108 	movi	r4,1		// r4 is quotient (1 for a sentinel)
    109 	cmpnei	r3,0		// look for 0 divisor
    110 	bt	9f
    111 	trap	3		// divide by 0
    112 9:
    113 	// control iterations; skip across high order 0 bits in dividend
    114 	mov	r7,r2
    115 	cmpnei	r7,0
    116 	bt	8f
    117 	movi	r2,0		// 0 dividend
    118 	jmp	r15		// quick return
    119 8:
    120 	ff1	r7		// figure distance to skip
    121 	lsl	r4,r7		// move the sentinel along (with 0's behind)
    122 	lsl	r2,r7		// and the low 32 bits of numerator
    123 
    124 1:	lslc	r2,1		// 1 bit left shift of r1-r2
    125 	addc	r1,r1
    126 	cmphs	r1,r3		// upper 32 of dividend >= divisor?
    127 	bf	2f
    128 	sub	r1,r3		// if yes, subtract divisor
    129 2:	addc	r4,r4		// shift by 1 and count subtracts
    130 	bf	1b		// if sentinel falls out of quotient, stop
    131 	mov	r2,r1		// return remainder
    132 	jmp	r15
    133 FUNC_END urem32
    134 FUNC_END umodsi3
    135 #endif
    136 
    137 #ifdef	L_divsi3
    138 FUNC_START div32
    139 FUNC_START divsi3
    140 	mov	r5,r2		// calc sign of quotient
    141 	xor	r5,r3
    142 	abs	r2		// do unsigned divide
    143 	abs	r3
    144 	movi	r1,0		// r1-r2 form 64 bit dividend
    145 	movi	r4,1		// r4 is quotient (1 for a sentinel)
    146 	cmpnei	r3,0		// look for 0 divisor
    147 	bt	9f
    148 	trap	3		// divide by 0
    149 9:
    150 	// control iterations; skip across high order 0 bits in dividend
    151 	mov	r7,r2
    152 	cmpnei	r7,0
    153 	bt	8f
    154 	movi	r2,0		// 0 dividend
    155 	jmp	r15		// quick return
    156 8:
    157 	ff1	r7		// figure distance to skip
    158 	lsl	r4,r7		// move the sentinel along (with 0's behind)
    159 	lsl	r2,r7		// and the low 32 bits of numerator
    160 
    161 // tested out incorrectly in our OS work...
    162 //	mov	r7,r3		// looking at divisor
    163 //	ff1	r7		// I can move 32-r7 more bits to left.
    164 //	addi	r7,1		// ok, one short of that...
    165 //	mov	r1,r2
    166 //	lsr	r1,r7		// bits that came from low order...
    167 //	rsubi	r7,31		// r7 == "32-n" == LEFT distance
    168 //	addi	r7,1		// this is (32-n)
    169 //	lsl	r4,r7		// fixes the high 32 (quotient)
    170 //	lsl	r2,r7
    171 //	cmpnei	r4,0
    172 //	bf	4f		// the sentinel went away...
    173 
    174 	// run the remaining bits
    175 1:	lslc	r2,1		// 1 bit left shift of r1-r2
    176 	addc	r1,r1
    177 	cmphs	r1,r3		// upper 32 of dividend >= divisor?
    178 	bf	2f
    179 	sub	r1,r3		// if yes, subtract divisor
    180 2:	addc	r4,r4		// shift by 1 and count subtracts
    181 	bf	1b		// if sentinel falls out of quotient, stop
    182 
    183 4:	mov	r2,r4		// return quotient
    184 	mov	r3,r1		// piggyback the remainder
    185 	btsti	r5,31		// after adjusting for sign
    186 	bf	3f
    187 	rsubi	r2,0
    188 	rsubi	r3,0
    189 3:	jmp	r15
    190 FUNC_END div32
    191 FUNC_END divsi3
    192 #endif
    193 
    194 #ifdef	L_modsi3
    195 FUNC_START rem32
    196 FUNC_START modsi3
    197 	mov	r5,r2		// calc sign of remainder
    198 	abs	r2		// do unsigned divide
    199 	abs	r3
    200 	movi	r1,0		// r1-r2 form 64 bit dividend
    201 	movi	r4,1		// r4 is quotient (1 for a sentinel)
    202 	cmpnei	r3,0		// look for 0 divisor
    203 	bt	9f
    204 	trap	3		// divide by 0
    205 9:
    206 	// control iterations; skip across high order 0 bits in dividend
    207 	mov	r7,r2
    208 	cmpnei	r7,0
    209 	bt	8f
    210 	movi	r2,0		// 0 dividend
    211 	jmp	r15		// quick return
    212 8:
    213 	ff1	r7		// figure distance to skip
    214 	lsl	r4,r7		// move the sentinel along (with 0's behind)
    215 	lsl	r2,r7		// and the low 32 bits of numerator
    216 
    217 1:	lslc	r2,1		// 1 bit left shift of r1-r2
    218 	addc	r1,r1
    219 	cmphs	r1,r3		// upper 32 of dividend >= divisor?
    220 	bf	2f
    221 	sub	r1,r3		// if yes, subtract divisor
    222 2:	addc	r4,r4		// shift by 1 and count subtracts
    223 	bf	1b		// if sentinel falls out of quotient, stop
    224 	mov	r2,r1		// return remainder
    225 	btsti	r5,31		// after adjusting for sign
    226 	bf	3f
    227 	rsubi	r2,0
    228 3:	jmp	r15
    229 FUNC_END rem32
    230 FUNC_END modsi3
    231 #endif
    232 
    233 
    234 /* GCC expects that {__eq,__ne,__gt,__ge,__le,__lt}{df2,sf2}
    235    will behave as __cmpdf2. So, we stub the implementations to
    236    jump on to __cmpdf2 and __cmpsf2.
    237 
    238    All of these shortcircuit the return path so that __cmp{sd}f2
    239    will go directly back to the caller.  */
    240 
    241 .macro  COMPARE_DF_JUMP name
    242 	.import SYM (cmpdf2)
    243 FUNC_START \name
    244 	jmpi SYM (cmpdf2)
    245 FUNC_END \name
    246 .endm
    247 
    248 #ifdef  L_eqdf2
    249 COMPARE_DF_JUMP eqdf2
    250 #endif /* L_eqdf2 */
    251 
    252 #ifdef  L_nedf2
    253 COMPARE_DF_JUMP nedf2
    254 #endif /* L_nedf2 */
    255 
    256 #ifdef  L_gtdf2
    257 COMPARE_DF_JUMP gtdf2
    258 #endif /* L_gtdf2 */
    259 
    260 #ifdef  L_gedf2
    261 COMPARE_DF_JUMP gedf2
    262 #endif /* L_gedf2 */
    263 
    264 #ifdef  L_ltdf2
    265 COMPARE_DF_JUMP ltdf2
    266 #endif /* L_ltdf2 */
    267 
    268 #ifdef  L_ledf2
    269 COMPARE_DF_JUMP ledf2
    270 #endif /* L_ledf2 */
    271 
    272 /* SINGLE PRECISION FLOATING POINT STUBS */
    273 
    274 .macro  COMPARE_SF_JUMP name
    275 	.import SYM (cmpsf2)
    276 FUNC_START \name
    277 	jmpi SYM (cmpsf2)
    278 FUNC_END \name
    279 .endm
    280 
    281 #ifdef  L_eqsf2
    282 COMPARE_SF_JUMP eqsf2
    283 #endif /* L_eqsf2 */
    284 
    285 #ifdef  L_nesf2
    286 COMPARE_SF_JUMP nesf2
    287 #endif /* L_nesf2 */
    288 
    289 #ifdef  L_gtsf2
    290 COMPARE_SF_JUMP gtsf2
    291 #endif /* L_gtsf2 */
    292 
    293 #ifdef  L_gesf2
    294 COMPARE_SF_JUMP __gesf2
    295 #endif /* L_gesf2 */
    296 
    297 #ifdef  L_ltsf2
    298 COMPARE_SF_JUMP __ltsf2
    299 #endif /* L_ltsf2 */
    300 
    301 #ifdef  L_lesf2
    302 COMPARE_SF_JUMP lesf2
    303 #endif /* L_lesf2 */
    304