1/* libgcc routines for C-SKY.
2   Copyright (C) 2018-2019 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)
58SYM (\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
7110:
72	cmphsi	\ry, 1
73	bf	11f
74	subi	\rx, \rx, 1
75	lsri	\ry, \ry, 1
76	br	10b
7711:
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
10410:
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
11210:
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
148FUNC_START udiv32
149FUNC_START udivsi3
150	cmpnei	a1, 0	// look for 0 divisor
151	bt	9f
152	trap	3	// divide by 0
1539:
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
1588:
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
1801:
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
1862:
187	addc	a2, a2	// shift by 1 and count subtracts
188	bf	1b	// if sentinel falls out of quotient, stop
189
1904:
191	mov	a0, a2	// return quotient
192	mov	a1, a3	// and piggyback the remainder
193	pop	l0
194FUNC_END udiv32
195FUNC_END udivsi3
196#endif
197
198#ifdef	L_umodsi3
199FUNC_START urem32
200FUNC_START umodsi3
201	cmpnei	a1, 0	// look for 0 divisor
202	bt	9f
203	trap	3	// divide by 0
2049:
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
2098:
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
2171:
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
2232:
224	addc	a2, a2	// shift by 1 and count subtracts
225	bf	1b	// if sentinel falls out of quotient, stop
226
2274:
228	mov	a0, a3	// and piggyback the remainder
229	jmp	lr
230FUNC_END urem32
231FUNC_END umodsi3
232#endif
233
234
235#ifdef	L_divsi3
236FUNC_START div32
237FUNC_START divsi3
238	cmpnei	a1, 0	// look for 0 divisor
239	bt	9f
240	trap	3	// divide by 0
2419:
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
2468:
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
2721:
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
2782:
279	addc	a2, a2	// shift by 1 and count subtracts
280	bf	1b	// if sentinel falls out of quotient, stop
281
2824:
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
2913:
292	pop	l0, l1
293FUNC_END div32
294FUNC_END divsi3
295#endif
296
297#ifdef	L_modsi3
298FUNC_START rem32
299FUNC_START modsi3
300	push	l0
301	cmpnei	a1, 0	// look for 0 divisor
302	bt	9f
303	trap	3	// divide by 0
3049:
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
3098:
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
3211:
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
3272:
328	addc	a2, a2	// shift by 1 and count subtracts
329	bf	1b	// if sentinel falls out of quotient, stop
330
3314:
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
3373:
338	pop	l0
339FUNC_END rem32
340FUNC_END modsi3
341#endif
342
343/* Unordered comparisons for single and double float.  */
344
345#ifdef L_unordsf2
346FUNC_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
3591:
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
3672:
368	 ld.w	  r4, (sp, 0x0)
369	 addi	  sp, 4
370	 movi	  r0, 0
371	 rts
3723:
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
3871:
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
3952:
396	 movi	  r0, 0
397	 rts
3983:
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
4091:
410	 asri	  r3, r3, 24
411	 not	  r13, r3
412	 bnez	  r13, 2f
413	 lsli	  r13, r1, 9
414	 bnez	  r13, 3f
4152:
416	 movi	  r0, 0
417	 rts
4183:
419	 movi	  r0, 1
420	 rts
421#endif
422FUNC_END unordsf2
423#endif
424
425#ifdef L_unorddf2
426FUNC_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
4411:
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
4522:
453	 ld.w	  r4, (sp, 0x0)
454	 ld.w	  r5, (sp, 0x4)
455	 addi	  sp, 8
456	 movi	  r0, 0
457	 rts
4583:
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
4741:
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
4842:
485	 movi	  r0, 0
486	 rts
4873:
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
4981:
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
5062:
507	 movi	  r0, 0
508	 rts
5093:
510	 movi	  r0, 1
511	 rts
512#endif
513FUNC_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
521FUNC_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
532FUNC_END _gnu_csky_case_sqi
533#endif
534
535#ifdef L_csky_case_uqi
536FUNC_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
547FUNC_END _gnu_csky_case_uqi
548#endif
549
550#ifdef L_csky_case_shi
551FUNC_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
565FUNC_END _gnu_csky_case_shi
566#endif
567
568#ifdef L_csky_case_uhi
569FUNC_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
583FUNC_END _gnu_csky_case_uhi
584#endif
585
586#ifdef L_csky_case_si
587FUNC_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
603FUNC_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)
615FUNC_START \name
616	jmpi SYM (cmpdf2)
617FUNC_END \name
618.endm
619
620#ifdef	L_eqdf2
621COMPARE_DF_JUMP eqdf2
622#endif /* L_eqdf2 */
623
624#ifdef	L_nedf2
625COMPARE_DF_JUMP nedf2
626#endif /* L_nedf2 */
627
628#ifdef	L_gtdf2
629COMPARE_DF_JUMP gtdf2
630#endif /* L_gtdf2 */
631
632#ifdef	L_gedf2
633COMPARE_DF_JUMP gedf2
634#endif /* L_gedf2 */
635
636#ifdef	L_ltdf2
637COMPARE_DF_JUMP ltdf2
638#endif /* L_ltdf2 */
639
640#ifdef	L_ledf2
641COMPARE_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)
648FUNC_START \name
649	jmpi SYM (cmpsf2)
650FUNC_END \name
651.endm
652
653#ifdef	L_eqsf2
654COMPARE_SF_JUMP eqsf2
655#endif /* L_eqsf2 */
656
657#ifdef	L_nesf2
658COMPARE_SF_JUMP nesf2
659#endif /* L_nesf2 */
660
661#ifdef	L_gtsf2
662COMPARE_SF_JUMP gtsf2
663#endif /* L_gtsf2 */
664
665#ifdef	L_gesf2
666COMPARE_SF_JUMP __gesf2
667#endif /* L_gesf2 */
668
669#ifdef	L_ltsf2
670COMPARE_SF_JUMP __ltsf2
671#endif /* L_ltsf2 */
672
673#ifdef	L_lesf2
674COMPARE_SF_JUMP lesf2
675#endif /* L_lesf2 */
676