Statistics
| Branch: | Revision:

root / target-s390x / fpu_helper.c @ 722bfec3

History | View | Annotate | Download (19.4 kB)

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
#if !defined(CONFIG_USER_ONLY)
25
#include "exec/softmmu_exec.h"
26
#endif
27

    
28
/* #define DEBUG_HELPER */
29
#ifdef DEBUG_HELPER
30
#define HELPER_LOG(x...) qemu_log(x)
31
#else
32
#define HELPER_LOG(x...)
33
#endif
34

    
35
#define RET128(F) (env->retxl = F.low, F.high)
36

    
37
#define convert_bit(mask, from, to) \
38
    (to < from                      \
39
     ? (mask / (from / to)) & to    \
40
     : (mask & from) * (to / from))
41

    
42
static void ieee_exception(CPUS390XState *env, uint32_t dxc, uintptr_t retaddr)
43
{
44
    /* Install the DXC code.  */
45
    env->fpc = (env->fpc & ~0xff00) | (dxc << 8);
46
    /* Trap.  */
47
    runtime_exception(env, PGM_DATA, retaddr);
48
}
49

    
50
/* Should be called after any operation that may raise IEEE exceptions.  */
51
static void handle_exceptions(CPUS390XState *env, uintptr_t retaddr)
52
{
53
    unsigned s390_exc, qemu_exc;
54

    
55
    /* Get the exceptions raised by the current operation.  Reset the
56
       fpu_status contents so that the next operation has a clean slate.  */
57
    qemu_exc = env->fpu_status.float_exception_flags;
58
    if (qemu_exc == 0) {
59
        return;
60
    }
61
    env->fpu_status.float_exception_flags = 0;
62

    
63
    /* Convert softfloat exception bits to s390 exception bits.  */
64
    s390_exc = 0;
65
    s390_exc |= convert_bit(qemu_exc, float_flag_invalid, 0x80);
66
    s390_exc |= convert_bit(qemu_exc, float_flag_divbyzero, 0x40);
67
    s390_exc |= convert_bit(qemu_exc, float_flag_overflow, 0x20);
68
    s390_exc |= convert_bit(qemu_exc, float_flag_underflow, 0x10);
69
    s390_exc |= convert_bit(qemu_exc, float_flag_inexact, 0x08);
70

    
71
    /* Install the exceptions that we raised.  */
72
    env->fpc |= s390_exc << 16;
73

    
74
    /* Send signals for enabled exceptions.  */
75
    s390_exc &= env->fpc >> 24;
76
    if (s390_exc) {
77
        ieee_exception(env, s390_exc, retaddr);
78
    }
79
}
80

    
81
static inline int float_comp_to_cc(CPUS390XState *env, int float_compare)
82
{
83
    switch (float_compare) {
84
    case float_relation_equal:
85
        return 0;
86
    case float_relation_less:
87
        return 1;
88
    case float_relation_greater:
89
        return 2;
90
    case float_relation_unordered:
91
        return 3;
92
    default:
93
        cpu_abort(env, "unknown return value for float compare\n");
94
    }
95
}
96

    
97
/* condition codes for unary FP ops */
98
uint32_t set_cc_nz_f32(float32 v)
99
{
100
    if (float32_is_any_nan(v)) {
101
        return 3;
102
    } else if (float32_is_zero(v)) {
103
        return 0;
104
    } else if (float32_is_neg(v)) {
105
        return 1;
106
    } else {
107
        return 2;
108
    }
109
}
110

    
111
uint32_t set_cc_nz_f64(float64 v)
112
{
113
    if (float64_is_any_nan(v)) {
114
        return 3;
115
    } else if (float64_is_zero(v)) {
116
        return 0;
117
    } else if (float64_is_neg(v)) {
118
        return 1;
119
    } else {
120
        return 2;
121
    }
122
}
123

    
124
uint32_t set_cc_nz_f128(float128 v)
125
{
126
    if (float128_is_any_nan(v)) {
127
        return 3;
128
    } else if (float128_is_zero(v)) {
129
        return 0;
130
    } else if (float128_is_neg(v)) {
131
        return 1;
132
    } else {
133
        return 2;
134
    }
135
}
136

    
137
/* convert 32-bit int to 64-bit float */
138
void HELPER(cdfbr)(CPUS390XState *env, uint32_t f1, int32_t v2)
139
{
140
    HELPER_LOG("%s: converting %d to f%d\n", __func__, v2, f1);
141
    env->fregs[f1].d = int32_to_float64(v2, &env->fpu_status);
142
}
143

    
144
/* convert 32-bit int to 128-bit float */
145
void HELPER(cxfbr)(CPUS390XState *env, uint32_t f1, int32_t v2)
146
{
147
    CPU_QuadU v1;
148

    
149
    v1.q = int32_to_float128(v2, &env->fpu_status);
150
    env->fregs[f1].ll = v1.ll.upper;
151
    env->fregs[f1 + 2].ll = v1.ll.lower;
152
}
153

    
154
/* convert 64-bit int to 32-bit float */
155
void HELPER(cegbr)(CPUS390XState *env, uint32_t f1, int64_t v2)
156
{
157
    HELPER_LOG("%s: converting %ld to f%d\n", __func__, v2, f1);
158
    env->fregs[f1].l.upper = int64_to_float32(v2, &env->fpu_status);
159
}
160

    
161
/* convert 64-bit int to 64-bit float */
162
void HELPER(cdgbr)(CPUS390XState *env, uint32_t f1, int64_t v2)
163
{
164
    HELPER_LOG("%s: converting %ld to f%d\n", __func__, v2, f1);
165
    env->fregs[f1].d = int64_to_float64(v2, &env->fpu_status);
166
}
167

    
168
/* convert 64-bit int to 128-bit float */
169
void HELPER(cxgbr)(CPUS390XState *env, uint32_t f1, int64_t v2)
170
{
171
    CPU_QuadU x1;
172

    
173
    x1.q = int64_to_float128(v2, &env->fpu_status);
174
    HELPER_LOG("%s: converted %ld to 0x%lx and 0x%lx\n", __func__, v2,
175
               x1.ll.upper, x1.ll.lower);
176
    env->fregs[f1].ll = x1.ll.upper;
177
    env->fregs[f1 + 2].ll = x1.ll.lower;
178
}
179

    
180
/* convert 32-bit int to 32-bit float */
181
void HELPER(cefbr)(CPUS390XState *env, uint32_t f1, int32_t v2)
182
{
183
    env->fregs[f1].l.upper = int32_to_float32(v2, &env->fpu_status);
184
    HELPER_LOG("%s: converting %d to 0x%d in f%d\n", __func__, v2,
185
               env->fregs[f1].l.upper, f1);
186
}
187

    
188
/* 32-bit FP addition */
189
uint64_t HELPER(aeb)(CPUS390XState *env, uint64_t f1, uint64_t f2)
190
{
191
    float32 ret = float32_add(f1, f2, &env->fpu_status);
192
    handle_exceptions(env, GETPC());
193
    return ret;
194
}
195

    
196
/* 64-bit FP addition */
197
uint64_t HELPER(adb)(CPUS390XState *env, uint64_t f1, uint64_t f2)
198
{
199
    float64 ret = float64_add(f1, f2, &env->fpu_status);
200
    handle_exceptions(env, GETPC());
201
    return ret;
202
}
203

    
204
/* 128-bit FP addition */
205
uint64_t HELPER(axb)(CPUS390XState *env, uint64_t ah, uint64_t al,
206
                     uint64_t bh, uint64_t bl)
