]> git.ipfire.org Git - thirdparty/gcc.git/blob - libgcc/config/csky/lib1funcs.S
Update copyright years.
[thirdparty/gcc.git] / libgcc / config / csky / lib1funcs.S
1 /* libgcc routines for C-SKY.
2 Copyright (C) 2018-2021 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 */