1 /* libgcc routines for C-SKY.
2 Copyright (C) 2018-2021 Free Software Foundation, Inc.
3 Contributed by C-SKY Microsystems and Mentor Graphics.
5 This file is part of GCC.
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
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.
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.
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/>. */
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)
46 #define TYPE(x) .type SYM (x),@function
47 #define SIZE(x) .size SYM (x), . - SYM (x)
53 .macro FUNC_START name
66 /* Emulate FF1 ("fast find 1") instruction on ck801.
67 Result goes in rx, clobbering ry. */
68 #if defined(__CK801__)
85 /* Likewise emulate lslc instruction ("logical left shift to C") on CK801. */
86 #if defined(__CK801__)
97 /* Emulate the abs instruction. */
98 #if defined(__CK802__)
106 #elif defined(__CK801__)
120 /* Emulate the ld.hs ("load signed halfword and extend") instruction
121 on ck801 and ck802. */
122 #if defined(__CK801__)
129 ld.bs \rx, (\ry, 0x0)
133 #if defined(__CK801__)
140 ld.hs \rx, (\ry, 0x0)
145 /* Signed and unsigned div/mod/rem functions. */
150 cmpnei a1, 0 // look for 0 divisor
152 trap 3 // divide by 0
154 // control iterations, skip across high order 0 bits in dividend
157 jmp lr // 0 dividend quick return
160 movi a2, 1 // a2 is quotient (1 for a sentinel)
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
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...
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)
177 bf 4f // the sentinel went away...
179 // run the remaining bits
181 LSLC_M a0 // 1 bit left shift of a3-a0
183 cmphs a3, a1 // upper 32 of dividend >= divisor?
185 subu a3, a1 // if yes, subtract divisor
187 addc a2, a2 // shift by 1 and count subtracts
188 bf 1b // if sentinel falls out of quotient, stop
191 mov a0, a2 // return quotient
192 mov a1, a3 // and piggyback the remainder
201 cmpnei a1, 0 // look for 0 divisor
203 trap 3 // divide by 0
205 // control iterations, skip across high order 0 bits in dividend
208 jmp lr // 0 dividend quick return
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
218 LSLC_M a0 // 1 bit left shift of a3-a0
220 cmphs a3, a1 // upper 32 of dividend >= divisor?
222 subu a3, a1 // if yes, subtract divisor
224 addc a2, a2 // shift by 1 and count subtracts
225 bf 1b // if sentinel falls out of quotient, stop
228 mov a0, a3 // and piggyback the remainder
238 cmpnei a1, 0 // look for 0 divisor
240 trap 3 // divide by 0
242 // control iterations, skip across high order 0 bits in dividend
245 jmp lr // 0 dividend quick return
249 xor l1, a1 // calc sign of quotient
252 movi a2, 1 // a2 is quotient (1 for a sentinel)
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
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...
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)
269 bf 4f // the sentinel went away...
271 // run the remaining bits
273 LSLC_M a0 // 1 bit left shift of a3-a0
275 cmphs a3, a1 // upper 32 of dividend >= divisor?
277 subu a3, a1 // if yes, subtract divisor
279 addc a2, a2 // shift by 1 and count subtracts
280 bf 1b // if sentinel falls out of quotient, stop
283 mov a0, a2 // return quotient
284 mov a1, a3 // and piggyback the remainder
285 LSLC_M l1 // after adjusting for sign
301 cmpnei a1, 0 // look for 0 divisor
303 trap 3 // divide by 0
305 // control iterations, skip across high order 0 bits in dividend
308 pop l0 // 0 dividend quick return
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
320 // run the remaining bits
322 LSLC_M a0 // 1 bit left shift of a3-a0
324 cmphs a3, a1 // upper 32 of dividend >= divisor?
326 subu a3, a1 // if yes, subtract divisor
328 addc a2, a2 // shift by 1 and count subtracts
329 bf 1b // if sentinel falls out of quotient, stop
332 mov a0, a3 // and piggyback the remainder
333 LSLC_M l0 // after adjusting for sign
343 /* Unordered comparisons for single and double float. */
347 #if defined(__CK801__)
377 #elif defined(__CK802__)
427 #if defined(__CK801__)
464 #elif defined(__CK802__)
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
532 FUNC_END _gnu_csky_case_sqi
535 #ifdef L_csky_case_uqi
536 FUNC_START _gnu_csky_case_uqi
547 FUNC_END _gnu_csky_case_uqi
550 #ifdef L_csky_case_shi
551 FUNC_START _gnu_csky_case_shi
565 FUNC_END _gnu_csky_case_shi
568 #ifdef L_csky_case_uhi
569 FUNC_START _gnu_csky_case_uhi
583 FUNC_END _gnu_csky_case_uhi
586 #ifdef L_csky_case_si
587 FUNC_START _gnu_csky_case_si
592 addi a1, a1, 2 // Align to word.
603 FUNC_END _gnu_csky_case_si
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.
610 All of these short-circuit the return path so that __cmp{sd}f2
611 will go directly back to the caller. */
613 .macro COMPARE_DF_JUMP name
621 COMPARE_DF_JUMP eqdf2
625 COMPARE_DF_JUMP nedf2
629 COMPARE_DF_JUMP gtdf2
633 COMPARE_DF_JUMP gedf2
637 COMPARE_DF_JUMP ltdf2
641 COMPARE_DF_JUMP ledf2
644 /* Single-precision floating point stubs. */
646 .macro COMPARE_SF_JUMP name
654 COMPARE_SF_JUMP eqsf2
658 COMPARE_SF_JUMP nesf2
662 COMPARE_SF_JUMP gtsf2
666 COMPARE_SF_JUMP __gesf2
670 COMPARE_SF_JUMP __ltsf2
674 COMPARE_SF_JUMP lesf2