207
{
208
    float128 ret = float128_add(make_float128(ah, al),
209
                                make_float128(bh, bl),
210
                                &env->fpu_status);
211
    handle_exceptions(env, GETPC());
212
    return RET128(ret);
213
}
214

    
215
/* 32-bit FP subtraction */
216
uint64_t HELPER(seb)(CPUS390XState *env, uint64_t f1, uint64_t f2)
217
{
218
    float32 ret = float32_sub(f1, f2, &env->fpu_status);
219
    handle_exceptions(env, GETPC());
220
    return ret;
221
}
222

    
223
/* 64-bit FP subtraction */
224
uint64_t HELPER(sdb)(CPUS390XState *env, uint64_t f1, uint64_t f2)
225
{
226
    float64 ret = float64_sub(f1, f2, &env->fpu_status);
227
    handle_exceptions(env, GETPC());
228
    return ret;
229
}
230

    
231
/* 128-bit FP subtraction */
232
uint64_t HELPER(sxb)(CPUS390XState *env, uint64_t ah, uint64_t al,
233
                     uint64_t bh, uint64_t bl)
234
{
235
    float128 ret = float128_sub(make_float128(ah, al),
236
                                make_float128(bh, bl),
237
                                &env->fpu_status);
238
    handle_exceptions(env, GETPC());
239
    return RET128(ret);
240
}
241

    
242
/* 32-bit FP division */
243
uint64_t HELPER(deb)(CPUS390XState *env, uint64_t f1, uint64_t f2)
244
{
245
    float32 ret = float32_div(f1, f2, &env->fpu_status);
246
    handle_exceptions(env, GETPC());
247
    return ret;
248
}
249

    
250
/* 64-bit FP division */
251
uint64_t HELPER(ddb)(CPUS390XState *env, uint64_t f1, uint64_t f2)
252
{
253
    float64 ret = float64_div(f1, f2, &env->fpu_status);
254
    handle_exceptions(env, GETPC());
255
    return ret;
256
}
257

    
258
/* 128-bit FP division */
259
uint64_t HELPER(dxb)(CPUS390XState *env, uint64_t ah, uint64_t al,
260
                     uint64_t bh, uint64_t bl)
