* add p cc
[mascara-docs.git] / compilers / pcc / pcc-1.0.0 / cc / ccom / softfloat.c
blob12f1758586aecd92815625d2289e0131018e3e55
1 /* $Id: softfloat.c,v 1.4 2009/07/29 12:32:34 ragge Exp $ */
3 /*
4 * Copyright (c) 2008 Anders Magnusson. All rights reserved.
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
8 * are met:
9 * 1. Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 * 2. Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
14 * 3. The name of the author may not be used to endorse or promote products
15 * derived from this software without specific prior written permission
17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
18 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
19 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
20 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
21 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
22 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
26 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29 #ifdef SOFTFLOAT
31 #include "pass1.h"
35 * Floating point emulation to be used when cross-compiling.
36 * Currently only supports F- and D-float, used in DEC machines.
37 * Should be trivial to add other emulations.
39 * XXX - assumes that:
40 * - long long is (at least) 64 bits
41 * - int is at least 32 bits.
42 * - short is 16 bits.
45 #ifdef FDFLOAT
48 * Useful macros to manipulate the float.
50 #define DSIGN(w) (((w).fd1 >> 15) & 1)
51 #define DSIGNSET(w,s) ((w).fd1 = (s << 15) | ((w).fd1 & 077777))
52 #define DEXP(w) (((w).fd1 >> 7) & 0377)
53 #define DEXPSET(w,e) ((w).fd1 = (((e) & 0377) << 7) | ((w).fd1 & 0100177))
54 #define DMANTH(w) ((w).fd1 & 0177)
55 #define DMANTHSET(w,m) ((w).fd1 = ((m) & 0177) | ((w).fd1 & 0177600))
57 typedef unsigned int lword;
58 typedef unsigned long long dword;
60 #define MAXMANT 0x100000000000000LL
63 * Returns a zero dfloat.
65 static SF
66 nulldf(void)
68 SF rv;
70 rv.fd1 = rv.fd2 = rv.fd3 = rv.fd4 = 0;
71 return rv;
75 * Convert a (u)longlong to dfloat.
76 * XXX - fails on too large (> 55 bits) numbers.
79 soft_cast(CONSZ ll, TWORD t)
81 int i;
82 SF rv;
84 rv = nulldf();
85 if (ll == 0)
86 return rv; /* fp is zero */
87 if (ll < 0)
88 DSIGNSET(rv,1), ll = -ll;
89 for (i = 0; ll > 0; i++, ll <<= 1)
91 DEXPSET(rv, 192-i);
92 DMANTHSET(rv, ll >> 56);
93 rv.fd2 = ll >> 40;
94 rv.fd3 = ll >> 24;
95 rv.fd4 = ll >> 8;
96 return rv;
100 * multiply two dfloat. Use chop, not round.
103 soft_mul(SF p1, SF p2)
105 SF rv;
106 lword a1[2], a2[2], res[4];
107 dword sum;
109 res[0] = res[1] = res[2] = res[3] = 0;
111 /* move mantissa into lwords */
112 a1[0] = p1.fd4 | (p1.fd3 << 16);
113 a1[1] = p1.fd2 | DMANTH(p1) << 16 | 0x800000;
115 a2[0] = p2.fd4 | (p2.fd3 << 16);
116 a2[1] = p2.fd2 | DMANTH(p2) << 16 | 0x800000;
118 #define MULONE(x,y,r) sum += (dword)a1[x] * (dword)a2[y]; sum += res[r]; \
119 res[r] = sum; sum >>= 32;
121 sum = 0;
122 MULONE(0, 0, 0);
123 MULONE(1, 0, 1);
124 res[2] = sum;
125 sum = 0;
126 MULONE(0, 1, 1);
127 MULONE(1, 1, 2);
128 res[3] = sum;
130 rv.fd1 = 0;
131 DSIGNSET(rv, DSIGN(p1) ^ DSIGN(p2));
132 DEXPSET(rv, DEXP(p1) + DEXP(p2) - 128);
133 if (res[3] & 0x8000) {
134 res[3] = (res[3] << 8) | (res[2] >> 24);
135 res[2] = (res[2] << 8) | (res[1] >> 24);
136 } else {
137 DEXPSET(rv, DEXP(rv) - 1);
138 res[3] = (res[3] << 9) | (res[2] >> 23);
139 res[2] = (res[2] << 9) | (res[1] >> 23);
141 DMANTHSET(rv, res[3] >> 16);
142 rv.fd2 = res[3];
143 rv.fd3 = res[2] >> 16;
144 rv.fd4 = res[2];
145 return rv;
149 soft_div(SF t, SF n)
151 SF rv;
152 dword T, N, K;
153 int c;
155 #define SHL(x,b) ((dword)(x) << b)
156 T = SHL(1,55) | SHL(DMANTH(t), 48) |
157 SHL(t.fd2, 32) | SHL(t.fd3, 16) | t.fd4;
158 N = SHL(1,55) | SHL(DMANTH(n), 48) |
159 SHL(n.fd2, 32) | SHL(n.fd3, 16) | n.fd4;
161 c = T > N;
162 for (K = 0; (K & 0x80000000000000ULL) == 0; ) {
163 if (T >= N) {
164 T -= N;
165 K |= 1;
167 T <<= 1;
168 K <<= 1;
170 rv.fd1 = 0;
171 DSIGNSET(rv, DSIGN(t) ^ DSIGN(n));
172 DEXPSET(rv, DEXP(t) - DEXP(n) + 128 + c);
173 DMANTHSET(rv, K >> 48);
174 rv.fd2 = K >> 32;
175 rv.fd3 = K >> 16;
176 rv.fd4 = K;
177 return rv;
181 * Negate a float number. Easy.
184 soft_neg(SF sf)
186 int sign = DSIGN(sf) == 0;
187 DSIGNSET(sf, sign);
188 return sf;
192 * Return true if fp number is zero.
195 soft_isz(SF sf)
197 return (DEXP(sf) == 0);
201 soft_cmp_eq(SF x1, SF x2)
203 cerror("soft_cmp_eq");
204 return 0;
208 soft_cmp_ne(SF x1, SF x2)
210 cerror("soft_cmp_ne");
211 return 0;
215 soft_cmp_le(SF x1, SF x2)
217 cerror("soft_cmp_le");
218 return 0;
222 soft_cmp_lt(SF x1, SF x2)
224 cerror("soft_cmp_lt");
225 return 0;
229 soft_cmp_ge(SF x1, SF x2)
231 cerror("soft_cmp_ge");
232 return 0;
236 soft_cmp_gt(SF x1, SF x2)
238 cerror("soft_cmp_gt");
239 return 0;
243 * Convert a fp number to a CONSZ.
245 CONSZ
246 soft_val(SF sf)
248 CONSZ mant;
249 int exp = DEXP(sf) - 128;
251 mant = SHL(1,55) | SHL(DMANTH(sf), 48) |
252 SHL(sf.fd2, 32) | SHL(sf.fd3, 16) | sf.fd4;
254 while (exp < 0)
255 mant >>= 1, exp++;
256 while (exp > 0)
257 mant <<= 1, exp--;
258 return mant;
262 soft_plus(SF x1, SF x2)
264 cerror("soft_plus");
265 return x1;
269 soft_minus(SF x1, SF x2)
271 cerror("soft_minus");
272 return x1;
276 * Convert a hex constant to floating point number.
278 NODE *
279 fhexcon(char *s)
281 cerror("fhexcon");
282 return NULL;
286 * Convert a floating-point constant to D-float and store it in a NODE.
288 NODE *
289 floatcon(char *s)
291 NODE *p;
292 dword mant;
293 SF fl, flexp, exp5;
294 int exp, negexp, bexp;
296 exp = 0;
297 mant = 0;
298 #define ADDTO(sum, val) sum = sum * 10 + val - '0'
299 for (; *s >= '0' && *s <= '9'; s++) {
300 if (mant<MAXMANT)
301 ADDTO(mant, *s);
302 else
303 exp++;
305 if (*s == '.') {
306 for (s++; *s >= '0' && *s <= '9'; s++) {
307 if (mant<MAXMANT) {
308 ADDTO(mant, *s);
309 exp--;
314 if ((*s == 'E') || (*s == 'e')) {
315 int eexp = 0, sign = 0;
316 s++;
317 if (*s == '+')
318 s++;
319 else if (*s=='-')
320 sign = 1, s++;
322 for (; *s >= '0' && *s <= '9'; s++)
323 ADDTO(eexp, *s);
324 if (sign)
325 eexp = -eexp;
326 exp = exp + eexp;
329 negexp = 1;
330 if (exp<0) {
331 negexp = -1;
332 exp = -exp;
336 flexp = soft_cast(1, INT);
337 exp5 = soft_cast(5, INT);
338 bexp = exp;
339 fl = soft_cast(mant, INT);
341 for (; exp; exp >>= 1) {
342 if (exp&01)
343 flexp = soft_mul(flexp, exp5);
344 exp5 = soft_mul(exp5, exp5);
346 if (negexp<0)
347 fl = soft_div(fl, flexp);
348 else
349 fl = soft_mul(fl, flexp);
351 DEXPSET(fl, DEXP(fl) + negexp*bexp);
352 p = block(FCON, NIL, NIL, DOUBLE, 0, MKSUE(DOUBLE)); /* XXX type */
353 p->n_dcon = fl;
354 return p;
356 #else
357 #error missing softfloat definition
358 #endif
359 #endif