]> git.proxmox.com Git - qemu.git/blob - target-s390x/fpu_helper.c
target-s390x: avoid AREG0 for FPU helpers
[qemu.git] / target-s390x / fpu_helper.c
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 /* temporarily disabled due to wrapper use */
25 #if 0 && !defined(CONFIG_USER_ONLY)
26 #include "softmmu_exec.h"
27 #endif
28
29 /* #define DEBUG_HELPER */
30 #ifdef DEBUG_HELPER
31 #define HELPER_LOG(x...) qemu_log(x)
32 #else
33 #define HELPER_LOG(x...)
34 #endif
35
36 static inline int float_comp_to_cc(CPUS390XState *env, int float_compare)
37 {
38 switch (float_compare) {
39 case float_relation_equal:
40 return 0;
41 case float_relation_less:
42 return 1;
43 case float_relation_greater:
44 return 2;
45 case float_relation_unordered:
46 return 3;
47 default:
48 cpu_abort(env, "unknown return value for float compare\n");
49 }
50 }
51
52 /* condition codes for binary FP ops */
53 uint32_t set_cc_f32(CPUS390XState *env, float32 v1, float32 v2)
54 {
55 return float_comp_to_cc(env, float32_compare_quiet(v1, v2,
56 &env->fpu_status));
57 }
58
59 uint32_t set_cc_f64(CPUS390XState *env, float64 v1, float64 v2)
60 {
61 return float_comp_to_cc(env, float64_compare_quiet(v1, v2,
62 &env->fpu_status));
63 }
64
65 /* condition codes for unary FP ops */
66 uint32_t set_cc_nz_f32(float32 v)
67 {
68 if (float32_is_any_nan(v)) {
69 return 3;
70 } else if (float32_is_zero(v)) {
71 return 0;
72 } else if (float32_is_neg(v)) {
73 return 1;
74 } else {
75 return 2;
76 }
77 }
78
79 uint32_t set_cc_nz_f64(float64 v)
80 {
81 if (float64_is_any_nan(v)) {
82 return 3;
83 } else if (float64_is_zero(v)) {
84 return 0;
85 } else if (float64_is_neg(v)) {
86 return 1;
87 } else {
88 return 2;
89 }
90 }
91
92 static uint32_t set_cc_nz_f128(float128 v)
93 {
94 if (float128_is_any_nan(v)) {
95 return 3;
96 } else if (float128_is_zero(v)) {
97 return 0;
98 } else if (float128_is_neg(v)) {
99 return 1;
100 } else {
101 return 2;
102 }
103 }
104
105 /* convert 32-bit int to 64-bit float */
106 void HELPER(cdfbr)(CPUS390XState *env, uint32_t f1, int32_t v2)
107 {
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);
110 }
111
112 /* convert 32-bit int to 128-bit float */
113 void HELPER(cxfbr)(CPUS390XState *env, uint32_t f1, int32_t v2)
114 {
115 CPU_QuadU v1;
116
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;
120 }
121
122 /* convert 64-bit int to 32-bit float */
123 void HELPER(cegbr)(CPUS390XState *env, uint32_t f1, int64_t v2)
124 {
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);
127 }
128
129 /* convert 64-bit int to 64-bit float */
130 void HELPER(cdgbr)(CPUS390XState *env, uint32_t f1, int64_t v2)
131 {
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);
134 }
135
136 /* convert 64-bit int to 128-bit float */
137 void HELPER(cxgbr)(CPUS390XState *env, uint32_t f1, int64_t v2)
138 {
139 CPU_QuadU x1;
140
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;
146 }
147
148 /* convert 32-bit int to 32-bit float */
149 void HELPER(cefbr)(CPUS390XState *env, uint32_t f1, int32_t v2)
150 {
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);
154 }
155
156 /* 32-bit FP addition RR */
157 uint32_t HELPER(aebr)(CPUS390XState *env, uint32_t f1, uint32_t f2)
158 {
159 env->fregs[f1].l.upper = float32_add(env->fregs[f1].l.upper,
160 env->fregs[f2].l.upper,
161 &env->fpu_status);
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);
164
165 return set_cc_nz_f32(env->fregs[f1].l.upper);
166 }
167
168 /* 64-bit FP addition RR */
169 uint32_t HELPER(adbr)(CPUS390XState *env, uint32_t f1, uint32_t f2)
170 {
171 env->fregs[f1].d = float64_add(env->fregs[f1].d, env->fregs[f2].d,
172 &env->fpu_status);
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);
175
176 return set_cc_nz_f64(env->fregs[f1].d);
177 }
178
179 /* 32-bit FP subtraction RR */
180 uint32_t HELPER(sebr)(CPUS390XState *env, uint32_t f1, uint32_t f2)
181 {
182 env->fregs[f1].l.upper = float32_sub(env->fregs[f1].l.upper,
183 env->fregs[f2].l.upper,
184 &env->fpu_status);
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);
187
188 return set_cc_nz_f32(env->fregs[f1].l.upper);
189 }
190
191 /* 64-bit FP subtraction RR */
192 uint32_t HELPER(sdbr)(CPUS390XState *env, uint32_t f1, uint32_t f2)
193 {
194 env->fregs[f1].d = float64_sub(env->fregs[f1].d, env->fregs[f2].d,
195 &env->fpu_status);
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);
198
199 return set_cc_nz_f64(env->fregs[f1].d);
200 }
201
202 /* 32-bit FP division RR */
203 void HELPER(debr)(CPUS390XState *env, uint32_t f1, uint32_t f2)
204 {
205 env->fregs[f1].l.upper = float32_div(env->fregs[f1].l.upper,
206 env->fregs[f2].l.upper,
207 &env->fpu_status);
208 }
209
210 /* 128-bit FP division RR */
211 void HELPER(dxbr)(CPUS390XState *env, uint32_t f1, uint32_t f2)
212 {
213 CPU_QuadU v1;
214 CPU_QuadU v2;
215 CPU_QuadU res;
216
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;
224 }
225
226 /* 64-bit FP multiplication RR */
227 void HELPER(mdbr)(CPUS390XState *env, uint32_t f1, uint32_t f2)
228 {
229 env->fregs[f1].d = float64_mul(env->fregs[f1].d, env->fregs[f2].d,
230 &env->fpu_status);
231 }
232
233 /* 128-bit FP multiplication RR */
234 void HELPER(mxbr)(CPUS390XState *env, uint32_t f1, uint32_t f2)
235 {
236 CPU_QuadU v1;
237 CPU_QuadU v2;
238 CPU_QuadU res;
239
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;
247 }
248
249 /* convert 32-bit float to 64-bit float */
250 void HELPER(ldebr)(CPUS390XState *env, uint32_t r1, uint32_t r2)
251 {
252 env->fregs[r1].d = float32_to_float64(env->fregs[r2].l.upper,
253 &env->fpu_status);
254 }
255
256 /* convert 128-bit float to 64-bit float */
257 void HELPER(ldxbr)(CPUS390XState *env, uint32_t f1, uint32_t f2)
258 {
259 CPU_QuadU x2;
260
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);
265 }
266
267 /* convert 64-bit float to 128-bit float */
268 void HELPER(lxdbr)(CPUS390XState *env, uint32_t f1, uint32_t f2)
269 {
270 CPU_QuadU res;
271
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;
275 }
276
277 /* convert 64-bit float to 32-bit float */
278 void HELPER(ledbr)(CPUS390XState *env, uint32_t f1, uint32_t f2)
279 {
280 float64 d2 = env->fregs[f2].d;
281
282 env->fregs[f1].l.upper = float64_to_float32(d2, &env->fpu_status);
283 }
284
285 /* convert 128-bit float to 32-bit float */
286 void HELPER(lexbr)(CPUS390XState *env, uint32_t f1, uint32_t f2)
287 {
288 CPU_QuadU x2;
289
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);
294 }
295
296 /* absolute value of 32-bit float */
297 uint32_t HELPER(lpebr)(CPUS390XState *env, uint32_t f1, uint32_t f2)
298 {
299 float32 v1;
300 float32 v2 = env->fregs[f2].d;
301
302 v1 = float32_abs(v2);
303 env->fregs[f1].d = v1;
304 return set_cc_nz_f32(v1);
305 }
306
307 /* absolute value of 64-bit float */
308 uint32_t HELPER(lpdbr)(CPUS390XState *env, uint32_t f1, uint32_t f2)
309 {
310 float64 v1;
311 float64 v2 = env->fregs[f2].d;
312
313 v1 = float64_abs(v2);
314 env->fregs[f1].d = v1;
315 return set_cc_nz_f64(v1);
316 }
317
318 /* absolute value of 128-bit float */
319 uint32_t HELPER(lpxbr)(CPUS390XState *env, uint32_t f1, uint32_t f2)
320 {
321 CPU_QuadU v1;
322 CPU_QuadU v2;
323
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);
330 }
331
332 /* load and test 64-bit float */
333 uint32_t HELPER(ltdbr)(CPUS390XState *env, uint32_t f1, uint32_t f2)
334 {
335 env->fregs[f1].d = env->fregs[f2].d;
336 return set_cc_nz_f64(env->fregs[f1].d);
337 }
338
339 /* load and test 32-bit float */
340 uint32_t HELPER(ltebr)(CPUS390XState *env, uint32_t f1, uint32_t f2)
341 {
342 env->fregs[f1].l.upper = env->fregs[f2].l.upper;
343 return set_cc_nz_f32(env->fregs[f1].l.upper);
344 }
345
346 /* load and test 128-bit float */
347 uint32_t HELPER(ltxbr)(CPUS390XState *env, uint32_t f1, uint32_t f2)
348 {
349 CPU_QuadU x;
350
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);
356 }
357
358 /* load complement of 32-bit float */
359 uint32_t HELPER(lcebr)(CPUS390XState *env, uint32_t f1, uint32_t f2)
360 {
361 env->fregs[f1].l.upper = float32_chs(env->fregs[f2].l.upper);
362
363 return set_cc_nz_f32(env->fregs[f1].l.upper);
364 }
365
366 /* load complement of 64-bit float */
367 uint32_t HELPER(lcdbr)(CPUS390XState *env, uint32_t f1, uint32_t f2)
368 {
369 env->fregs[f1].d = float64_chs(env->fregs[f2].d);
370
371 return set_cc_nz_f64(env->fregs[f1].d);
372 }
373
374 /* load complement of 128-bit float */
375 uint32_t HELPER(lcxbr)(CPUS390XState *env, uint32_t f1, uint32_t f2)
376 {
377 CPU_QuadU x1, x2;
378
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);
385 }
386
387 /* 32-bit FP addition RM */
388 void HELPER(aeb)(CPUS390XState *env, uint32_t f1, uint32_t val)
389 {
390 float32 v1 = env->fregs[f1].l.upper;
391 CPU_FloatU v2;
392
393 v2.l = val;
394 HELPER_LOG("%s: adding 0x%d from f%d and 0x%d\n", __func__,
395 v1, f1, v2.f);
396 env->fregs[f1].l.upper = float32_add(v1, v2.f, &env->fpu_status);
397 }
398
399 /* 32-bit FP division RM */
400 void HELPER(deb)(CPUS390XState *env, uint32_t f1, uint32_t val)
401 {
402 float32 v1 = env->fregs[f1].l.upper;
403 CPU_FloatU v2;
404
405 v2.l = val;
406 HELPER_LOG("%s: dividing 0x%d from f%d by 0x%d\n", __func__,
407 v1, f1, v2.f);
408 env->fregs[f1].l.upper = float32_div(v1, v2.f, &env->fpu_status);
409 }
410
411 /* 32-bit FP multiplication RM */
412 void HELPER(meeb)(CPUS390XState *env, uint32_t f1, uint32_t val)
413 {
414 float32 v1 = env->fregs[f1].l.upper;
415 CPU_FloatU v2;
416
417 v2.l = val;
418 HELPER_LOG("%s: multiplying 0x%d from f%d and 0x%d\n", __func__,
419 v1, f1, v2.f);
420 env->fregs[f1].l.upper = float32_mul(v1, v2.f, &env->fpu_status);
421 }
422
423 /* 32-bit FP compare RR */
424 uint32_t HELPER(cebr)(CPUS390XState *env, uint32_t f1, uint32_t f2)
425 {
426 float32 v1 = env->fregs[f1].l.upper;
427 float32 v2 = env->fregs[f2].l.upper;
428
429 HELPER_LOG("%s: comparing 0x%d from f%d and 0x%d\n", __func__,
430 v1, f1, v2);
431 return set_cc_f32(env, v1, v2);
432 }
433
434 /* 64-bit FP compare RR */
435 uint32_t HELPER(cdbr)(CPUS390XState *env, uint32_t f1, uint32_t f2)
436 {
437 float64 v1 = env->fregs[f1].d;
438 float64 v2 = env->fregs[f2].d;
439
440 HELPER_LOG("%s: comparing 0x%ld from f%d and 0x%ld\n", __func__,
441 v1, f1, v2);
442 return set_cc_f64(env, v1, v2);
443 }
444
445 /* 128-bit FP compare RR */
446 uint32_t HELPER(cxbr)(CPUS390XState *env, uint32_t f1, uint32_t f2)
447 {
448 CPU_QuadU v1;
449 CPU_QuadU v2;
450
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;
455
456 return float_comp_to_cc(env, float128_compare_quiet(v1.q, v2.q,
457 &env->fpu_status));
458 }
459
460 /* 64-bit FP compare RM */
461 uint32_t HELPER(cdb)(CPUS390XState *env, uint32_t f1, uint64_t a2)
462 {
463 float64 v1 = env->fregs[f1].d;
464 CPU_DoubleU v2;
465
466 v2.ll = cpu_ldq_data(env, a2);
467 HELPER_LOG("%s: comparing 0x%ld from f%d and 0x%lx\n", __func__, v1,
468 f1, v2.d);
469 return set_cc_f64(env, v1, v2.d);
470 }
471
472 /* 64-bit FP addition RM */
473 uint32_t HELPER(adb)(CPUS390XState *env, uint32_t f1, uint64_t a2)
474 {
475 float64 v1 = env->fregs[f1].d;
476 CPU_DoubleU v2;
477
478 v2.ll = cpu_ldq_data(env, a2);
479 HELPER_LOG("%s: adding 0x%lx from f%d and 0x%lx\n", __func__,
480 v1, f1, v2.d);
481 env->fregs[f1].d = v1 = float64_add(v1, v2.d, &env->fpu_status);
482 return set_cc_nz_f64(v1);
483 }
484
485 /* 32-bit FP subtraction RM */
486 void HELPER(seb)(CPUS390XState *env, uint32_t f1, uint32_t val)
487 {
488 float32 v1 = env->fregs[f1].l.upper;
489 CPU_FloatU v2;
490
491 v2.l = val;
492 env->fregs[f1].l.upper = float32_sub(v1, v2.f, &env->fpu_status);
493 }
494
495 /* 64-bit FP subtraction RM */
496 uint32_t HELPER(sdb)(CPUS390XState *env, uint32_t f1, uint64_t a2)
497 {
498 float64 v1 = env->fregs[f1].d;
499 CPU_DoubleU v2;
500
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);
504 }
505
506 /* 64-bit FP multiplication RM */
507 void HELPER(mdb)(CPUS390XState *env, uint32_t f1, uint64_t a2)
508 {
509 float64 v1 = env->fregs[f1].d;
510 CPU_DoubleU v2;
511
512 v2.ll = cpu_ldq_data(env, a2);
513 HELPER_LOG("%s: multiplying 0x%lx from f%d and 0x%ld\n", __func__,
514 v1, f1, v2.d);
515 env->fregs[f1].d = float64_mul(v1, v2.d, &env->fpu_status);
516 }
517
518 /* 64-bit FP division RM */
519 void HELPER(ddb)(CPUS390XState *env, uint32_t f1, uint64_t a2)
520 {
521 float64 v1 = env->fregs[f1].d;
522 CPU_DoubleU v2;
523
524 v2.ll = cpu_ldq_data(env, a2);
525 HELPER_LOG("%s: dividing 0x%lx from f%d by 0x%ld\n", __func__,
526 v1, f1, v2.d);
527 env->fregs[f1].d = float64_div(v1, v2.d, &env->fpu_status);
528 }
529
530 static void set_round_mode(CPUS390XState *env, int m3)
531 {
532 switch (m3) {
533 case 0:
534 /* current mode */
535 break;
536 case 1:
537 /* biased round no nearest */
538 case 4:
539 /* round to nearest */
540 set_float_rounding_mode(float_round_nearest_even, &env->fpu_status);
541 break;
542 case 5:
543 /* round to zero */
544 set_float_rounding_mode(float_round_to_zero, &env->fpu_status);
545 break;
546 case 6:
547 /* round to +inf */
548 set_float_rounding_mode(float_round_up, &env->fpu_status);
549 break;
550 case 7:
551 /* round to -inf */
552 set_float_rounding_mode(float_round_down, &env->fpu_status);
553 break;
554 }
555 }
556
557 /* convert 32-bit float to 64-bit int */
558 uint32_t HELPER(cgebr)(CPUS390XState *env, uint32_t r1, uint32_t f2,
559 uint32_t m3)
560 {
561 float32 v2 = env->fregs[f2].l.upper;
562
563 set_round_mode(env, m3);
564 env->regs[r1] = float32_to_int64(v2, &env->fpu_status);
565 return set_cc_nz_f32(v2);
566 }
567
568 /* convert 64-bit float to 64-bit int */
569 uint32_t HELPER(cgdbr)(CPUS390XState *env, uint32_t r1, uint32_t f2,
570 uint32_t m3)
571 {
572 float64 v2 = env->fregs[f2].d;
573
574 set_round_mode(env, m3);
575 env->regs[r1] = float64_to_int64(v2, &env->fpu_status);
576 return set_cc_nz_f64(v2);
577 }
578
579 /* convert 128-bit float to 64-bit int */
580 uint32_t HELPER(cgxbr)(CPUS390XState *env, uint32_t r1, uint32_t f2,
581 uint32_t m3)
582 {
583 CPU_QuadU v2;
584
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)) {
590 return 3;
591 } else if (float128_is_zero(v2.q)) {
592 return 0;
593 } else if (float128_is_neg(v2.q)) {
594 return 1;
595 } else {
596 return 2;
597 }
598 }
599
600 /* convert 32-bit float to 32-bit int */
601 uint32_t HELPER(cfebr)(CPUS390XState *env, uint32_t r1, uint32_t f2,
602 uint32_t m3)
603 {
604 float32 v2 = env->fregs[f2].l.upper;
605
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);
610 }
611
612 /* convert 64-bit float to 32-bit int */
613 uint32_t HELPER(cfdbr)(CPUS390XState *env, uint32_t r1, uint32_t f2,
614 uint32_t m3)
615 {
616 float64 v2 = env->fregs[f2].d;
617
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);
622 }
623
624 /* convert 128-bit float to 32-bit int */
625 uint32_t HELPER(cfxbr)(CPUS390XState *env, uint32_t r1, uint32_t f2,
626 uint32_t m3)
627 {
628 CPU_QuadU v2;
629
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);
635 }
636
637 /* load 32-bit FP zero */
638 void HELPER(lzer)(CPUS390XState *env, uint32_t f1)
639 {
640 env->fregs[f1].l.upper = float32_zero;
641 }
642
643 /* load 64-bit FP zero */
644 void HELPER(lzdr)(CPUS390XState *env, uint32_t f1)
645 {
646 env->fregs[f1].d = float64_zero;
647 }
648
649 /* load 128-bit FP zero */
650 void HELPER(lzxr)(CPUS390XState *env, uint32_t f1)
651 {
652 CPU_QuadU x;
653
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;
657 }
658
659 /* 128-bit FP subtraction RR */
660 uint32_t HELPER(sxbr)(CPUS390XState *env, uint32_t f1, uint32_t f2)
661 {
662 CPU_QuadU v1;
663 CPU_QuadU v2;
664 CPU_QuadU res;
665
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);
674 }
675
676 /* 128-bit FP addition RR */
677 uint32_t HELPER(axbr)(CPUS390XState *env, uint32_t f1, uint32_t f2)
678 {
679 CPU_QuadU v1;
680 CPU_QuadU v2;
681 CPU_QuadU res;
682
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);
691 }
692
693 /* 32-bit FP multiplication RR */
694 void HELPER(meebr)(CPUS390XState *env, uint32_t f1, uint32_t f2)
695 {
696 env->fregs[f1].l.upper = float32_mul(env->fregs[f1].l.upper,
697 env->fregs[f2].l.upper,
698 &env->fpu_status);
699 }
700
701 /* 64-bit FP division RR */
702 void HELPER(ddbr)(CPUS390XState *env, uint32_t f1, uint32_t f2)
703 {
704 env->fregs[f1].d = float64_div(env->fregs[f1].d, env->fregs[f2].d,
705 &env->fpu_status);
706 }
707
708 /* 64-bit FP multiply and add RM */
709 void HELPER(madb)(CPUS390XState *env, uint32_t f1, uint64_t a2, uint32_t f3)
710 {
711 CPU_DoubleU v2;
712
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,
717 &env->fpu_status),
718 &env->fpu_status);
719 }
720
721 /* 64-bit FP multiply and add RR */
722 void HELPER(madbr)(CPUS390XState *env, uint32_t f1, uint32_t f3, uint32_t f2)
723 {
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,
726 env->fregs[f3].d,
727 &env->fpu_status),
728 env->fregs[f1].d, &env->fpu_status);
729 }
730
731 /* 64-bit FP multiply and subtract RR */
732 void HELPER(msdbr)(CPUS390XState *env, uint32_t f1, uint32_t f3, uint32_t f2)
733 {
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,
736 env->fregs[f3].d,
737 &env->fpu_status),
738 env->fregs[f1].d, &env->fpu_status);
739 }
740
741 /* 32-bit FP multiply and add RR */
742 void HELPER(maebr)(CPUS390XState *env, uint32_t f1, uint32_t f3, uint32_t f2)
743 {
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,
747 &env->fpu_status),
748 &env->fpu_status);
749 }
750
751 /* convert 32-bit float to 64-bit float */
752 void HELPER(ldeb)(CPUS390XState *env, uint32_t f1, uint64_t a2)
753 {
754 uint32_t v2;
755
756 v2 = cpu_ldl_data(env, a2);
757 env->fregs[f1].d = float32_to_float64(v2,
758 &env->fpu_status);
759 }
760
761 /* convert 64-bit float to 128-bit float */
762 void HELPER(lxdb)(CPUS390XState *env, uint32_t f1, uint64_t a2)
763 {
764 CPU_DoubleU v2;
765 CPU_QuadU v1;
766
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;
771 }
772
773 /* test data class 32-bit */
774 uint32_t HELPER(tceb)(CPUS390XState *env, uint32_t f1, uint64_t m2)
775 {
776 float32 v1 = env->fregs[f1].l.upper;
777 int neg = float32_is_neg(v1);
778 uint32_t cc = 0;
779
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))))) {
785 cc = 1;
786 } else if (m2 & (1 << (9-neg))) {
787 /* assume normalized number */
788 cc = 1;
789 }
790
791 /* FIXME: denormalized? */
792 return cc;
793 }
794
795 /* test data class 64-bit */
796 uint32_t HELPER(tcdb)(CPUS390XState *env, uint32_t f1, uint64_t m2)
797 {
798 float64 v1 = env->fregs[f1].d;
799 int neg = float64_is_neg(v1);
800 uint32_t cc = 0;
801
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))))) {
807 cc = 1;
808 } else if (m2 & (1 << (9-neg))) {
809 /* assume normalized number */
810 cc = 1;
811 }
812 /* FIXME: denormalized? */
813 return cc;
814 }
815
816 /* test data class 128-bit */
817 uint32_t HELPER(tcxb)(CPUS390XState *env, uint32_t f1, uint64_t m2)
818 {
819 CPU_QuadU v1;
820 uint32_t cc = 0;
821 int neg;
822
823 v1.ll.upper = env->fregs[f1].ll;
824 v1.ll.lower = env->fregs[f1 + 2].ll;
825
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))))) {
831 cc = 1;
832 } else if (m2 & (1 << (9-neg))) {
833 /* assume normalized number */
834 cc = 1;
835 }
836 /* FIXME: denormalized? */
837 return cc;
838 }
839
840 /* square root 64-bit RR */
841 void HELPER(sqdbr)(CPUS390XState *env, uint32_t f1, uint32_t f2)
842 {
843 env->fregs[f1].d = float64_sqrt(env->fregs[f2].d, &env->fpu_status);
844 }