261
{
262
    float128 ret = float128_div(make_float128(ah, al),
263
                                make_float128(bh, bl),
264
                                &env->fpu_status);
265
    handle_exceptions(env, GETPC());
266
    return RET128(ret);
267
}
268

    
269
/* 32-bit FP multiplication */
270
uint64_t HELPER(meeb)(CPUS390XState *env, uint64_t f1, uint64_t f2)
271
{
272
    float32 ret = float32_mul(f1, f2, &env->fpu_status);
273
    handle_exceptions(env, GETPC());
274
    return ret;
275
}
276

    
277
/* 64-bit FP multiplication */
278
uint64_t HELPER(mdb)(CPUS390XState *env, uint64_t f1, uint64_t f2)
279
{
280
    float64 ret = float64_mul(f1, f2, &env->fpu_status);
281
    handle_exceptions(env, GETPC());
282
    return ret;
283
}
284

    
285
/* 64/32-bit FP multiplication */
286
uint64_t HELPER(mdeb)(CPUS390XState *env, uint64_t f1, uint64_t f2)
287
{
288
    float64 ret = float32_to_float64(f2, &env->fpu_status);
289
    ret = float64_mul(f1, ret, &env->fpu_status);
290
    handle_exceptions(env, GETPC());
291
    return ret;
292
}
293

    
294
/* 128-bit FP multiplication */
295
uint64_t HELPER(mxb)(CPUS390XState *env, uint64_t ah, uint64_t al,
296
                     uint64_t bh, uint64_t bl)
297
{
298
    float128 ret = float128_mul(make_float128(ah, al),
299
                                make_float128(bh, bl),
300
                                &env->fpu_status);
301
    handle_exceptions(env, GETPC());
302
    return RET128(ret);
303
}
304

    
305
/* 128/64-bit FP multiplication */
306
uint64_t HELPER(mxdb)(CPUS390XState *env, uint64_t ah, uint64_t al,
307
                      uint64_t f2)
