Home | History | Annotate | Line # | Download | only in csky
      1 /* libgcc routines for C-SKY.
      2    Copyright (C) 2018-2024 Free Software Foundation, Inc.
      3    Contributed by C-SKY Microsystems and Mentor Graphics.
      4 
      5    This file is part of GCC.
      6 
      7    GCC is free software; you can redistribute it and/or modify it
      8    under the terms of the GNU General Public License as published by the
      9    Free Software Foundation; either version 3, or (at your option) any
     10    later version.
     11 
     12    This file is distributed in the hope that it will be useful, but
     13    WITHOUT ANY WARRANTY; without even the implied warranty of
     14    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
     15    General Public License for more details.
     16 
     17    Under Section 7 of GPL version 3, you are granted additional
     18    permissions described in the GCC Runtime Library Exception, version
     19    3.1, as published by the Free Software Foundation.
     20 
     21    You should have received a copy of the GNU General Public License and
     22    a copy of the GCC Runtime Library Exception along with this program;
     23    see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
     24    <http://www.gnu.org/licenses/>.  */
     25 
     26 
     27 /* Use the right prefix for global labels.  */
     28 #define CONCAT1(a, b) CONCAT2(a, b)
     29 #define CONCAT2(a, b) a ## b
     30 #define SYM(x) CONCAT1 (__, x)
     31 
     32 #ifndef __CSKYBE__
     33 #define xl r0
     34 #define xh r1
     35 #define yl r2
     36 #define yh r3
     37 #else
     38 #define xh r0
     39 #define xl r1
     40 #define yh r2
     41 #define yl r3
     42 #endif
     43 
     44 
     45 #ifdef __ELF__
     46 #define TYPE(x) .type SYM (x),@function
     47 #define SIZE(x) .size SYM (x), . - SYM (x)
     48 #else
     49 #define TYPE(x)
     50 #define SIZE(x)
     51 #endif
     52 
     53 .macro FUNC_START name
     54 	.text
     55 	.align	2
     56 	.globl SYM (\name)
     57 	TYPE (\name)
     58 SYM (\name):
     59 .endm
     60 
     61 .macro FUNC_END name
     62 	SIZE (\name)
     63 .endm
     64 
     65 
     66 /* Emulate FF1 ("fast find 1") instruction on ck801.
     67    Result goes in rx, clobbering ry.  */
     68 #if defined(__CK801__)
     69 .macro FF1_M rx, ry
     70 	movi	\rx, 32
     71 10:
     72 	cmphsi	\ry, 1
     73 	bf	11f
     74 	subi	\rx, \rx, 1
     75 	lsri	\ry, \ry, 1
     76 	br	10b
     77 11:
     78 .endm
     79 #else
     80 .macro FF1_M rx, ry
     81 	ff1	\rx, \ry
     82 .endm
     83 #endif
     84 
     85 /* Likewise emulate lslc instruction ("logical left shift to C") on CK801.  */
     86 #if defined(__CK801__)
     87 .macro LSLC_M rx
     88 	cmpne	\rx, \rx
     89 	addc	\rx, \rx
     90 .endm
     91 #else
     92 .macro LSLC_M rx
     93 	lslc	\rx
     94 .endm
     95 #endif
     96 
     97 /* Emulate the abs instruction.  */
     98 #if  defined(__CK802__)
     99 .macro ABS_M rx
    100 	btsti	\rx, 31
    101 	bf	10f
    102 	not	\rx
    103 	addi	\rx, 1
    104 10:
    105 .endm
    106 #elif defined(__CK801__)
    107 .macro ABS_M rx
    108 	cmplti	\rx, 1
    109 	bf	10f
    110 	not	\rx
    111 	addi	\rx, 1
    112 10:
    113 .endm
    114 #else
    115 .macro ABS_M rx
    116 	abs	\rx
    117 .endm
    118 #endif
    119 
    120 /* Emulate the ld.hs ("load signed halfword and extend") instruction
    121    on ck801 and ck802.  */
    122 #if defined(__CK801__)
    123 .macro LDBS_M rx, ry
    124 	ld.b \rx, (\ry, 0x0)
    125 	sextb \rx, \rx
    126 .endm
    127 #else
    128 .macro LDBS_M rx, ry
    129 	ld.bs \rx, (\ry, 0x0)
    130 .endm
    131 #endif
    132 
    133 #if defined(__CK801__)
    134 .macro LDHS_M rx, ry
    135 	ld.h \rx, (\ry, 0x0)
    136 	sexth \rx, \rx
    137 .endm
    138 #else
    139 .macro LDHS_M rx, ry
    140 	ld.hs \rx, (\ry, 0x0)
    141 .endm
    142 #endif
    143 
    144 
    145 /* Signed and unsigned div/mod/rem functions.  */
    146 
    147 #ifdef	L_udivsi3
    148 FUNC_START udiv32
    149 FUNC_START udivsi3
    150 	cmpnei	a1, 0	// look for 0 divisor
    151 	bt	9f
    152 	trap	3	// divide by 0
    153 9:
    154 	// control iterations, skip across high order 0 bits in dividend
    155 	cmpnei	a0, 0
    156 	bt	8f
    157 	jmp	lr	// 0 dividend quick return
    158 8:
    159 	push	l0
    160 	movi	a2, 1	// a2 is quotient (1 for a sentinel)
    161 	mov	a3, a0
    162 	FF1_M	l0, a3	// figure distance to skip
    163 	lsl	a2, l0	// move the sentinel along (with 0's behind)
    164 	lsl	a0, l0	// and the low 32 bits of numerator
    165 
    166 	// FIXME:  Is this correct?
    167 	mov	a3, a1	// looking at divisor
    168 	FF1_M	l0, a3	// I can move 32-l0 more bits to left.
    169 	addi	l0, 1	// ok, one short of that...
    170 	mov	a3, a0
    171 	lsr	a3, l0	// bits that came from low order...
    172 	not	l0	// l0 == "32-n" == LEFT distance
    173 	addi	l0, 33	// this is (32-n)
    174 	lsl	a2,l0	// fixes the high 32 (quotient)
    175 	lsl	a0,l0
    176 	cmpnei	a2,0
    177 	bf	4f	// the sentinel went away...
    178 
    179 	// run the remaining bits
    180 1:
    181 	LSLC_M	a0	// 1 bit left shift of a3-a0
    182 	addc	a3, a3
    183 	cmphs	a3, a1	// upper 32 of dividend >= divisor?
    184 	bf	2f
    185 	subu	a3, a1	// if yes, subtract divisor
    186 2:
    187 	addc	a2, a2	// shift by 1 and count subtracts
    188 	bf	1b	// if sentinel falls out of quotient, stop
    189 
    190 4:
    191 	mov	a0, a2	// return quotient
    192 	mov	a1, a3	// and piggyback the remainder
    193 	pop	l0
    194 FUNC_END udiv32
    195 FUNC_END udivsi3
    196 #endif
    197 
    198 #ifdef	L_umodsi3
    199 FUNC_START urem32
    200 FUNC_START umodsi3
    201 	cmpnei	a1, 0	// look for 0 divisor
    202 	bt	9f
    203 	trap	3	// divide by 0
    204 9:
    205 	// control iterations, skip across high order 0 bits in dividend
    206 	cmpnei	a0, 0
    207 	bt	8f
    208 	jmp	lr	// 0 dividend quick return
    209 8:
    210 	mov	a2, a0
    211 	FF1_M	a3, a2	// figure distance to skip
    212 	movi	a2, 1	// a2 is quotient (1 for a sentinel)
    213 	lsl	a2, a3	// move the sentinel along (with 0's behind)
    214 	lsl	a0, a3	// and the low 32 bits of numerator
    215 	movi	a3, 0
    216 
    217 1:
    218 	LSLC_M	a0	// 1 bit left shift of a3-a0
    219 	addc	a3, a3
    220 	cmphs	a3, a1	// upper 32 of dividend >= divisor?
    221 	bf	2f
    222 	subu	a3, a1	// if yes, subtract divisor
    223 2:
    224 	addc	a2, a2	// shift by 1 and count subtracts
    225 	bf	1b	// if sentinel falls out of quotient, stop
    226 
    227 4:
    228 	mov	a0, a3	// and piggyback the remainder
    229 	jmp	lr
    230 FUNC_END urem32
    231 FUNC_END umodsi3
    232 #endif
    233 
    234 
    235 #ifdef	L_divsi3
    236 FUNC_START div32
    237 FUNC_START divsi3
    238 	cmpnei	a1, 0	// look for 0 divisor
    239 	bt	9f
    240 	trap	3	// divide by 0
    241 9:
    242 	// control iterations, skip across high order 0 bits in dividend
    243 	cmpnei	a0, 0
    244 	bt	8f
    245 	jmp	lr	// 0 dividend quick return
    246 8:
    247 	push	l0, l1
    248 	mov	l1, a0
    249 	xor	l1, a1	// calc sign of quotient
    250 	ABS_M	a0
    251 	ABS_M	a1
    252 	movi	a2, 1	// a2 is quotient (1 for a sentinel)
    253 	mov	a3, a0
    254 	FF1_M	l0, a3	// figure distance to skip
    255 	lsl	a2, l0	// move the sentinel along (with 0's behind)
    256 	lsl	a0, l0	// and the low 32 bits of numerator
    257 
    258 	// FIXME: is this correct?
    259 	mov	a3, a1	// looking at divisor
    260 	FF1_M	l0, a3	// I can move 32-l0 more bits to left.
    261 	addi	l0, 1	// ok, one short of that...
    262 	mov	a3, a0
    263 	lsr	a3, l0	// bits that came from low order...
    264 	not	l0	// l0 == "32-n" == LEFT distance
    265 	addi	l0, 33	// this is (32-n)
    266 	lsl	a2,l0	// fixes the high 32 (quotient)
    267 	lsl	a0,l0
    268 	cmpnei	a2,0
    269 	bf	4f	// the sentinel went away...
    270 
    271 	// run the remaining bits
    272 1:
    273 	LSLC_M	a0	// 1 bit left shift of a3-a0
    274 	addc	a3, a3
    275 	cmphs	a3, a1	// upper 32 of dividend >= divisor?
    276 	bf	2f
    277 	subu	a3, a1	// if yes, subtract divisor
    278 2:
    279 	addc	a2, a2	// shift by 1 and count subtracts
    280 	bf	1b	// if sentinel falls out of quotient, stop
    281 
    282 4:
    283 	mov	a0, a2	// return quotient
    284 	mov	a1, a3	// and piggyback the remainder
    285 	LSLC_M	l1	// after adjusting for sign
    286 	bf	3f
    287 	not	a0
    288 	addi	a0, 1
    289 	not	a1
    290 	addi	a1, 1
    291 3:
    292 	pop	l0, l1
    293 FUNC_END div32
    294 FUNC_END divsi3
    295 #endif
    296 
    297 #ifdef	L_modsi3
    298 FUNC_START rem32
    299 FUNC_START modsi3
    300 	push	l0
    301 	cmpnei	a1, 0	// look for 0 divisor
    302 	bt	9f
    303 	trap	3	// divide by 0
    304 9:
    305 	// control iterations, skip across high order 0 bits in dividend
    306 	cmpnei	a0, 0
    307 	bt	8f
    308 	pop	l0	// 0 dividend quick return
    309 8:
    310 	mov	l0, a0
    311 	ABS_M	a0
    312 	ABS_M	a1
    313 	mov	a2, a0
    314 	FF1_M	a3, a2	// figure distance to skip
    315 	movi	a2, 1	// a2 is quotient (1 for a sentinel)
    316 	lsl	a2, a3	// move the sentinel along (with 0's behind)
    317 	lsl	a0, a3	// and the low 32 bits of numerator
    318 	movi	a3, 0
    319 
    320 	// run the remaining bits
    321 1:
    322 	LSLC_M	a0	// 1 bit left shift of a3-a0
    323 	addc	a3, a3
    324 	cmphs	a3, a1	// upper 32 of dividend >= divisor?
    325 	bf	2f
    326 	subu	a3, a1	// if yes, subtract divisor
    327 2:
    328 	addc	a2, a2	// shift by 1 and count subtracts
    329 	bf	1b	// if sentinel falls out of quotient, stop
    330 
    331 4:
    332 	mov	a0, a3	// and piggyback the remainder
    333 	LSLC_M	l0	// after adjusting for sign
    334 	bf	3f
    335 	not	a0
    336 	addi	a0, 1
    337 3:
    338 	pop	l0
    339 FUNC_END rem32
    340 FUNC_END modsi3
    341 #endif
    342 
    343 /* Unordered comparisons for single and double float.  */
    344 
    345 #ifdef L_unordsf2
    346 FUNC_START unordsf2
    347 #if defined(__CK801__)
    348 	 subi	  sp, 4
    349 	 st.w	  r4, (sp, 0x0)
    350 	 lsli	  r2, r0, 1
    351 	 lsli	  r3, r1, 1
    352 	 asri	  r4, r2, 24
    353 	 not	  r4
    354 	 cmpnei	  r4, 0
    355 	 bt	  1f
    356 	 lsli	  r4, r0, 9
    357 	 cmpnei	  r4, 0
    358 	 bt	  3f
    359 1:
    360 	 asri	  r4, r3, 24
    361 	 not	  r4
    362 	 cmpnei	  r4, 0
    363 	 bt	  2f
    364 	 lsli	  r4, r1, 9
    365 	 cmpnei	  r4, 0
    366 	 bt	  3f
    367 2:
    368 	 ld.w	  r4, (sp, 0x0)
    369 	 addi	  sp, 4
    370 	 movi	  r0, 0
    371 	 rts
    372 3:
    373 	 ld.w	  r4, (sp, 0x0)
    374 	 addi	  sp, 4
    375 	 movi	  r0, 1
    376 	 rts
    377 #elif defined(__CK802__)
    378 	 lsli	  r2, r0, 1
    379 	 lsli	  r3, r1, 1
    380 	 asri	  r2, r2, 24
    381 	 not	  r13, r2
    382 	 cmpnei	  r13, 0
    383 	 bt	  1f
    384 	 lsli	  r13, r0, 9
    385 	 cmpnei	  r13, 0
    386 	 bt	  3f
    387 1:
    388 	 asri	  r3, r3, 24
    389 	 not	  r13, r3
    390 	 cmpnei	  r13, 0
    391 	 bt	  2f
    392 	 lsli	  r13, r1, 9
    393 	 cmpnei	  r13, 0
    394 	 bt	  3f
    395 2:
    396 	 movi	  r0, 0
    397 	 rts
    398 3:
    399 	 movi	  r0, 1
    400 	 rts
    401 #else
    402 	 lsli	  r2, r0, 1
    403 	 lsli	  r3, r1, 1
    404 	 asri	  r2, r2, 24
    405 	 not	  r13, r2
    406 	 bnez	  r13, 1f
    407 	 lsli	  r13, r0, 9
    408 	 bnez	  r13, 3f
    409 1:
    410 	 asri	  r3, r3, 24
    411 	 not	  r13, r3
    412 	 bnez	  r13, 2f
    413 	 lsli	  r13, r1, 9
    414 	 bnez	  r13, 3f
    415 2:
    416 	 movi	  r0, 0
    417 	 rts
    418 3:
    419 	 movi	  r0, 1
    420 	 rts
    421 #endif
    422 FUNC_END unordsf2
    423 #endif
    424 
    425 #ifdef L_unorddf2
    426 FUNC_START unorddf2
    427 #if defined(__CK801__)
    428 	 subi	  sp, 8
    429 	 st.w	  r4, (sp, 0x0)
    430 	 st.w	  r5, (sp, 0x4)
    431 	 lsli	  r4, xh, 1
    432 	 asri	  r4, r4, 21
    433 	 not	  r4
    434 	 cmpnei	  r4, 0
    435 	 bt	  1f
    436 	 mov	  r4, xl
    437 	 lsli	  r5, xh, 12
    438 	 or	  r4, r5
    439 	 cmpnei	  r4, 0
    440 	 bt	  3f
    441 1:
    442 	 lsli	  r4, yh, 1
    443 	 asri	  r4, r4, 21
    444 	 not	  r4
    445 	 cmpnei	  r4, 0
    446 	 bt	  2f
    447 	 mov	  r4,yl
    448 	 lsli	  r5, yh, 12
    449 	 or	  r4, r5
    450 	 cmpnei	  r4, 0
    451 	 bt	  3f
    452 2:
    453 	 ld.w	  r4, (sp, 0x0)
    454 	 ld.w	  r5, (sp, 0x4)
    455 	 addi	  sp, 8
    456 	 movi	  r0, 0
    457 	 rts
    458 3:
    459 	 ld.w	  r4, (sp, 0x0)
    460 	 ld.w	  r5, (sp, 0x4)
    461 	 addi	  sp, 8
    462 	 movi	  r0, 1
    463 	 rts
    464 #elif defined(__CK802__)
    465 	 lsli	  r13, xh, 1
    466 	 asri	  r13, r13, 21
    467 	 not	  r13
    468 	 cmpnei	  r13, 0
    469 	 bt	  1f
    470 	 lsli	  xh, xh, 12
    471 	 or	  r13, xl, xh
    472 	 cmpnei	  r13, 0
    473 	 bt	  3f
    474 1:
    475 	 lsli	  r13, yh, 1
    476 	 asri	  r13, r13, 21
    477 	 not	  r13
    478 	 cmpnei	  r13, 0
    479 	 bt	  2f
    480 	 lsli	  yh, yh, 12
    481 	 or	  r13, yl, yh
    482 	 cmpnei	  r13, 0
    483 	 bt	  3f
    484 2:
    485 	 movi	  r0, 0
    486 	 rts
    487 3:
    488 	 movi	  r0, 1
    489 	 rts
    490 #else
    491 	 lsli	  r13, xh, 1
    492 	 asri	  r13, r13, 21
    493 	 not	  r13
    494 	 bnez	  r13, 1f
    495 	 lsli	  xh, xh, 12
    496 	 or	  r13, xl, xh
    497 	 bnez	  r13, 3f
    498 1:
    499 	 lsli	  r13, yh, 1
    500 	 asri	  r13, r13, 21
    501 	 not	  r13
    502 	 bnez	  r13, 2f
    503 	 lsli	  yh, yh, 12
    504 	 or	  r13, yl, yh
    505 	 bnez	  r13, 3f
    506 2:
    507 	 movi	  r0, 0
    508 	 rts
    509 3:
    510 	 movi	  r0, 1
    511 	 rts
    512 #endif
    513 FUNC_END unorddf2
    514 #endif
    515 
    516 /* When optimizing for size on ck801 and ck802, GCC emits calls to the
    517    following helper functions when expanding casesi, instead of emitting
    518    the table lookup and jump inline.  Note that in these functions the
    519    jump is handled by tweaking the value of lr before rts.  */
    520 #ifdef L_csky_case_sqi
    521 FUNC_START _gnu_csky_case_sqi
    522 	subi	sp, 4
    523 	st.w	a1, (sp, 0x0)
    524 	mov	a1, lr
    525 	add	a1, a1, a0
    526 	LDBS_M	a1, a1
    527 	lsli	a1, a1, 1
    528 	add	lr, lr, a1
    529 	ld.w	a1, (sp, 0x0)
    530 	addi	sp, 4
    531 	rts
    532 FUNC_END _gnu_csky_case_sqi
    533 #endif
    534 
    535 #ifdef L_csky_case_uqi
    536 FUNC_START _gnu_csky_case_uqi
    537 	subi	sp, 4
    538 	st.w	a1, (sp, 0x0)
    539 	mov	a1, lr
    540 	add	a1, a1, a0
    541 	ld.b	a1, (a1, 0x0)
    542 	lsli	a1, a1, 1
    543 	add	lr, lr, a1
    544 	ld.w	a1, (sp, 0x0)
    545 	addi	sp, 4
    546 	rts
    547 FUNC_END _gnu_csky_case_uqi
    548 #endif
    549 
    550 #ifdef L_csky_case_shi
    551 FUNC_START _gnu_csky_case_shi
    552 	subi	sp, 8
    553 	st.w	a0, (sp, 0x4)
    554 	st.w	a1, (sp, 0x0)
    555 	mov	a1, lr
    556 	lsli	a0, a0, 1
    557 	add	a1, a1, a0
    558 	LDHS_M	a1, a1
    559 	lsli	a1, a1, 1
    560 	add	lr, lr, a1
    561 	ld.w	a0, (sp, 0x4)
    562 	ld.w	a1, (sp, 0x0)
    563 	addi	sp, 8
    564 	rts
    565 FUNC_END _gnu_csky_case_shi
    566 #endif
    567 
    568 #ifdef L_csky_case_uhi
    569 FUNC_START _gnu_csky_case_uhi
    570 	subi	sp, 8
    571 	st.w	a0, (sp, 0x4)
    572 	st.w	a1, (sp, 0x0)
    573 	mov	a1, lr
    574 	lsli	a0, a0, 1
    575 	add	a1, a1, a0
    576 	ld.h	a1, (a1, 0x0)
    577 	lsli	a1, a1, 1
    578 	add	lr, lr, a1
    579 	ld.w	a0, (sp, 0x4)
    580 	ld.w	a1, (sp, 0x0)
    581 	addi	sp, 8
    582 	rts
    583 FUNC_END _gnu_csky_case_uhi
    584 #endif
    585 
    586 #ifdef L_csky_case_si
    587 FUNC_START _gnu_csky_case_si
    588 	subi	sp, 8
    589 	st.w	a0, (sp, 0x4)
    590 	st.w	a1, (sp, 0x0)
    591 	mov	a1, lr
    592 	addi	a1, a1, 2	// Align to word.
    593 	bclri	a1, a1, 1
    594 	mov	lr, a1
    595 	lsli	a0, a0, 2
    596 	add	a1, a1, a0
    597 	ld.w	a0, (a1, 0x0)
    598 	add	lr, lr, a0
    599 	ld.w	a0, (sp, 0x4)
    600 	ld.w	a1, (sp, 0x0)
    601 	addi	sp, 8
    602 	rts
    603 FUNC_END _gnu_csky_case_si
    604 #endif
    605 
    606 /* GCC expects that {__eq,__ne,__gt,__ge,__le,__lt}{df2,sf2}
    607    will behave as __cmpdf2. So, we stub the implementations to
    608    jump on to __cmpdf2 and __cmpsf2.
    609 
    610    All of these short-circuit the return path so that __cmp{sd}f2
    611    will go directly back to the caller.  */
    612 
    613 .macro	COMPARE_DF_JUMP name
    614 	.import SYM (cmpdf2)
    615 FUNC_START \name
    616 	jmpi SYM (cmpdf2)
    617 FUNC_END \name
    618 .endm
    619 
    620 #ifdef	L_eqdf2
    621 COMPARE_DF_JUMP eqdf2
    622 #endif /* L_eqdf2 */
    623 
    624 #ifdef	L_nedf2
    625 COMPARE_DF_JUMP nedf2
    626 #endif /* L_nedf2 */
    627 
    628 #ifdef	L_gtdf2
    629 COMPARE_DF_JUMP gtdf2
    630 #endif /* L_gtdf2 */
    631 
    632 #ifdef	L_gedf2
    633 COMPARE_DF_JUMP gedf2
    634 #endif /* L_gedf2 */
    635 
    636 #ifdef	L_ltdf2
    637 COMPARE_DF_JUMP ltdf2
    638 #endif /* L_ltdf2 */
    639 
    640 #ifdef	L_ledf2
    641 COMPARE_DF_JUMP ledf2
    642 #endif /* L_ledf2 */
    643 
    644 /* Single-precision floating point stubs.  */
    645 
    646 .macro	COMPARE_SF_JUMP name
    647 	.import SYM (cmpsf2)
    648 FUNC_START \name
    649 	jmpi SYM (cmpsf2)
    650 FUNC_END \name
    651 .endm
    652 
    653 #ifdef	L_eqsf2
    654 COMPARE_SF_JUMP eqsf2
    655 #endif /* L_eqsf2 */
    656 
    657 #ifdef	L_nesf2
    658 COMPARE_SF_JUMP nesf2
    659 #endif /* L_nesf2 */
    660 
    661 #ifdef	L_gtsf2
    662 COMPARE_SF_JUMP gtsf2
    663 #endif /* L_gtsf2 */
    664 
    665 #ifdef	L_gesf2
    666 COMPARE_SF_JUMP __gesf2
    667 #endif /* L_gesf2 */
    668 
    669 #ifdef	L_ltsf2
    670 COMPARE_SF_JUMP __ltsf2
    671 #endif /* L_ltsf2 */
    672 
    673 #ifdef	L_lesf2
    674 COMPARE_SF_JUMP lesf2
    675 #endif /* L_lesf2 */
    676