]>
git.proxmox.com Git - qemu.git/blob - target-s390x/fpu_helper.c
2 * S/390 FPU helper routines
4 * Copyright (c) 2009 Ulrich Hecht
5 * Copyright (c) 2009 Alexander Graf
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.
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.
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/>.
24 /* temporarily disabled due to wrapper use */
25 #if 0 && !defined(CONFIG_USER_ONLY)
26 #include "softmmu_exec.h"
29 /* #define DEBUG_HELPER */
31 #define HELPER_LOG(x...) qemu_log(x)
33 #define HELPER_LOG(x...)
36 static inline int float_comp_to_cc(CPUS390XState
*env
, int float_compare
)
38 switch (float_compare
) {
39 case float_relation_equal
:
41 case float_relation_less
:
43 case float_relation_greater
:
45 case float_relation_unordered
:
48 cpu_abort(env
, "unknown return value for float compare\n");
52 /* condition codes for binary FP ops */
53 uint32_t set_cc_f32(CPUS390XState
*env
, float32 v1
, float32 v2
)
55 return float_comp_to_cc(env
, float32_compare_quiet(v1
, v2
,
59 uint32_t set_cc_f64(CPUS390XState
*env
, float64 v1
, float64 v2
)
61 return float_comp_to_cc(env
, float64_compare_quiet(v1
, v2
,
65 /* condition codes for unary FP ops */
66 uint32_t set_cc_nz_f32(float32 v
)
68 if (float32_is_any_nan(v
)) {
70 } else if (float32_is_zero(v
)) {
72 } else if (float32_is_neg(v
)) {
79 uint32_t set_cc_nz_f64(float64 v
)
81 if (float64_is_any_nan(v
)) {
83 } else if (float64_is_zero(v
)) {
85 } else if (float64_is_neg(v
)) {
92 static uint32_t set_cc_nz_f128(float128 v
)
94 if (float128_is_any_nan(v
)) {
96 } else if (float128_is_zero(v
)) {
98 } else if (float128_is_neg(v
)) {
105 /* convert 32-bit int to 64-bit float */
106 void HELPER(cdfbr
)(CPUS390XState
*env
, uint32_t f1
, int32_t v2
)
108 HELPER_LOG("%s: converting %d to f%d\n", __func__
, v2
, f1
);
109 env
->fregs
[f1
].d
= int32_to_float64(v2
, &env
->fpu_status
);
112 /* convert 32-bit int to 128-bit float */
113 void HELPER(cxfbr
)(CPUS390XState
*env
, uint32_t f1
, int32_t v2
)
117 v1
.q
= int32_to_float128(v2
, &env
->fpu_status
);
118 env
->fregs
[f1
].ll
= v1
.ll
.upper
;
119 env
->fregs
[f1
+ 2].ll
= v1
.ll
.lower
;
122 /* convert 64-bit int to 32-bit float */
123 void HELPER(cegbr
)(CPUS390XState
*env
, uint32_t f1
, int64_t v2
)
125 HELPER_LOG("%s: converting %ld to f%d\n", __func__
, v2
, f1
);
126 env
->fregs
[f1
].l
.upper
= int64_to_float32(v2
, &env
->fpu_status
);
129 /* convert 64-bit int to 64-bit float */
130 void HELPER(cdgbr
)(CPUS390XState
*env
, uint32_t f1
, int64_t v2
)
132 HELPER_LOG("%s: converting %ld to f%d\n", __func__
, v2
, f1
);
133 env
->fregs
[f1
].d
= int64_to_float64(v2
, &env
->fpu_status
);
136 /* convert 64-bit int to 128-bit float */
137 void HELPER(cxgbr
)(CPUS390XState
*env
, uint32_t f1
, int64_t v2
)
141 x1
.q
= int64_to_float128(v2
, &env
->fpu_status
);
142 HELPER_LOG("%s: converted %ld to 0x%lx and 0x%lx\n", __func__
, v2
,
143 x1
.ll
.upper
, x1
.ll
.lower
);
144 env
->fregs
[f1
].ll
= x1
.ll
.upper
;
145 env
->fregs
[f1
+ 2].ll
= x1
.ll
.lower
;
148 /* convert 32-bit int to 32-bit float */
149 void HELPER(cefbr
)(CPUS390XState
*env
, uint32_t f1
, int32_t v2
)
151 env
->fregs
[f1
].l
.upper
= int32_to_float32(v2
, &env
->fpu_status
);
152 HELPER_LOG("%s: converting %d to 0x%d in f%d\n", __func__
, v2
,
153 env
->fregs
[f1
].l
.upper
, f1
);
156 /* 32-bit FP addition RR */
157 uint32_t HELPER(aebr
)(CPUS390XState
*env
, uint32_t f1
, uint32_t f2
)
159 env
->fregs
[f1
].l
.upper
= float32_add(env
->fregs
[f1
].l
.upper
,
160 env
->fregs
[f2
].l
.upper
,
162 HELPER_LOG("%s: adding 0x%d resulting in 0x%d in f%d\n", __func__
,
163 env
->fregs
[f2
].l
.upper
, env
->fregs
[f1
].l
.upper
, f1
);
165 return set_cc_nz_f32(env
->fregs
[f1
].l
.upper
);
168 /* 64-bit FP addition RR */
169 uint32_t HELPER(adbr
)(CPUS390XState
*env
, uint32_t f1
, uint32_t f2
)
171 env
->fregs
[f1
].d
= float64_add(env
->fregs
[f1
].d
, env
->fregs
[f2
].d
,
173 HELPER_LOG("%s: adding 0x%ld resulting in 0x%ld in f%d\n", __func__
,
174 env
->fregs
[f2
].d
, env
->fregs
[f1
].d
, f1
);
176 return set_cc_nz_f64(env
->fregs
[f1
].d
);
179 /* 32-bit FP subtraction RR */
180 uint32_t HELPER(sebr
)(CPUS390XState
*env
, uint32_t f1
, uint32_t f2
)
182 env
->fregs
[f1
].l
.upper
= float32_sub(env
->fregs
[f1
].l
.upper
,
183 env
->fregs
[f2
].l
.upper
,
185 HELPER_LOG("%s: adding 0x%d resulting in 0x%d in f%d\n", __func__
,
186 env
->fregs
[f2
].l
.upper
, env
->fregs
[f1
].l
.upper
, f1
);
188 return set_cc_nz_f32(env
->fregs
[f1
].l
.upper
);
191 /* 64-bit FP subtraction RR */
192 uint32_t HELPER(sdbr
)(CPUS390XState
*env
, uint32_t f1
, uint32_t f2
)
194 env
->fregs
[f1
].d
= float64_sub(env
->fregs
[f1
].d
, env
->fregs
[f2
].d
,
196 HELPER_LOG("%s: subtracting 0x%ld resulting in 0x%ld in f%d\n",
197 __func__
, env
->fregs
[f2
].d
, env
->fregs
[f1
].d
, f1
);
199 return set_cc_nz_f64(env
->fregs
[f1
].d
);
202 /* 32-bit FP division RR */
203 void HELPER(debr
)(CPUS390XState
*env
, uint32_t f1
, uint32_t f2
)
205 env
->fregs
[f1
].l
.upper
= float32_div(env
->fregs
[f1
].l
.upper
,
206 env
->fregs
[f2
].l
.upper
,
210 /* 128-bit FP division RR */
211 void HELPER(dxbr
)(CPUS390XState
*env
, uint32_t f1
, uint32_t f2
)
217 v1
.ll
.upper
= env
->fregs
[f1
].ll
;
218 v1
.ll
.lower
= env
->fregs
[f1
+ 2].ll
;
219 v2
.ll
.upper
= env
->fregs
[f2
].ll
;
220 v2
.ll
.lower
= env
->fregs
[f2
+ 2].ll
;
221 res
.q
= float128_div(v1
.q
, v2
.q
, &env
->fpu_status
);
222 env
->fregs
[f1
].ll
= res
.ll
.upper
;
223 env
->fregs
[f1
+ 2].ll
= res
.ll
.lower
;
226 /* 64-bit FP multiplication RR */
227 void HELPER(mdbr
)(CPUS390XState
*env
, uint32_t f1
, uint32_t f2
)
229 env
->fregs
[f1
].d
= float64_mul(env
->fregs
[f1
].d
, env
->fregs
[f2
].d
,
233 /* 128-bit FP multiplication RR */
234 void HELPER(mxbr
)(CPUS390XState
*env
, uint32_t f1
, uint32_t f2
)
240 v1
.ll
.upper
= env
->fregs
[f1
].ll
;
241 v1
.ll
.lower
= env
->fregs
[f1
+ 2].ll
;
242 v2
.ll
.upper
= env
->fregs
[f2
].ll
;
243 v2
.ll
.lower
= env
->fregs
[f2
+ 2].ll
;
244 res
.q
= float128_mul(v1
.q
, v2
.q
, &env
->fpu_status
);
245 env
->fregs
[f1
].ll
= res
.ll
.upper
;
246 env
->fregs
[f1
+ 2].ll
= res
.ll
.lower
;
249 /* convert 32-bit float to 64-bit float */
250 void HELPER(ldebr
)(CPUS390XState
*env
, uint32_t r1
, uint32_t r2
)
252 env
->fregs
[r1
].d
= float32_to_float64(env
->fregs
[r2
].l
.upper
,
256 /* convert 128-bit float to 64-bit float */
257 void HELPER(ldxbr
)(CPUS390XState
*env
, uint32_t f1
, uint32_t f2
)
261 x2
.ll
.upper
= env
->fregs
[f2
].ll
;
262 x2
.ll
.lower
= env
->fregs
[f2
+ 2].ll
;
263 env
->fregs
[f1
].d
= float128_to_float64(x2
.q
, &env
->fpu_status
);
264 HELPER_LOG("%s: to 0x%ld\n", __func__
, env
->fregs
[f1
].d
);
267 /* convert 64-bit float to 128-bit float */
268 void HELPER(lxdbr
)(CPUS390XState
*env
, uint32_t f1
, uint32_t f2
)
272 res
.q
= float64_to_float128(env
->fregs
[f2
].d
, &env
->fpu_status
);
273 env
->fregs
[f1
].ll
= res
.ll
.upper
;
274 env
->fregs
[f1
+ 2].ll
= res
.ll
.lower
;
277 /* convert 64-bit float to 32-bit float */
278 void HELPER(ledbr
)(CPUS390XState
*env
, uint32_t f1
, uint32_t f2
)
280 float64 d2
= env
->fregs
[f2
].d
;
282 env
->fregs
[f1
].l
.upper
= float64_to_float32(d2
, &env
->fpu_status
);
285 /* convert 128-bit float to 32-bit float */
286 void HELPER(lexbr
)(CPUS390XState
*env
, uint32_t f1
, uint32_t f2
)
290 x2
.ll
.upper
= env
->fregs
[f2
].ll
;
291 x2
.ll
.lower
= env
->fregs
[f2
+ 2].ll
;
292 env
->fregs
[f1
].l
.upper
= float128_to_float32(x2
.q
, &env
->fpu_status
);
293 HELPER_LOG("%s: to 0x%d\n", __func__
, env
->fregs
[f1
].l
.upper
);
296 /* absolute value of 32-bit float */
297 uint32_t HELPER(lpebr
)(CPUS390XState
*env
, uint32_t f1
, uint32_t f2
)
300 float32 v2
= env
->fregs
[f2
].d
;
302 v1
= float32_abs(v2
);
303 env
->fregs
[f1
].d
= v1
;
304 return set_cc_nz_f32(v1
);
307 /* absolute value of 64-bit float */
308 uint32_t HELPER(lpdbr
)(CPUS390XState
*env
, uint32_t f1
, uint32_t f2
)
311 float64 v2
= env
->fregs
[f2
].d
;
313 v1
= float64_abs(v2
);
314 env
->fregs
[f1
].d
= v1
;
315 return set_cc_nz_f64(v1
);
318 /* absolute value of 128-bit float */
319 uint32_t HELPER(lpxbr
)(CPUS390XState
*env
, uint32_t f1
, uint32_t f2
)
324 v2
.ll
.upper
= env
->fregs
[f2
].ll
;
325 v2
.ll
.lower
= env
->fregs
[f2
+ 2].ll
;
326 v1
.q
= float128_abs(v2
.q
);
327 env
->fregs
[f1
].ll
= v1
.ll
.upper
;
328 env
->fregs
[f1
+ 2].ll
= v1
.ll
.lower
;
329 return set_cc_nz_f128(v1
.q
);
332 /* load and test 64-bit float */
333 uint32_t HELPER(ltdbr
)(CPUS390XState
*env
, uint32_t f1
, uint32_t f2
)
335 env
->fregs
[f1
].d
= env
->fregs
[f2
].d
;
336 return set_cc_nz_f64(env
->fregs
[f1
].d
);
339 /* load and test 32-bit float */
340 uint32_t HELPER(ltebr
)(CPUS390XState
*env
, uint32_t f1
, uint32_t f2
)
342 env
->fregs
[f1
].l
.upper
= env
->fregs
[f2
].l
.upper
;
343 return set_cc_nz_f32(env
->fregs
[f1
].l
.upper
);
346 /* load and test 128-bit float */
347 uint32_t HELPER(ltxbr
)(CPUS390XState
*env
, uint32_t f1
, uint32_t f2
)
351 x
.ll
.upper
= env
->fregs
[f2
].ll
;
352 x
.ll
.lower
= env
->fregs
[f2
+ 2].ll
;
353 env
->fregs
[f1
].ll
= x
.ll
.upper
;
354 env
->fregs
[f1
+ 2].ll
= x
.ll
.lower
;
355 return set_cc_nz_f128(x
.q
);
358 /* load complement of 32-bit float */
359 uint32_t HELPER(lcebr
)(CPUS390XState
*env
, uint32_t f1
, uint32_t f2
)
361 env
->fregs
[f1
].l
.upper
= float32_chs(env
->fregs
[f2
].l
.upper
);
363 return set_cc_nz_f32(env
->fregs
[f1
].l
.upper
);
366 /* load complement of 64-bit float */
367 uint32_t HELPER(lcdbr
)(CPUS390XState
*env
, uint32_t f1
, uint32_t f2
)
369 env
->fregs
[f1
].d
= float64_chs(env
->fregs
[f2
].d
);
371 return set_cc_nz_f64(env
->fregs
[f1
].d
);
374 /* load complement of 128-bit float */
375 uint32_t HELPER(lcxbr
)(CPUS390XState
*env
, uint32_t f1
, uint32_t f2
)
379 x2
.ll
.upper
= env
->fregs
[f2
].ll
;
380 x2
.ll
.lower
= env
->fregs
[f2
+ 2].ll
;
381 x1
.q
= float128_chs(x2
.q
);
382 env
->fregs
[f1
].ll
= x1
.ll
.upper
;
383 env
->fregs
[f1
+ 2].ll
= x1
.ll
.lower
;
384 return set_cc_nz_f128(x1
.q
);
387 /* 32-bit FP addition RM */
388 void HELPER(aeb
)(CPUS390XState
*env
, uint32_t f1
, uint32_t val
)
390 float32 v1
= env
->fregs
[f1
].l
.upper
;
394 HELPER_LOG("%s: adding 0x%d from f%d and 0x%d\n", __func__
,
396 env
->fregs
[f1
].l
.upper
= float32_add(v1
, v2
.f
, &env
->fpu_status
);
399 /* 32-bit FP division RM */
400 void HELPER(deb
)(CPUS390XState
*env
, uint32_t f1
, uint32_t val
)
402 float32 v1
= env
->fregs
[f1
].l
.upper
;
406 HELPER_LOG("%s: dividing 0x%d from f%d by 0x%d\n", __func__
,
408 env
->fregs
[f1
].l
.upper
= float32_div(v1
, v2
.f
, &env
->fpu_status
);
411 /* 32-bit FP multiplication RM */
412 void HELPER(meeb
)(CPUS390XState
*env
, uint32_t f1
, uint32_t val
)
414 float32 v1
= env
->fregs
[f1
].l
.upper
;
418 HELPER_LOG("%s: multiplying 0x%d from f%d and 0x%d\n", __func__
,
420 env
->fregs
[f1
].l
.upper
= float32_mul(v1
, v2
.f
, &env
->fpu_status
);
423 /* 32-bit FP compare RR */
424 uint32_t HELPER(cebr
)(CPUS390XState
*env
, uint32_t f1
, uint32_t f2
)
426 float32 v1
= env
->fregs
[f1
].l
.upper
;
427 float32 v2
= env
->fregs
[f2
].l
.upper
;
429 HELPER_LOG("%s: comparing 0x%d from f%d and 0x%d\n", __func__
,
431 return set_cc_f32(env
, v1
, v2
);
434 /* 64-bit FP compare RR */
435 uint32_t HELPER(cdbr
)(CPUS390XState
*env
, uint32_t f1
, uint32_t f2
)
437 float64 v1
= env
->fregs
[f1
].d
;
438 float64 v2
= env
->fregs
[f2
].d
;
440 HELPER_LOG("%s: comparing 0x%ld from f%d and 0x%ld\n", __func__
,
442 return set_cc_f64(env
, v1
, v2
);
445 /* 128-bit FP compare RR */
446 uint32_t HELPER(cxbr
)(CPUS390XState
*env
, uint32_t f1
, uint32_t f2
)
451 v1
.ll
.upper
= env
->fregs
[f1
].ll
;
452 v1
.ll
.lower
= env
->fregs
[f1
+ 2].ll
;
453 v2
.ll
.upper
= env
->fregs
[f2
].ll
;
454 v2
.ll
.lower
= env
->fregs
[f2
+ 2].ll
;
456 return float_comp_to_cc(env
, float128_compare_quiet(v1
.q
, v2
.q
,
460 /* 64-bit FP compare RM */
461 uint32_t HELPER(cdb
)(CPUS390XState
*env
, uint32_t f1
, uint64_t a2
)
463 float64 v1
= env
->fregs
[f1
].d
;
466 v2
.ll
= cpu_ldq_data(env
, a2
);
467 HELPER_LOG("%s: comparing 0x%ld from f%d and 0x%lx\n", __func__
, v1
,
469 return set_cc_f64(env
, v1
, v2
.d
);
472 /* 64-bit FP addition RM */
473 uint32_t HELPER(adb
)(CPUS390XState
*env
, uint32_t f1
, uint64_t a2
)
475 float64 v1
= env
->fregs
[f1
].d
;
478 v2
.ll
= cpu_ldq_data(env
, a2
);
479 HELPER_LOG("%s: adding 0x%lx from f%d and 0x%lx\n", __func__
,
481 env
->fregs
[f1
].d
= v1
= float64_add(v1
, v2
.d
, &env
->fpu_status
);
482 return set_cc_nz_f64(v1
);
485 /* 32-bit FP subtraction RM */
486 void HELPER(seb
)(CPUS390XState
*env
, uint32_t f1
, uint32_t val
)
488 float32 v1
= env
->fregs
[f1
].l
.upper
;
492 env
->fregs
[f1
].l
.upper
= float32_sub(v1
, v2
.f
, &env
->fpu_status
);
495 /* 64-bit FP subtraction RM */
496 uint32_t HELPER(sdb
)(CPUS390XState
*env
, uint32_t f1
, uint64_t a2
)
498 float64 v1
= env
->fregs
[f1
].d
;
501 v2
.ll
= cpu_ldq_data(env
, a2
);
502 env
->fregs
[f1
].d
= v1
= float64_sub(v1
, v2
.d
, &env
->fpu_status
);
503 return set_cc_nz_f64(v1
);
506 /* 64-bit FP multiplication RM */
507 void HELPER(mdb
)(CPUS390XState
*env
, uint32_t f1
, uint64_t a2
)
509 float64 v1
= env
->fregs
[f1
].d
;
512 v2
.ll
= cpu_ldq_data(env
, a2
);
513 HELPER_LOG("%s: multiplying 0x%lx from f%d and 0x%ld\n", __func__
,
515 env
->fregs
[f1
].d
= float64_mul(v1
, v2
.d
, &env
->fpu_status
);
518 /* 64-bit FP division RM */
519 void HELPER(ddb
)(CPUS390XState
*env
, uint32_t f1
, uint64_t a2
)
521 float64 v1
= env
->fregs
[f1
].d
;
524 v2
.ll
= cpu_ldq_data(env
, a2
);
525 HELPER_LOG("%s: dividing 0x%lx from f%d by 0x%ld\n", __func__
,
527 env
->fregs
[f1
].d
= float64_div(v1
, v2
.d
, &env
->fpu_status
);
530 static void set_round_mode(CPUS390XState
*env
, int m3
)
537 /* biased round no nearest */
539 /* round to nearest */
540 set_float_rounding_mode(float_round_nearest_even
, &env
->fpu_status
);
544 set_float_rounding_mode(float_round_to_zero
, &env
->fpu_status
);
548 set_float_rounding_mode(float_round_up
, &env
->fpu_status
);
552 set_float_rounding_mode(float_round_down
, &env
->fpu_status
);
557 /* convert 32-bit float to 64-bit int */
558 uint32_t HELPER(cgebr
)(CPUS390XState
*env
, uint32_t r1
, uint32_t f2
,
561 float32 v2
= env
->fregs
[f2
].l
.upper
;
563 set_round_mode(env
, m3
);
564 env
->regs
[r1
] = float32_to_int64(v2
, &env
->fpu_status
);
565 return set_cc_nz_f32(v2
);
568 /* convert 64-bit float to 64-bit int */
569 uint32_t HELPER(cgdbr
)(CPUS390XState
*env
, uint32_t r1
, uint32_t f2
,
572 float64 v2
= env
->fregs
[f2
].d
;
574 set_round_mode(env
, m3
);
575 env
->regs
[r1
] = float64_to_int64(v2
, &env
->fpu_status
);
576 return set_cc_nz_f64(v2
);
579 /* convert 128-bit float to 64-bit int */
580 uint32_t HELPER(cgxbr
)(CPUS390XState
*env
, uint32_t r1
, uint32_t f2
,
585 v2
.ll
.upper
= env
->fregs
[f2
].ll
;
586 v2
.ll
.lower
= env
->fregs
[f2
+ 2].ll
;
587 set_round_mode(env
, m3
);
588 env
->regs
[r1
] = float128_to_int64(v2
.q
, &env
->fpu_status
);
589 if (float128_is_any_nan(v2
.q
)) {
591 } else if (float128_is_zero(v2
.q
)) {
593 } else if (float128_is_neg(v2
.q
)) {
600 /* convert 32-bit float to 32-bit int */
601 uint32_t HELPER(cfebr
)(CPUS390XState
*env
, uint32_t r1
, uint32_t f2
,
604 float32 v2
= env
->fregs
[f2
].l
.upper
;
606 set_round_mode(env
, m3
);
607 env
->regs
[r1
] = (env
->regs
[r1
] & 0xffffffff00000000ULL
) |
608 float32_to_int32(v2
, &env
->fpu_status
);
609 return set_cc_nz_f32(v2
);
612 /* convert 64-bit float to 32-bit int */
613 uint32_t HELPER(cfdbr
)(CPUS390XState
*env
, uint32_t r1
, uint32_t f2
,
616 float64 v2
= env
->fregs
[f2
].d
;
618 set_round_mode(env
, m3
);
619 env
->regs
[r1
] = (env
->regs
[r1
] & 0xffffffff00000000ULL
) |
620 float64_to_int32(v2
, &env
->fpu_status
);
621 return set_cc_nz_f64(v2
);
624 /* convert 128-bit float to 32-bit int */
625 uint32_t HELPER(cfxbr
)(CPUS390XState
*env
, uint32_t r1
, uint32_t f2
,
630 v2
.ll
.upper
= env
->fregs
[f2
].ll
;
631 v2
.ll
.lower
= env
->fregs
[f2
+ 2].ll
;
632 env
->regs
[r1
] = (env
->regs
[r1
] & 0xffffffff00000000ULL
) |
633 float128_to_int32(v2
.q
, &env
->fpu_status
);
634 return set_cc_nz_f128(v2
.q
);
637 /* load 32-bit FP zero */
638 void HELPER(lzer
)(CPUS390XState
*env
, uint32_t f1
)
640 env
->fregs
[f1
].l
.upper
= float32_zero
;
643 /* load 64-bit FP zero */
644 void HELPER(lzdr
)(CPUS390XState
*env
, uint32_t f1
)
646 env
->fregs
[f1
].d
= float64_zero
;
649 /* load 128-bit FP zero */
650 void HELPER(lzxr
)(CPUS390XState
*env
, uint32_t f1
)
654 x
.q
= float64_to_float128(float64_zero
, &env
->fpu_status
);
655 env
->fregs
[f1
].ll
= x
.ll
.upper
;
656 env
->fregs
[f1
+ 1].ll
= x
.ll
.lower
;
659 /* 128-bit FP subtraction RR */
660 uint32_t HELPER(sxbr
)(CPUS390XState
*env
, uint32_t f1
, uint32_t f2
)
666 v1
.ll
.upper
= env
->fregs
[f1
].ll
;
667 v1
.ll
.lower
= env
->fregs
[f1
+ 2].ll
;
668 v2
.ll
.upper
= env
->fregs
[f2
].ll
;
669 v2
.ll
.lower
= env
->fregs
[f2
+ 2].ll
;
670 res
.q
= float128_sub(v1
.q
, v2
.q
, &env
->fpu_status
);
671 env
->fregs
[f1
].ll
= res
.ll
.upper
;
672 env
->fregs
[f1
+ 2].ll
= res
.ll
.lower
;
673 return set_cc_nz_f128(res
.q
);
676 /* 128-bit FP addition RR */
677 uint32_t HELPER(axbr
)(CPUS390XState
*env
, uint32_t f1
, uint32_t f2
)
683 v1
.ll
.upper
= env
->fregs
[f1
].ll
;
684 v1
.ll
.lower
= env
->fregs
[f1
+ 2].ll
;
685 v2
.ll
.upper
= env
->fregs
[f2
].ll
;
686 v2
.ll
.lower
= env
->fregs
[f2
+ 2].ll
;
687 res
.q
= float128_add(v1
.q
, v2
.q
, &env
->fpu_status
);
688 env
->fregs
[f1
].ll
= res
.ll
.upper
;
689 env
->fregs
[f1
+ 2].ll
= res
.ll
.lower
;
690 return set_cc_nz_f128(res
.q
);
693 /* 32-bit FP multiplication RR */
694 void HELPER(meebr
)(CPUS390XState
*env
, uint32_t f1
, uint32_t f2
)
696 env
->fregs
[f1
].l
.upper
= float32_mul(env
->fregs
[f1
].l
.upper
,
697 env
->fregs
[f2
].l
.upper
,
701 /* 64-bit FP division RR */
702 void HELPER(ddbr
)(CPUS390XState
*env
, uint32_t f1
, uint32_t f2
)
704 env
->fregs
[f1
].d
= float64_div(env
->fregs
[f1
].d
, env
->fregs
[f2
].d
,
708 /* 64-bit FP multiply and add RM */
709 void HELPER(madb
)(CPUS390XState
*env
, uint32_t f1
, uint64_t a2
, uint32_t f3
)
713 HELPER_LOG("%s: f1 %d a2 0x%lx f3 %d\n", __func__
, f1
, a2
, f3
);
714 v2
.ll
= cpu_ldq_data(env
, a2
);
715 env
->fregs
[f1
].d
= float64_add(env
->fregs
[f1
].d
,
716 float64_mul(v2
.d
, env
->fregs
[f3
].d
,
721 /* 64-bit FP multiply and add RR */
722 void HELPER(madbr
)(CPUS390XState
*env
, uint32_t f1
, uint32_t f3
, uint32_t f2
)
724 HELPER_LOG("%s: f1 %d f2 %d f3 %d\n", __func__
, f1
, f2
, f3
);
725 env
->fregs
[f1
].d
= float64_add(float64_mul(env
->fregs
[f2
].d
,
728 env
->fregs
[f1
].d
, &env
->fpu_status
);
731 /* 64-bit FP multiply and subtract RR */
732 void HELPER(msdbr
)(CPUS390XState
*env
, uint32_t f1
, uint32_t f3
, uint32_t f2
)
734 HELPER_LOG("%s: f1 %d f2 %d f3 %d\n", __func__
, f1
, f2
, f3
);
735 env
->fregs
[f1
].d
= float64_sub(float64_mul(env
->fregs
[f2
].d
,
738 env
->fregs
[f1
].d
, &env
->fpu_status
);
741 /* 32-bit FP multiply and add RR */
742 void HELPER(maebr
)(CPUS390XState
*env
, uint32_t f1
, uint32_t f3
, uint32_t f2
)
744 env
->fregs
[f1
].l
.upper
= float32_add(env
->fregs
[f1
].l
.upper
,
745 float32_mul(env
->fregs
[f2
].l
.upper
,
746 env
->fregs
[f3
].l
.upper
,
751 /* convert 32-bit float to 64-bit float */
752 void HELPER(ldeb
)(CPUS390XState
*env
, uint32_t f1
, uint64_t a2
)
756 v2
= cpu_ldl_data(env
, a2
);
757 env
->fregs
[f1
].d
= float32_to_float64(v2
,
761 /* convert 64-bit float to 128-bit float */
762 void HELPER(lxdb
)(CPUS390XState
*env
, uint32_t f1
, uint64_t a2
)
767 v2
.ll
= cpu_ldq_data(env
, a2
);
768 v1
.q
= float64_to_float128(v2
.d
, &env
->fpu_status
);
769 env
->fregs
[f1
].ll
= v1
.ll
.upper
;
770 env
->fregs
[f1
+ 2].ll
= v1
.ll
.lower
;
773 /* test data class 32-bit */
774 uint32_t HELPER(tceb
)(CPUS390XState
*env
, uint32_t f1
, uint64_t m2
)
776 float32 v1
= env
->fregs
[f1
].l
.upper
;
777 int neg
= float32_is_neg(v1
);
780 HELPER_LOG("%s: v1 0x%lx m2 0x%lx neg %d\n", __func__
, (long)v1
, m2
, neg
);
781 if ((float32_is_zero(v1
) && (m2
& (1 << (11-neg
)))) ||
782 (float32_is_infinity(v1
) && (m2
& (1 << (5-neg
)))) ||
783 (float32_is_any_nan(v1
) && (m2
& (1 << (3-neg
)))) ||
784 (float32_is_signaling_nan(v1
) && (m2
& (1 << (1-neg
))))) {
786 } else if (m2
& (1 << (9-neg
))) {
787 /* assume normalized number */
791 /* FIXME: denormalized? */
795 /* test data class 64-bit */
796 uint32_t HELPER(tcdb
)(CPUS390XState
*env
, uint32_t f1
, uint64_t m2
)
798 float64 v1
= env
->fregs
[f1
].d
;
799 int neg
= float64_is_neg(v1
);
802 HELPER_LOG("%s: v1 0x%lx m2 0x%lx neg %d\n", __func__
, v1
, m2
, neg
);
803 if ((float64_is_zero(v1
) && (m2
& (1 << (11-neg
)))) ||
804 (float64_is_infinity(v1
) && (m2
& (1 << (5-neg
)))) ||
805 (float64_is_any_nan(v1
) && (m2
& (1 << (3-neg
)))) ||
806 (float64_is_signaling_nan(v1
) && (m2
& (1 << (1-neg
))))) {
808 } else if (m2
& (1 << (9-neg
))) {
809 /* assume normalized number */
812 /* FIXME: denormalized? */
816 /* test data class 128-bit */
817 uint32_t HELPER(tcxb
)(CPUS390XState
*env
, uint32_t f1
, uint64_t m2
)
823 v1
.ll
.upper
= env
->fregs
[f1
].ll
;
824 v1
.ll
.lower
= env
->fregs
[f1
+ 2].ll
;
826 neg
= float128_is_neg(v1
.q
);
827 if ((float128_is_zero(v1
.q
) && (m2
& (1 << (11-neg
)))) ||
828 (float128_is_infinity(v1
.q
) && (m2
& (1 << (5-neg
)))) ||
829 (float128_is_any_nan(v1
.q
) && (m2
& (1 << (3-neg
)))) ||
830 (float128_is_signaling_nan(v1
.q
) && (m2
& (1 << (1-neg
))))) {
832 } else if (m2
& (1 << (9-neg
))) {
833 /* assume normalized number */
836 /* FIXME: denormalized? */
840 /* square root 64-bit RR */
841 void HELPER(sqdbr
)(CPUS390XState
*env
, uint32_t f1
, uint32_t f2
)
843 env
->fregs
[f1
].d
= float64_sqrt(env
->fregs
[f2
].d
, &env
->fpu_status
);