308
{
309
    float128 ret = float64_to_float128(f2, &env->fpu_status);
310
    ret = float128_mul(make_float128(ah, al), ret, &env->fpu_status);
311
    handle_exceptions(env, GETPC());
312
    return RET128(ret);
313
}
314

    
315
/* convert 32-bit float to 64-bit float */
316
uint64_t HELPER(ldeb)(CPUS390XState *env, uint64_t f2)
317
{
318
    float64 ret = float32_to_float64(f2, &env->fpu_status);
319
    handle_exceptions(env, GETPC());
320
    return ret;
321
}
322

    
323
/* convert 128-bit float to 64-bit float */
324
uint64_t HELPER(ldxb)(CPUS390XState *env, uint64_t ah, uint64_t al)
325
{
326
    float64 ret = float128_to_float64(make_float128(ah, al), &env->fpu_status);
327
    handle_exceptions(env, GETPC());
328
    return ret;
329
}
330

    
331
/* convert 64-bit float to 128-bit float */
332
uint64_t HELPER(lxdb)(CPUS390XState *env, uint64_t f2)
333
{
334
    float128 ret = float64_to_float128(f2, &env->fpu_status);
335
    handle_exceptions(env, GETPC());
336
    return RET128(ret);
337
}
338

    
339
/* convert 32-bit float to 128-bit float */
340
uint64_t HELPER(lxeb)(CPUS390XState *env, uint64_t f2)
341
{
342
    float128 ret = float32_to_float128(f2, &env->fpu_status);
343
    handle_exceptions(env, GETPC());
344
    return RET128(ret);
345
}
346

    
347
/* convert 64-bit float to 32-bit float */
348
uint64_t HELPER(ledb)(CPUS390XState *env, uint64_t f2)
349
{
350
    float32 ret = float64_to_float32(f2, &env->fpu_status);
351
    handle_exceptions(env, GETPC());
352
    return ret;
353
}
354

    
355
/* convert 128-bit float to 32-bit float */
356
uint64_t HELPER(lexb)(CPUS390XState *env, uint64_t ah, uint64_t al)
357
{
358
    float32 ret = float128_to_float32(make_float128(ah, al), &env->fpu_status);
359
    handle_exceptions(env, GETPC());
360
    return ret;
361
}
362

    
363
/* absolute value of 32-bit float */
364
uint32_t HELPER(lpebr)(CPUS390XState *env, uint32_t f1, uint32_t f2)
365
{
366
    float32 v1;
367
    float32 v2 = env->fregs[f2].d;
368

    
369
    v1 = float32_abs(v2);
370
    env->fregs[f1].d = v1;
371
    return set_cc_nz_f32(v1);
372
}
373

    
374
/* absolute value of 64-bit float */
375
uint32_t HELPER(lpdbr)(CPUS390XState *env, uint32_t f1, uint32_t f2)
376
{
377
    float64 v1;
378
    float64 v2 = env->fregs[f2].d;
379

    
380
    v1 = float64_abs(v2);
381
    env->fregs[f1].d = v1;
382
    return set_cc_nz_f64(v1);
383
}
384

    
385
/* absolute value of 128-bit float */
386
uint32_t HELPER(lpxbr)(CPUS390XState *env, uint32_t f1, uint32_t f2)
387
{
388
    CPU_QuadU v1;
389
    CPU_QuadU v2;
390

    
391
    v2.ll.upper = env->fregs[f2].ll;
392
    v2.ll.lower = env->fregs[f2 + 2].ll;
393
    v1.q = float128_abs(v2.q);
394
    env->fregs[f1].ll = v1.ll.upper;
395
    env->fregs[f1 + 2].ll = v1.ll.lower;
396
    return set_cc_nz_f128(v1.q);
397
}
398

    
399
/* load complement of 32-bit float */
400
uint32_t HELPER(lcebr)(CPUS390XState *env, uint32_t f1, uint32_t f2)
401
{
402
    env->fregs[f1].l.upper = float32_chs(env->fregs[f2].l.upper);
403

    
404
    return set_cc_nz_f32(env->fregs[f1].l.upper);
405
}
406

    
407
/* load complement of 64-bit float */
408
uint32_t HELPER(lcdbr)(CPUS390XState *env, uint32_t f1, uint32_t f2)
409
{
410
    env->fregs[f1].d = float64_chs(env->fregs[f2].d);
411

    
412
    return set_cc_nz_f64(env->fregs[f1].d);
413
}
414

    
415
/* load complement of 128-bit float */
416
uint32_t HELPER(lcxbr)(CPUS390XState *env, uint32_t f1, uint32_t f2)
417
{
418
    CPU_QuadU x1, x2;
419

    
420
    x2.ll.upper = env->fregs[f2].ll;
421
    x2.ll.lower = env->fregs[f2 + 2].ll;
422
    x1.q = float128_chs(x2.q);
423
    env->fregs[f1].ll = x1.ll.upper;
424
    env->fregs[f1 + 2].ll = x1.ll.lower;
425
    return set_cc_nz_f128(x1.q);
426
}
427

    
428
/* 32-bit FP compare */
429
uint32_t HELPER(ceb)(CPUS390XState *env, uint64_t f1, uint64_t f2)
430
{
431
    int cmp = float32_compare_quiet(f1, f2, &env->fpu_status);
432
    handle_exceptions(env, GETPC());
433
    return float_comp_to_cc(env, cmp);
434
}
435

    
436
/* 64-bit FP compare */
437
uint32_t HELPER(cdb)(CPUS390XState *env, uint64_t f1, uint64_t f2)
438
{
439
    int cmp = float64_compare_quiet(f1, f2, &env->fpu_status);
440
    handle_exceptions(env, GETPC());
441
    return float_comp_to_cc(env, cmp);
442
}
443

    
444
/* 128-bit FP compare */
445
uint32_t HELPER(cxb)(CPUS390XState *env, uint64_t ah, uint64_t al,
446
                     uint64_t bh, uint64_t bl)
