merge kaps
[libfirm] / ir / tv / IeeeCC754 / BasicOp / fltcalc / fpenv_fltcalc.cc
1 /*
2 ##########################################################################
3 #                                                                        #
4 # Program: IeeeCC754                                                     #
5 #                                                                        #
6 # Description:                                                           #
7 #   IeeeCC754 or IEEE 754 Compliance Checker is a precision and range    #
8 #   independent tool to test whether an implementation of                #
9 #   floating-point arithmetic (in hardware or software) is compliant     #
10 #   with the principles of the IEEE 754-854 floating-point standards.    #
11 #   You can find out more about the testing tool IeeeCC754 at            #
12 #                                                                        #
13 #         http://win-www.uia.ac.be/u/cant/ieeecc754.html                 #
14 #                                                                        #
15 #   This tool is in parts based on and greatly benefited from the        #
16 #   the program FPTEST developed by Jerome Coonen. For a full            #
17 #   description of the extensions to FPTEST and a reference to           #
18 #   the original Coonen program, please refer to the URL given above.    #
19 #   For the options available with the program IeeeCC754 and its         #
20 #   compatibility with David Hough's hexadecimal UCB format, we          #
21 #   also refer to the file readme.usage.                                 #
22 #                                                                        #
23 #  Usage: see readme.usage                                               #
24 #                                                                        #
25 #  Responsible authors:                                                  #
26 #         Brigitte Verdonk                                               #
27 #         Annie Cuyt                                                     #
28 #                                                                        #
29 #  Contributors:                                                         #
30 #         Johan Bogo (1998-1999)                                         #
31 #         Tim Gevers (10-12/2000)                                        #
32 #         Debby Ooms (1996-1997)                                         #
33 #         Geert Vermuyten (1996-1997)                                    #
34 #         Dennis Verschaeren (09/1996-06/2000)                           #
35 #                                                                        #
36 #  Copyright (C) 2000  University of Antwerp                             #
37 #                                                                        #
38 #  This program can be obtained from the authors, free, but WITHOUT ANY  #
39 #  WARRANTY; without even the implied warranty of MERCHANTABILITY or     #
40 #  FITNESS FOR A PARTICULAR PURPOSE.                                     #
41 #                                                                        #
42 #  Contact:                                                              #
43 #       Brigitte.Verdonk@uia.ua.ac.be                                    #
44 #       Department of Mathematics and Computer Science                   #
45 #       University of Antwerp (UIA)                                      #
46 #       Universiteitsplein 1                                             #
47 #       B2610 Antwerp, BELGIUM                                           #
48 #                                                                        #
49 ##########################################################################
50
51 Filename:
52        $RCSfile$
53
54 Last updated:
55        $Date$
56
57 */
58
59 #include <math.h>
60 #include <DriverFloatRepr.h>
61 extern "C" {
62 #include <fltcalc.h>
63 }
64
65 #ifndef DOUBLE
66 #define DOUBLE
67 #endif
68 /*
69 By default, all functions in this file are declared in the header file
70
71   DriverFloatRepr.h
72
73 except for two functions
74
75 DriverFloatRepr::DriverFloatRepr(<MyDatatype &D>)
76 <MyDatatype> DriverFloatRepr::to()
77
78 These two functions, for conversion between the floating-point
79 data type of your target implementation and DriverFloatRepr, the
80 floating-point data type of the driver program, should be declared
81 explicitly in the header file DriverFloatRepr.h, with MyDatatype
82 replaced by the appropriate identifier.  */
83
84 void DriverFloatRepr::SetLibRound()
85 {
86   /* Make your library calls for changing the rounding mode */
87
88   switch (GetFPRound())
89     {
90       case RM_NEAR:
91       // change rounding mode to round to nearest break;
92         fc_set_rounding_mode(FC_TONEAREST);
93         break;
94       case RM_ZERO:
95       // change rounding mode to round to zero break;
96         fc_set_rounding_mode(FC_TOZERO);
97         break;
98       case RM_UP:
99       // change rounding mode to round up break;
100         fc_set_rounding_mode(FC_TOPOSITIVE);
101         break;
102       case RM_DOWN:
103       // change rounding mode to round down break;
104         fc_set_rounding_mode(FC_TONEGATIVE);
105         break;
106     }
107 }
108
109 void DriverFloatRepr::SetLibEnvironment()
110 {
111   // clear all floating-point exceptions
112 }
113
114 void DriverFloatRepr::GetLibExceptions()
115 {
116   // do nothing, exceptions are unsupported
117 }
118
119 DriverFloatRepr::DriverFloatRepr(void* val) {
120   // convert your floating-point data type to the floating-point
121   // representation of the driver program
122   // replace MyDatatype by the appropriate identifier
123   int exponent;
124   unsigned int mantissa0;
125   unsigned int mantissa1;
126
127 #ifdef DOUBLE
128   sizeExp = 11;
129   sizeMant = 52;
130 #else
131   sizeExp = 8;
132   sizeMant = 23;
133 #endif
134   mant = Bitstring(sizeMant);
135   exp = Bitstring(sizeExp);
136
137   if (fc_is_negative(val))
138     sign = 1;
139   else
140     sign = 0;
141
142 #ifdef DOUBLE
143   // convert exponent
144   exponent = ((int)(fc_sub_bits(val, 64, 7) & 0x7F)) << 4;
145   exponent |= ((fc_sub_bits(NULL, 64, 6) & 0xF0) >> 4);
146   for (int i = sizeExp - 1;i >= 0; i--) {
147     exp.PutBit(i,exponent%2);
148     exponent /= 2;
149   }
150   // convert mantissa
151   mantissa0 = ((int)(fc_sub_bits(NULL, 64, 6) & 0x0F)) << 16;
152   mantissa0 |= ((int)fc_sub_bits(NULL, 64, 5)) << 8;
153   mantissa0 |= (int)fc_sub_bits(NULL, 64, 4);
154
155   mantissa1 = ((int)fc_sub_bits(NULL, 64, 3)) << 24;
156   mantissa1 |= ((int)fc_sub_bits(NULL, 64, 2)) << 16;
157   mantissa1 |= ((int)fc_sub_bits(NULL, 64, 1)) << 8;
158   mantissa1 |= ((int)fc_sub_bits(NULL, 64, 0));
159
160   for (int i = 19;i >= 0; i--) {
161     mant.PutBit(i,mantissa0%2);
162     mantissa0 /= 2;
163   }
164   for (int i = 31;i >= 0; i--) {
165     mant.PutBit(20+i,mantissa1%2);
166     mantissa1 /= 2;
167   }
168 #else
169   // convert exponent
170   exponent = ((int)(fc_sub_bits(val, 32, 3) & 0x7F)) << 1;
171   exponent |= ((fc_sub_bits(NULL, 32, 2) & 0x80) >> 7);
172   for (int i = sizeExp - 1;i >= 0; i--) {
173     exp.PutBit(i,exponent%2);
174     exponent /= 2;
175   }
176   // convert mantissa
177   mantissa0 = ((int)(fc_sub_bits(NULL, 32, 2) & 0x7F)) << 16;
178   mantissa0 |= ((int)fc_sub_bits(NULL, 32, 1)) << 8;
179   mantissa0 |= (int)fc_sub_bits(NULL, 32, 0);
180
181   for (int i = 22;i >= 0; i--) {
182     mant.PutBit(i,mantissa0%2);
183     mantissa0 /= 2;
184   }
185 #endif
186 }
187
188 void *DriverFloatRepr::to(void *buf)
189   // convert the the floating-point representation of the driver program
190   // to the floating-point data type of your implementation
191 {
192   unsigned int upper = 0;
193   unsigned int lower = 0;
194 #ifdef DOUBLE
195   double im_val;
196 #else
197   float im_val;
198 #endif
199
200   if (sign != 0) {
201     upper |= 0x80000000;
202   }
203   for (int i = 0;i < sizeExp; i++) {
204     if (exp.GetBit(i) == 1)
205       upper |= 1<<(30-i);
206   }
207 #ifdef DOUBLE
208   for (int i = 0;i < 20; i++) {
209     if (mant.GetBit(i) == 1)
210       upper |= 1<<(19-i);
211   }
212   for (int i = 20;i < sizeMant; i++) {
213     if (mant.GetBit(i) == 1)
214       lower |= 1<<(51-i);
215   }
216
217   if (Endian == MYLITTLE_ENDIAN)
218   {
219     ((unsigned int*)&im_val)[0] = lower;
220     ((unsigned int*)&im_val)[1] = upper;
221   }
222   else
223   {
224     ((unsigned int*)&im_val)[1] = lower;
225     ((unsigned int*)&im_val)[0] = upper;
226   }
227   fc_val_from_float(im_val, 11, 52, (char*)buf);
228 #else
229   for (int i = 0;i < sizeMant; i++) {
230     if (mant.GetBit(i) == 1)
231       upper |= 1<<(22-i);
232   }
233
234   *((unsigned int*)&im_val) = upper;
235   fc_val_from_float(im_val, 8, 23, (char*)buf);
236 #endif
237   return buf;
238 }
239
240 // conversions between DriverFloatRepr and hardware integer
241 // data types; implementation should not be modified !
242
243 DriverFloatRepr::DriverFloatRepr(long i) {
244   Bitstring temp(32);
245   hidden = 0;
246   sizeMant = 32;
247   sizeExp = 0;
248   temp[0] = (unsigned long) i;
249   temp.SubBitstring(0,mant);
250 }
251
252 DriverFloatRepr::DriverFloatRepr(unsigned long i) {
253   Bitstring temp(32);
254   hidden = 0;
255   sizeMant = 32;
256   sizeExp = 0;
257   temp[0] = (unsigned long) i;
258   temp.SubBitstring(0,mant);
259 }
260
261 DriverFloatRepr::DriverFloatRepr(long long i) {
262   unsigned long *tmparray=new unsigned long[2];
263   tmparray = (unsigned long *)&i;
264   Bitstring temp(64);
265   if (Endian == MYLITTLE_ENDIAN)
266     {
267       temp[0] = tmparray[0];
268       temp[1] = tmparray[1];
269     }
270   else
271     {
272       temp[0] = tmparray[1];
273       temp[1] = tmparray[0];
274     }
275   hidden = 0;
276   sizeMant = 64;
277   sizeExp = 0;
278   temp.SubBitstring(0,mant);
279 }
280
281 DriverFloatRepr::DriverFloatRepr(unsigned long long i) {
282   unsigned long *tmparray=new unsigned long[2];
283   tmparray = (unsigned long *)&i;
284   Bitstring temp(64);
285   if (Endian == MYLITTLE_ENDIAN)
286     {
287       temp[0] = tmparray[0];
288       temp[1] = tmparray[1];
289     }
290   else
291     {
292       temp[0] = tmparray[1];
293       temp[1] = tmparray[0];
294     }
295   hidden = 0;
296   sizeMant = 64;
297   sizeExp = 0;
298   temp.SubBitstring(0,mant);
299 }
300
301 int DriverFloatRepr::toint() {
302   return (int&)mant[0];
303 }
304
305 unsigned int DriverFloatRepr::touint() {
306   return (unsigned int&)mant[0];
307 }
308
309 long long int DriverFloatRepr::tolonglong() {
310   unsigned long tmparray[2];
311
312   if (Endian == MYLITTLE_ENDIAN)
313     {
314       tmparray[0] = mant[0];
315       tmparray[1] = mant[1];
316     }
317   else
318     {
319       tmparray[0] = mant[1];
320       tmparray[1] = mant[0];
321     }
322   return (long long int&)*tmparray;
323 }
324
325 unsigned long long int DriverFloatRepr::toulonglong() {
326   unsigned long tmparray[2];
327   if (Endian == MYLITTLE_ENDIAN)
328     {
329       tmparray[0] = mant[0];
330       tmparray[1] = mant[1];
331     }
332   else
333     {
334       tmparray[0] = mant[1];
335       tmparray[1] = mant[0];
336     }
337   return (unsigned long long int&)*tmparray;
338 }