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 #if !defined(CONFIG_USER_ONLY)
25 #include "exec/softmmu_exec.h"
28 /* #define DEBUG_HELPER */
30 #define HELPER_LOG(x...) qemu_log(x)
32 #define HELPER_LOG(x...)
35 static inline int float_comp_to_cc(CPUS390XState
*env
, int float_compare
)
37 switch (float_compare
) {
38 case float_relation_equal
:
40 case float_relation_less
:
42 case float_relation_greater
:
44 case float_relation_unordered
:
47 cpu_abort(env
, "unknown return value for float compare\n");
51 /* condition codes for binary FP ops */
52 uint32_t set_cc_f32(CPUS390XState
*env
, float32 v1
, float32 v2
)
54 return float_comp_to_cc(env
, float32_compare_quiet(v1
, v2
,
58 uint32_t set_cc_f64(CPUS390XState
*env
, float64 v1
, float64 v2
)
60 return float_comp_to_cc(env
, float64_compare_quiet(v1
, v2
,
64 /* condition codes for unary FP ops */
65 uint32_t set_cc_nz_f32(float32 v
)
67 if (float32_is_any_nan(v
)) {
69 } else if (float32_is_zero(v
)) {
71 } else if (float32_is_neg(v
)) {
78 uint32_t set_cc_nz_f64(float64 v
)
80 if (float64_is_any_nan(v
)) {
82 } else if (float64_is_zero(v
)) {
84 } else if (float64_is_neg(v
)) {
91 static uint32_t set_cc_nz_f128(float128 v
)
93 if (float128_is_any_nan(v
)) {
95 } else if (float128_is_zero(v
)) {
97 } else if (float128_is_neg(v
)) {
104 /* convert 32-bit int to 64-bit float */
105 void HELPER(cdfbr
)(CPUS390XState
*env
, uint32_t f1
, int32_t v2
)
107 HELPER_LOG("%s: converting %d to f%d\n", __func__
, v2
, f1
);
108 env
->fregs
[f1
].d
= int32_to_float64(v2
, &env
->fpu_status
);
111 /* convert 32-bit int to 128-bit float */
112 void HELPER(cxfbr
)(CPUS390XState
*env
, uint32_t f1
, int32_t v2
)
116 v1
.q
= int32_to_float128(v2
, &env
->fpu_status
);
117 env
->fregs
[f1
].ll
= v1
.ll
.upper
;
118 env
->fregs
[f1
+ 2].ll
= v1
.ll
.lower
;
121 /* convert 64-bit int to 32-bit float */
122 void HELPER(cegbr
)(CPUS390XState
*env
, uint32_t f1
, int64_t v2
)
124 HELPER_LOG("%s: converting %ld to f%d\n", __func__
, v2
, f1
);
125 env
->fregs
[f1
].l
.upper
= int64_to_float32(v2
, &env
->fpu_status
);
128 /* convert 64-bit int to 64-bit float */
129 void HELPER(cdgbr
)(CPUS390XState
*env
, uint32_t f1
, int64_t v2
)
131 HELPER_LOG("%s: converting %ld to f%d\n", __func__
, v2
, f1
);
132 env
->fregs
[f1
].d
= int64_to_float64(v2
, &env
->fpu_status
);
135 /* convert 64-bit int to 128-bit float */
136 void HELPER(cxgbr
)(CPUS390XState
*env
, uint32_t f1
, int64_t v2
)
140 x1
.q
= int64_to_float128(v2
, &env
->fpu_status
);
141 HELPER_LOG("%s: converted %ld to 0x%lx and 0x%lx\n", __func__
, v2
,
142 x1
.ll
.upper
, x1
.ll
.lower
);
143 env
->fregs
[f1
].ll
= x1
.ll
.upper
;
144 env
->fregs
[f1
+ 2].ll
= x1
.ll
.lower
;
147 /* convert 32-bit int to 32-bit float */
148 void HELPER(cefbr
)(CPUS390XState
*env
, uint32_t f1
, int32_t v2
)
150 env
->fregs
[f1
].l
.upper
= int32_to_float32(v2
, &env
->fpu_status
);
151 HELPER_LOG("%s: converting %d to 0x%d in f%d\n", __func__
, v2
,
152 env
->fregs
[f1
].l
.upper
, f1
);
155 /* 32-bit FP addition RR */
156 uint32_t HELPER(aebr
)(CPUS390XState
*env
, uint32_t f1
, uint32_t f2
)
158 env
->fregs
[f1
].l
.upper
= float32_add(env
->fregs
[f1
].l
.upper
,
159 env
->fregs
[f2
].l
.upper
,
161 HELPER_LOG("%s: adding 0x%d resulting in 0x%d in f%d\n", __func__
,
162 env
->fregs
[f2
].l
.upper
, env
->fregs
[f1
].l
.upper
, f1
);
164 return set_cc_nz_f32(env
->fregs
[f1
].l
.upper
);
167 /* 64-bit FP addition RR */
168 uint32_t HELPER(adbr
)(CPUS390XState
*env
, uint32_t f1
, uint32_t f2
)
170 env
->fregs
[f1
].d
= float64_add(env
->fregs
[f1
].d
, env
->fregs
[f2
].d
,
172 HELPER_LOG("%s: adding 0x%ld resulting in 0x%ld in f%d\n", __func__
,
173 env
->fregs
[f2
].d
, env
->fregs
[f1
].d
, f1
);
175 return set_cc_nz_f64(env
->fregs
[f1
].d
);
178 /* 32-bit FP subtraction RR */
179 uint32_t HELPER(sebr
)(CPUS390XState
*env
, uint32_t f1
, uint32_t f2
)
181 env
->fregs
[f1
].l
.upper
= float32_sub(env
->fregs
[f1
].l
.upper
,
182 env
->fregs
[f2
].l
.upper
,
184 HELPER_LOG("%s: adding 0x%d resulting in 0x%d in f%d\n", __func__
,
185 env
->fregs
[f2
].l
.upper
, env
->fregs
[f1
].l
.upper
, f1
);
187 return set_cc_nz_f32(env
->fregs
[f1
].l
.upper
);
190 /* 64-bit FP subtraction RR */
191 uint32_t HELPER(sdbr
)(CPUS390XState
*env
, uint32_t f1
, uint32_t f2
)
193 env
->fregs
[f1
].d
= float64_sub(env
->fregs
[f1
].d
, env
->fregs
[f2
].d
,
195 HELPER_LOG("%s: subtracting 0x%ld resulting in 0x%ld in f%d\n",
196 __func__
, env
->fregs
[f2
].d
, env
->fregs
[f1
].d
, f1
);
198 return set_cc_nz_f64(env
->fregs
[f1
].d
);
201 /* 32-bit FP division RR */
202 void HELPER(debr
)(CPUS390XState
*env
, uint32_t f1
, uint32_t f2
)
204 env
->fregs
[f1
].l
.upper
= float32_div(env
->fregs
[f1
].l
.upper
,
205 env
->fregs
[f2
].l
.upper
,
209 /* 128-bit FP division RR */
210 void HELPER(dxbr
)(CPUS390XState
*env
, uint32_t f1
, uint32_t f2
)
216 v1
.ll
.upper
= env
->fregs
[f1
].ll
;
217 v1
.ll
.lower
= env
->fregs
[f1
+ 2].ll
;
218 v2
.ll
.upper
= env
->fregs
[f2
].ll
;
219 v2
.ll
.lower
= env
->fregs
[f2
+ 2].ll
;
220 res
.q
= float128_div(v1
.q
, v2
.q
, &env
->fpu_status
);
221 env
->fregs
[f1
].ll
= res
.ll
.upper
;
222 env
->fregs
[f1
+ 2].ll
= res
.ll
.lower
;
225 /* 64-bit FP multiplication RR */
226 void HELPER(mdbr
)(CPUS390XState
*env
, uint32_t f1
, uint32_t f2
)
228 env
->fregs
[f1
].d
= float64_mul(env
->fregs
[f1
].d
, env
->fregs
[f2
].d
,
232 /* 128-bit FP multiplication RR */
233 void HELPER(mxbr
)(CPUS390XState
*env
, uint32_t f1
, uint32_t f2
)
239 v1
.ll
.upper
= env
->fregs
[f1
].ll
;
240 v1
.ll
.lower
= env
->fregs
[f1
+ 2].ll
;
241 v2
.ll
.upper
= env
->fregs
[f2
].ll
;
242 v2
.ll
.lower
= env
->fregs
[f2
+ 2].ll
;
243 res
.q
= float128_mul(v1
.q
, v2
.q
, &env
->fpu_status
);
244 env
->fregs
[f1
].ll
= res
.ll
.upper
;
245 env
->fregs
[f1
+ 2].ll
= res
.ll
.lower
;
248 /* convert 32-bit float to 64-bit float */
249 void HELPER(ldebr
)(CPUS390XState
*env
, uint32_t r1
, uint32_t r2
)
251 env
->fregs
[r1
].d
= float32_to_float64(env
->fregs
[r2
].l
.upper
,
255 /* convert 128-bit float to 64-bit float */
256 void HELPER(ldxbr
)(CPUS390XState
*env
, uint32_t f1
, uint32_t f2
)
260 x2
.ll
.upper
= env
->fregs
[f2
].ll
;
261 x2
.ll
.lower
= env
->fregs
[f2
+ 2].ll
;
262 env
->fregs
[f1
].d
= float128_to_float64(x2
.q
, &env
->fpu_status
);
263 HELPER_LOG("%s: to 0x%ld\n", __func__
, env
->fregs
[f1
].d
);
266 /* convert 64-bit float to 128-bit float */
267 void HELPER(lxdbr
)(CPUS390XState
*env
, uint32_t f1
, uint32_t f2
)
271 res
.q
= float64_to_float128(env
->fregs
[f2
].d
, &env
->fpu_status
);
272 env
->fregs
[f1
].ll
= res
.ll
.upper
;
273 env
->fregs
[f1
+ 2].ll
= res
.ll
.lower
;
276 /* convert 64-bit float to 32-bit float */
277 void HELPER(ledbr
)(CPUS390XState
*env
, uint32_t f1
, uint32_t f2
)
279 float64 d2
= env
->fregs
[f2
].d
;
281 env
->fregs
[f1
].l
.upper
= float64_to_float32(d2
, &env
->fpu_status
);
284 /* convert 128-bit float to 32-bit float */
285 void HELPER(lexbr
)(CPUS390XState
*env
, uint32_t f1
, uint32_t f2
)
289 x2
.ll
.upper
= env
->fregs
[f2
].ll
;
290 x2
.ll
.lower
= env
->fregs
[f2
+ 2].ll
;
291 env
->fregs
[f1
].l
.upper
= float128_to_float32(x2
.q
, &env
->fpu_status
);
292 HELPER_LOG("%s: to 0x%d\n", __func__
, env
->fregs
[f1
].l
.upper
);
295 /* absolute value of 32-bit float */
296 uint32_t HELPER(lpebr
)(CPUS390XState
*env
, uint32_t f1
, uint32_t f2
)
299 float32 v2
= env
->fregs
[f2
].d
;
301 v1
= float32_abs(v2
);
302 env
->fregs
[f1
].d
= v1
;
303 return set_cc_nz_f32(v1
);
306 /* absolute value of 64-bit float */
307 uint32_t HELPER(lpdbr
)(CPUS390XState
*env
, uint32_t f1
, uint32_t f2
)
310 float64 v2
= env
->fregs
[f2
].d
;
312 v1
= float64_abs(v2
);
313 env
->fregs
[f1
].d
= v1
;
314 return set_cc_nz_f64(v1
);
317 /* absolute value of 128-bit float */
318 uint32_t HELPER(lpxbr
)(CPUS390XState
*env
, uint32_t f1
, uint32_t f2
)
323 v2
.ll
.upper
= env
->fregs
[f2
].ll
;
324 v2
.ll
.lower
= env
->fregs
[f2
+ 2].ll
;
325 v1
.q
= float128_abs(v2
.q
);
326 env
->fregs
[f1
].ll
= v1
.ll
.upper
;
327 env
->fregs
[f1
+ 2].ll
= v1
.ll
.lower
;
328 return set_cc_nz_f128(v1
.q
);
331 /* load and test 64-bit float */
332 uint32_t HELPER(ltdbr
)(CPUS390XState
*env
, uint32_t f1
, uint32_t f2
)
334 env
->fregs
[f1
].d
= env
->fregs
[f2
].d
;
335 return set_cc_nz_f64(env
->fregs
[f1
].d
);
338 /* load and test 32-bit float */
339 uint32_t HELPER(ltebr
)(CPUS390XState
*env
, uint32_t f1
, uint32_t f2
)
341 env
->fregs
[f1
].l
.upper
= env
->fregs
[f2
].l
.upper
;
342 return set_cc_nz_f32(env
->fregs
[f1
].l
.upper
);
345 /* load and test 128-bit float */
346 uint32_t HELPER(ltxbr
)(CPUS390XState
*env
, uint32_t f1
, uint32_t f2
)
350 x
.ll
.upper
= env
->fregs
[f2
].ll
;
351 x
.ll
.lower
= env
->fregs
[f2
+ 2].ll
;
352 env
->fregs
[f1
].ll
= x
.ll
.upper
;
353 env
->fregs
[f1
+ 2].ll
= x
.ll
.lower
;
354 return set_cc_nz_f128(x
.q
);
357 /* load complement of 32-bit float */
358 uint32_t HELPER(lcebr
)(CPUS390XState
*env
, uint32_t f1
, uint32_t f2
)
360 env
->fregs
[f1
].l
.upper
= float32_chs(env
->fregs
[f2
].l
.upper
);
362 return set_cc_nz_f32(env
->fregs
[f1
].l
.upper
);
365 /* load complement of 64-bit float */
366 uint32_t HELPER(lcdbr
)(CPUS390XState
*env
, uint32_t f1
, uint32_t f2
)
368 env
->fregs
[f1
].d
= float64_chs(env
->fregs
[f2
].d
);
370 return set_cc_nz_f64(env
->fregs
[f1
].d
);
373 /* load complement of 128-bit float */
374 uint32_t HELPER(lcxbr
)(CPUS390XState
*env
, uint32_t f1
, uint32_t f2
)
378 x2
.ll
.upper
= env
->fregs
[f2
].ll
;
379 x2
.ll
.lower
= env
->fregs
[f2
+ 2].ll
;
380 x1
.q
= float128_chs(x2
.q
);
381 env
->fregs
[f1
].ll
= x1
.ll
.upper
;
382 env
->fregs
[f1
+ 2].ll
= x1
.ll
.lower
;
383 return set_cc_nz_f128(x1
.q
);
386 /* 32-bit FP addition RM */
387 void HELPER(aeb
)(CPUS390XState
*env
, uint32_t f1
, uint32_t val
)
389 float32 v1
= env
->fregs
[f1
].l
.upper
;
393 HELPER_LOG("%s: adding 0x%d from f%d and 0x%d\n", __func__
,
395 env
->fregs
[f1
].l
.upper
= float32_add(v1
, v2
.f
, &env
->fpu_status
);
398 /* 32-bit FP division RM */
399 void HELPER(deb
)(CPUS390XState
*env
, uint32_t f1
, uint32_t val
)
401 float32 v1
= env
->fregs
[f1
].l
.upper
;
405 HELPER_LOG("%s: dividing 0x%d from f%d by 0x%d\n", __func__
,
407 env
->fregs
[f1
].l
.upper
= float32_div(v1
, v2
.f
, &env
->fpu_status
);
410 /* 32-bit FP multiplication RM */
411 void HELPER(meeb
)(CPUS390XState
*env
, uint32_t f1
, uint32_t val
)
413 float32 v1
= env
->fregs
[f1
].l
.upper
;
417 HELPER_LOG("%s: multiplying 0x%d from f%d and 0x%d\n", __func__
,
419 env
->fregs
[f1
].l
.upper
= float32_mul(v1
, v2
.f
, &env
->fpu_status
);
422 /* 32-bit FP compare RR */
423 uint32_t HELPER(cebr
)(CPUS390XState
*env
, uint32_t f1
, uint32_t f2
)
425 float32 v1
= env
->fregs
[f1
].l
.upper
;
426 float32 v2
= env
->fregs
[f2
].l
.upper
;
428 HELPER_LOG("%s: comparing 0x%d from f%d and 0x%d\n", __func__
,
430 return set_cc_f32(env
, v1
, v2
);
433 /* 64-bit FP compare RR */
434 uint32_t HELPER(cdbr
)(CPUS390XState
*env
, uint32_t f1
, uint32_t f2
)
436 float64 v1
= env
->fregs
[f1
].d
;
437 float64 v2
= env
->fregs
[f2
].d
;
439 HELPER_LOG("%s: comparing 0x%ld from f%d and 0x%ld\n", __func__
,
441 return set_cc_f64(env
, v1
, v2
);
444 /* 128-bit FP compare RR */
445 uint32_t HELPER(cxbr
)(CPUS390XState
*env
, uint32_t f1
, uint32_t f2
)
450 v1
.ll
.upper
= env
->fregs
[f1
].ll
;
451 v1
.ll
.lower
= env
->fregs
[f1
+ 2].ll
;
452 v2
.ll
.upper
= env
->fregs
[f2
].ll
;
453 v2
.ll
.lower
= env
->fregs
[f2
+ 2].ll
;
455 return float_comp_to_cc(env
, float128_compare_quiet(v1
.q
, v2
.q
,
459 /* 64-bit FP compare RM */
460 uint32_t HELPER(cdb
)(CPUS390XState
*env
, uint32_t f1
, uint64_t a2
)
462 float64 v1
= env
->fregs
[f1
].d
;
465 v2
.ll
= cpu_ldq_data(env
, a2
);
466 HELPER_LOG("%s: comparing 0x%ld from f%d and 0x%lx\n", __func__
, v1
,
468 return set_cc_f64(env
, v1
, v2
.d
);
471 /* 64-bit FP addition RM */
472 uint32_t HELPER(adb
)(CPUS390XState
*env
, uint32_t f1
, uint64_t a2
)
474 float64 v1
= env
->fregs
[f1
].d
;
477 v2
.ll
= cpu_ldq_data(env
, a2
);
478 HELPER_LOG("%s: adding 0x%lx from f%d and 0x%lx\n", __func__
,
480 env
->fregs
[f1
].d
= v1
= float64_add(v1
, v2
.d
, &env
->fpu_status
);
481 return set_cc_nz_f64(v1
);
484 /* 32-bit FP subtraction RM */
485 void HELPER(seb
)(CPUS390XState
*env
, uint32_t f1
, uint32_t val
)
487 float32 v1
= env
->fregs
[f1
].l
.upper
;
491 env
->fregs
[f1
].l
.upper
= float32_sub(v1
, v2
.f
, &env
->fpu_status
);
494 /* 64-bit FP subtraction RM */
495 uint32_t HELPER(sdb
)(CPUS390XState
*env
, uint32_t f1
, uint64_t a2
)
497 float64 v1
= env
->fregs
[f1
].d
;
500 v2
.ll
= cpu_ldq_data(env
, a2
);
501 env
->fregs
[f1
].d
= v1
= float64_sub(v1
, v2
.d
, &env
->fpu_status
);
502 return set_cc_nz_f64(v1
);
505 /* 64-bit FP multiplication RM */
506 void HELPER(mdb
)(CPUS390XState
*env
, uint32_t f1
, uint64_t a2
)
508 float64 v1
= env
->fregs
[f1
].d
;
511 v2
.ll
= cpu_ldq_data(env
, a2
);
512 HELPER_LOG("%s: multiplying 0x%lx from f%d and 0x%ld\n", __func__
,
514 env
->fregs
[f1
].d
= float64_mul(v1
, v2
.d
, &env
->fpu_status
);
517 /* 64-bit FP division RM */
518 void HELPER(ddb
)(CPUS390XState
*env
, uint32_t f1
, uint64_t a2
)
520 float64 v1
= env
->fregs
[f1
].d
;
523 v2
.ll
= cpu_ldq_data(env
, a2
);
524 HELPER_LOG("%s: dividing 0x%lx from f%d by 0x%ld\n", __func__
,
526 env
->fregs
[f1
].d
= float64_div(v1
, v2
.d
, &env
->fpu_status
);
529 static void set_round_mode(CPUS390XState
*env
, int m3
)
536 /* biased round no nearest */
538 /* round to nearest */
539 set_float_rounding_mode(float_round_nearest_even
, &env
->fpu_status
);
543 set_float_rounding_mode(float_round_to_zero
, &env
->fpu_status
);
547 set_float_rounding_mode(float_round_up
, &env
->fpu_status
);
551 set_float_rounding_mode(float_round_down
, &env
->fpu_status
);
556 /* convert 32-bit float to 64-bit int */
557 uint32_t HELPER(cgebr
)(CPUS390XState
*env
, uint32_t r1
, uint32_t f2
,
560 float32 v2
= env
->fregs
[f2
].l
.upper
;
562 set_round_mode(env
, m3
);
563 env
->regs
[r1
] = float32_to_int64(v2
, &env
->fpu_status
);
564 return set_cc_nz_f32(v2
);
567 /* convert 64-bit float to 64-bit int */
568 uint32_t HELPER(cgdbr
)(CPUS390XState
*env
, uint32_t r1
, uint32_t f2
,
571 float64 v2
= env
->fregs
[f2
].d
;
573 set_round_mode(env
, m3
);
574 env
->regs
[r1
] = float64_to_int64(v2
, &env
->fpu_status
);
575 return set_cc_nz_f64(v2
);
578 /* convert 128-bit float to 64-bit int */
579 uint32_t HELPER(cgxbr
)(CPUS390XState
*env
, uint32_t r1
, uint32_t f2
,
584 v2
.ll
.upper
= env
->fregs
[f2
].ll
;
585 v2
.ll
.lower
= env
->fregs
[f2
+ 2].ll
;
586 set_round_mode(env
, m3
);
587 env
->regs
[r1
] = float128_to_int64(v2
.q
, &env
->fpu_status
);
588 if (float128_is_any_nan(v2
.q
)) {
590 } else if (float128_is_zero(v2
.q
)) {
592 } else if (float128_is_neg(v2
.q
)) {
599 /* convert 32-bit float to 32-bit int */
600 uint32_t HELPER(cfebr
)(CPUS390XState
*env
, uint32_t r1
, uint32_t f2
,
603 float32 v2
= env
->fregs
[f2
].l
.upper
;
605 set_round_mode(env
, m3
);
606 env
->regs
[r1
] = (env
->regs
[r1
] & 0xffffffff00000000ULL
) |
607 float32_to_int32(v2
, &env
->fpu_status
);
608 return set_cc_nz_f32(v2
);
611 /* convert 64-bit float to 32-bit int */
612 uint32_t HELPER(cfdbr
)(CPUS390XState
*env
, uint32_t r1
, uint32_t f2
,
615 float64 v2
= env
->fregs
[f2
].d
;
617 set_round_mode(env
, m3
);
618 env
->regs
[r1
] = (env
->regs
[r1
] & 0xffffffff00000000ULL
) |
619 float64_to_int32(v2
, &env
->fpu_status
);
620 return set_cc_nz_f64(v2
);
623 /* convert 128-bit float to 32-bit int */
624 uint32_t HELPER(cfxbr
)(CPUS390XState
*env
, uint32_t r1
, uint32_t f2
,
629 v2
.ll
.upper
= env
->fregs
[f2
].ll
;
630 v2
.ll
.lower
= env
->fregs
[f2
+ 2].ll
;
631 env
->regs
[r1
] = (env
->regs
[r1
] & 0xffffffff00000000ULL
) |
632 float128_to_int32(v2
.q
, &env
->fpu_status
);
633 return set_cc_nz_f128(v2
.q
);
636 /* load 32-bit FP zero */
637 void HELPER(lzer
)(CPUS390XState
*env
, uint32_t f1
)
639 env
->fregs
[f1
].l
.upper
= float32_zero
;
642 /* load 64-bit FP zero */
643 void HELPER(lzdr
)(CPUS390XState
*env
, uint32_t f1
)
645 env
->fregs
[f1
].d
= float64_zero
;
648 /* load 128-bit FP zero */
649 void HELPER(lzxr
)(CPUS390XState
*env
, uint32_t f1
)
653 x
.q
= float64_to_float128(float64_zero
, &env
->fpu_status
);
654 env
->fregs
[f1
].ll
= x
.ll
.upper
;
655 env
->fregs
[f1
+ 1].ll
= x
.ll
.lower
;
658 /* 128-bit FP subtraction RR */
659 uint32_t HELPER(sxbr
)(CPUS390XState
*env
, uint32_t f1
, uint32_t f2
)
665 v1
.ll
.upper
= env
->fregs
[f1
].ll
;
666 v1
.ll
.lower
= env
->fregs
[f1
+ 2].ll
;
667 v2
.ll
.upper
= env
->fregs
[f2
].ll
;
668 v2
.ll
.lower
= env
->fregs
[f2
+ 2].ll
;
669 res
.q
= float128_sub(v1
.q
, v2
.q
, &env
->fpu_status
);
670 env
->fregs
[f1
].ll
= res
.ll
.upper
;
671 env
->fregs
[f1
+ 2].ll
= res
.ll
.lower
;
672 return set_cc_nz_f128(res
.q
);
675 /* 128-bit FP addition RR */
676 uint32_t HELPER(axbr
)(CPUS390XState
*env
, uint32_t f1
, uint32_t f2
)
682 v1
.ll
.upper
= env
->fregs
[f1
].ll
;
683 v1
.ll
.lower
= env
->fregs
[f1
+ 2].ll
;
684 v2
.ll
.upper
= env
->fregs
[f2
].ll
;
685 v2
.ll
.lower
= env
->fregs
[f2
+ 2].ll
;
686 res
.q
= float128_add(v1
.q
, v2
.q
, &env
->fpu_status
);
687 env
->fregs
[f1
].ll
= res
.ll
.upper
;
688 env
->fregs
[f1
+ 2].ll
= res
.ll
.lower
;
689 return set_cc_nz_f128(res
.q
);
692 /* 32-bit FP multiplication RR */
693 void HELPER(meebr
)(CPUS390XState
*env
, uint32_t f1
, uint32_t f2
)
695 env
->fregs
[f1
].l
.upper
= float32_mul(env
->fregs
[f1
].l
.upper
,
696 env
->fregs
[f2
].l
.upper
,
700 /* 64-bit FP division RR */
701 void HELPER(ddbr
)(CPUS390XState
*env
, uint32_t f1
, uint32_t f2
)
703 env
->fregs
[f1
].d
= float64_div(env
->fregs
[f1
].d
, env
->fregs
[f2
].d
,
707 /* 64-bit FP multiply and add RM */
708 void HELPER(madb
)(CPUS390XState
*env
, uint32_t f1
, uint64_t a2
, uint32_t f3
)
712 HELPER_LOG("%s: f1 %d a2 0x%lx f3 %d\n", __func__
, f1
, a2
, f3
);
713 v2
.ll
= cpu_ldq_data(env
, a2
);
714 env
->fregs
[f1
].d
= float64_add(env
->fregs
[f1
].d
,
715 float64_mul(v2
.d
, env
->fregs
[f3
].d
,
720 /* 64-bit FP multiply and add RR */
721 void HELPER(madbr
)(CPUS390XState
*env
, uint32_t f1
, uint32_t f3
, uint32_t f2
)
723 HELPER_LOG("%s: f1 %d f2 %d f3 %d\n", __func__
, f1
, f2
, f3
);
724 env
->fregs
[f1
].d
= float64_add(float64_mul(env
->fregs
[f2
].d
,
727 env
->fregs
[f1
].d
, &env
->fpu_status
);
730 /* 64-bit FP multiply and subtract RR */
731 void HELPER(msdbr
)(CPUS390XState
*env
, uint32_t f1
, uint32_t f3
, uint32_t f2
)
733 HELPER_LOG("%s: f1 %d f2 %d f3 %d\n", __func__
, f1
, f2
, f3
);
734 env
->fregs
[f1
].d
= float64_sub(float64_mul(env
->fregs
[f2
].d
,
737 env
->fregs
[f1
].d
, &env
->fpu_status
);
740 /* 32-bit FP multiply and add RR */
741 void HELPER(maebr
)(CPUS390XState
*env
, uint32_t f1
, uint32_t f3
, uint32_t f2
)
743 env
->fregs
[f1
].l
.upper
= float32_add(env
->fregs
[f1
].l
.upper
,
744 float32_mul(env
->fregs
[f2
].l
.upper
,
745 env
->fregs
[f3
].l
.upper
,
750 /* convert 32-bit float to 64-bit float */
751 void HELPER(ldeb
)(CPUS390XState
*env
, uint32_t f1
, uint64_t a2
)
755 v2
= cpu_ldl_data(env
, a2
);
756 env
->fregs
[f1
].d
= float32_to_float64(v2
,
760 /* convert 64-bit float to 128-bit float */
761 void HELPER(lxdb
)(CPUS390XState
*env
, uint32_t f1
, uint64_t a2
)
766 v2
.ll
= cpu_ldq_data(env
, a2
);
767 v1
.q
= float64_to_float128(v2
.d
, &env
->fpu_status
);
768 env
->fregs
[f1
].ll
= v1
.ll
.upper
;
769 env
->fregs
[f1
+ 2].ll
= v1
.ll
.lower
;
772 /* test data class 32-bit */
773 uint32_t HELPER(tceb
)(CPUS390XState
*env
, uint32_t f1
, uint64_t m2
)
775 float32 v1
= env
->fregs
[f1
].l
.upper
;
776 int neg
= float32_is_neg(v1
);
779 HELPER_LOG("%s: v1 0x%lx m2 0x%lx neg %d\n", __func__
, (long)v1
, m2
, neg
);
780 if ((float32_is_zero(v1
) && (m2
& (1 << (11-neg
)))) ||
781 (float32_is_infinity(v1
) && (m2
& (1 << (5-neg
)))) ||
782 (float32_is_any_nan(v1
) && (m2
& (1 << (3-neg
)))) ||
783 (float32_is_signaling_nan(v1
) && (m2
& (1 << (1-neg
))))) {
785 } else if (m2
& (1 << (9-neg
))) {
786 /* assume normalized number */
790 /* FIXME: denormalized? */
794 /* test data class 64-bit */
795 uint32_t HELPER(tcdb
)(CPUS390XState
*env
, uint32_t f1
, uint64_t m2
)
797 float64 v1
= env
->fregs
[f1
].d
;
798 int neg
= float64_is_neg(v1
);
801 HELPER_LOG("%s: v1 0x%lx m2 0x%lx neg %d\n", __func__
, v1
, m2
, neg
);
802 if ((float64_is_zero(v1
) && (m2
& (1 << (11-neg
)))) ||
803 (float64_is_infinity(v1
) && (m2
& (1 << (5-neg
)))) ||
804 (float64_is_any_nan(v1
) && (m2
& (1 << (3-neg
)))) ||
805 (float64_is_signaling_nan(v1
) && (m2
& (1 << (1-neg
))))) {
807 } else if (m2
& (1 << (9-neg
))) {
808 /* assume normalized number */
811 /* FIXME: denormalized? */
815 /* test data class 128-bit */
816 uint32_t HELPER(tcxb
)(CPUS390XState
*env
, uint32_t f1
, uint64_t m2
)
822 v1
.ll
.upper
= env
->fregs
[f1
].ll
;
823 v1
.ll
.lower
= env
->fregs
[f1
+ 2].ll
;
825 neg
= float128_is_neg(v1
.q
);
826 if ((float128_is_zero(v1
.q
) && (m2
& (1 << (11-neg
)))) ||
827 (float128_is_infinity(v1
.q
) && (m2
& (1 << (5-neg
)))) ||
828 (float128_is_any_nan(v1
.q
) && (m2
& (1 << (3-neg
)))) ||
829 (float128_is_signaling_nan(v1
.q
) && (m2
& (1 << (1-neg
))))) {
831 } else if (m2
& (1 << (9-neg
))) {
832 /* assume normalized number */
835 /* FIXME: denormalized? */
839 /* square root 64-bit RR */
840 void HELPER(sqdbr
)(CPUS390XState
*env
, uint32_t f1
, uint32_t f2
)
842 env
->fregs
[f1
].d
= float64_sqrt(env
->fregs
[f2
].d
, &env
->fpu_status
);