447
{
448
    int cmp = float128_compare_quiet(make_float128(ah, al),
449
                                     make_float128(bh, bl),
450
                                     &env->fpu_status);
451
    handle_exceptions(env, GETPC());
452
    return float_comp_to_cc(env, cmp);
453
}
454

    
455
static void set_round_mode(CPUS390XState *env, int m3)
456
{
457
    switch (m3) {
458
    case 0:
459
        /* current mode */
460
        break;
461
    case 1:
462
        /* biased round no nearest */
463
    case 4:
464
        /* round to nearest */
465
        set_float_rounding_mode(float_round_nearest_even, &env->fpu_status);
466
        break;
467
    case 5:
468
        /* round to zero */
469
        set_float_rounding_mode(float_round_to_zero, &env->fpu_status);
470
        break;
471
    case 6:
472
        /* round to +inf */
473
        set_float_rounding_mode(float_round_up, &env->fpu_status);
474
        break;
475
    case 7:
476
        /* round to -inf */
477
        set_float_rounding_mode(float_round_down, &env->fpu_status);
478
        break;
479
    }
480
}
481

    
482
/* convert 32-bit float to 64-bit int */
483
uint32_t HELPER(cgebr)(CPUS390XState *env, uint32_t r1, uint32_t f2,
484
                       uint32_t m3)
485
{
486
    float32 v2 = env->fregs[f2].l.upper;
487

    
488
    set_round_mode(env, m3);
489
    env->regs[r1] = float32_to_int64(v2, &env->fpu_status);
490
    return set_cc_nz_f32(v2);
491
}
492

    
493
/* convert 64-bit float to 64-bit int */
494
uint32_t HELPER(cgdbr)(CPUS390XState *env, uint32_t r1, uint32_t f2,
495
                       uint32_t m3)
496
{
497
    float64 v2 = env->fregs[f2].d;
498

    
499
    set_round_mode(env, m3);
500
    env->regs[r1] = float64_to_int64(v2, &env->fpu_status);
501
    return set_cc_nz_f64(v2);
502
}
503

    
504
/* convert 128-bit float to 64-bit int */
505
uint32_t HELPER(cgxbr)(CPUS390XState *env, uint32_t r1, uint32_t f2,
506
                       uint32_t m3)
