xref: /netbsd-src/external/gpl3/gcc.old/dist/libgcc/config/visium/lib2funcs.c (revision 8feb0f0b7eaff0608f8350bbfa3098827b4bb91b)
1 /* Copyright (C) 2014-2020 Free Software Foundation, Inc.
2 
3 This file is part of GCC.
4 
5 GCC is free software; you can redistribute it and/or modify it under
6 the terms of the GNU General Public License as published by the Free
7 Software Foundation; either version 3, or (at your option) any later
8 version.
9 
10 GCC is distributed in the hope that it will be useful, but WITHOUT ANY
11 WARRANTY; without even the implied warranty of MERCHANTABILITY or
12 FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
13 for more details.
14 
15 Under Section 7 of GPL version 3, you are granted additional
16 permissions described in the GCC Runtime Library Exception, version
17 3.1, as published by the Free Software Foundation.
18 
19 You should have received a copy of the GNU General Public License and
20 a copy of the GCC Runtime Library Exception along with this program;
21 see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
22 <http://www.gnu.org/licenses/>.  */
23 
24 #include "tconfig.h"
25 #include "tsystem.h"
26 #include "coretypes.h"
27 #include "tm.h"
28 #include "libgcc_tm.h"
29 
30 #ifdef HAVE_GAS_HIDDEN
31 #define ATTRIBUTE_HIDDEN  __attribute__ ((__visibility__ ("hidden")))
32 #else
33 #define ATTRIBUTE_HIDDEN
34 #endif
35 
36 /* Work out the largest "word" size that we can deal with on this target.  */
37 #if MIN_UNITS_PER_WORD > 4
38 # define LIBGCC2_MAX_UNITS_PER_WORD 8
39 #elif (MIN_UNITS_PER_WORD > 2 \
40        || (MIN_UNITS_PER_WORD > 1 && __SIZEOF_LONG_LONG__ > 4))
41 # define LIBGCC2_MAX_UNITS_PER_WORD 4
42 #else
43 # define LIBGCC2_MAX_UNITS_PER_WORD MIN_UNITS_PER_WORD
44 #endif
45 
46 /* Work out what word size we are using for this compilation.
47    The value can be set on the command line.  */
48 #ifndef LIBGCC2_UNITS_PER_WORD
49 #define LIBGCC2_UNITS_PER_WORD LIBGCC2_MAX_UNITS_PER_WORD
50 #endif
51 
52 #if LIBGCC2_UNITS_PER_WORD <= LIBGCC2_MAX_UNITS_PER_WORD
53 
54 #include "libgcc2.h"
55 
56 /* umul_ppmm(high_prod, low_prod, multiplier, multiplicand) multiplies two
57    UWtype integers MULTIPLIER and MULTIPLICAND, and generates a two UWtype
58    word product in HIGH_PROD and LOW_PROD.  */
59 
60 #undef umul_ppmm
61 #define umul_ppmm(wh, wl, u, v)			\
62   do {						\
63     /* Generate multu instruction.  */		\
64     UDWtype __t = (UDWtype)(u) * (UDWtype)(v);	\
65     (wl) = (UWtype)__t;				\
66     (wh) = (UWtype)(__t >> W_TYPE_SIZE);	\
67   } while (0)
68 
69 /* sub_ddmmss(high_difference, low_difference, high_minuend, low_minuend,
70    high_subtrahend, low_subtrahend) subtracts two two-word UWtype integers,
71    composed by HIGH_MINUEND_1 and LOW_MINUEND_1, and HIGH_SUBTRAHEND_2 and
72    LOW_SUBTRAHEND_2 respectively.  The result is placed in HIGH_DIFFERENCE
73    and LOW_DIFFERENCE.  Overflow (i.e. carry out) is not stored anywhere,
74    and is lost.  */
75 
76 #undef sub_ddmmss
77 #define sub_ddmmss(sh, sl, ah, al, bh, bl)		\
78   __asm__ ("sub.l   %0,%2,%4\n\t"			\
79 	   "subc.l  %1,%3,%5"				\
80 	   : "=&r" (sl), "=r" (sh)			\
81 	   : "r" (al), "r" (ah), "r" (bl), "r" (bh))
82 
83 /* udiv_qqrnnd(high_quotient, low_quotient, remainder, high_numerator,
84    low_numerator, denominator) divides a UDWtype, composed by the UWtype
85    HIGH_NUMERATOR and LOW_NUMERATOR, by DENOMINATOR and places the quotient
86    in QUOTIENT and the remainder in REMAINDER.  */
87 
88 #define udiv_qqrnnd(qh, ql, r, nh, nl, d)	\
89   __asm__ ("writemd %3,%4\n\t"			\
90 	   "divdu   %5\n\t"			\
91 	   "readmda %0\n\t"			\
92 	   "readmdb %1\n\t"			\
93 	   "readmdc %2"				\
94 	   : "=r" (ql), "=r" (qh), "=r" (r)	\
95 	   : "r" (nl), "r" (nh), "r" (d)	\
96 	   : "mdb", "mdc")
97 
98 #if (defined (L_udivdi3) || defined (L_divdi3) || \
99      defined (L_umoddi3) || defined (L_moddi3))
100 #define L_udivmoddi4
101 #endif
102 
103 #ifdef L_udivmoddi4
104 
105 #if (defined (L_udivdi3) || defined (L_divdi3) || \
106      defined (L_umoddi3) || defined (L_moddi3))
107 static inline __attribute__ ((__always_inline__))
108 #endif
109 UDWtype
__udivmoddi4(UDWtype n,UDWtype d,UDWtype * rp)110 __udivmoddi4 (UDWtype n, UDWtype d, UDWtype *rp)
111 {
112   const DWunion nn = {.ll = n};
113   const DWunion dd = {.ll = d};
114   DWunion rr;
115   UWtype d0, d1, n0, n1, n2;
116   UWtype q0, q1;
117   UWtype b, bm;
118 
119   d0 = dd.s.low;
120   d1 = dd.s.high;
121   n0 = nn.s.low;
122   n1 = nn.s.high;
123 
124   if (d1 == 0)
125     {
126       /* qq = NN / 0d */
127 
128       if (d0 == 0)
129 	d0 = 1 / d0;	/* Divide intentionally by zero.  */
130 
131       udiv_qqrnnd (q1, q0, n0, n1, n0, d0);
132 
133       /* Remainder in n0.  */
134 
135       if (rp != 0)
136 	{
137 	  rr.s.low = n0;
138 	  rr.s.high = 0;
139 	  *rp = rr.ll;
140 	}
141     }
142 
143   else
144     {
145       if (d1 > n1)
146 	{
147 	  /* 00 = nn / DD */
148 
149 	  q0 = 0;
150 	  q1 = 0;
151 
152 	  /* Remainder in n1n0.  */
153 	  if (rp != 0)
154 	    {
155 	      rr.s.low = n0;
156 	      rr.s.high = n1;
157 	      *rp = rr.ll;
158 	    }
159 	}
160       else
161 	{
162 	  /* 0q = NN / dd */
163 
164 	  count_leading_zeros (bm, d1);
165 	  if (bm == 0)
166 	    {
167 	      /* From (n1 >= d1) /\ (the most significant bit of d1 is set),
168 		 conclude (the most significant bit of n1 is set) /\ (the
169 		 quotient digit q0 = 0 or 1).
170 
171 		 This special case is necessary, not an optimization.  */
172 
173 	      /* The condition on the next line takes advantage of that
174 		 n1 >= d1 (true due to program flow).  */
175 	      if (n1 > d1 || n0 >= d0)
176 		{
177 		  q0 = 1;
178 		  sub_ddmmss (n1, n0, n1, n0, d1, d0);
179 		}
180 	      else
181 		q0 = 0;
182 
183 	      q1 = 0;
184 
185 	      if (rp != 0)
186 		{
187 		  rr.s.low = n0;
188 		  rr.s.high = n1;
189 		  *rp = rr.ll;
190 		}
191 	    }
192 	  else
193 	    {
194 	      UWtype m1, m0;
195 	      /* Normalize.  */
196 
197 	      b = W_TYPE_SIZE - bm;
198 
199 	      d1 = (d1 << bm) | (d0 >> b);
200 	      d0 = d0 << bm;
201 	      n2 = n1 >> b;
202 	      n1 = (n1 << bm) | (n0 >> b);
203 	      n0 = n0 << bm;
204 
205 	      udiv_qqrnnd (q1, q0, n1, n2, n1, d1);
206 	      umul_ppmm (m1, m0, q0, d0);
207 
208 	      if (m1 > n1 || (m1 == n1 && m0 > n0))
209 		{
210 		  q0--;
211 		  sub_ddmmss (m1, m0, m1, m0, d1, d0);
212 		}
213 
214 	      /* Remainder in (n1n0 - m1m0) >> bm.  */
215 	      if (rp != 0)
216 		{
217 		  sub_ddmmss (n1, n0, n1, n0, m1, m0);
218 		  rr.s.low = (n1 << b) | (n0 >> bm);
219 		  rr.s.high = n1 >> bm;
220 		  *rp = rr.ll;
221 		}
222 	    }
223 	}
224     }
225 
226   const DWunion ww = {{.low = q0, .high = q1}};
227   return ww.ll;
228 }
229 #endif
230 
231 #ifdef L_divdi3
232 DWtype
__divdi3(DWtype u,DWtype v)233 __divdi3 (DWtype u, DWtype v)
234 {
235   Wtype c = 0;
236   DWunion uu = {.ll = u};
237   DWunion vv = {.ll = v};
238   DWtype w;
239 
240   if (uu.s.high < 0)
241     c = ~c,
242     uu.ll = -uu.ll;
243   if (vv.s.high < 0)
244     c = ~c,
245     vv.ll = -vv.ll;
246 
247   w = __udivmoddi4 (uu.ll, vv.ll, (UDWtype *) 0);
248   if (c)
249     w = -w;
250 
251   return w;
252 }
253 #endif
254 
255 #ifdef L_moddi3
256 DWtype
__moddi3(DWtype u,DWtype v)257 __moddi3 (DWtype u, DWtype v)
258 {
259   Wtype c = 0;
260   DWunion uu = {.ll = u};
261   DWunion vv = {.ll = v};
262   DWtype w;
263 
264   if (uu.s.high < 0)
265     c = ~c,
266     uu.ll = -uu.ll;
267   if (vv.s.high < 0)
268     vv.ll = -vv.ll;
269 
270   (void) __udivmoddi4 (uu.ll, vv.ll, (UDWtype*)&w);
271   if (c)
272     w = -w;
273 
274   return w;
275 }
276 #endif
277 
278 #ifdef L_umoddi3
279 UDWtype
__umoddi3(UDWtype u,UDWtype v)280 __umoddi3 (UDWtype u, UDWtype v)
281 {
282   UDWtype w;
283 
284   (void) __udivmoddi4 (u, v, &w);
285 
286   return w;
287 }
288 #endif
289 
290 #ifdef L_udivdi3
291 UDWtype
__udivdi3(UDWtype n,UDWtype d)292 __udivdi3 (UDWtype n, UDWtype d)
293 {
294   return __udivmoddi4 (n, d, (UDWtype *) 0);
295 }
296 #endif
297 
298 #ifdef L_set_trampoline_parity
299 #undef int
300 extern void __set_trampoline_parity (UWtype *);
301 
302 static inline UWtype
parity_bit(UWtype x)303 parity_bit (UWtype x)
304 {
305   x ^= x << 16;
306   x ^= x << 8;
307   x ^= x << 4;
308   x ^= x << 2;
309   x ^= x << 1;
310   return x & ((UWtype) 1 << (W_TYPE_SIZE - 1));
311 }
312 
313 void
__set_trampoline_parity(UWtype * addr)314 __set_trampoline_parity (UWtype *addr)
315 {
316   int i;
317 
318   for (i = 0;
319        i < (__LIBGCC_TRAMPOLINE_SIZE__ * __CHAR_BIT__) / W_TYPE_SIZE;
320        i++)
321     addr[i] |= parity_bit (addr[i]);
322 }
323 #endif
324 
325 #endif /* LIBGCC2_UNITS_PER_WORD <= MIN_UNITS_PER_WORD */
326