root / target-s390x / fpu_helper.c @ 8379bfdb
History | View | Annotate | Download (17 kB)
1 |
/*
|
---|---|
2 |
* S/390 FPU helper routines
|
3 |
*
|
4 |
* Copyright (c) 2009 Ulrich Hecht
|
5 |
* Copyright (c) 2009 Alexander Graf
|
6 |
*
|
7 |
* This library is free software; you can redistribute it and/or
|
8 |
* modify it under the terms of the GNU Lesser General Public
|
9 |
* License as published by the Free Software Foundation; either
|
10 |
* version 2 of the License, or (at your option) any later version.
|
11 |
*
|
12 |
* This library is distributed in the hope that it will be useful,
|
13 |
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
14 |
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
15 |
* Lesser General Public License for more details.
|
16 |
*
|
17 |
* You should have received a copy of the GNU Lesser General Public
|
18 |
* License along with this library; if not, see <http://www.gnu.org/licenses/>.
|
19 |
*/
|
20 |
|
21 |
#include "cpu.h" |
22 |
#include "helper.h" |
23 |
|
24 |
#if !defined(CONFIG_USER_ONLY)
|
25 |
#include "exec/softmmu_exec.h" |
26 |
#endif
|
27 |
|
28 |
/* #define DEBUG_HELPER */
|
29 |
#ifdef DEBUG_HELPER
|
30 |
#define HELPER_LOG(x...) qemu_log(x)
|
31 |
#else
|
32 |
#define HELPER_LOG(x...)
|
33 |
#endif
|
34 |
|
35 |
#define RET128(F) (env->retxl = F.low, F.high)
|
36 |
|
37 |
#define convert_bit(mask, from, to) \
|
38 |
(to < from \ |
39 |
? (mask / (from / to)) & to \ |
40 |
: (mask & from) * (to / from)) |
41 |
|
42 |
static void ieee_exception(CPUS390XState *env, uint32_t dxc, uintptr_t retaddr) |
43 |
{ |
44 |
/* Install the DXC code. */
|
45 |
env->fpc = (env->fpc & ~0xff00) | (dxc << 8); |
46 |
/* Trap. */
|
47 |
runtime_exception(env, PGM_DATA, retaddr); |
48 |
} |
49 |
|
50 |
/* Should be called after any operation that may raise IEEE exceptions. */
|
51 |
static void handle_exceptions(CPUS390XState *env, uintptr_t retaddr) |
52 |
{ |
53 |
unsigned s390_exc, qemu_exc;
|
54 |
|
55 |
/* Get the exceptions raised by the current operation. Reset the
|
56 |
fpu_status contents so that the next operation has a clean slate. */
|
57 |
qemu_exc = env->fpu_status.float_exception_flags; |
58 |
if (qemu_exc == 0) { |
59 |
return;
|
60 |
} |
61 |
env->fpu_status.float_exception_flags = 0;
|
62 |
|
63 |
/* Convert softfloat exception bits to s390 exception bits. */
|
64 |
s390_exc = 0;
|
65 |
s390_exc |= convert_bit(qemu_exc, float_flag_invalid, 0x80);
|
66 |
s390_exc |= convert_bit(qemu_exc, float_flag_divbyzero, 0x40);
|
67 |
s390_exc |= convert_bit(qemu_exc, float_flag_overflow, 0x20);
|
68 |
s390_exc |= convert_bit(qemu_exc, float_flag_underflow, 0x10);
|
69 |
s390_exc |= convert_bit(qemu_exc, float_flag_inexact, 0x08);
|
70 |
|
71 |
/* Install the exceptions that we raised. */
|
72 |
env->fpc |= s390_exc << 16;
|
73 |
|
74 |
/* Send signals for enabled exceptions. */
|
75 |
s390_exc &= env->fpc >> 24;
|
76 |
if (s390_exc) {
|
77 |
ieee_exception(env, s390_exc, retaddr); |
78 |
} |
79 |
} |
80 |
|
81 |
static inline int float_comp_to_cc(CPUS390XState *env, int float_compare) |
82 |
{ |
83 |
switch (float_compare) {
|
84 |
case float_relation_equal:
|
85 |
return 0; |
86 |
case float_relation_less:
|
87 |
return 1; |
88 |
case float_relation_greater:
|
89 |
return 2; |
90 |
case float_relation_unordered:
|
91 |
return 3; |
92 |
default:
|
93 |
cpu_abort(env, "unknown return value for float compare\n");
|
94 |
} |
95 |
} |
96 |
|
97 |
/* condition codes for unary FP ops */
|
98 |
uint32_t set_cc_nz_f32(float32 v) |
99 |
{ |
100 |
if (float32_is_any_nan(v)) {
|
101 |
return 3; |
102 |
} else if (float32_is_zero(v)) { |
103 |
return 0; |
104 |
} else if (float32_is_neg(v)) { |
105 |
return 1; |
106 |
} else {
|
107 |
return 2; |
108 |
} |
109 |
} |
110 |
|
111 |
uint32_t set_cc_nz_f64(float64 v) |
112 |
{ |
113 |
if (float64_is_any_nan(v)) {
|
114 |
return 3; |
115 |
} else if (float64_is_zero(v)) { |
116 |
return 0; |
117 |
} else if (float64_is_neg(v)) { |
118 |
return 1; |
119 |
} else {
|
120 |
return 2; |
121 |
} |
122 |
} |
123 |
|
124 |
uint32_t set_cc_nz_f128(float128 v) |
125 |
{ |
126 |
if (float128_is_any_nan(v)) {
|
127 |
return 3; |
128 |
} else if (float128_is_zero(v)) { |
129 |
return 0; |
130 |
} else if (float128_is_neg(v)) { |
131 |
return 1; |
132 |
} else {
|
133 |
return 2; |
134 |
} |
135 |
} |
136 |
|
137 |
/* 32-bit FP addition */
|
138 |
uint64_t HELPER(aeb)(CPUS390XState *env, uint64_t f1, uint64_t f2) |
139 |
{ |
140 |
float32 ret = float32_add(f1, f2, &env->fpu_status); |
141 |
handle_exceptions(env, GETPC()); |
142 |
return ret;
|
143 |
} |
144 |
|
145 |
/* 64-bit FP addition */
|
146 |
uint64_t HELPER(adb)(CPUS390XState *env, uint64_t f1, uint64_t f2) |
147 |
{ |
148 |
float64 ret = float64_add(f1, f2, &env->fpu_status); |
149 |
handle_exceptions(env, GETPC()); |
150 |
return ret;
|
151 |
} |
152 |
|
153 |
/* 128-bit FP addition */
|
154 |
uint64_t HELPER(axb)(CPUS390XState *env, uint64_t ah, uint64_t al, |
155 |
uint64_t bh, uint64_t bl) |
156 |
{ |
157 |
float128 ret = float128_add(make_float128(ah, al), |
158 |
make_float128(bh, bl), |
159 |
&env->fpu_status); |
160 |
handle_exceptions(env, GETPC()); |
161 |
return RET128(ret);
|
162 |
} |
163 |
|
164 |
/* 32-bit FP subtraction */
|
165 |
uint64_t HELPER(seb)(CPUS390XState *env, uint64_t f1, uint64_t f2) |
166 |
{ |
167 |
float32 ret = float32_sub(f1, f2, &env->fpu_status); |
168 |
handle_exceptions(env, GETPC()); |
169 |
return ret;
|
170 |
} |
171 |
|
172 |
/* 64-bit FP subtraction */
|
173 |
uint64_t HELPER(sdb)(CPUS390XState *env, uint64_t f1, uint64_t f2) |
174 |
{ |
175 |
float64 ret = float64_sub(f1, f2, &env->fpu_status); |
176 |
handle_exceptions(env, GETPC()); |
177 |
return ret;
|
178 |
} |
179 |
|
180 |
/* 128-bit FP subtraction */
|
181 |
uint64_t HELPER(sxb)(CPUS390XState *env, uint64_t ah, uint64_t al, |
182 |
uint64_t bh, uint64_t bl) |
183 |
{ |
184 |
float128 ret = float128_sub(make_float128(ah, al), |
185 |
make_float128(bh, bl), |
186 |
&env->fpu_status); |
187 |
handle_exceptions(env, GETPC()); |
188 |
return RET128(ret);
|
189 |
} |
190 |
|
191 |
/* 32-bit FP division */
|
192 |
uint64_t HELPER(deb)(CPUS390XState *env, uint64_t f1, uint64_t f2) |
193 |
{ |
194 |
float32 ret = float32_div(f1, f2, &env->fpu_status); |
195 |
handle_exceptions(env, GETPC()); |
196 |
return ret;
|
197 |
} |
198 |
|
199 |
/* 64-bit FP division */
|
200 |
uint64_t HELPER(ddb)(CPUS390XState *env, uint64_t f1, uint64_t f2) |
201 |
{ |
202 |
float64 ret = float64_div(f1, f2, &env->fpu_status); |
203 |
handle_exceptions(env, GETPC()); |
204 |
return ret;
|
205 |
} |
206 |
|
207 |
/* 128-bit FP division */
|
208 |
uint64_t HELPER(dxb)(CPUS390XState *env, uint64_t ah, uint64_t al, |
209 |
uint64_t bh, uint64_t bl) |
210 |
{ |
211 |
float128 ret = float128_div(make_float128(ah, al), |
212 |
make_float128(bh, bl), |
213 |
&env->fpu_status); |
214 |
handle_exceptions(env, GETPC()); |
215 |
return RET128(ret);
|
216 |
} |
217 |
|
218 |
/* 32-bit FP multiplication */
|
219 |
uint64_t HELPER(meeb)(CPUS390XState *env, uint64_t f1, uint64_t f2) |
220 |
{ |
221 |
float32 ret = float32_mul(f1, f2, &env->fpu_status); |
222 |
handle_exceptions(env, GETPC()); |
223 |
return ret;
|
224 |
} |
225 |
|
226 |
/* 64-bit FP multiplication */
|
227 |
uint64_t HELPER(mdb)(CPUS390XState *env, uint64_t f1, uint64_t f2) |
228 |
{ |
229 |
float64 ret = float64_mul(f1, f2, &env->fpu_status); |
230 |
handle_exceptions(env, GETPC()); |
231 |
return ret;
|
232 |
} |
233 |
|
234 |
/* 64/32-bit FP multiplication */
|
235 |
uint64_t HELPER(mdeb)(CPUS390XState *env, uint64_t f1, uint64_t f2) |
236 |
{ |
237 |
float64 ret = float32_to_float64(f2, &env->fpu_status); |
238 |
ret = float64_mul(f1, ret, &env->fpu_status); |
239 |
handle_exceptions(env, GETPC()); |
240 |
return ret;
|
241 |
} |
242 |
|
243 |
/* 128-bit FP multiplication */
|
244 |
uint64_t HELPER(mxb)(CPUS390XState *env, uint64_t ah, uint64_t al, |
245 |
uint64_t bh, uint64_t bl) |
246 |
{ |
247 |
float128 ret = float128_mul(make_float128(ah, al), |
248 |
make_float128(bh, bl), |
249 |
&env->fpu_status); |
250 |
handle_exceptions(env, GETPC()); |
251 |
return RET128(ret);
|
252 |
} |
253 |
|
254 |
/* 128/64-bit FP multiplication */
|
255 |
uint64_t HELPER(mxdb)(CPUS390XState *env, uint64_t ah, uint64_t al, |
256 |
uint64_t f2) |
257 |
{ |
258 |
float128 ret = float64_to_float128(f2, &env->fpu_status); |
259 |
ret = float128_mul(make_float128(ah, al), ret, &env->fpu_status); |
260 |
handle_exceptions(env, GETPC()); |
261 |
return RET128(ret);
|
262 |
} |
263 |
|
264 |
/* convert 32-bit float to 64-bit float */
|
265 |
uint64_t HELPER(ldeb)(CPUS390XState *env, uint64_t f2) |
266 |
{ |
267 |
float64 ret = float32_to_float64(f2, &env->fpu_status); |
268 |
handle_exceptions(env, GETPC()); |
269 |
return ret;
|
270 |
} |
271 |
|
272 |
/* convert 128-bit float to 64-bit float */
|
273 |
uint64_t HELPER(ldxb)(CPUS390XState *env, uint64_t ah, uint64_t al) |
274 |
{ |
275 |
float64 ret = float128_to_float64(make_float128(ah, al), &env->fpu_status); |
276 |
handle_exceptions(env, GETPC()); |
277 |
return ret;
|
278 |
} |
279 |
|
280 |
/* convert 64-bit float to 128-bit float */
|
281 |
uint64_t HELPER(lxdb)(CPUS390XState *env, uint64_t f2) |
282 |
{ |
283 |
float128 ret = float64_to_float128(f2, &env->fpu_status); |
284 |
handle_exceptions(env, GETPC()); |
285 |
return RET128(ret);
|
286 |
} |
287 |
|
288 |
/* convert 32-bit float to 128-bit float */
|
289 |
uint64_t HELPER(lxeb)(CPUS390XState *env, uint64_t f2) |
290 |
{ |
291 |
float128 ret = float32_to_float128(f2, &env->fpu_status); |
292 |
handle_exceptions(env, GETPC()); |
293 |
return RET128(ret);
|
294 |
} |
295 |
|
296 |
/* convert 64-bit float to 32-bit float */
|
297 |
uint64_t HELPER(ledb)(CPUS390XState *env, uint64_t f2) |
298 |
{ |
299 |
float32 ret = float64_to_float32(f2, &env->fpu_status); |
300 |
handle_exceptions(env, GETPC()); |
301 |
return ret;
|
302 |
} |
303 |
|
304 |
/* convert 128-bit float to 32-bit float */
|
305 |
uint64_t HELPER(lexb)(CPUS390XState *env, uint64_t ah, uint64_t al) |
306 |
{ |
307 |
float32 ret = float128_to_float32(make_float128(ah, al), &env->fpu_status); |
308 |
handle_exceptions(env, GETPC()); |
309 |
return ret;
|
310 |
} |
311 |
|
312 |
/* 32-bit FP compare */
|
313 |
uint32_t HELPER(ceb)(CPUS390XState *env, uint64_t f1, uint64_t f2) |
314 |
{ |
315 |
int cmp = float32_compare_quiet(f1, f2, &env->fpu_status);
|
316 |
handle_exceptions(env, GETPC()); |
317 |
return float_comp_to_cc(env, cmp);
|
318 |
} |
319 |
|
320 |
/* 64-bit FP compare */
|
321 |
uint32_t HELPER(cdb)(CPUS390XState *env, uint64_t f1, uint64_t f2) |
322 |
{ |
323 |
int cmp = float64_compare_quiet(f1, f2, &env->fpu_status);
|
324 |
handle_exceptions(env, GETPC()); |
325 |
return float_comp_to_cc(env, cmp);
|
326 |
} |
327 |
|
328 |
/* 128-bit FP compare */
|
329 |
uint32_t HELPER(cxb)(CPUS390XState *env, uint64_t ah, uint64_t al, |
330 |
uint64_t bh, uint64_t bl) |
331 |
{ |
332 |
int cmp = float128_compare_quiet(make_float128(ah, al),
|
333 |
make_float128(bh, bl), |
334 |
&env->fpu_status); |
335 |
handle_exceptions(env, GETPC()); |
336 |
return float_comp_to_cc(env, cmp);
|
337 |
} |
338 |
|
339 |
static int swap_round_mode(CPUS390XState *env, int m3) |
340 |
{ |
341 |
int ret = env->fpu_status.float_rounding_mode;
|
342 |
switch (m3) {
|
343 |
case 0: |
344 |
/* current mode */
|
345 |
break;
|
346 |
case 1: |
347 |
/* biased round no nearest */
|
348 |
case 4: |
349 |
/* round to nearest */
|
350 |
set_float_rounding_mode(float_round_nearest_even, &env->fpu_status); |
351 |
break;
|
352 |
case 5: |
353 |
/* round to zero */
|
354 |
set_float_rounding_mode(float_round_to_zero, &env->fpu_status); |
355 |
break;
|
356 |
case 6: |
357 |
/* round to +inf */
|
358 |
set_float_rounding_mode(float_round_up, &env->fpu_status); |
359 |
break;
|
360 |
case 7: |
361 |
/* round to -inf */
|
362 |
set_float_rounding_mode(float_round_down, &env->fpu_status); |
363 |
break;
|
364 |
} |
365 |
return ret;
|
366 |
} |
367 |
|
368 |
/* convert 64-bit int to 32-bit float */
|
369 |
uint64_t HELPER(cegb)(CPUS390XState *env, int64_t v2, uint32_t m3) |
370 |
{ |
371 |
int hold = swap_round_mode(env, m3);
|
372 |
float32 ret = int64_to_float32(v2, &env->fpu_status); |
373 |
set_float_rounding_mode(hold, &env->fpu_status); |
374 |
handle_exceptions(env, GETPC()); |
375 |
return ret;
|
376 |
} |
377 |
|
378 |
/* convert 64-bit int to 64-bit float */
|
379 |
uint64_t HELPER(cdgb)(CPUS390XState *env, int64_t v2, uint32_t m3) |
380 |
{ |
381 |
int hold = swap_round_mode(env, m3);
|
382 |
float64 ret = int64_to_float64(v2, &env->fpu_status); |
383 |
set_float_rounding_mode(hold, &env->fpu_status); |
384 |
handle_exceptions(env, GETPC()); |
385 |
return ret;
|
386 |
} |
387 |
|
388 |
/* convert 64-bit int to 128-bit float */
|
389 |
uint64_t HELPER(cxgb)(CPUS390XState *env, int64_t v2, uint32_t m3) |
390 |
{ |
391 |
int hold = swap_round_mode(env, m3);
|
392 |
float128 ret = int64_to_float128(v2, &env->fpu_status); |
393 |
set_float_rounding_mode(hold, &env->fpu_status); |
394 |
handle_exceptions(env, GETPC()); |
395 |
return RET128(ret);
|
396 |
} |
397 |
|
398 |
/* convert 32-bit float to 64-bit int */
|
399 |
uint64_t HELPER(cgeb)(CPUS390XState *env, uint64_t v2, uint32_t m3) |
400 |
{ |
401 |
int hold = swap_round_mode(env, m3);
|
402 |
int64_t ret = float32_to_int64(v2, &env->fpu_status); |
403 |
set_float_rounding_mode(hold, &env->fpu_status); |
404 |
handle_exceptions(env, GETPC()); |
405 |
return ret;
|
406 |
} |
407 |
|
408 |
/* convert 64-bit float to 64-bit int */
|
409 |
uint64_t HELPER(cgdb)(CPUS390XState *env, uint64_t v2, uint32_t m3) |
410 |
{ |
411 |
int hold = swap_round_mode(env, m3);
|
412 |
int64_t ret = float64_to_int64(v2, &env->fpu_status); |
413 |
set_float_rounding_mode(hold, &env->fpu_status); |
414 |
handle_exceptions(env, GETPC()); |
415 |
return ret;
|
416 |
} |
417 |
|
418 |
/* convert 128-bit float to 64-bit int */
|
419 |
uint64_t HELPER(cgxb)(CPUS390XState *env, uint64_t h, uint64_t l, uint32_t m3) |
420 |
{ |
421 |
int hold = swap_round_mode(env, m3);
|
422 |
float128 v2 = make_float128(h, l); |
423 |
int64_t ret = float128_to_int64(v2, &env->fpu_status); |
424 |
set_float_rounding_mode(hold, &env->fpu_status); |
425 |
handle_exceptions(env, GETPC()); |
426 |
return ret;
|
427 |
} |
428 |
|
429 |
/* convert 32-bit float to 32-bit int */
|
430 |
uint64_t HELPER(cfeb)(CPUS390XState *env, uint64_t v2, uint32_t m3) |
431 |
{ |
432 |
int hold = swap_round_mode(env, m3);
|
433 |
int32_t ret = float32_to_int32(v2, &env->fpu_status); |
434 |
set_float_rounding_mode(hold, &env->fpu_status); |
435 |
handle_exceptions(env, GETPC()); |
436 |
return ret;
|
437 |
} |
438 |
|
439 |
/* convert 64-bit float to 32-bit int */
|
440 |
uint64_t HELPER(cfdb)(CPUS390XState *env, uint64_t v2, uint32_t m3) |
441 |
{ |
442 |
int hold = swap_round_mode(env, m3);
|
443 |
int32_t ret = float64_to_int32(v2, &env->fpu_status); |
444 |
set_float_rounding_mode(hold, &env->fpu_status); |
445 |
handle_exceptions(env, GETPC()); |
446 |
return ret;
|
447 |
} |
448 |
|
449 |
/* convert 128-bit float to 32-bit int */
|
450 |
uint64_t HELPER(cfxb)(CPUS390XState *env, uint64_t h, uint64_t l, uint32_t m3) |
451 |
{ |
452 |
int hold = swap_round_mode(env, m3);
|
453 |
float128 v2 = make_float128(h, l); |
454 |
int32_t ret = float128_to_int32(v2, &env->fpu_status); |
455 |
set_float_rounding_mode(hold, &env->fpu_status); |
456 |
handle_exceptions(env, GETPC()); |
457 |
return ret;
|
458 |
} |
459 |
|
460 |
/* 32-bit FP multiply and add */
|
461 |
uint64_t HELPER(maeb)(CPUS390XState *env, uint64_t f1, |
462 |
uint64_t f2, uint64_t f3) |
463 |
{ |
464 |
float32 ret = float32_muladd(f2, f3, f1, 0, &env->fpu_status);
|
465 |
handle_exceptions(env, GETPC()); |
466 |
return ret;
|
467 |
} |
468 |
|
469 |
/* 64-bit FP multiply and add */
|
470 |
uint64_t HELPER(madb)(CPUS390XState *env, uint64_t f1, |
471 |
uint64_t f2, uint64_t f3) |
472 |
{ |
473 |
float64 ret = float64_muladd(f2, f3, f1, 0, &env->fpu_status);
|
474 |
handle_exceptions(env, GETPC()); |
475 |
return ret;
|
476 |
} |
477 |
|
478 |
/* 32-bit FP multiply and subtract */
|
479 |
uint64_t HELPER(mseb)(CPUS390XState *env, uint64_t f1, |
480 |
uint64_t f2, uint64_t f3) |
481 |
{ |
482 |
float32 ret = float32_muladd(f2, f3, f1, float_muladd_negate_c, |
483 |
&env->fpu_status); |
484 |
handle_exceptions(env, GETPC()); |
485 |
return ret;
|
486 |
} |
487 |
|
488 |
/* 64-bit FP multiply and subtract */
|
489 |
uint64_t HELPER(msdb)(CPUS390XState *env, uint64_t f1, |
490 |
uint64_t f2, uint64_t f3) |
491 |
{ |
492 |
float64 ret = float64_muladd(f2, f3, f1, float_muladd_negate_c, |
493 |
&env->fpu_status); |
494 |
handle_exceptions(env, GETPC()); |
495 |
return ret;
|
496 |
} |
497 |
|
498 |
/* test data class 32-bit */
|
499 |
uint32_t HELPER(tceb)(uint64_t f1, uint64_t m2) |
500 |
{ |
501 |
float32 v1 = f1; |
502 |
int neg = float32_is_neg(v1);
|
503 |
uint32_t cc = 0;
|
504 |
|
505 |
if ((float32_is_zero(v1) && (m2 & (1 << (11-neg)))) || |
506 |
(float32_is_infinity(v1) && (m2 & (1 << (5-neg)))) || |
507 |
(float32_is_any_nan(v1) && (m2 & (1 << (3-neg)))) || |
508 |
(float32_is_signaling_nan(v1) && (m2 & (1 << (1-neg))))) { |
509 |
cc = 1;
|
510 |
} else if (m2 & (1 << (9-neg))) { |
511 |
/* assume normalized number */
|
512 |
cc = 1;
|
513 |
} |
514 |
/* FIXME: denormalized? */
|
515 |
return cc;
|
516 |
} |
517 |
|
518 |
/* test data class 64-bit */
|
519 |
uint32_t HELPER(tcdb)(uint64_t v1, uint64_t m2) |
520 |
{ |
521 |
int neg = float64_is_neg(v1);
|
522 |
uint32_t cc = 0;
|
523 |
|
524 |
if ((float64_is_zero(v1) && (m2 & (1 << (11-neg)))) || |
525 |
(float64_is_infinity(v1) && (m2 & (1 << (5-neg)))) || |
526 |
(float64_is_any_nan(v1) && (m2 & (1 << (3-neg)))) || |
527 |
(float64_is_signaling_nan(v1) && (m2 & (1 << (1-neg))))) { |
528 |
cc = 1;
|
529 |
} else if (m2 & (1 << (9-neg))) { |
530 |
/* assume normalized number */
|
531 |
cc = 1;
|
532 |
} |
533 |
/* FIXME: denormalized? */
|
534 |
return cc;
|
535 |
} |
536 |
|
537 |
/* test data class 128-bit */
|
538 |
uint32_t HELPER(tcxb)(uint64_t ah, uint64_t al, uint64_t m2) |
539 |
{ |
540 |
float128 v1 = make_float128(ah, al); |
541 |
int neg = float128_is_neg(v1);
|
542 |
uint32_t cc = 0;
|
543 |
|
544 |
if ((float128_is_zero(v1) && (m2 & (1 << (11-neg)))) || |
545 |
(float128_is_infinity(v1) && (m2 & (1 << (5-neg)))) || |
546 |
(float128_is_any_nan(v1) && (m2 & (1 << (3-neg)))) || |
547 |
(float128_is_signaling_nan(v1) && (m2 & (1 << (1-neg))))) { |
548 |
cc = 1;
|
549 |
} else if (m2 & (1 << (9-neg))) { |
550 |
/* assume normalized number */
|
551 |
cc = 1;
|
552 |
} |
553 |
/* FIXME: denormalized? */
|
554 |
return cc;
|
555 |
} |
556 |
|
557 |
/* square root 32-bit */
|
558 |
uint64_t HELPER(sqeb)(CPUS390XState *env, uint64_t f2) |
559 |
{ |
560 |
float32 ret = float32_sqrt(f2, &env->fpu_status); |
561 |
handle_exceptions(env, GETPC()); |
562 |
return ret;
|
563 |
} |
564 |
|
565 |
/* square root 64-bit */
|
566 |
uint64_t HELPER(sqdb)(CPUS390XState *env, uint64_t f2) |
567 |
{ |
568 |
float64 ret = float64_sqrt(f2, &env->fpu_status); |
569 |
handle_exceptions(env, GETPC()); |
570 |
return ret;
|
571 |
} |
572 |
|
573 |
/* square root 128-bit */
|
574 |
uint64_t HELPER(sqxb)(CPUS390XState *env, uint64_t ah, uint64_t al) |
575 |
{ |
576 |
float128 ret = float128_sqrt(make_float128(ah, al), &env->fpu_status); |
577 |
handle_exceptions(env, GETPC()); |
578 |
return RET128(ret);
|
579 |
} |
580 |
|
581 |
/* set fpc */
|
582 |
void HELPER(sfpc)(CPUS390XState *env, uint64_t fpc)
|
583 |
{ |
584 |
static const int rnd[4] = { |
585 |
float_round_nearest_even, |
586 |
float_round_to_zero, |
587 |
float_round_up, |
588 |
float_round_down |
589 |
}; |
590 |
|
591 |
/* Install everything in the main FPC. */
|
592 |
env->fpc = fpc; |
593 |
|
594 |
/* Install the rounding mode in the shadow fpu_status. */
|
595 |
set_float_rounding_mode(rnd[fpc & 3], &env->fpu_status);
|
596 |
} |