507
{
508
    CPU_QuadU v2;
509

    
510
    v2.ll.upper = env->fregs[f2].ll;
511
    v2.ll.lower = env->fregs[f2 + 2].ll;
512
    set_round_mode(env, m3);
513
    env->regs[r1] = float128_to_int64(v2.q, &env->fpu_status);
514
    if (float128_is_any_nan(v2.q)) {
515
        return 3;
516
    } else if (float128_is_zero(v2.q)) {
517
        return 0;
518
    } else if (float128_is_neg(v2.q)) {
519
        return 1;
520
    } else {
521
        return 2;
522
    }
523
}
524

    
525
/* convert 32-bit float to 32-bit int */
526
uint32_t HELPER(cfebr)(CPUS390XState *env, uint32_t r1, uint32_t f2,
527
                       uint32_t m3)
528
{
529
    float32 v2 = env->fregs[f2].l.upper;
530

    
531
    set_round_mode(env, m3);
532
    env->regs[r1] = (env->regs[r1] & 0xffffffff00000000ULL) |
533
        float32_to_int32(v2, &env->fpu_status);
534
    return set_cc_nz_f32(v2);
535
}
536

    
537
/* convert 64-bit float to 32-bit int */
538
uint32_t HELPER(cfdbr)(CPUS390XState *env, uint32_t r1, uint32_t f2,
539
                       uint32_t m3)
540
{
541
    float64 v2 = env->fregs[f2].d;
542

    
543
    set_round_mode(env, m3);
544
    env->regs[r1] = (env->regs[r1] & 0xffffffff00000000ULL) |
545
        float64_to_int32(v2, &env->fpu_status);
546
    return set_cc_nz_f64(v2);
547
}
548

    
549
/* convert 128-bit float to 32-bit int */
550
uint32_t HELPER(cfxbr)(CPUS390XState *env, uint32_t r1, uint32_t f2,
551
                       uint32_t m3)
552
{
553
    CPU_QuadU v2;
554

    
555
    v2.ll.upper = env->fregs[f2].ll;
556
    v2.ll.lower = env->fregs[f2 + 2].ll;
557
    env->regs[r1] = (env->regs[r1] & 0xffffffff00000000ULL) |
558
        float128_to_int32(v2.q, &env->fpu_status);
559
    return set_cc_nz_f128(v2.q);
560
}
561

    
562
/* load 32-bit FP zero */
563
void HELPER(lzer)(CPUS390XState *env, uint32_t f1)
564
{
565
    env->fregs[f1].l.upper = float32_zero;
566
}
567

    
568
/* load 64-bit FP zero */
569
void HELPER(lzdr)(CPUS390XState *env, uint32_t f1)
570
{
571
    env->fregs[f1].d = float64_zero;
572
}
573

    
574
/* load 128-bit FP zero */
575
void HELPER(lzxr)(CPUS390XState *env, uint32_t f1)
576
{
577
    CPU_QuadU x;
578

    
579
    x.q = float64_to_float128(float64_zero, &env->fpu_status);
580
    env->fregs[f1].ll = x.ll.upper;
581
    env->fregs[f1 + 1].ll = x.ll.lower;
582
}
583

    
584
/* 32-bit FP multiply and add */
585
uint64_t HELPER(maeb)(CPUS390XState *env, uint64_t f1,
586
                      uint64_t f2, uint64_t f3)
587
{
588
    float32 ret = float32_muladd(f2, f3, f1, 0, &env->fpu_status);
589
    handle_exceptions(env, GETPC());
590
    return ret;
591
}
592

    
593
/* 64-bit FP multiply and add */
594
uint64_t HELPER(madb)(CPUS390XState *env, uint64_t f1,
595
                      uint64_t f2, uint64_t f3)
596
{
597
    float64 ret = float64_muladd(f2, f3, f1, 0, &env->fpu_status);
598
    handle_exceptions(env, GETPC());
599
    return ret;
600
}
601

    
602
/* 32-bit FP multiply and subtract */
603
uint64_t HELPER(mseb)(CPUS390XState *env, uint64_t f1,
604
                      uint64_t f2, uint64_t f3)
