xref: /openbsd/gnu/gcc/gcc/config/arc/lib1funcs.asm (revision a6445c1d)
1; libgcc routines for ARC cpu.
2
3/* Copyright (C) 1995, 1997,2004 Free Software Foundation, Inc.
4
5This file is free software; you can redistribute it and/or modify it
6under the terms of the GNU General Public License as published by the
7Free Software Foundation; either version 2, or (at your option) any
8later version.
9
10In addition to the permissions in the GNU General Public License, the
11Free Software Foundation gives you unlimited permission to link the
12compiled version of this file into combinations with other programs,
13and to distribute those combinations without any restriction coming
14from the use of this file.  (The General Public License restrictions
15do apply in other respects; for example, they cover modification of
16the file, and distribution when not linked into a combine
17executable.)
18
19This file is distributed in the hope that it will be useful, but
20WITHOUT ANY WARRANTY; without even the implied warranty of
21MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
22General Public License for more details.
23
24You should have received a copy of the GNU General Public License
25along with GCC; see the file COPYING.  If not, write to
26the Free Software Foundation, 51 Franklin Street, Fifth Floor,
27Boston, MA 02110-1301, USA.  */
28
29#ifdef  L_mulsi3
30	.section .text
31	.align 4
32
33#ifdef __base__
34	.cpu base
35	.global ___mulsi3
36___mulsi3:
37
38/* This the simple version.
39
40  while (a)
41    {
42      if (a & 1)
43        r += b;
44      a >>= 1;
45      b <<= 1;
46    }
47*/
48	mov r2,0		; Accumulate result here.
49.Lloop:
50	sub.f 0,r0,0		; while (a)
51	nop
52	beq.nd .Ldone
53	and.f 0,r0,1		; if (a & 1)
54	add.nz r2,r2,r1		; r += b
55	lsr r0,r0		; a >>= 1
56	b.d .Lloop
57	lsl r1,r1		; b <<= 1
58.Ldone:
59	j.d blink
60	mov r0,r2
61#endif
62
63#endif /* L_mulsi3 */
64
65#ifdef  L_umulsidi3
66	.section .text
67	.align 4
68
69#ifdef __base__
70	.cpu base
71	.global ___umulsidi3
72___umulsidi3:
73
74/* This the simple version.
75
76  while (a)
77    {
78      if (a & 1)
79        r += b;
80      a >>= 1;
81      b <<= 1;
82    }
83*/
84	mov r2,0		; Top part of b.
85	mov r3,0		; Accumulate result here.
86	mov r4,0
87.Lloop:
88	sub.f 0,r0,0		; while (a)
89	nop
90	beq.nd .Ldone
91	and.f 0,r0,1		; if (a & 1)
92	sub.f 0,r0,0
93	nop
94	beq .Ldontadd
95	add.f r4,r4,r1		; r += b
96	adc   r3,r3,r2
97.Ldontadd:
98	lsr r0,r0		; a >>= 1
99	lsl.f r1,r1		; b <<= 1
100	b.d .Lloop
101	rlc r2,r2
102.Ldone:
103#ifdef __big_endian__
104	mov r1,r4
105	j.d blink
106	mov r0,r3
107#else
108	mov r0,r4
109	j.d blink
110	mov r1,r3
111#endif
112#endif
113
114#endif /* L_umulsidi3 */
115
116#ifdef L_divmod_tools
117
118; Utilities used by all routines.
119
120	.section .text
121	.align 4
122
123; inputs: r0 = numerator, r1 = denominator
124; outputs: positive r0/r1,
125;          r6.bit1 = sign of numerator, r6.bit0 = sign of result
126
127	.global ___divnorm
128___divnorm:
129	mov r6,0		; keep sign in r6
130	sub.f 0,r0,0		; is numerator -ve?
131	sub.lt r0,0,r0		; negate numerator
132	mov.lt r6,3		; sign is -ve
133	sub.f 0,r1,0		; is denominator -ve?
134	sub.lt r1,0,r1		; negate denominator
135	xor.lt r6,r6,1		; toggle sign
136	j.nd blink
137
138/*
139unsigned long
140udivmodsi4(int modwanted, unsigned long num, unsigned long den)
141{
142  unsigned long bit = 1;
143  unsigned long res = 0;
144
145  while (den < num && bit && !(den & (1L<<31)))
146    {
147      den <<=1;
148      bit <<=1;
149    }
150  while (bit)
151    {
152      if (num >= den)
153	{
154	  num -= den;
155	  res |= bit;
156	}
157      bit >>=1;
158      den >>=1;
159    }
160  if (modwanted) return num;
161  return res;
162}
163*/
164
165; inputs: r0 = numerator, r1 = denominator
166; outputs: r0 = quotient, r1 = remainder, r2/r3 trashed
167
168	.global ___udivmodsi4
169___udivmodsi4:
170	mov r2,1		; bit = 1
171	mov r3,0		; res = 0
172.Lloop1:
173	sub.f 0,r1,r0		; while (den < num
174	nop
175	bnc.nd .Lloop2
176	sub.f 0,r2,0		; && bit
177	nop
178	bz.nd .Lloop2
179	lsl.f 0,r1		; && !(den & (1<<31))
180	nop
181	bc.nd .Lloop2
182	lsl r1,r1		; den <<= 1
183	b.d .Lloop1
184	lsl r2,r2		; bit <<= 1
185.Lloop2:
186	sub.f 0,r2,0		; while (bit)
187	nop
188	bz.nd .Ldivmodend
189	sub.f 0,r0,r1		; if (num >= den)
190	nop
191	bc.nd .Lshiftdown
192	sub r0,r0,r1		; num -= den
193	or r3,r3,r2		; res |= bit
194.Lshiftdown:
195	lsr r2,r2		; bit >>= 1
196	b.d .Lloop2
197	lsr r1,r1		; den >>= 1
198.Ldivmodend:
199	mov r1,r0		; r1 = mod
200	j.d blink
201	mov r0,r3		; r0 = res
202
203#endif
204
205#ifdef  L_udivsi3
206	.section .text
207	.align 4
208
209#ifdef __base__
210	.cpu base
211	.global ___udivsi3
212___udivsi3:
213	mov r7,blink
214	bl.nd ___udivmodsi4
215	j.nd r7
216#endif
217
218#endif /* L_udivsi3 */
219
220#ifdef  L_divsi3
221	.section .text
222	.align 4
223
224#ifdef __base__
225	.cpu base
226	.global ___divsi3
227___divsi3:
228	mov r7,blink
229	bl.nd ___divnorm
230	bl.nd ___udivmodsi4
231	and.f 0,r6,1
232	sub.nz r0,0,r0		; cannot go in delay slot, has limm value
233	j.nd r7
234#endif
235
236#endif /* L_divsi3 */
237
238#ifdef  L_umodsi3
239	.section .text
240	.align 4
241
242#ifdef __base__
243	.cpu base
244	.global ___umodsi3
245___umodsi3:
246	mov r7,blink
247	bl.nd ___udivmodsi4
248	j.d r7
249	mov r0,r1
250#endif
251
252#endif /* L_umodsi3 */
253
254#ifdef  L_modsi3
255	.section .text
256	.align 4
257
258#ifdef __base__
259	.cpu base
260	.global ___modsi3
261___modsi3:
262	mov r7,blink
263	bl.nd ___divnorm
264	bl.nd ___udivmodsi4
265	and.f 0,r6,2
266	sub.nz r1,0,r1
267	j.d r7
268	mov r0,r1
269#endif
270
271#endif /* L_modsi3 */
272