]> Git Repo - qemu.git/blame - target-s390x/fpu_helper.c
target-s390x: avoid AREG0 for misc helpers
[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"
e72ca652
BS
22#include "helper.h"
23
449c0d70
BS
24/* temporarily disabled due to wrapper use */
25#if 0 && !defined(CONFIG_USER_ONLY)
e72ca652
BS
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
449c0d70 36static inline int float_comp_to_cc(CPUS390XState *env, int float_compare)
e72ca652
BS
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 */
449c0d70 53uint32_t set_cc_f32(CPUS390XState *env, float32 v1, float32 v2)
e72ca652 54{
449c0d70
BS
55 return float_comp_to_cc(env, float32_compare_quiet(v1, v2,
56 &env->fpu_status));
e72ca652
BS
57}
58
449c0d70 59uint32_t set_cc_f64(CPUS390XState *env, float64 v1, float64 v2)
e72ca652 60{
449c0d70
BS
61 return float_comp_to_cc(env, float64_compare_quiet(v1, v2,
62 &env->fpu_status));
e72ca652
BS
63}
64
65/* condition codes for unary FP ops */
66uint32_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
79uint32_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
92static 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 */
449c0d70 106void HELPER(cdfbr)(CPUS390XState *env, uint32_t f1, int32_t v2)
e72ca652
BS
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 */
449c0d70 113void HELPER(cxfbr)(CPUS390XState *env, uint32_t f1, int32_t v2)
e72ca652
BS
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 */
449c0d70 123void HELPER(cegbr)(CPUS390XState *env, uint32_t f1, int64_t v2)
e72ca652
BS
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 */
449c0d70 130void HELPER(cdgbr)(CPUS390XState *env, uint32_t f1, int64_t v2)
e72ca652
BS
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 */
449c0d70 137void HELPER(cxgbr)(CPUS390XState *env, uint32_t f1, int64_t v2)
e72ca652
BS
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 */
449c0d70 149void HELPER(cefbr)(CPUS390XState *env, uint32_t f1, int32_t v2)
e72ca652
BS
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 */
449c0d70 157uint32_t HELPER(aebr)(CPUS390XState *env, uint32_t f1, uint32_t f2)
e72ca652
BS
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 */
449c0d70 169uint32_t HELPER(adbr)(CPUS390XState *env, uint32_t f1, uint32_t f2)
e72ca652
BS
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 */
449c0d70 180uint32_t HELPER(sebr)(CPUS390XState *env, uint32_t f1, uint32_t f2)
e72ca652
BS
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 */
449c0d70 192uint32_t HELPER(sdbr)(CPUS390XState *env, uint32_t f1, uint32_t f2)
e72ca652
BS
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 */
449c0d70 203void HELPER(debr)(CPUS390XState *env, uint32_t f1, uint32_t f2)
e72ca652
BS
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 */
449c0d70 211void HELPER(dxbr)(CPUS390XState *env, uint32_t f1, uint32_t f2)
e72ca652
BS
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 */
449c0d70 227void HELPER(mdbr)(CPUS390XState *env, uint32_t f1, uint32_t f2)
e72ca652
BS
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 */
449c0d70 234void HELPER(mxbr)(CPUS390XState *env, uint32_t f1, uint32_t f2)
e72ca652
BS
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 */
449c0d70 250void HELPER(ldebr)(CPUS390XState *env, uint32_t r1, uint32_t r2)
e72ca652
BS
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 */
449c0d70 257void HELPER(ldxbr)(CPUS390XState *env, uint32_t f1, uint32_t f2)
e72ca652
BS
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 */
449c0d70 268void HELPER(lxdbr)(CPUS390XState *env, uint32_t f1, uint32_t f2)
e72ca652
BS
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 */
449c0d70 278void HELPER(ledbr)(CPUS390XState *env, uint32_t f1, uint32_t f2)
e72ca652
BS
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 */
449c0d70 286void HELPER(lexbr)(CPUS390XState *env, uint32_t f1, uint32_t f2)
e72ca652
BS
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 */
449c0d70 297uint32_t HELPER(lpebr)(CPUS390XState *env, uint32_t f1, uint32_t f2)
e72ca652
BS
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 */
449c0d70 308uint32_t HELPER(lpdbr)(CPUS390XState *env, uint32_t f1, uint32_t f2)
e72ca652
BS
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 */
449c0d70 319uint32_t HELPER(lpxbr)(CPUS390XState *env, uint32_t f1, uint32_t f2)
e72ca652
BS
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 */
449c0d70 333uint32_t HELPER(ltdbr)(CPUS390XState *env, uint32_t f1, uint32_t f2)
e72ca652
BS
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 */
449c0d70 340uint32_t HELPER(ltebr)(CPUS390XState *env, uint32_t f1, uint32_t f2)
e72ca652
BS
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 */
449c0d70 347uint32_t HELPER(ltxbr)(CPUS390XState *env, uint32_t f1, uint32_t f2)
e72ca652
BS
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 */
449c0d70 359uint32_t HELPER(lcebr)(CPUS390XState *env, uint32_t f1, uint32_t f2)
e72ca652
BS
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 */
449c0d70 367uint32_t HELPER(lcdbr)(CPUS390XState *env, uint32_t f1, uint32_t f2)
e72ca652
BS
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 */
449c0d70 375uint32_t HELPER(lcxbr)(CPUS390XState *env, uint32_t f1, uint32_t f2)
e72ca652
BS
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 */
449c0d70 388void HELPER(aeb)(CPUS390XState *env, uint32_t f1, uint32_t val)
e72ca652
BS
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 */
449c0d70 400void HELPER(deb)(CPUS390XState *env, uint32_t f1, uint32_t val)
e72ca652
BS
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 */
449c0d70 412void HELPER(meeb)(CPUS390XState *env, uint32_t f1, uint32_t val)
e72ca652
BS
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 */
449c0d70 424uint32_t HELPER(cebr)(CPUS390XState *env, uint32_t f1, uint32_t f2)
e72ca652
BS
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);
449c0d70 431 return set_cc_f32(env, v1, v2);
e72ca652
BS
432}
433
434/* 64-bit FP compare RR */
449c0d70 435uint32_t HELPER(cdbr)(CPUS390XState *env, uint32_t f1, uint32_t f2)
e72ca652
BS
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);
449c0d70 442 return set_cc_f64(env, v1, v2);
e72ca652
BS
443}
444
445/* 128-bit FP compare RR */
449c0d70 446uint32_t HELPER(cxbr)(CPUS390XState *env, uint32_t f1, uint32_t f2)
e72ca652
BS
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
449c0d70 456 return float_comp_to_cc(env, float128_compare_quiet(v1.q, v2.q,
e72ca652
BS
457 &env->fpu_status));
458}
459
460/* 64-bit FP compare RM */
449c0d70 461uint32_t HELPER(cdb)(CPUS390XState *env, uint32_t f1, uint64_t a2)
e72ca652
BS
462{
463 float64 v1 = env->fregs[f1].d;
464 CPU_DoubleU v2;
465
449c0d70 466 v2.ll = cpu_ldq_data(env, a2);
e72ca652
BS
467 HELPER_LOG("%s: comparing 0x%ld from f%d and 0x%lx\n", __func__, v1,
468 f1, v2.d);
449c0d70 469 return set_cc_f64(env, v1, v2.d);
e72ca652
BS
470}
471
472/* 64-bit FP addition RM */
449c0d70 473uint32_t HELPER(adb)(CPUS390XState *env, uint32_t f1, uint64_t a2)
e72ca652
BS
474{
475 float64 v1 = env->fregs[f1].d;
476 CPU_DoubleU v2;
477
449c0d70 478 v2.ll = cpu_ldq_data(env, a2);
e72ca652
BS
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 */
449c0d70 486void HELPER(seb)(CPUS390XState *env, uint32_t f1, uint32_t val)
e72ca652
BS
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 */
449c0d70 496uint32_t HELPER(sdb)(CPUS390XState *env, uint32_t f1, uint64_t a2)
e72ca652
BS
497{
498 float64 v1 = env->fregs[f1].d;
499 CPU_DoubleU v2;
500
449c0d70 501 v2.ll = cpu_ldq_data(env, a2);
e72ca652
BS
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 */
449c0d70 507void HELPER(mdb)(CPUS390XState *env, uint32_t f1, uint64_t a2)
e72ca652
BS
508{
509 float64 v1 = env->fregs[f1].d;
510 CPU_DoubleU v2;
511
449c0d70 512 v2.ll = cpu_ldq_data(env, a2);
e72ca652
BS
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 */
449c0d70 519void HELPER(ddb)(CPUS390XState *env, uint32_t f1, uint64_t a2)
e72ca652
BS
520{
521 float64 v1 = env->fregs[f1].d;
522 CPU_DoubleU v2;
523
449c0d70 524 v2.ll = cpu_ldq_data(env, a2);
e72ca652
BS
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
449c0d70 530static void set_round_mode(CPUS390XState *env, int m3)
e72ca652
BS
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 */
449c0d70
BS
558uint32_t HELPER(cgebr)(CPUS390XState *env, uint32_t r1, uint32_t f2,
559 uint32_t m3)
e72ca652
BS
560{
561 float32 v2 = env->fregs[f2].l.upper;
562
449c0d70 563 set_round_mode(env, m3);
e72ca652
BS
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 */
449c0d70
BS
569uint32_t HELPER(cgdbr)(CPUS390XState *env, uint32_t r1, uint32_t f2,
570 uint32_t m3)
e72ca652
BS
571{
572 float64 v2 = env->fregs[f2].d;
573
449c0d70 574 set_round_mode(env, m3);
e72ca652
BS
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 */
449c0d70
BS
580uint32_t HELPER(cgxbr)(CPUS390XState *env, uint32_t r1, uint32_t f2,
581 uint32_t m3)
e72ca652
BS
582{
583 CPU_QuadU v2;
584
585 v2.ll.upper = env->fregs[f2].ll;
586 v2.ll.lower = env->fregs[f2 + 2].ll;
449c0d70 587 set_round_mode(env, m3);
e72ca652
BS
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 */
449c0d70
BS
601uint32_t HELPER(cfebr)(CPUS390XState *env, uint32_t r1, uint32_t f2,
602 uint32_t m3)
e72ca652
BS
603{
604 float32 v2 = env->fregs[f2].l.upper;
605
449c0d70 606 set_round_mode(env, m3);
e72ca652
BS
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 */
449c0d70
BS
613uint32_t HELPER(cfdbr)(CPUS390XState *env, uint32_t r1, uint32_t f2,
614 uint32_t m3)
e72ca652
BS
615{
616 float64 v2 = env->fregs[f2].d;
617
449c0d70 618 set_round_mode(env, m3);
e72ca652
BS
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 */
449c0d70
BS
625uint32_t HELPER(cfxbr)(CPUS390XState *env, uint32_t r1, uint32_t f2,
626 uint32_t m3)
e72ca652
BS
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 */
449c0d70 638void HELPER(lzer)(CPUS390XState *env, uint32_t f1)
e72ca652
BS
639{
640 env->fregs[f1].l.upper = float32_zero;
641}
642
643/* load 64-bit FP zero */
449c0d70 644void HELPER(lzdr)(CPUS390XState *env, uint32_t f1)
e72ca652
BS
645{
646 env->fregs[f1].d = float64_zero;
647}
648
649/* load 128-bit FP zero */
449c0d70 650void HELPER(lzxr)(CPUS390XState *env, uint32_t f1)
e72ca652
BS
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 */
449c0d70 660uint32_t HELPER(sxbr)(CPUS390XState *env, uint32_t f1, uint32_t f2)
e72ca652
BS
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 */
449c0d70 677uint32_t HELPER(axbr)(CPUS390XState *env, uint32_t f1, uint32_t f2)
e72ca652
BS
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 */
449c0d70 694void HELPER(meebr)(CPUS390XState *env, uint32_t f1, uint32_t f2)
e72ca652
BS
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 */
449c0d70 702void HELPER(ddbr)(CPUS390XState *env, uint32_t f1, uint32_t f2)
e72ca652
BS
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 */
449c0d70 709void HELPER(madb)(CPUS390XState *env, uint32_t f1, uint64_t a2, uint32_t f3)
e72ca652
BS
710{
711 CPU_DoubleU v2;
712
713 HELPER_LOG("%s: f1 %d a2 0x%lx f3 %d\n", __func__, f1, a2, f3);
449c0d70 714 v2.ll = cpu_ldq_data(env, a2);
e72ca652
BS
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 */
449c0d70 722void HELPER(madbr)(CPUS390XState *env, uint32_t f1, uint32_t f3, uint32_t f2)
e72ca652
BS
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 */
449c0d70 732void HELPER(msdbr)(CPUS390XState *env, uint32_t f1, uint32_t f3, uint32_t f2)
e72ca652
BS
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 */
449c0d70 742void HELPER(maebr)(CPUS390XState *env, uint32_t f1, uint32_t f3, uint32_t f2)
e72ca652
BS
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 */
449c0d70 752void HELPER(ldeb)(CPUS390XState *env, uint32_t f1, uint64_t a2)
e72ca652
BS
753{
754 uint32_t v2;
755
449c0d70 756 v2 = cpu_ldl_data(env, a2);
e72ca652
BS
757 env->fregs[f1].d = float32_to_float64(v2,
758 &env->fpu_status);
759}
760
761/* convert 64-bit float to 128-bit float */
449c0d70 762void HELPER(lxdb)(CPUS390XState *env, uint32_t f1, uint64_t a2)
e72ca652
BS
763{
764 CPU_DoubleU v2;
765 CPU_QuadU v1;
766
449c0d70 767 v2.ll = cpu_ldq_data(env, a2);
e72ca652
BS
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 */
449c0d70 774uint32_t HELPER(tceb)(CPUS390XState *env, uint32_t f1, uint64_t m2)
e72ca652
BS
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 */
449c0d70 796uint32_t HELPER(tcdb)(CPUS390XState *env, uint32_t f1, uint64_t m2)
e72ca652
BS
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 */
449c0d70 817uint32_t HELPER(tcxb)(CPUS390XState *env, uint32_t f1, uint64_t m2)
e72ca652
BS
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 */
449c0d70 841void HELPER(sqdbr)(CPUS390XState *env, uint32_t f1, uint32_t f2)
e72ca652
BS
842{
843 env->fregs[f1].d = float64_sqrt(env->fregs[f2].d, &env->fpu_status);
844}
This page took 0.120716 seconds and 4 git commands to generate.