605
{
606
    float32 ret = float32_muladd(f2, f3, f1, float_muladd_negate_c,
607
                                 &env->fpu_status);
608
    handle_exceptions(env, GETPC());
609
    return ret;
610
}
611

    
612
/* 64-bit FP multiply and subtract */
613
uint64_t HELPER(msdb)(CPUS390XState *env, uint64_t f1,
614
                      uint64_t f2, uint64_t f3)
615
{
616
    float64 ret = float64_muladd(f2, f3, f1, float_muladd_negate_c,
617
                                 &env->fpu_status);
618
    handle_exceptions(env, GETPC());
619
    return ret;
620
}
621

    
622
/* test data class 32-bit */
623
uint32_t HELPER(tceb)(CPUS390XState *env, uint32_t f1, uint64_t m2)
624
{
625
    float32 v1 = env->fregs[f1].l.upper;
626
    int neg = float32_is_neg(v1);
627
    uint32_t cc = 0;
628

    
629
    HELPER_LOG("%s: v1 0x%lx m2 0x%lx neg %d\n", __func__, (long)v1, m2, neg);
630
    if ((float32_is_zero(v1) && (m2 & (1 << (11-neg)))) ||
631
        (float32_is_infinity(v1) && (m2 & (1 << (5-neg)))) ||
632
        (float32_is_any_nan(v1) && (m2 & (1 << (3-neg)))) ||
633
        (float32_is_signaling_nan(v1) && (m2 & (1 << (1-neg))))) {
634
        cc = 1;
635
    } else if (m2 & (1 << (9-neg))) {
636
        /* assume normalized number */
637
        cc = 1;
638
    }
639

    
640
    /* FIXME: denormalized? */
641
    return cc;
642
}
643

    
644
/* test data class 64-bit */
645
uint32_t HELPER(tcdb)(CPUS390XState *env, uint32_t f1, uint64_t m2)
646
{
647
    float64 v1 = env->fregs[f1].d;
648
    int neg = float64_is_neg(v1);
649
    uint32_t cc = 0;
650

    
651
    HELPER_LOG("%s: v1 0x%lx m2 0x%lx neg %d\n", __func__, v1, m2, neg);
652
    if ((float64_is_zero(v1) && (m2 & (1 << (11-neg)))) ||
653
        (float64_is_infinity(v1) && (m2 & (1 << (5-neg)))) ||
654
        (float64_is_any_nan(v1) && (m2 & (1 << (3-neg)))) ||
655
        (float64_is_signaling_nan(v1) && (m2 & (1 << (1-neg))))) {
656
        cc = 1;
657
    } else if (m2 & (1 << (9-neg))) {
658
        /* assume normalized number */
659
        cc = 1;
660
    }
661
    /* FIXME: denormalized? */
662
    return cc;
663
}
664

    
665
/* test data class 128-bit */
666
uint32_t HELPER(tcxb)(CPUS390XState *env, uint32_t f1, uint64_t m2)
667
{
668
    CPU_QuadU v1;
669
    uint32_t cc = 0;
670
    int neg;
671

    
672
    v1.ll.upper = env->fregs[f1].ll;
673
    v1.ll.lower = env->fregs[f1 + 2].ll;
674

    
675
    neg = float128_is_neg(v1.q);
676
    if ((float128_is_zero(v1.q) && (m2 & (1 << (11-neg)))) ||
677
        (float128_is_infinity(v1.q) && (m2 & (1 << (5-neg)))) ||
678
        (float128_is_any_nan(v1.q) && (m2 & (1 << (3-neg)))) ||
679
        (float128_is_signaling_nan(v1.q) && (m2 & (1 << (1-neg))))) {
680
        cc = 1;
681
    } else if (m2 & (1 << (9-neg))) {
682
        /* assume normalized number */
683
        cc = 1;
684
    }
685
    /* FIXME: denormalized? */
686
    return cc;
687
}
688

    
689
/* square root 64-bit RR */
690
void HELPER(sqdbr)(CPUS390XState *env, uint32_t f1, uint32_t f2)
691
{
692
    env->fregs[f1].d = float64_sqrt(env->fregs[f2].d, &env->fpu_status);
693
}