This source file includes following definitions.
- short_to_temp
- long_to_temp
- temp_to_short
- temp_to_long
- frndint
- real_to_int
- int_to_real
1
2
3
4
5
6
7 #include <linux/math_emu.h>
8
9
10
11
12
13
14
15
16
17
18
19
20
21 void short_to_temp(const short_real * a, temp_real * b)
22 {
23 if (!(*a & 0x7fffffff)) {
24 b->a = b->b = 0;
25 if (*a)
26 b->exponent = 0x8000;
27 else
28 b->exponent = 0;
29 return;
30 }
31 b->exponent = ((*a>>23) & 0xff)-127+16383;
32 if (*a<0)
33 b->exponent |= 0x8000;
34 b->b = (*a<<8) | 0x80000000;
35 b->a = 0;
36 }
37
38 void long_to_temp(const long_real * a, temp_real * b)
39 {
40 if (!a->a && !(a->b & 0x7fffffff)) {
41 b->a = b->b = 0;
42 if (a->b)
43 b->exponent = 0x8000;
44 else
45 b->exponent = 0;
46 return;
47 }
48 b->exponent = ((a->b >> 20) & 0x7ff)-1023+16383;
49 if (a->b<0)
50 b->exponent |= 0x8000;
51 b->b = 0x80000000 | (a->b<<11) | (((unsigned long)a->a)>>21);
52 b->a = a->a<<11;
53 }
54
55 void temp_to_short(const temp_real * a, short_real * b)
56 {
57 if (!(a->exponent & 0x7fff)) {
58 *b = (a->exponent)?0x80000000:0;
59 return;
60 }
61 *b = ((((long) a->exponent)-16383+127) << 23) & 0x7f800000;
62 if (a->exponent < 0)
63 *b |= 0x80000000;
64 *b |= (a->b >> 8) & 0x007fffff;
65 switch (ROUNDING) {
66 case ROUND_NEAREST:
67 if ((a->b & 0xff) > 0x80)
68 ++*b;
69 break;
70 case ROUND_DOWN:
71 if ((a->exponent & 0x8000) && (a->b & 0xff))
72 ++*b;
73 break;
74 case ROUND_UP:
75 if (!(a->exponent & 0x8000) && (a->b & 0xff))
76 ++*b;
77 break;
78 }
79 }
80
81 void temp_to_long(const temp_real * a, long_real * b)
82 {
83 if (!(a->exponent & 0x7fff)) {
84 b->a = 0;
85 b->b = (a->exponent)?0x80000000:0;
86 return;
87 }
88 b->b = (((0x7fff & (long) a->exponent)-16383+1023) << 20) & 0x7ff00000;
89 if (a->exponent < 0)
90 b->b |= 0x80000000;
91 b->b |= (a->b >> 11) & 0x000fffff;
92 b->a = a->b << 21;
93 b->a |= (a->a >> 11) & 0x001fffff;
94 switch (ROUNDING) {
95 case ROUND_NEAREST:
96 if ((a->a & 0x7ff) > 0x400)
97 __asm__("addl $1,%0 ; adcl $0,%1"
98 :"=r" (b->a),"=r" (b->b)
99 :"0" (b->a),"1" (b->b));
100 break;
101 case ROUND_DOWN:
102 if ((a->exponent & 0x8000) && (a->b & 0xff))
103 __asm__("addl $1,%0 ; adcl $0,%1"
104 :"=r" (b->a),"=r" (b->b)
105 :"0" (b->a),"1" (b->b));
106 break;
107 case ROUND_UP:
108 if (!(a->exponent & 0x8000) && (a->b & 0xff))
109 __asm__("addl $1,%0 ; adcl $0,%1"
110 :"=r" (b->a),"=r" (b->b)
111 :"0" (b->a),"1" (b->b));
112 break;
113 }
114 }
115
116 void frndint(const temp_real * a, temp_real * b)
117 {
118 int shift = 16383 + 63 - (a->exponent & 0x7fff);
119 unsigned long underflow;
120
121 if ((shift < 0) || (shift == 16383+63)) {
122 *b = *a;
123 return;
124 }
125 b->a = b->b = underflow = 0;
126 b->exponent = a->exponent;
127 if (shift < 32) {
128 b->b = a->b; b->a = a->a;
129 } else if (shift < 64) {
130 b->a = a->b; underflow = a->a;
131 shift -= 32;
132 b->exponent += 32;
133 } else if (shift < 96) {
134 underflow = a->b;
135 shift -= 64;
136 b->exponent += 64;
137 } else {
138 underflow = 1;
139 shift = 0;
140 }
141 b->exponent += shift;
142 __asm__("shrdl %2,%1,%0"
143 :"=r" (underflow),"=r" (b->a)
144 :"c" ((char) shift),"0" (underflow),"1" (b->a));
145 __asm__("shrdl %2,%1,%0"
146 :"=r" (b->a),"=r" (b->b)
147 :"c" ((char) shift),"0" (b->a),"1" (b->b));
148 __asm__("shrl %1,%0"
149 :"=r" (b->b)
150 :"c" ((char) shift),"0" (b->b));
151 switch (ROUNDING) {
152 case ROUND_NEAREST:
153 __asm__("addl %4,%5 ; adcl $0,%0 ; adcl $0,%1"
154 :"=r" (b->a),"=r" (b->b)
155 :"0" (b->a),"1" (b->b)
156 ,"r" (0x7fffffff + (b->a & 1))
157 ,"m" (*&underflow));
158 break;
159 case ROUND_UP:
160 if ((b->exponent >= 0) && underflow)
161 __asm__("addl $1,%0 ; adcl $0,%1"
162 :"=r" (b->a),"=r" (b->b)
163 :"0" (b->a),"1" (b->b));
164 break;
165 case ROUND_DOWN:
166 if ((b->exponent < 0) && underflow)
167 __asm__("addl $1,%0 ; adcl $0,%1"
168 :"=r" (b->a),"=r" (b->b)
169 :"0" (b->a),"1" (b->b));
170 break;
171 }
172 if (b->a || b->b)
173 while (b->b >= 0) {
174 b->exponent--;
175 __asm__("addl %0,%0 ; adcl %1,%1"
176 :"=r" (b->a),"=r" (b->b)
177 :"0" (b->a),"1" (b->b));
178 }
179 else
180 b->exponent = 0;
181 }
182
183 void real_to_int(const temp_real * a, temp_int * b)
184 {
185 int shift = 16383 + 63 - (a->exponent & 0x7fff);
186 unsigned long underflow;
187
188 b->a = b->b = underflow = 0;
189 b->sign = (a->exponent < 0);
190 if (shift < 0) {
191 set_OE();
192 return;
193 }
194 if (shift < 32) {
195 b->b = a->b; b->a = a->a;
196 } else if (shift < 64) {
197 b->a = a->b; underflow = a->a;
198 shift -= 32;
199 } else if (shift < 96) {
200 underflow = a->b;
201 shift -= 64;
202 } else {
203 underflow = 1;
204 shift = 0;
205 }
206 __asm__("shrdl %2,%1,%0"
207 :"=r" (underflow),"=r" (b->a)
208 :"c" ((char) shift),"0" (underflow),"1" (b->a));
209 __asm__("shrdl %2,%1,%0"
210 :"=r" (b->a),"=r" (b->b)
211 :"c" ((char) shift),"0" (b->a),"1" (b->b));
212 __asm__("shrl %1,%0"
213 :"=r" (b->b)
214 :"c" ((char) shift),"0" (b->b));
215 switch (ROUNDING) {
216 case ROUND_NEAREST:
217 __asm__("addl %4,%5 ; adcl $0,%0 ; adcl $0,%1"
218 :"=r" (b->a),"=r" (b->b)
219 :"0" (b->a),"1" (b->b)
220 ,"r" (0x7fffffff + (b->a & 1))
221 ,"m" (*&underflow));
222 break;
223 case ROUND_UP:
224 if (!b->sign && underflow)
225 __asm__("addl $1,%0 ; adcl $0,%1"
226 :"=r" (b->a),"=r" (b->b)
227 :"0" (b->a),"1" (b->b));
228 break;
229 case ROUND_DOWN:
230 if (b->sign && underflow)
231 __asm__("addl $1,%0 ; adcl $0,%1"
232 :"=r" (b->a),"=r" (b->b)
233 :"0" (b->a),"1" (b->b));
234 break;
235 }
236 }
237
238 void int_to_real(const temp_int * a, temp_real * b)
239 {
240 b->a = a->a;
241 b->b = a->b;
242 if (b->a || b->b)
243 b->exponent = 16383 + 63 + (a->sign? 0x8000:0);
244 else {
245 b->exponent = 0;
246 return;
247 }
248 while (b->b >= 0) {
249 b->exponent--;
250 __asm__("addl %0,%0 ; adcl %1,%1"
251 :"=r" (b->a),"=r" (b->b)
252 :"0" (b->a),"1" (b->b));
253 }
254 }