]> git.proxmox.com Git - mirror_qemu.git/blame - target-s390x/fpu_helper.c
target-s390x: rename op_helper.c to misc_helper.c
[mirror_qemu.git] / target-s390x / fpu_helper.c
CommitLineData
e72ca652
BS
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 "dyngen-exec.h"
23#include "helper.h"
24
25#if !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
36static inline int float_comp_to_cc(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 */
53uint32_t set_cc_f32(float32 v1, float32 v2)
54{
55 return float_comp_to_cc(float32_compare_quiet(v1, v2, &env->fpu_status));
56}
57
58uint32_t set_cc_f64(float64 v1, float64 v2)
59{
60 return float_comp_to_cc(float64_compare_quiet(v1, v2, &env->fpu_status));
61}
62
63/* condition codes for unary FP ops */
64uint32_t set_cc_nz_f32(float32 v)
65{
66 if (float32_is_any_nan(v)) {
67 return 3;
68 } else if (float32_is_zero(v)) {
69 return 0;
70 } else if (float32_is_neg(v)) {
71 return 1;
72 } else {
73 return 2;
74 }
75}
76
77uint32_t set_cc_nz_f64(float64 v)
78{
79 if (float64_is_any_nan(v)) {
80 return 3;
81 } else if (float64_is_zero(v)) {
82 return 0;
83 } else if (float64_is_neg(v)) {
84 return 1;
85 } else {
86 return 2;
87 }
88}
89
90static uint32_t set_cc_nz_f128(float128 v)
91{
92 if (float128_is_any_nan(v)) {
93 return 3;
94 } else if (float128_is_zero(v)) {
95 return 0;
96 } else if (float128_is_neg(v)) {
97 return 1;
98 } else {
99 return 2;
100 }
101}
102
103/* convert 32-bit int to 64-bit float */
104void HELPER(cdfbr)(uint32_t f1, int32_t v2)
105{
106 HELPER_LOG("%s: converting %d to f%d\n", __func__, v2, f1);
107 env->fregs[f1].d = int32_to_float64(v2, &env->fpu_status);
108}
109
110/* convert 32-bit int to 128-bit float */
111void HELPER(cxfbr)(uint32_t f1, int32_t v2)
112{
113 CPU_QuadU v1;
114
115 v1.q = int32_to_float128(v2, &env->fpu_status);
116 env->fregs[f1].ll = v1.ll.upper;
117 env->fregs[f1 + 2].ll = v1.ll.lower;
118}
119
120/* convert 64-bit int to 32-bit float */
121void HELPER(cegbr)(uint32_t f1, int64_t v2)
122{
123 HELPER_LOG("%s: converting %ld to f%d\n", __func__, v2, f1);
124 env->fregs[f1].l.upper = int64_to_float32(v2, &env->fpu_status);
125}
126
127/* convert 64-bit int to 64-bit float */
128void HELPER(cdgbr)(uint32_t f1, int64_t v2)
129{
130 HELPER_LOG("%s: converting %ld to f%d\n", __func__, v2, f1);
131 env->fregs[f1].d = int64_to_float64(v2, &env->fpu_status);
132}
133
134/* convert 64-bit int to 128-bit float */
135void HELPER(cxgbr)(uint32_t f1, int64_t v2)
136{
137 CPU_QuadU x1;
138
139 x1.q = int64_to_float128(v2, &env->fpu_status);
140 HELPER_LOG("%s: converted %ld to 0x%lx and 0x%lx\n", __func__, v2,
141 x1.ll.upper, x1.ll.lower);
142 env->fregs[f1].ll = x1.ll.upper;
143 env->fregs[f1 + 2].ll = x1.ll.lower;
144}
145
146/* convert 32-bit int to 32-bit float */
147void HELPER(cefbr)(uint32_t f1, int32_t v2)
148{
149 env->fregs[f1].l.upper = int32_to_float32(v2, &env->fpu_status);
150 HELPER_LOG("%s: converting %d to 0x%d in f%d\n", __func__, v2,
151 env->fregs[f1].l.upper, f1);
152}
153
154/* 32-bit FP addition RR */
155uint32_t HELPER(aebr)(uint32_t f1, uint32_t f2)
156{
157 env->fregs[f1].l.upper = float32_add(env->fregs[f1].l.upper,
158 env->fregs[f2].l.upper,
159 &env->fpu_status);
160 HELPER_LOG("%s: adding 0x%d resulting in 0x%d in f%d\n", __func__,
161 env->fregs[f2].l.upper, env->fregs[f1].l.upper, f1);
162
163 return set_cc_nz_f32(env->fregs[f1].l.upper);
164}
165
166/* 64-bit FP addition RR */
167uint32_t HELPER(adbr)(uint32_t f1, uint32_t f2)
168{
169 env->fregs[f1].d = float64_add(env->fregs[f1].d, env->fregs[f2].d,
170 &env->fpu_status);
171 HELPER_LOG("%s: adding 0x%ld resulting in 0x%ld in f%d\n", __func__,
172 env->fregs[f2].d, env->fregs[f1].d, f1);
173
174 return set_cc_nz_f64(env->fregs[f1].d);
175}
176
177/* 32-bit FP subtraction RR */
178uint32_t HELPER(sebr)(uint32_t f1, uint32_t f2)
179{
180 env->fregs[f1].l.upper = float32_sub(env->fregs[f1].l.upper,
181 env->fregs[f2].l.upper,
182 &env->fpu_status);
183 HELPER_LOG("%s: adding 0x%d resulting in 0x%d in f%d\n", __func__,
184 env->fregs[f2].l.upper, env->fregs[f1].l.upper, f1);
185
186 return set_cc_nz_f32(env->fregs[f1].l.upper);
187}
188
189/* 64-bit FP subtraction RR */
190uint32_t HELPER(sdbr)(uint32_t f1, uint32_t f2)
191{
192 env->fregs[f1].d = float64_sub(env->fregs[f1].d, env->fregs[f2].d,
193 &env->fpu_status);
194 HELPER_LOG("%s: subtracting 0x%ld resulting in 0x%ld in f%d\n",
195 __func__, env->fregs[f2].d, env->fregs[f1].d, f1);
196
197 return set_cc_nz_f64(env->fregs[f1].d);
198}
199
200/* 32-bit FP division RR */
201void HELPER(debr)(uint32_t f1, uint32_t f2)
202{
203 env->fregs[f1].l.upper = float32_div(env->fregs[f1].l.upper,
204 env->fregs[f2].l.upper,
205 &env->fpu_status);
206}
207
208/* 128-bit FP division RR */
209void HELPER(dxbr)(uint32_t f1, uint32_t f2)
210{
211 CPU_QuadU v1;
212 CPU_QuadU v2;
213 CPU_QuadU res;
214
215 v1.ll.upper = env->fregs[f1].ll;
216 v1.ll.lower = env->fregs[f1 + 2].ll;
217 v2.ll.upper = env->fregs[f2].ll;
218 v2.ll.lower = env->fregs[f2 + 2].ll;
219 res.q = float128_div(v1.q, v2.q, &env->fpu_status);
220 env->fregs[f1].ll = res.ll.upper;
221 env->fregs[f1 + 2].ll = res.ll.lower;
222}
223
224/* 64-bit FP multiplication RR */
225void HELPER(mdbr)(uint32_t f1, uint32_t f2)
226{
227 env->fregs[f1].d = float64_mul(env->fregs[f1].d, env->fregs[f2].d,
228 &env->fpu_status);
229}
230
231/* 128-bit FP multiplication RR */
232void HELPER(mxbr)(uint32_t f1, uint32_t f2)
233{
234 CPU_QuadU v1;
235 CPU_QuadU v2;
236 CPU_QuadU res;
237
238 v1.ll.upper = env->fregs[f1].ll;
239 v1.ll.lower = env->fregs[f1 + 2].ll;
240 v2.ll.upper = env->fregs[f2].ll;
241 v2.ll.lower = env->fregs[f2 + 2].ll;
242 res.q = float128_mul(v1.q, v2.q, &env->fpu_status);
243 env->fregs[f1].ll = res.ll.upper;
244 env->fregs[f1 + 2].ll = res.ll.lower;
245}
246
247/* convert 32-bit float to 64-bit float */
248void HELPER(ldebr)(uint32_t r1, uint32_t r2)
249{
250 env->fregs[r1].d = float32_to_float64(env->fregs[r2].l.upper,
251 &env->fpu_status);
252}
253
254/* convert 128-bit float to 64-bit float */
255void HELPER(ldxbr)(uint32_t f1, uint32_t f2)
256{
257 CPU_QuadU x2;
258
259 x2.ll.upper = env->fregs[f2].ll;
260 x2.ll.lower = env->fregs[f2 + 2].ll;
261 env->fregs[f1].d = float128_to_float64(x2.q, &env->fpu_status);
262 HELPER_LOG("%s: to 0x%ld\n", __func__, env->fregs[f1].d);
263}
264
265/* convert 64-bit float to 128-bit float */
266void HELPER(lxdbr)(uint32_t f1, uint32_t f2)
267{
268 CPU_QuadU res;
269
270 res.q = float64_to_float128(env->fregs[f2].d, &env->fpu_status);
271 env->fregs[f1].ll = res.ll.upper;
272 env->fregs[f1 + 2].ll = res.ll.lower;
273}
274
275/* convert 64-bit float to 32-bit float */
276void HELPER(ledbr)(uint32_t f1, uint32_t f2)
277{
278 float64 d2 = env->fregs[f2].d;
279
280 env->fregs[f1].l.upper = float64_to_float32(d2, &env->fpu_status);
281}
282
283/* convert 128-bit float to 32-bit float */
284void HELPER(lexbr)(uint32_t f1, uint32_t f2)
285{
286 CPU_QuadU x2;
287
288 x2.ll.upper = env->fregs[f2].ll;
289 x2.ll.lower = env->fregs[f2 + 2].ll;
290 env->fregs[f1].l.upper = float128_to_float32(x2.q, &env->fpu_status);
291 HELPER_LOG("%s: to 0x%d\n", __func__, env->fregs[f1].l.upper);
292}
293
294/* absolute value of 32-bit float */
295uint32_t HELPER(lpebr)(uint32_t f1, uint32_t f2)
296{
297 float32 v1;
298 float32 v2 = env->fregs[f2].d;
299
300 v1 = float32_abs(v2);
301 env->fregs[f1].d = v1;
302 return set_cc_nz_f32(v1);
303}
304
305/* absolute value of 64-bit float */
306uint32_t HELPER(lpdbr)(uint32_t f1, uint32_t f2)
307{
308 float64 v1;
309 float64 v2 = env->fregs[f2].d;
310
311 v1 = float64_abs(v2);
312 env->fregs[f1].d = v1;
313 return set_cc_nz_f64(v1);
314}
315
316/* absolute value of 128-bit float */
317uint32_t HELPER(lpxbr)(uint32_t f1, uint32_t f2)
318{
319 CPU_QuadU v1;
320 CPU_QuadU v2;
321
322 v2.ll.upper = env->fregs[f2].ll;
323 v2.ll.lower = env->fregs[f2 + 2].ll;
324 v1.q = float128_abs(v2.q);
325 env->fregs[f1].ll = v1.ll.upper;
326 env->fregs[f1 + 2].ll = v1.ll.lower;
327 return set_cc_nz_f128(v1.q);
328}
329
330/* load and test 64-bit float */
331uint32_t HELPER(ltdbr)(uint32_t f1, uint32_t f2)
332{
333 env->fregs[f1].d = env->fregs[f2].d;
334 return set_cc_nz_f64(env->fregs[f1].d);
335}
336
337/* load and test 32-bit float */
338uint32_t HELPER(ltebr)(uint32_t f1, uint32_t f2)
339{
340 env->fregs[f1].l.upper = env->fregs[f2].l.upper;
341 return set_cc_nz_f32(env->fregs[f1].l.upper);
342}
343
344/* load and test 128-bit float */
345uint32_t HELPER(ltxbr)(uint32_t f1, uint32_t f2)
346{
347 CPU_QuadU x;
348
349 x.ll.upper = env->fregs[f2].ll;
350 x.ll.lower = env->fregs[f2 + 2].ll;
351 env->fregs[f1].ll = x.ll.upper;
352 env->fregs[f1 + 2].ll = x.ll.lower;
353 return set_cc_nz_f128(x.q);
354}
355
356/* load complement of 32-bit float */
357uint32_t HELPER(lcebr)(uint32_t f1, uint32_t f2)
358{
359 env->fregs[f1].l.upper = float32_chs(env->fregs[f2].l.upper);
360
361 return set_cc_nz_f32(env->fregs[f1].l.upper);
362}
363
364/* load complement of 64-bit float */
365uint32_t HELPER(lcdbr)(uint32_t f1, uint32_t f2)
366{
367 env->fregs[f1].d = float64_chs(env->fregs[f2].d);
368
369 return set_cc_nz_f64(env->fregs[f1].d);
370}
371
372/* load complement of 128-bit float */
373uint32_t HELPER(lcxbr)(uint32_t f1, uint32_t f2)
374{
375 CPU_QuadU x1, x2;
376
377 x2.ll.upper = env->fregs[f2].ll;
378 x2.ll.lower = env->fregs[f2 + 2].ll;
379 x1.q = float128_chs(x2.q);
380 env->fregs[f1].ll = x1.ll.upper;
381 env->fregs[f1 + 2].ll = x1.ll.lower;
382 return set_cc_nz_f128(x1.q);
383}
384
385/* 32-bit FP addition RM */
386void HELPER(aeb)(uint32_t f1, uint32_t val)
387{
388 float32 v1 = env->fregs[f1].l.upper;
389 CPU_FloatU v2;
390
391 v2.l = val;
392 HELPER_LOG("%s: adding 0x%d from f%d and 0x%d\n", __func__,
393 v1, f1, v2.f);
394 env->fregs[f1].l.upper = float32_add(v1, v2.f, &env->fpu_status);
395}
396
397/* 32-bit FP division RM */
398void HELPER(deb)(uint32_t f1, uint32_t val)
399{
400 float32 v1 = env->fregs[f1].l.upper;
401 CPU_FloatU v2;
402
403 v2.l = val;
404 HELPER_LOG("%s: dividing 0x%d from f%d by 0x%d\n", __func__,
405 v1, f1, v2.f);
406 env->fregs[f1].l.upper = float32_div(v1, v2.f, &env->fpu_status);
407}
408
409/* 32-bit FP multiplication RM */
410void HELPER(meeb)(uint32_t f1, uint32_t val)
411{
412 float32 v1 = env->fregs[f1].l.upper;
413 CPU_FloatU v2;
414
415 v2.l = val;
416 HELPER_LOG("%s: multiplying 0x%d from f%d and 0x%d\n", __func__,
417 v1, f1, v2.f);
418 env->fregs[f1].l.upper = float32_mul(v1, v2.f, &env->fpu_status);
419}
420
421/* 32-bit FP compare RR */
422uint32_t HELPER(cebr)(uint32_t f1, uint32_t f2)
423{
424 float32 v1 = env->fregs[f1].l.upper;
425 float32 v2 = env->fregs[f2].l.upper;
426
427 HELPER_LOG("%s: comparing 0x%d from f%d and 0x%d\n", __func__,
428 v1, f1, v2);
429 return set_cc_f32(v1, v2);
430}
431
432/* 64-bit FP compare RR */
433uint32_t HELPER(cdbr)(uint32_t f1, uint32_t f2)
434{
435 float64 v1 = env->fregs[f1].d;
436 float64 v2 = env->fregs[f2].d;
437
438 HELPER_LOG("%s: comparing 0x%ld from f%d and 0x%ld\n", __func__,
439 v1, f1, v2);
440 return set_cc_f64(v1, v2);
441}
442
443/* 128-bit FP compare RR */
444uint32_t HELPER(cxbr)(uint32_t f1, uint32_t f2)
445{
446 CPU_QuadU v1;
447 CPU_QuadU v2;
448
449 v1.ll.upper = env->fregs[f1].ll;
450 v1.ll.lower = env->fregs[f1 + 2].ll;
451 v2.ll.upper = env->fregs[f2].ll;
452 v2.ll.lower = env->fregs[f2 + 2].ll;
453
454 return float_comp_to_cc(float128_compare_quiet(v1.q, v2.q,
455 &env->fpu_status));
456}
457
458/* 64-bit FP compare RM */
459uint32_t HELPER(cdb)(uint32_t f1, uint64_t a2)
460{
461 float64 v1 = env->fregs[f1].d;
462 CPU_DoubleU v2;
463
464 v2.ll = ldq(a2);
465 HELPER_LOG("%s: comparing 0x%ld from f%d and 0x%lx\n", __func__, v1,
466 f1, v2.d);
467 return set_cc_f64(v1, v2.d);
468}
469
470/* 64-bit FP addition RM */
471uint32_t HELPER(adb)(uint32_t f1, uint64_t a2)
472{
473 float64 v1 = env->fregs[f1].d;
474 CPU_DoubleU v2;
475
476 v2.ll = ldq(a2);
477 HELPER_LOG("%s: adding 0x%lx from f%d and 0x%lx\n", __func__,
478 v1, f1, v2.d);
479 env->fregs[f1].d = v1 = float64_add(v1, v2.d, &env->fpu_status);
480 return set_cc_nz_f64(v1);
481}
482
483/* 32-bit FP subtraction RM */
484void HELPER(seb)(uint32_t f1, uint32_t val)
485{
486 float32 v1 = env->fregs[f1].l.upper;
487 CPU_FloatU v2;
488
489 v2.l = val;
490 env->fregs[f1].l.upper = float32_sub(v1, v2.f, &env->fpu_status);
491}
492
493/* 64-bit FP subtraction RM */
494uint32_t HELPER(sdb)(uint32_t f1, uint64_t a2)
495{
496 float64 v1 = env->fregs[f1].d;
497 CPU_DoubleU v2;
498
499 v2.ll = ldq(a2);
500 env->fregs[f1].d = v1 = float64_sub(v1, v2.d, &env->fpu_status);
501 return set_cc_nz_f64(v1);
502}
503
504/* 64-bit FP multiplication RM */
505void HELPER(mdb)(uint32_t f1, uint64_t a2)
506{
507 float64 v1 = env->fregs[f1].d;
508 CPU_DoubleU v2;
509
510 v2.ll = ldq(a2);
511 HELPER_LOG("%s: multiplying 0x%lx from f%d and 0x%ld\n", __func__,
512 v1, f1, v2.d);
513 env->fregs[f1].d = float64_mul(v1, v2.d, &env->fpu_status);
514}
515
516/* 64-bit FP division RM */
517void HELPER(ddb)(uint32_t f1, uint64_t a2)
518{
519 float64 v1 = env->fregs[f1].d;
520 CPU_DoubleU v2;
521
522 v2.ll = ldq(a2);
523 HELPER_LOG("%s: dividing 0x%lx from f%d by 0x%ld\n", __func__,
524 v1, f1, v2.d);
525 env->fregs[f1].d = float64_div(v1, v2.d, &env->fpu_status);
526}
527
528static void set_round_mode(int m3)
529{
530 switch (m3) {
531 case 0:
532 /* current mode */
533 break;
534 case 1:
535 /* biased round no nearest */
536 case 4:
537 /* round to nearest */
538 set_float_rounding_mode(float_round_nearest_even, &env->fpu_status);
539 break;
540 case 5:
541 /* round to zero */
542 set_float_rounding_mode(float_round_to_zero, &env->fpu_status);
543 break;
544 case 6:
545 /* round to +inf */
546 set_float_rounding_mode(float_round_up, &env->fpu_status);
547 break;
548 case 7:
549 /* round to -inf */
550 set_float_rounding_mode(float_round_down, &env->fpu_status);
551 break;
552 }
553}
554
555/* convert 32-bit float to 64-bit int */
556uint32_t HELPER(cgebr)(uint32_t r1, uint32_t f2, uint32_t m3)
557{
558 float32 v2 = env->fregs[f2].l.upper;
559
560 set_round_mode(m3);
561 env->regs[r1] = float32_to_int64(v2, &env->fpu_status);
562 return set_cc_nz_f32(v2);
563}
564
565/* convert 64-bit float to 64-bit int */
566uint32_t HELPER(cgdbr)(uint32_t r1, uint32_t f2, uint32_t m3)
567{
568 float64 v2 = env->fregs[f2].d;
569
570 set_round_mode(m3);
571 env->regs[r1] = float64_to_int64(v2, &env->fpu_status);
572 return set_cc_nz_f64(v2);
573}
574
575/* convert 128-bit float to 64-bit int */
576uint32_t HELPER(cgxbr)(uint32_t r1, uint32_t f2, uint32_t m3)
577{
578 CPU_QuadU v2;
579
580 v2.ll.upper = env->fregs[f2].ll;
581 v2.ll.lower = env->fregs[f2 + 2].ll;
582 set_round_mode(m3);
583 env->regs[r1] = float128_to_int64(v2.q, &env->fpu_status);
584 if (float128_is_any_nan(v2.q)) {
585 return 3;
586 } else if (float128_is_zero(v2.q)) {
587 return 0;
588 } else if (float128_is_neg(v2.q)) {
589 return 1;
590 } else {
591 return 2;
592 }
593}
594
595/* convert 32-bit float to 32-bit int */
596uint32_t HELPER(cfebr)(uint32_t r1, uint32_t f2, uint32_t m3)
597{
598 float32 v2 = env->fregs[f2].l.upper;
599
600 set_round_mode(m3);
601 env->regs[r1] = (env->regs[r1] & 0xffffffff00000000ULL) |
602 float32_to_int32(v2, &env->fpu_status);
603 return set_cc_nz_f32(v2);
604}
605
606/* convert 64-bit float to 32-bit int */
607uint32_t HELPER(cfdbr)(uint32_t r1, uint32_t f2, uint32_t m3)
608{
609 float64 v2 = env->fregs[f2].d;
610
611 set_round_mode(m3);
612 env->regs[r1] = (env->regs[r1] & 0xffffffff00000000ULL) |
613 float64_to_int32(v2, &env->fpu_status);
614 return set_cc_nz_f64(v2);
615}
616
617/* convert 128-bit float to 32-bit int */
618uint32_t HELPER(cfxbr)(uint32_t r1, uint32_t f2, uint32_t m3)
619{
620 CPU_QuadU v2;
621
622 v2.ll.upper = env->fregs[f2].ll;
623 v2.ll.lower = env->fregs[f2 + 2].ll;
624 env->regs[r1] = (env->regs[r1] & 0xffffffff00000000ULL) |
625 float128_to_int32(v2.q, &env->fpu_status);
626 return set_cc_nz_f128(v2.q);
627}
628
629/* load 32-bit FP zero */
630void HELPER(lzer)(uint32_t f1)
631{
632 env->fregs[f1].l.upper = float32_zero;
633}
634
635/* load 64-bit FP zero */
636void HELPER(lzdr)(uint32_t f1)
637{
638 env->fregs[f1].d = float64_zero;
639}
640
641/* load 128-bit FP zero */
642void HELPER(lzxr)(uint32_t f1)
643{
644 CPU_QuadU x;
645
646 x.q = float64_to_float128(float64_zero, &env->fpu_status);
647 env->fregs[f1].ll = x.ll.upper;
648 env->fregs[f1 + 1].ll = x.ll.lower;
649}
650
651/* 128-bit FP subtraction RR */
652uint32_t HELPER(sxbr)(uint32_t f1, uint32_t f2)
653{
654 CPU_QuadU v1;
655 CPU_QuadU v2;
656 CPU_QuadU res;
657
658 v1.ll.upper = env->fregs[f1].ll;
659 v1.ll.lower = env->fregs[f1 + 2].ll;
660 v2.ll.upper = env->fregs[f2].ll;
661 v2.ll.lower = env->fregs[f2 + 2].ll;
662 res.q = float128_sub(v1.q, v2.q, &env->fpu_status);
663 env->fregs[f1].ll = res.ll.upper;
664 env->fregs[f1 + 2].ll = res.ll.lower;
665 return set_cc_nz_f128(res.q);
666}
667
668/* 128-bit FP addition RR */
669uint32_t HELPER(axbr)(uint32_t f1, uint32_t f2)
670{
671 CPU_QuadU v1;
672 CPU_QuadU v2;
673 CPU_QuadU res;
674
675 v1.ll.upper = env->fregs[f1].ll;
676 v1.ll.lower = env->fregs[f1 + 2].ll;
677 v2.ll.upper = env->fregs[f2].ll;
678 v2.ll.lower = env->fregs[f2 + 2].ll;
679 res.q = float128_add(v1.q, v2.q, &env->fpu_status);
680 env->fregs[f1].ll = res.ll.upper;
681 env->fregs[f1 + 2].ll = res.ll.lower;
682 return set_cc_nz_f128(res.q);
683}
684
685/* 32-bit FP multiplication RR */
686void HELPER(meebr)(uint32_t f1, uint32_t f2)
687{
688 env->fregs[f1].l.upper = float32_mul(env->fregs[f1].l.upper,
689 env->fregs[f2].l.upper,
690 &env->fpu_status);
691}
692
693/* 64-bit FP division RR */
694void HELPER(ddbr)(uint32_t f1, uint32_t f2)
695{
696 env->fregs[f1].d = float64_div(env->fregs[f1].d, env->fregs[f2].d,
697 &env->fpu_status);
698}
699
700/* 64-bit FP multiply and add RM */
701void HELPER(madb)(uint32_t f1, uint64_t a2, uint32_t f3)
702{
703 CPU_DoubleU v2;
704
705 HELPER_LOG("%s: f1 %d a2 0x%lx f3 %d\n", __func__, f1, a2, f3);
706 v2.ll = ldq(a2);
707 env->fregs[f1].d = float64_add(env->fregs[f1].d,
708 float64_mul(v2.d, env->fregs[f3].d,
709 &env->fpu_status),
710 &env->fpu_status);
711}
712
713/* 64-bit FP multiply and add RR */
714void HELPER(madbr)(uint32_t f1, uint32_t f3, uint32_t f2)
715{
716 HELPER_LOG("%s: f1 %d f2 %d f3 %d\n", __func__, f1, f2, f3);
717 env->fregs[f1].d = float64_add(float64_mul(env->fregs[f2].d,
718 env->fregs[f3].d,
719 &env->fpu_status),
720 env->fregs[f1].d, &env->fpu_status);
721}
722
723/* 64-bit FP multiply and subtract RR */
724void HELPER(msdbr)(uint32_t f1, uint32_t f3, uint32_t f2)
725{
726 HELPER_LOG("%s: f1 %d f2 %d f3 %d\n", __func__, f1, f2, f3);
727 env->fregs[f1].d = float64_sub(float64_mul(env->fregs[f2].d,
728 env->fregs[f3].d,
729 &env->fpu_status),
730 env->fregs[f1].d, &env->fpu_status);
731}
732
733/* 32-bit FP multiply and add RR */
734void HELPER(maebr)(uint32_t f1, uint32_t f3, uint32_t f2)
735{
736 env->fregs[f1].l.upper = float32_add(env->fregs[f1].l.upper,
737 float32_mul(env->fregs[f2].l.upper,
738 env->fregs[f3].l.upper,
739 &env->fpu_status),
740 &env->fpu_status);
741}
742
743/* convert 32-bit float to 64-bit float */
744void HELPER(ldeb)(uint32_t f1, uint64_t a2)
745{
746 uint32_t v2;
747
748 v2 = ldl(a2);
749 env->fregs[f1].d = float32_to_float64(v2,
750 &env->fpu_status);
751}
752
753/* convert 64-bit float to 128-bit float */
754void HELPER(lxdb)(uint32_t f1, uint64_t a2)
755{
756 CPU_DoubleU v2;
757 CPU_QuadU v1;
758
759 v2.ll = ldq(a2);
760 v1.q = float64_to_float128(v2.d, &env->fpu_status);
761 env->fregs[f1].ll = v1.ll.upper;
762 env->fregs[f1 + 2].ll = v1.ll.lower;
763}
764
765/* test data class 32-bit */
766uint32_t HELPER(tceb)(uint32_t f1, uint64_t m2)
767{
768 float32 v1 = env->fregs[f1].l.upper;
769 int neg = float32_is_neg(v1);
770 uint32_t cc = 0;
771
772 HELPER_LOG("%s: v1 0x%lx m2 0x%lx neg %d\n", __func__, (long)v1, m2, neg);
773 if ((float32_is_zero(v1) && (m2 & (1 << (11-neg)))) ||
774 (float32_is_infinity(v1) && (m2 & (1 << (5-neg)))) ||
775 (float32_is_any_nan(v1) && (m2 & (1 << (3-neg)))) ||
776 (float32_is_signaling_nan(v1) && (m2 & (1 << (1-neg))))) {
777 cc = 1;
778 } else if (m2 & (1 << (9-neg))) {
779 /* assume normalized number */
780 cc = 1;
781 }
782
783 /* FIXME: denormalized? */
784 return cc;
785}
786
787/* test data class 64-bit */
788uint32_t HELPER(tcdb)(uint32_t f1, uint64_t m2)
789{
790 float64 v1 = env->fregs[f1].d;
791 int neg = float64_is_neg(v1);
792 uint32_t cc = 0;
793
794 HELPER_LOG("%s: v1 0x%lx m2 0x%lx neg %d\n", __func__, v1, m2, neg);
795 if ((float64_is_zero(v1) && (m2 & (1 << (11-neg)))) ||
796 (float64_is_infinity(v1) && (m2 & (1 << (5-neg)))) ||
797 (float64_is_any_nan(v1) && (m2 & (1 << (3-neg)))) ||
798 (float64_is_signaling_nan(v1) && (m2 & (1 << (1-neg))))) {
799 cc = 1;
800 } else if (m2 & (1 << (9-neg))) {
801 /* assume normalized number */
802 cc = 1;
803 }
804 /* FIXME: denormalized? */
805 return cc;
806}
807
808/* test data class 128-bit */
809uint32_t HELPER(tcxb)(uint32_t f1, uint64_t m2)
810{
811 CPU_QuadU v1;
812 uint32_t cc = 0;
813 int neg;
814
815 v1.ll.upper = env->fregs[f1].ll;
816 v1.ll.lower = env->fregs[f1 + 2].ll;
817
818 neg = float128_is_neg(v1.q);
819 if ((float128_is_zero(v1.q) && (m2 & (1 << (11-neg)))) ||
820 (float128_is_infinity(v1.q) && (m2 & (1 << (5-neg)))) ||
821 (float128_is_any_nan(v1.q) && (m2 & (1 << (3-neg)))) ||
822 (float128_is_signaling_nan(v1.q) && (m2 & (1 << (1-neg))))) {
823 cc = 1;
824 } else if (m2 & (1 << (9-neg))) {
825 /* assume normalized number */
826 cc = 1;
827 }
828 /* FIXME: denormalized? */
829 return cc;
830}
831
832/* square root 64-bit RR */
833void HELPER(sqdbr)(uint32_t f1, uint32_t f2)
834{
835 env->fregs[f1].d = float64_sqrt(env->fregs[f2].d, &env->fpu_status);
836}