~pmdj/ubuntu/trusty/qemu/2.9+applesmc+fadtv3

« back to all changes in this revision

Viewing changes to target-ppc/dfp_helper.c

  • Committer: Phil Dennis-Jordan
  • Date: 2017-07-21 08:03:43 UTC
  • mfrom: (1.1.1)
  • Revision ID: phil@philjordan.eu-20170721080343-2yr2vdj7713czahv
New upstream release 2.9.0.

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
/*
2
 
 *  PowerPC Decimal Floating Point (DPF) emulation helpers for QEMU.
3
 
 *
4
 
 *  Copyright (c) 2014 IBM Corporation.
5
 
 *
6
 
 * This library is free software; you can redistribute it and/or
7
 
 * modify it under the terms of the GNU Lesser General Public
8
 
 * License as published by the Free Software Foundation; either
9
 
 * version 2 of the License, or (at your option) any later version.
10
 
 *
11
 
 * This library is distributed in the hope that it will be useful,
12
 
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13
 
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14
 
 * Lesser General Public License for more details.
15
 
 *
16
 
 * You should have received a copy of the GNU Lesser General Public
17
 
 * License along with this library; if not, see <http://www.gnu.org/licenses/>.
18
 
 */
19
 
 
20
 
#include "qemu/osdep.h"
21
 
#include "cpu.h"
22
 
#include "exec/helper-proto.h"
23
 
 
24
 
#define DECNUMDIGITS 34
25
 
#include "libdecnumber/decContext.h"
26
 
#include "libdecnumber/decNumber.h"
27
 
#include "libdecnumber/dpd/decimal32.h"
28
 
#include "libdecnumber/dpd/decimal64.h"
29
 
#include "libdecnumber/dpd/decimal128.h"
30
 
 
31
 
#if defined(HOST_WORDS_BIGENDIAN)
32
 
#define HI_IDX 0
33
 
#define LO_IDX 1
34
 
#else
35
 
#define HI_IDX 1
36
 
#define LO_IDX 0
37
 
#endif
38
 
 
39
 
struct PPC_DFP {
40
 
    CPUPPCState *env;
41
 
    uint64_t t64[2], a64[2], b64[2];
42
 
    decNumber t, a, b;
43
 
    decContext context;
44
 
    uint8_t crbf;
45
 
};
46
 
 
47
 
static void dfp_prepare_rounding_mode(decContext *context, uint64_t fpscr)
48
 
{
49
 
    enum rounding rnd;
50
 
 
51
 
    switch ((fpscr >> 32) & 0x7) {
52
 
    case 0:
53
 
        rnd = DEC_ROUND_HALF_EVEN;
54
 
        break;
55
 
    case 1:
56
 
        rnd = DEC_ROUND_DOWN;
57
 
        break;
58
 
    case 2:
59
 
         rnd = DEC_ROUND_CEILING;
60
 
         break;
61
 
    case 3:
62
 
         rnd = DEC_ROUND_FLOOR;
63
 
         break;
64
 
    case 4:
65
 
         rnd = DEC_ROUND_HALF_UP;
66
 
         break;
67
 
    case 5:
68
 
         rnd = DEC_ROUND_HALF_DOWN;
69
 
         break;
70
 
    case 6:
71
 
         rnd = DEC_ROUND_UP;
72
 
         break;
73
 
    case 7:
74
 
         rnd = DEC_ROUND_05UP;
75
 
         break;
76
 
    default:
77
 
        g_assert_not_reached();
78
 
    }
79
 
 
80
 
    decContextSetRounding(context, rnd);
81
 
}
82
 
 
83
 
static void dfp_set_round_mode_from_immediate(uint8_t r, uint8_t rmc,
84
 
                                                  struct PPC_DFP *dfp)
85
 
{
86
 
    enum rounding rnd;
87
 
    if (r == 0) {
88
 
        switch (rmc & 3) {
89
 
        case 0:
90
 
            rnd = DEC_ROUND_HALF_EVEN;
91
 
            break;
92
 
        case 1:
93
 
            rnd = DEC_ROUND_DOWN;
94
 
            break;
95
 
        case 2:
96
 
            rnd = DEC_ROUND_HALF_UP;
97
 
            break;
98
 
        case 3: /* use FPSCR rounding mode */
99
 
            return;
100
 
        default:
101
 
            assert(0); /* cannot get here */
102
 
        }
103
 
    } else { /* r == 1 */
104
 
        switch (rmc & 3) {
105
 
        case 0:
106
 
            rnd = DEC_ROUND_CEILING;
107
 
            break;
108
 
        case 1:
109
 
            rnd = DEC_ROUND_FLOOR;
110
 
            break;
111
 
        case 2:
112
 
            rnd = DEC_ROUND_UP;
113
 
            break;
114
 
        case 3:
115
 
            rnd = DEC_ROUND_HALF_DOWN;
116
 
            break;
117
 
        default:
118
 
            assert(0); /* cannot get here */
119
 
        }
120
 
    }
121
 
    decContextSetRounding(&dfp->context, rnd);
122
 
}
123
 
 
124
 
static void dfp_prepare_decimal64(struct PPC_DFP *dfp, uint64_t *a,
125
 
                uint64_t *b, CPUPPCState *env)
126
 
{
127
 
    decContextDefault(&dfp->context, DEC_INIT_DECIMAL64);
128
 
    dfp_prepare_rounding_mode(&dfp->context, env->fpscr);
129
 
    dfp->env = env;
130
 
 
131
 
    if (a) {
132
 
        dfp->a64[0] = *a;
133
 
        decimal64ToNumber((decimal64 *)dfp->a64, &dfp->a);
134
 
    } else {
135
 
        dfp->a64[0] = 0;
136
 
        decNumberZero(&dfp->a);
137
 
    }
138
 
 
139
 
    if (b) {
140
 
        dfp->b64[0] = *b;
141
 
        decimal64ToNumber((decimal64 *)dfp->b64, &dfp->b);
142
 
    } else {
143
 
        dfp->b64[0] = 0;
144
 
        decNumberZero(&dfp->b);
145
 
    }
146
 
}
147
 
 
148
 
static void dfp_prepare_decimal128(struct PPC_DFP *dfp, uint64_t *a,
149
 
                uint64_t *b, CPUPPCState *env)
150
 
{
151
 
    decContextDefault(&dfp->context, DEC_INIT_DECIMAL128);
152
 
    dfp_prepare_rounding_mode(&dfp->context, env->fpscr);
153
 
    dfp->env = env;
154
 
 
155
 
    if (a) {
156
 
        dfp->a64[0] = a[HI_IDX];
157
 
        dfp->a64[1] = a[LO_IDX];
158
 
        decimal128ToNumber((decimal128 *)dfp->a64, &dfp->a);
159
 
    } else {
160
 
        dfp->a64[0] = dfp->a64[1] = 0;
161
 
        decNumberZero(&dfp->a);
162
 
    }
163
 
 
164
 
    if (b) {
165
 
        dfp->b64[0] = b[HI_IDX];
166
 
        dfp->b64[1] = b[LO_IDX];
167
 
        decimal128ToNumber((decimal128 *)dfp->b64, &dfp->b);
168
 
    } else {
169
 
        dfp->b64[0] = dfp->b64[1] = 0;
170
 
        decNumberZero(&dfp->b);
171
 
    }
172
 
}
173
 
 
174
 
static void dfp_set_FPSCR_flag(struct PPC_DFP *dfp, uint64_t flag,
175
 
                uint64_t enabled)
176
 
{
177
 
    dfp->env->fpscr |= (flag | FP_FX);
178
 
    if (dfp->env->fpscr & enabled) {
179
 
        dfp->env->fpscr |= FP_FEX;
180
 
    }
181
 
}
182
 
 
183
 
static void dfp_set_FPRF_from_FRT_with_context(struct PPC_DFP *dfp,
184
 
                decContext *context)
185
 
{
186
 
    uint64_t fprf = 0;
187
 
 
188
 
    /* construct FPRF */
189
 
    switch (decNumberClass(&dfp->t, context)) {
190
 
    case DEC_CLASS_SNAN:
191
 
        fprf = 0x01;
192
 
        break;
193
 
    case DEC_CLASS_QNAN:
194
 
        fprf = 0x11;
195
 
        break;
196
 
    case DEC_CLASS_NEG_INF:
197
 
        fprf = 0x09;
198
 
        break;
199
 
    case DEC_CLASS_NEG_NORMAL:
200
 
        fprf = 0x08;
201
 
        break;
202
 
    case DEC_CLASS_NEG_SUBNORMAL:
203
 
        fprf = 0x18;
204
 
        break;
205
 
    case DEC_CLASS_NEG_ZERO:
206
 
        fprf = 0x12;
207
 
        break;
208
 
    case DEC_CLASS_POS_ZERO:
209
 
        fprf = 0x02;
210
 
        break;
211
 
    case DEC_CLASS_POS_SUBNORMAL:
212
 
        fprf = 0x14;
213
 
        break;
214
 
    case DEC_CLASS_POS_NORMAL:
215
 
        fprf = 0x04;
216
 
        break;
217
 
    case DEC_CLASS_POS_INF:
218
 
        fprf = 0x05;
219
 
        break;
220
 
    default:
221
 
        assert(0); /* should never get here */
222
 
    }
223
 
    dfp->env->fpscr &= ~(0x1F << 12);
224
 
    dfp->env->fpscr |= (fprf << 12);
225
 
}
226
 
 
227
 
static void dfp_set_FPRF_from_FRT(struct PPC_DFP *dfp)
228
 
{
229
 
    dfp_set_FPRF_from_FRT_with_context(dfp, &dfp->context);
230
 
}
231
 
 
232
 
static void dfp_set_FPRF_from_FRT_short(struct PPC_DFP *dfp)
233
 
{
234
 
    decContext shortContext;
235
 
    decContextDefault(&shortContext, DEC_INIT_DECIMAL32);
236
 
    dfp_set_FPRF_from_FRT_with_context(dfp, &shortContext);
237
 
}
238
 
 
239
 
static void dfp_set_FPRF_from_FRT_long(struct PPC_DFP *dfp)
240
 
{
241
 
    decContext longContext;
242
 
    decContextDefault(&longContext, DEC_INIT_DECIMAL64);
243
 
    dfp_set_FPRF_from_FRT_with_context(dfp, &longContext);
244
 
}
245
 
 
246
 
static void dfp_check_for_OX(struct PPC_DFP *dfp)
247
 
{
248
 
    if (dfp->context.status & DEC_Overflow) {
249
 
        dfp_set_FPSCR_flag(dfp, FP_OX, FP_OE);
250
 
    }
251
 
}
252
 
 
253
 
static void dfp_check_for_UX(struct PPC_DFP *dfp)
254
 
{
255
 
    if (dfp->context.status & DEC_Underflow) {
256
 
        dfp_set_FPSCR_flag(dfp, FP_UX, FP_UE);
257
 
    }
258
 
}
259
 
 
260
 
static void dfp_check_for_XX(struct PPC_DFP *dfp)
261
 
{
262
 
    if (dfp->context.status & DEC_Inexact) {
263
 
        dfp_set_FPSCR_flag(dfp, FP_XX | FP_FI, FP_XE);
264
 
    }
265
 
}
266
 
 
267
 
static void dfp_check_for_ZX(struct PPC_DFP *dfp)
268
 
{
269
 
    if (dfp->context.status & DEC_Division_by_zero) {
270
 
        dfp_set_FPSCR_flag(dfp, FP_ZX, FP_ZE);
271
 
    }
272
 
}
273
 
 
274
 
static void dfp_check_for_VXSNAN(struct PPC_DFP *dfp)
275
 
{
276
 
    if (dfp->context.status & DEC_Invalid_operation) {
277
 
        if (decNumberIsSNaN(&dfp->a) || decNumberIsSNaN(&dfp->b)) {
278
 
            dfp_set_FPSCR_flag(dfp, FP_VX | FP_VXSNAN, FP_VE);
279
 
        }
280
 
    }
281
 
}
282
 
 
283
 
static void dfp_check_for_VXSNAN_and_convert_to_QNaN(struct PPC_DFP *dfp)
284
 
{
285
 
    if (decNumberIsSNaN(&dfp->t)) {
286
 
        dfp->t.bits &= ~DECSNAN;
287
 
        dfp->t.bits |= DECNAN;
288
 
        dfp_set_FPSCR_flag(dfp, FP_VX | FP_VXSNAN, FP_VE);
289
 
    }
290
 
}
291
 
 
292
 
static void dfp_check_for_VXISI(struct PPC_DFP *dfp, int testForSameSign)
293
 
{
294
 
    if (dfp->context.status & DEC_Invalid_operation) {
295
 
        if (decNumberIsInfinite(&dfp->a) && decNumberIsInfinite(&dfp->b)) {
296
 
            int same = decNumberClass(&dfp->a, &dfp->context) ==
297
 
                       decNumberClass(&dfp->b, &dfp->context);
298
 
            if ((same && testForSameSign) || (!same && !testForSameSign)) {
299
 
                dfp_set_FPSCR_flag(dfp, FP_VX | FP_VXISI, FP_VE);
300
 
            }
301
 
        }
302
 
    }
303
 
}
304
 
 
305
 
static void dfp_check_for_VXISI_add(struct PPC_DFP *dfp)
306
 
{
307
 
    dfp_check_for_VXISI(dfp, 0);
308
 
}
309
 
 
310
 
static void dfp_check_for_VXISI_subtract(struct PPC_DFP *dfp)
311
 
{
312
 
    dfp_check_for_VXISI(dfp, 1);
313
 
}
314
 
 
315
 
static void dfp_check_for_VXIMZ(struct PPC_DFP *dfp)
316
 
{
317
 
    if (dfp->context.status & DEC_Invalid_operation) {
318
 
        if ((decNumberIsInfinite(&dfp->a) && decNumberIsZero(&dfp->b)) ||
319
 
            (decNumberIsInfinite(&dfp->b) && decNumberIsZero(&dfp->a))) {
320
 
            dfp_set_FPSCR_flag(dfp, FP_VX | FP_VXIMZ, FP_VE);
321
 
        }
322
 
    }
323
 
}
324
 
 
325
 
static void dfp_check_for_VXZDZ(struct PPC_DFP *dfp)
326
 
{
327
 
    if (dfp->context.status & DEC_Division_undefined) {
328
 
        dfp_set_FPSCR_flag(dfp, FP_VX | FP_VXZDZ, FP_VE);
329
 
    }
330
 
}
331
 
 
332
 
static void dfp_check_for_VXIDI(struct PPC_DFP *dfp)
333
 
{
334
 
    if (dfp->context.status & DEC_Invalid_operation) {
335
 
        if (decNumberIsInfinite(&dfp->a) && decNumberIsInfinite(&dfp->b)) {
336
 
            dfp_set_FPSCR_flag(dfp, FP_VX | FP_VXIDI, FP_VE);
337
 
        }
338
 
    }
339
 
}
340
 
 
341
 
static void dfp_check_for_VXVC(struct PPC_DFP *dfp)
342
 
{
343
 
    if (decNumberIsNaN(&dfp->a) || decNumberIsNaN(&dfp->b)) {
344
 
        dfp_set_FPSCR_flag(dfp, FP_VX | FP_VXVC, FP_VE);
345
 
    }
346
 
}
347
 
 
348
 
static void dfp_check_for_VXCVI(struct PPC_DFP *dfp)
349
 
{
350
 
    if ((dfp->context.status & DEC_Invalid_operation) &&
351
 
        (!decNumberIsSNaN(&dfp->a)) &&
352
 
        (!decNumberIsSNaN(&dfp->b))) {
353
 
        dfp_set_FPSCR_flag(dfp, FP_VX | FP_VXCVI, FP_VE);
354
 
    }
355
 
}
356
 
 
357
 
static void dfp_set_CRBF_from_T(struct PPC_DFP *dfp)
358
 
{
359
 
    if (decNumberIsNaN(&dfp->t)) {
360
 
        dfp->crbf = 1;
361
 
    } else if (decNumberIsZero(&dfp->t)) {
362
 
        dfp->crbf = 2;
363
 
    } else if (decNumberIsNegative(&dfp->t)) {
364
 
        dfp->crbf = 8;
365
 
    } else {
366
 
        dfp->crbf = 4;
367
 
    }
368
 
}
369
 
 
370
 
static void dfp_set_FPCC_from_CRBF(struct PPC_DFP *dfp)
371
 
{
372
 
    dfp->env->fpscr &= ~(0xF << 12);
373
 
    dfp->env->fpscr |= (dfp->crbf << 12);
374
 
}
375
 
 
376
 
static inline void dfp_makeQNaN(decNumber *dn)
377
 
{
378
 
    dn->bits &= ~DECSPECIAL;
379
 
    dn->bits |= DECNAN;
380
 
}
381
 
 
382
 
static inline int dfp_get_digit(decNumber *dn, int n)
383
 
{
384
 
    assert(DECDPUN == 3);
385
 
    int unit = n / DECDPUN;
386
 
    int dig = n % DECDPUN;
387
 
    switch (dig) {
388
 
    case 0:
389
 
        return dn->lsu[unit] % 10;
390
 
    case 1:
391
 
        return (dn->lsu[unit] / 10) % 10;
392
 
    case 2:
393
 
        return dn->lsu[unit] / 100;
394
 
    }
395
 
    g_assert_not_reached();
396
 
}
397
 
 
398
 
#define DFP_HELPER_TAB(op, dnop, postprocs, size)                              \
399
 
void helper_##op(CPUPPCState *env, uint64_t *t, uint64_t *a, uint64_t *b)      \
400
 
{                                                                              \
401
 
    struct PPC_DFP dfp;                                                        \
402
 
    dfp_prepare_decimal##size(&dfp, a, b, env);                                \
403
 
    dnop(&dfp.t, &dfp.a, &dfp.b, &dfp.context);                                \
404
 
    decimal##size##FromNumber((decimal##size *)dfp.t64, &dfp.t, &dfp.context); \
405
 
    postprocs(&dfp);                                                           \
406
 
    if (size == 64) {                                                          \
407
 
        t[0] = dfp.t64[0];                                                     \
408
 
    } else if (size == 128) {                                                  \
409
 
        t[0] = dfp.t64[HI_IDX];                                                \
410
 
        t[1] = dfp.t64[LO_IDX];                                                \
411
 
    }                                                                          \
412
 
}
413
 
 
414
 
static void ADD_PPs(struct PPC_DFP *dfp)
415
 
{
416
 
    dfp_set_FPRF_from_FRT(dfp);
417
 
    dfp_check_for_OX(dfp);
418
 
    dfp_check_for_UX(dfp);
419
 
    dfp_check_for_XX(dfp);
420
 
    dfp_check_for_VXSNAN(dfp);
421
 
    dfp_check_for_VXISI_add(dfp);
422
 
}
423
 
 
424
 
DFP_HELPER_TAB(dadd, decNumberAdd, ADD_PPs, 64)
425
 
DFP_HELPER_TAB(daddq, decNumberAdd, ADD_PPs, 128)
426
 
 
427
 
static void SUB_PPs(struct PPC_DFP *dfp)
428
 
{
429
 
    dfp_set_FPRF_from_FRT(dfp);
430
 
    dfp_check_for_OX(dfp);
431
 
    dfp_check_for_UX(dfp);
432
 
    dfp_check_for_XX(dfp);
433
 
    dfp_check_for_VXSNAN(dfp);
434
 
    dfp_check_for_VXISI_subtract(dfp);
435
 
}
436
 
 
437
 
DFP_HELPER_TAB(dsub, decNumberSubtract, SUB_PPs, 64)
438
 
DFP_HELPER_TAB(dsubq, decNumberSubtract, SUB_PPs, 128)
439
 
 
440
 
static void MUL_PPs(struct PPC_DFP *dfp)
441
 
{
442
 
    dfp_set_FPRF_from_FRT(dfp);
443
 
    dfp_check_for_OX(dfp);
444
 
    dfp_check_for_UX(dfp);
445
 
    dfp_check_for_XX(dfp);
446
 
    dfp_check_for_VXSNAN(dfp);
447
 
    dfp_check_for_VXIMZ(dfp);
448
 
}
449
 
 
450
 
DFP_HELPER_TAB(dmul, decNumberMultiply, MUL_PPs, 64)
451
 
DFP_HELPER_TAB(dmulq, decNumberMultiply, MUL_PPs, 128)
452
 
 
453
 
static void DIV_PPs(struct PPC_DFP *dfp)
454
 
{
455
 
    dfp_set_FPRF_from_FRT(dfp);
456
 
    dfp_check_for_OX(dfp);
457
 
    dfp_check_for_UX(dfp);
458
 
    dfp_check_for_ZX(dfp);
459
 
    dfp_check_for_XX(dfp);
460
 
    dfp_check_for_VXSNAN(dfp);
461
 
    dfp_check_for_VXZDZ(dfp);
462
 
    dfp_check_for_VXIDI(dfp);
463
 
}
464
 
 
465
 
DFP_HELPER_TAB(ddiv, decNumberDivide, DIV_PPs, 64)
466
 
DFP_HELPER_TAB(ddivq, decNumberDivide, DIV_PPs, 128)
467
 
 
468
 
#define DFP_HELPER_BF_AB(op, dnop, postprocs, size)                            \
469
 
uint32_t helper_##op(CPUPPCState *env, uint64_t *a, uint64_t *b)               \
470
 
{                                                                              \
471
 
    struct PPC_DFP dfp;                                                        \
472
 
    dfp_prepare_decimal##size(&dfp, a, b, env);                                \
473
 
    dnop(&dfp.t, &dfp.a, &dfp.b, &dfp.context);                                \
474
 
    decimal##size##FromNumber((decimal##size *)dfp.t64, &dfp.t, &dfp.context); \
475
 
    postprocs(&dfp);                                                           \
476
 
    return dfp.crbf;                                                           \
477
 
}
478
 
 
479
 
static void CMPU_PPs(struct PPC_DFP *dfp)
480
 
{
481
 
    dfp_set_CRBF_from_T(dfp);
482
 
    dfp_set_FPCC_from_CRBF(dfp);
483
 
    dfp_check_for_VXSNAN(dfp);
484
 
}
485
 
 
486
 
DFP_HELPER_BF_AB(dcmpu, decNumberCompare, CMPU_PPs, 64)
487
 
DFP_HELPER_BF_AB(dcmpuq, decNumberCompare, CMPU_PPs, 128)
488
 
 
489
 
static void CMPO_PPs(struct PPC_DFP *dfp)
490
 
{
491
 
    dfp_set_CRBF_from_T(dfp);
492
 
    dfp_set_FPCC_from_CRBF(dfp);
493
 
    dfp_check_for_VXSNAN(dfp);
494
 
    dfp_check_for_VXVC(dfp);
495
 
}
496
 
 
497
 
DFP_HELPER_BF_AB(dcmpo, decNumberCompare, CMPO_PPs, 64)
498
 
DFP_HELPER_BF_AB(dcmpoq, decNumberCompare, CMPO_PPs, 128)
499
 
 
500
 
#define DFP_HELPER_TSTDC(op, size)                                       \
501
 
uint32_t helper_##op(CPUPPCState *env, uint64_t *a, uint32_t dcm)        \
502
 
{                                                                        \
503
 
    struct PPC_DFP dfp;                                                  \
504
 
    int match = 0;                                                       \
505
 
                                                                         \
506
 
    dfp_prepare_decimal##size(&dfp, a, 0, env);                          \
507
 
                                                                         \
508
 
    match |= (dcm & 0x20) && decNumberIsZero(&dfp.a);                    \
509
 
    match |= (dcm & 0x10) && decNumberIsSubnormal(&dfp.a, &dfp.context); \
510
 
    match |= (dcm & 0x08) && decNumberIsNormal(&dfp.a, &dfp.context);    \
511
 
    match |= (dcm & 0x04) && decNumberIsInfinite(&dfp.a);                \
512
 
    match |= (dcm & 0x02) && decNumberIsQNaN(&dfp.a);                    \
513
 
    match |= (dcm & 0x01) && decNumberIsSNaN(&dfp.a);                    \
514
 
                                                                         \
515
 
    if (decNumberIsNegative(&dfp.a)) {                                   \
516
 
        dfp.crbf = match ? 0xA : 0x8;                                    \
517
 
    } else {                                                             \
518
 
        dfp.crbf = match ? 0x2 : 0x0;                                    \
519
 
    }                                                                    \
520
 
                                                                         \
521
 
    dfp_set_FPCC_from_CRBF(&dfp);                                        \
522
 
    return dfp.crbf;                                                     \
523
 
}
524
 
 
525
 
DFP_HELPER_TSTDC(dtstdc, 64)
526
 
DFP_HELPER_TSTDC(dtstdcq, 128)
527
 
 
528
 
#define DFP_HELPER_TSTDG(op, size)                                       \
529
 
uint32_t helper_##op(CPUPPCState *env, uint64_t *a, uint32_t dcm)        \
530
 
{                                                                        \
531
 
    struct PPC_DFP dfp;                                                  \
532
 
    int minexp, maxexp, nzero_digits, nzero_idx, is_negative, is_zero,   \
533
 
        is_extreme_exp, is_subnormal, is_normal, leftmost_is_nonzero,    \
534
 
        match;                                                           \
535
 
                                                                         \
536
 
    dfp_prepare_decimal##size(&dfp, a, 0, env);                          \
537
 
                                                                         \
538
 
    if ((size) == 64) {                                                  \
539
 
        minexp = -398;                                                   \
540
 
        maxexp = 369;                                                    \
541
 
        nzero_digits = 16;                                               \
542
 
        nzero_idx = 5;                                                   \
543
 
    } else if ((size) == 128) {                                          \
544
 
        minexp = -6176;                                                  \
545
 
        maxexp = 6111;                                                   \
546
 
        nzero_digits = 34;                                               \
547
 
        nzero_idx = 11;                                                  \
548
 
    }                                                                    \
549
 
                                                                         \
550
 
    is_negative = decNumberIsNegative(&dfp.a);                           \
551
 
    is_zero = decNumberIsZero(&dfp.a);                                   \
552
 
    is_extreme_exp = (dfp.a.exponent == maxexp) ||                       \
553
 
                     (dfp.a.exponent == minexp);                         \
554
 
    is_subnormal = decNumberIsSubnormal(&dfp.a, &dfp.context);           \
555
 
    is_normal = decNumberIsNormal(&dfp.a, &dfp.context);                 \
556
 
    leftmost_is_nonzero = (dfp.a.digits == nzero_digits) &&              \
557
 
                          (dfp.a.lsu[nzero_idx] != 0);                   \
558
 
    match = 0;                                                           \
559
 
                                                                         \
560
 
    match |= (dcm & 0x20) && is_zero && !is_extreme_exp;                 \
561
 
    match |= (dcm & 0x10) && is_zero && is_extreme_exp;                  \
562
 
    match |= (dcm & 0x08) &&                                             \
563
 
             (is_subnormal || (is_normal && is_extreme_exp));            \
564
 
    match |= (dcm & 0x04) && is_normal && !is_extreme_exp &&             \
565
 
             !leftmost_is_nonzero;                                       \
566
 
    match |= (dcm & 0x02) && is_normal && !is_extreme_exp &&             \
567
 
             leftmost_is_nonzero;                                        \
568
 
    match |= (dcm & 0x01) && decNumberIsSpecial(&dfp.a);                 \
569
 
                                                                         \
570
 
    if (is_negative) {                                                   \
571
 
        dfp.crbf = match ? 0xA : 0x8;                                    \
572
 
    } else {                                                             \
573
 
        dfp.crbf = match ? 0x2 : 0x0;                                    \
574
 
    }                                                                    \
575
 
                                                                         \
576
 
    dfp_set_FPCC_from_CRBF(&dfp);                                        \
577
 
    return dfp.crbf;                                                     \
578
 
}
579
 
 
580
 
DFP_HELPER_TSTDG(dtstdg, 64)
581
 
DFP_HELPER_TSTDG(dtstdgq, 128)
582
 
 
583
 
#define DFP_HELPER_TSTEX(op, size)                                       \
584
 
uint32_t helper_##op(CPUPPCState *env, uint64_t *a, uint64_t *b)         \
585
 
{                                                                        \
586
 
    struct PPC_DFP dfp;                                                  \
587
 
    int expa, expb, a_is_special, b_is_special;                          \
588
 
                                                                         \
589
 
    dfp_prepare_decimal##size(&dfp, a, b, env);                          \
590
 
                                                                         \
591
 
    expa = dfp.a.exponent;                                               \
592
 
    expb = dfp.b.exponent;                                               \
593
 
    a_is_special = decNumberIsSpecial(&dfp.a);                           \
594
 
    b_is_special = decNumberIsSpecial(&dfp.b);                           \
595
 
                                                                         \
596
 
    if (a_is_special || b_is_special) {                                  \
597
 
        int atype = a_is_special ? (decNumberIsNaN(&dfp.a) ? 4 : 2) : 1; \
598
 
        int btype = b_is_special ? (decNumberIsNaN(&dfp.b) ? 4 : 2) : 1; \
599
 
        dfp.crbf = (atype ^ btype) ? 0x1 : 0x2;                          \
600
 
    } else if (expa < expb) {                                            \
601
 
        dfp.crbf = 0x8;                                                  \
602
 
    } else if (expa > expb) {                                            \
603
 
        dfp.crbf = 0x4;                                                  \
604
 
    } else {                                                             \
605
 
        dfp.crbf = 0x2;                                                  \
606
 
    }                                                                    \
607
 
                                                                         \
608
 
    dfp_set_FPCC_from_CRBF(&dfp);                                        \
609
 
    return dfp.crbf;                                                     \
610
 
}
611
 
 
612
 
DFP_HELPER_TSTEX(dtstex, 64)
613
 
DFP_HELPER_TSTEX(dtstexq, 128)
614
 
 
615
 
#define DFP_HELPER_TSTSF(op, size)                                       \
616
 
uint32_t helper_##op(CPUPPCState *env, uint64_t *a, uint64_t *b)         \
617
 
{                                                                        \
618
 
    struct PPC_DFP dfp;                                                  \
619
 
    unsigned k;                                                          \
620
 
                                                                         \
621
 
    dfp_prepare_decimal##size(&dfp, 0, b, env);                          \
622
 
                                                                         \
623
 
    k = *a & 0x3F;                                                       \
624
 
                                                                         \
625
 
    if (unlikely(decNumberIsSpecial(&dfp.b))) {                          \
626
 
        dfp.crbf = 1;                                                    \
627
 
    } else if (k == 0) {                                                 \
628
 
        dfp.crbf = 4;                                                    \
629
 
    } else if (unlikely(decNumberIsZero(&dfp.b))) {                      \
630
 
        /* Zero has no sig digits */                                     \
631
 
        dfp.crbf = 4;                                                    \
632
 
    } else {                                                             \
633
 
        unsigned nsd = dfp.b.digits;                                     \
634
 
        if (k < nsd) {                                                   \
635
 
            dfp.crbf = 8;                                                \
636
 
        } else if (k > nsd) {                                            \
637
 
            dfp.crbf = 4;                                                \
638
 
        } else {                                                         \
639
 
            dfp.crbf = 2;                                                \
640
 
        }                                                                \
641
 
    }                                                                    \
642
 
                                                                         \
643
 
    dfp_set_FPCC_from_CRBF(&dfp);                                        \
644
 
    return dfp.crbf;                                                     \
645
 
}
646
 
 
647
 
DFP_HELPER_TSTSF(dtstsf, 64)
648
 
DFP_HELPER_TSTSF(dtstsfq, 128)
649
 
 
650
 
#define DFP_HELPER_TSTSFI(op, size)                                     \
651
 
uint32_t helper_##op(CPUPPCState *env, uint32_t a, uint64_t *b)         \
652
 
{                                                                       \
653
 
    struct PPC_DFP dfp;                                                 \
654
 
    unsigned uim;                                                       \
655
 
                                                                        \
656
 
    dfp_prepare_decimal##size(&dfp, 0, b, env);                         \
657
 
                                                                        \
658
 
    uim = a & 0x3F;                                                     \
659
 
                                                                        \
660
 
    if (unlikely(decNumberIsSpecial(&dfp.b))) {                         \
661
 
        dfp.crbf = 1;                                                   \
662
 
    } else if (uim == 0) {                                              \
663
 
        dfp.crbf = 4;                                                   \
664
 
    } else if (unlikely(decNumberIsZero(&dfp.b))) {                     \
665
 
        /* Zero has no sig digits */                                    \
666
 
        dfp.crbf = 4;                                                   \
667
 
    } else {                                                            \
668
 
        unsigned nsd = dfp.b.digits;                                    \
669
 
        if (uim < nsd) {                                                \
670
 
            dfp.crbf = 8;                                               \
671
 
        } else if (uim > nsd) {                                         \
672
 
            dfp.crbf = 4;                                               \
673
 
        } else {                                                        \
674
 
            dfp.crbf = 2;                                               \
675
 
        }                                                               \
676
 
    }                                                                   \
677
 
                                                                        \
678
 
    dfp_set_FPCC_from_CRBF(&dfp);                                       \
679
 
    return dfp.crbf;                                                    \
680
 
}
681
 
 
682
 
DFP_HELPER_TSTSFI(dtstsfi, 64)
683
 
DFP_HELPER_TSTSFI(dtstsfiq, 128)
684
 
 
685
 
static void QUA_PPs(struct PPC_DFP *dfp)
686
 
{
687
 
    dfp_set_FPRF_from_FRT(dfp);
688
 
    dfp_check_for_XX(dfp);
689
 
    dfp_check_for_VXSNAN(dfp);
690
 
    dfp_check_for_VXCVI(dfp);
691
 
}
692
 
 
693
 
static void dfp_quantize(uint8_t rmc, struct PPC_DFP *dfp)
694
 
{
695
 
    dfp_set_round_mode_from_immediate(0, rmc, dfp);
696
 
    decNumberQuantize(&dfp->t, &dfp->b, &dfp->a, &dfp->context);
697
 
    if (decNumberIsSNaN(&dfp->a)) {
698
 
        dfp->t = dfp->a;
699
 
        dfp_makeQNaN(&dfp->t);
700
 
    } else if (decNumberIsSNaN(&dfp->b)) {
701
 
        dfp->t = dfp->b;
702
 
        dfp_makeQNaN(&dfp->t);
703
 
    } else if (decNumberIsQNaN(&dfp->a)) {
704
 
        dfp->t = dfp->a;
705
 
    } else if (decNumberIsQNaN(&dfp->b)) {
706
 
        dfp->t = dfp->b;
707
 
    }
708
 
}
709
 
 
710
 
#define DFP_HELPER_QUAI(op, size)                                       \
711
 
void helper_##op(CPUPPCState *env, uint64_t *t, uint64_t *b,            \
712
 
                 uint32_t te, uint32_t rmc)                             \
713
 
{                                                                       \
714
 
    struct PPC_DFP dfp;                                                 \
715
 
                                                                        \
716
 
    dfp_prepare_decimal##size(&dfp, 0, b, env);                         \
717
 
                                                                        \
718
 
    decNumberFromUInt32(&dfp.a, 1);                                     \
719
 
    dfp.a.exponent = (int32_t)((int8_t)(te << 3) >> 3);                 \
720
 
                                                                        \
721
 
    dfp_quantize(rmc, &dfp);                                            \
722
 
    decimal##size##FromNumber((decimal##size *)dfp.t64, &dfp.t,         \
723
 
                              &dfp.context);                            \
724
 
    QUA_PPs(&dfp);                                                      \
725
 
                                                                        \
726
 
    if (size == 64) {                                                   \
727
 
        t[0] = dfp.t64[0];                                              \
728
 
    } else if (size == 128) {                                           \
729
 
        t[0] = dfp.t64[HI_IDX];                                         \
730
 
        t[1] = dfp.t64[LO_IDX];                                         \
731
 
    }                                                                   \
732
 
}
733
 
 
734
 
DFP_HELPER_QUAI(dquai, 64)
735
 
DFP_HELPER_QUAI(dquaiq, 128)
736
 
 
737
 
#define DFP_HELPER_QUA(op, size)                                        \
738
 
void helper_##op(CPUPPCState *env, uint64_t *t, uint64_t *a,            \
739
 
                 uint64_t *b, uint32_t rmc)                             \
740
 
{                                                                       \
741
 
    struct PPC_DFP dfp;                                                 \
742
 
                                                                        \
743
 
    dfp_prepare_decimal##size(&dfp, a, b, env);                         \
744
 
                                                                        \
745
 
    dfp_quantize(rmc, &dfp);                                            \
746
 
    decimal##size##FromNumber((decimal##size *)dfp.t64, &dfp.t,         \
747
 
                              &dfp.context);                            \
748
 
    QUA_PPs(&dfp);                                                      \
749
 
                                                                        \
750
 
    if (size == 64) {                                                   \
751
 
        t[0] = dfp.t64[0];                                              \
752
 
    } else if (size == 128) {                                           \
753
 
        t[0] = dfp.t64[HI_IDX];                                         \
754
 
        t[1] = dfp.t64[LO_IDX];                                         \
755
 
    }                                                                   \
756
 
}
757
 
 
758
 
DFP_HELPER_QUA(dqua, 64)
759
 
DFP_HELPER_QUA(dquaq, 128)
760
 
 
761
 
static void _dfp_reround(uint8_t rmc, int32_t ref_sig, int32_t xmax,
762
 
                             struct PPC_DFP *dfp)
763
 
{
764
 
    int msd_orig, msd_rslt;
765
 
 
766
 
    if (unlikely((ref_sig == 0) || (dfp->b.digits <= ref_sig))) {
767
 
        dfp->t = dfp->b;
768
 
        if (decNumberIsSNaN(&dfp->b)) {
769
 
            dfp_makeQNaN(&dfp->t);
770
 
            dfp_set_FPSCR_flag(dfp, FP_VX | FP_VXSNAN, FPSCR_VE);
771
 
        }
772
 
        return;
773
 
    }
774
 
 
775
 
    /* Reround is equivalent to quantizing b with 1**E(n) where */
776
 
    /* n = exp(b) + numDigits(b) - reference_significance.      */
777
 
 
778
 
    decNumberFromUInt32(&dfp->a, 1);
779
 
    dfp->a.exponent = dfp->b.exponent + dfp->b.digits - ref_sig;
780
 
 
781
 
    if (unlikely(dfp->a.exponent > xmax)) {
782
 
        dfp->t.digits = 0;
783
 
        dfp->t.bits &= ~DECNEG;
784
 
        dfp_makeQNaN(&dfp->t);
785
 
        dfp_set_FPSCR_flag(dfp, FP_VX | FP_VXCVI, FPSCR_VE);
786
 
        return;
787
 
    }
788
 
 
789
 
    dfp_quantize(rmc, dfp);
790
 
 
791
 
    msd_orig = dfp_get_digit(&dfp->b, dfp->b.digits-1);
792
 
    msd_rslt = dfp_get_digit(&dfp->t, dfp->t.digits-1);
793
 
 
794
 
    /* If the quantization resulted in rounding up to the next magnitude, */
795
 
    /* then we need to shift the significand and adjust the exponent.     */
796
 
 
797
 
    if (unlikely((msd_orig == 9) && (msd_rslt == 1))) {
798
 
 
799
 
        decNumber negone;
800
 
 
801
 
        decNumberFromInt32(&negone, -1);
802
 
        decNumberShift(&dfp->t, &dfp->t, &negone, &dfp->context);
803
 
        dfp->t.exponent++;
804
 
 
805
 
        if (unlikely(dfp->t.exponent > xmax)) {
806
 
            dfp_makeQNaN(&dfp->t);
807
 
            dfp->t.digits = 0;
808
 
            dfp_set_FPSCR_flag(dfp, FP_VX | FP_VXCVI, FP_VE);
809
 
            /* Inhibit XX in this case */
810
 
            decContextClearStatus(&dfp->context, DEC_Inexact);
811
 
        }
812
 
    }
813
 
}
814
 
 
815
 
#define DFP_HELPER_RRND(op, size)                                       \
816
 
void helper_##op(CPUPPCState *env, uint64_t *t, uint64_t *a,            \
817
 
                 uint64_t *b, uint32_t rmc)                             \
818
 
{                                                                       \
819
 
    struct PPC_DFP dfp;                                                 \
820
 
    int32_t ref_sig = *a & 0x3F;                                        \
821
 
    int32_t xmax = ((size) == 64) ? 369 : 6111;                         \
822
 
                                                                        \
823
 
    dfp_prepare_decimal##size(&dfp, 0, b, env);                         \
824
 
                                                                        \
825
 
    _dfp_reround(rmc, ref_sig, xmax, &dfp);                             \
826
 
    decimal##size##FromNumber((decimal##size *)dfp.t64, &dfp.t,         \
827
 
                              &dfp.context);                            \
828
 
    QUA_PPs(&dfp);                                                      \
829
 
                                                                        \
830
 
    if (size == 64) {                                                   \
831
 
        t[0] = dfp.t64[0];                                              \
832
 
    } else if (size == 128) {                                           \
833
 
        t[0] = dfp.t64[HI_IDX];                                         \
834
 
        t[1] = dfp.t64[LO_IDX];                                         \
835
 
    }                                                                   \
836
 
}
837
 
 
838
 
DFP_HELPER_RRND(drrnd, 64)
839
 
DFP_HELPER_RRND(drrndq, 128)
840
 
 
841
 
#define DFP_HELPER_RINT(op, postprocs, size)                                   \
842
 
void helper_##op(CPUPPCState *env, uint64_t *t, uint64_t *b,                   \
843
 
             uint32_t r, uint32_t rmc)                                         \
844
 
{                                                                              \
845
 
    struct PPC_DFP dfp;                                                        \
846
 
                                                                               \
847
 
    dfp_prepare_decimal##size(&dfp, 0, b, env);                                \
848
 
                                                                               \
849
 
    dfp_set_round_mode_from_immediate(r, rmc, &dfp);                           \
850
 
    decNumberToIntegralExact(&dfp.t, &dfp.b, &dfp.context);                    \
851
 
    decimal##size##FromNumber((decimal##size *)dfp.t64, &dfp.t, &dfp.context); \
852
 
    postprocs(&dfp);                                                           \
853
 
                                                                               \
854
 
    if (size == 64) {                                                          \
855
 
        t[0] = dfp.t64[0];                                                     \
856
 
    } else if (size == 128) {                                                  \
857
 
        t[0] = dfp.t64[HI_IDX];                                                \
858
 
        t[1] = dfp.t64[LO_IDX];                                                \
859
 
    }                                                                          \
860
 
}
861
 
 
862
 
static void RINTX_PPs(struct PPC_DFP *dfp)
863
 
{
864
 
    dfp_set_FPRF_from_FRT(dfp);
865
 
    dfp_check_for_XX(dfp);
866
 
    dfp_check_for_VXSNAN(dfp);
867
 
}
868
 
 
869
 
DFP_HELPER_RINT(drintx, RINTX_PPs, 64)
870
 
DFP_HELPER_RINT(drintxq, RINTX_PPs, 128)
871
 
 
872
 
static void RINTN_PPs(struct PPC_DFP *dfp)
873
 
{
874
 
    dfp_set_FPRF_from_FRT(dfp);
875
 
    dfp_check_for_VXSNAN(dfp);
876
 
}
877
 
 
878
 
DFP_HELPER_RINT(drintn, RINTN_PPs, 64)
879
 
DFP_HELPER_RINT(drintnq, RINTN_PPs, 128)
880
 
 
881
 
void helper_dctdp(CPUPPCState *env, uint64_t *t, uint64_t *b)
882
 
{
883
 
    struct PPC_DFP dfp;
884
 
    uint32_t b_short = *b;
885
 
    dfp_prepare_decimal64(&dfp, 0, 0, env);
886
 
    decimal32ToNumber((decimal32 *)&b_short, &dfp.t);
887
 
    decimal64FromNumber((decimal64 *)t, &dfp.t, &dfp.context);
888
 
    dfp_set_FPRF_from_FRT(&dfp);
889
 
}
890
 
 
891
 
void helper_dctqpq(CPUPPCState *env, uint64_t *t, uint64_t *b)
892
 
{
893
 
    struct PPC_DFP dfp;
894
 
    dfp_prepare_decimal128(&dfp, 0, 0, env);
895
 
    decimal64ToNumber((decimal64 *)b, &dfp.t);
896
 
 
897
 
    dfp_check_for_VXSNAN_and_convert_to_QNaN(&dfp);
898
 
    dfp_set_FPRF_from_FRT(&dfp);
899
 
 
900
 
    decimal128FromNumber((decimal128 *)&dfp.t64, &dfp.t, &dfp.context);
901
 
    t[0] = dfp.t64[HI_IDX];
902
 
    t[1] = dfp.t64[LO_IDX];
903
 
}
904
 
 
905
 
void helper_drsp(CPUPPCState *env, uint64_t *t, uint64_t *b)
906
 
{
907
 
    struct PPC_DFP dfp;
908
 
    uint32_t t_short = 0;
909
 
    dfp_prepare_decimal64(&dfp, 0, b, env);
910
 
    decimal32FromNumber((decimal32 *)&t_short, &dfp.b, &dfp.context);
911
 
    decimal32ToNumber((decimal32 *)&t_short, &dfp.t);
912
 
 
913
 
    dfp_set_FPRF_from_FRT_short(&dfp);
914
 
    dfp_check_for_OX(&dfp);
915
 
    dfp_check_for_UX(&dfp);
916
 
    dfp_check_for_XX(&dfp);
917
 
 
918
 
    *t = t_short;
919
 
}
920
 
 
921
 
void helper_drdpq(CPUPPCState *env, uint64_t *t, uint64_t *b)
922
 
{
923
 
    struct PPC_DFP dfp;
924
 
    dfp_prepare_decimal128(&dfp, 0, b, env);
925
 
    decimal64FromNumber((decimal64 *)&dfp.t64, &dfp.b, &dfp.context);
926
 
    decimal64ToNumber((decimal64 *)&dfp.t64, &dfp.t);
927
 
 
928
 
    dfp_check_for_VXSNAN_and_convert_to_QNaN(&dfp);
929
 
    dfp_set_FPRF_from_FRT_long(&dfp);
930
 
    dfp_check_for_OX(&dfp);
931
 
    dfp_check_for_UX(&dfp);
932
 
    dfp_check_for_XX(&dfp);
933
 
 
934
 
    decimal64FromNumber((decimal64 *)dfp.t64, &dfp.t, &dfp.context);
935
 
    t[0] = dfp.t64[0];
936
 
    t[1] = 0;
937
 
}
938
 
 
939
 
#define DFP_HELPER_CFFIX(op, size)                                             \
940
 
void helper_##op(CPUPPCState *env, uint64_t *t, uint64_t *b)                   \
941
 
{                                                                              \
942
 
    struct PPC_DFP dfp;                                                        \
943
 
    dfp_prepare_decimal##size(&dfp, 0, b, env);                                \
944
 
    decNumberFromInt64(&dfp.t, (int64_t)(*b));                                 \
945
 
    decimal##size##FromNumber((decimal##size *)dfp.t64, &dfp.t, &dfp.context); \
946
 
    CFFIX_PPs(&dfp);                                                           \
947
 
                                                                               \
948
 
    if (size == 64) {                                                          \
949
 
        t[0] = dfp.t64[0];                                                     \
950
 
    } else if (size == 128) {                                                  \
951
 
        t[0] = dfp.t64[HI_IDX];                                                \
952
 
        t[1] = dfp.t64[LO_IDX];                                                \
953
 
    }                                                                          \
954
 
}
955
 
 
956
 
static void CFFIX_PPs(struct PPC_DFP *dfp)
957
 
{
958
 
    dfp_set_FPRF_from_FRT(dfp);
959
 
    dfp_check_for_XX(dfp);
960
 
}
961
 
 
962
 
DFP_HELPER_CFFIX(dcffix, 64)
963
 
DFP_HELPER_CFFIX(dcffixq, 128)
964
 
 
965
 
#define DFP_HELPER_CTFIX(op, size)                                            \
966
 
void helper_##op(CPUPPCState *env, uint64_t *t, uint64_t *b)                  \
967
 
{                                                                             \
968
 
    struct PPC_DFP dfp;                                                       \
969
 
    dfp_prepare_decimal##size(&dfp, 0, b, env);                               \
970
 
                                                                              \
971
 
    if (unlikely(decNumberIsSpecial(&dfp.b))) {                               \
972
 
        uint64_t invalid_flags = FP_VX | FP_VXCVI;                            \
973
 
        if (decNumberIsInfinite(&dfp.b)) {                                    \
974
 
            dfp.t64[0] = decNumberIsNegative(&dfp.b) ? INT64_MIN : INT64_MAX; \
975
 
        } else { /* NaN */                                                    \
976
 
            dfp.t64[0] = INT64_MIN;                                           \
977
 
            if (decNumberIsSNaN(&dfp.b)) {                                    \
978
 
                invalid_flags |= FP_VXSNAN;                                   \
979
 
            }                                                                 \
980
 
        }                                                                     \
981
 
        dfp_set_FPSCR_flag(&dfp, invalid_flags, FP_VE);                       \
982
 
    } else if (unlikely(decNumberIsZero(&dfp.b))) {                           \
983
 
        dfp.t64[0] = 0;                                                       \
984
 
    } else {                                                                  \
985
 
        decNumberToIntegralExact(&dfp.b, &dfp.b, &dfp.context);               \
986
 
        dfp.t64[0] = decNumberIntegralToInt64(&dfp.b, &dfp.context);          \
987
 
        if (decContextTestStatus(&dfp.context, DEC_Invalid_operation)) {      \
988
 
            dfp.t64[0] = decNumberIsNegative(&dfp.b) ? INT64_MIN : INT64_MAX; \
989
 
            dfp_set_FPSCR_flag(&dfp, FP_VX | FP_VXCVI, FP_VE);                \
990
 
        } else {                                                              \
991
 
            dfp_check_for_XX(&dfp);                                           \
992
 
        }                                                                     \
993
 
    }                                                                         \
994
 
                                                                              \
995
 
    *t = dfp.t64[0];                                                          \
996
 
}
997
 
 
998
 
DFP_HELPER_CTFIX(dctfix, 64)
999
 
DFP_HELPER_CTFIX(dctfixq, 128)
1000
 
 
1001
 
static inline void dfp_set_bcd_digit_64(uint64_t *t, uint8_t digit,
1002
 
                                            unsigned n)
1003
 
{
1004
 
    *t |= ((uint64_t)(digit & 0xF) << (n << 2));
1005
 
}
1006
 
 
1007
 
static inline void dfp_set_bcd_digit_128(uint64_t *t, uint8_t digit,
1008
 
                                             unsigned n)
1009
 
{
1010
 
    t[(n & 0x10) ? HI_IDX : LO_IDX] |=
1011
 
        ((uint64_t)(digit & 0xF) << ((n & 15) << 2));
1012
 
}
1013
 
 
1014
 
static inline void dfp_set_sign_64(uint64_t *t, uint8_t sgn)
1015
 
{
1016
 
    *t <<= 4;
1017
 
    *t |= (sgn & 0xF);
1018
 
}
1019
 
 
1020
 
static inline void dfp_set_sign_128(uint64_t *t, uint8_t sgn)
1021
 
{
1022
 
    t[HI_IDX] <<= 4;
1023
 
    t[HI_IDX] |= (t[LO_IDX] >> 60);
1024
 
    t[LO_IDX] <<= 4;
1025
 
    t[LO_IDX] |= (sgn & 0xF);
1026
 
}
1027
 
 
1028
 
#define DFP_HELPER_DEDPD(op, size)                                        \
1029
 
void helper_##op(CPUPPCState *env, uint64_t *t, uint64_t *b, uint32_t sp) \
1030
 
{                                                                         \
1031
 
    struct PPC_DFP dfp;                                                   \
1032
 
    uint8_t digits[34];                                                   \
1033
 
    int i, N;                                                             \
1034
 
                                                                          \
1035
 
    dfp_prepare_decimal##size(&dfp, 0, b, env);                           \
1036
 
                                                                          \
1037
 
    decNumberGetBCD(&dfp.b, digits);                                      \
1038
 
    dfp.t64[0] = dfp.t64[1] = 0;                                          \
1039
 
    N = dfp.b.digits;                                                     \
1040
 
                                                                          \
1041
 
    for (i = 0; (i < N) && (i < (size)/4); i++) {                         \
1042
 
        dfp_set_bcd_digit_##size(dfp.t64, digits[N-i-1], i);              \
1043
 
    }                                                                     \
1044
 
                                                                          \
1045
 
    if (sp & 2) {                                                         \
1046
 
        uint8_t sgn;                                                      \
1047
 
                                                                          \
1048
 
        if (decNumberIsNegative(&dfp.b)) {                                \
1049
 
            sgn = 0xD;                                                    \
1050
 
        } else {                                                          \
1051
 
            sgn = ((sp & 1) ? 0xF : 0xC);                                 \
1052
 
        }                                                                 \
1053
 
        dfp_set_sign_##size(dfp.t64, sgn);                                \
1054
 
    }                                                                     \
1055
 
                                                                          \
1056
 
    if (size == 64) {                                                     \
1057
 
        t[0] = dfp.t64[0];                                                \
1058
 
    } else if (size == 128) {                                             \
1059
 
        t[0] = dfp.t64[HI_IDX];                                           \
1060
 
        t[1] = dfp.t64[LO_IDX];                                           \
1061
 
    }                                                                     \
1062
 
}
1063
 
 
1064
 
DFP_HELPER_DEDPD(ddedpd, 64)
1065
 
DFP_HELPER_DEDPD(ddedpdq, 128)
1066
 
 
1067
 
static inline uint8_t dfp_get_bcd_digit_64(uint64_t *t, unsigned n)
1068
 
{
1069
 
    return *t >> ((n << 2) & 63) & 15;
1070
 
}
1071
 
 
1072
 
static inline uint8_t dfp_get_bcd_digit_128(uint64_t *t, unsigned n)
1073
 
{
1074
 
    return t[(n & 0x10) ? HI_IDX : LO_IDX] >> ((n << 2) & 63) & 15;
1075
 
}
1076
 
 
1077
 
#define DFP_HELPER_ENBCD(op, size)                                           \
1078
 
void helper_##op(CPUPPCState *env, uint64_t *t, uint64_t *b, uint32_t s)     \
1079
 
{                                                                            \
1080
 
    struct PPC_DFP dfp;                                                      \
1081
 
    uint8_t digits[32];                                                      \
1082
 
    int n = 0, offset = 0, sgn = 0, nonzero = 0;                             \
1083
 
                                                                             \
1084
 
    dfp_prepare_decimal##size(&dfp, 0, b, env);                              \
1085
 
                                                                             \
1086
 
    decNumberZero(&dfp.t);                                                   \
1087
 
                                                                             \
1088
 
    if (s) {                                                                 \
1089
 
        uint8_t sgnNibble = dfp_get_bcd_digit_##size(dfp.b64, offset++);     \
1090
 
        switch (sgnNibble) {                                                 \
1091
 
        case 0xD:                                                            \
1092
 
        case 0xB:                                                            \
1093
 
            sgn = 1;                                                         \
1094
 
            break;                                                           \
1095
 
        case 0xC:                                                            \
1096
 
        case 0xF:                                                            \
1097
 
        case 0xA:                                                            \
1098
 
        case 0xE:                                                            \
1099
 
            sgn = 0;                                                         \
1100
 
            break;                                                           \
1101
 
        default:                                                             \
1102
 
            dfp_set_FPSCR_flag(&dfp, FP_VX | FP_VXCVI, FPSCR_VE);            \
1103
 
            return;                                                          \
1104
 
        }                                                                    \
1105
 
        }                                                                    \
1106
 
                                                                             \
1107
 
    while (offset < (size)/4) {                                              \
1108
 
        n++;                                                                 \
1109
 
        digits[(size)/4-n] = dfp_get_bcd_digit_##size(dfp.b64, offset++);    \
1110
 
        if (digits[(size)/4-n] > 10) {                                       \
1111
 
            dfp_set_FPSCR_flag(&dfp, FP_VX | FP_VXCVI, FPSCR_VE);            \
1112
 
            return;                                                          \
1113
 
        } else {                                                             \
1114
 
            nonzero |= (digits[(size)/4-n] > 0);                             \
1115
 
        }                                                                    \
1116
 
    }                                                                        \
1117
 
                                                                             \
1118
 
    if (nonzero) {                                                           \
1119
 
        decNumberSetBCD(&dfp.t, digits+((size)/4)-n, n);                     \
1120
 
    }                                                                        \
1121
 
                                                                             \
1122
 
    if (s && sgn)  {                                                         \
1123
 
        dfp.t.bits |= DECNEG;                                                \
1124
 
    }                                                                        \
1125
 
    decimal##size##FromNumber((decimal##size *)dfp.t64, &dfp.t,              \
1126
 
                              &dfp.context);                                 \
1127
 
    dfp_set_FPRF_from_FRT(&dfp);                                             \
1128
 
    if ((size) == 64) {                                                      \
1129
 
        t[0] = dfp.t64[0];                                                   \
1130
 
    } else if ((size) == 128) {                                              \
1131
 
        t[0] = dfp.t64[HI_IDX];                                              \
1132
 
        t[1] = dfp.t64[LO_IDX];                                              \
1133
 
    }                                                                        \
1134
 
}
1135
 
 
1136
 
DFP_HELPER_ENBCD(denbcd, 64)
1137
 
DFP_HELPER_ENBCD(denbcdq, 128)
1138
 
 
1139
 
#define DFP_HELPER_XEX(op, size)                               \
1140
 
void helper_##op(CPUPPCState *env, uint64_t *t, uint64_t *b)   \
1141
 
{                                                              \
1142
 
    struct PPC_DFP dfp;                                        \
1143
 
                                                               \
1144
 
    dfp_prepare_decimal##size(&dfp, 0, b, env);                \
1145
 
                                                               \
1146
 
    if (unlikely(decNumberIsSpecial(&dfp.b))) {                \
1147
 
        if (decNumberIsInfinite(&dfp.b)) {                     \
1148
 
            *t = -1;                                           \
1149
 
        } else if (decNumberIsSNaN(&dfp.b)) {                  \
1150
 
            *t = -3;                                           \
1151
 
        } else if (decNumberIsQNaN(&dfp.b)) {                  \
1152
 
            *t = -2;                                           \
1153
 
        } else {                                               \
1154
 
            assert(0);                                         \
1155
 
        }                                                      \
1156
 
    } else {                                                   \
1157
 
        if ((size) == 64) {                                    \
1158
 
            *t = dfp.b.exponent + 398;                         \
1159
 
        } else if ((size) == 128) {                            \
1160
 
            *t = dfp.b.exponent + 6176;                        \
1161
 
        } else {                                               \
1162
 
            assert(0);                                         \
1163
 
        }                                                      \
1164
 
    }                                                          \
1165
 
}
1166
 
 
1167
 
DFP_HELPER_XEX(dxex, 64)
1168
 
DFP_HELPER_XEX(dxexq, 128)
1169
 
 
1170
 
static void dfp_set_raw_exp_64(uint64_t *t, uint64_t raw)
1171
 
{
1172
 
    *t &= 0x8003ffffffffffffULL;
1173
 
    *t |= (raw << (63-13));
1174
 
}
1175
 
 
1176
 
static void dfp_set_raw_exp_128(uint64_t *t, uint64_t raw)
1177
 
{
1178
 
    t[HI_IDX] &= 0x80003fffffffffffULL;
1179
 
    t[HI_IDX] |= (raw << (63-17));
1180
 
}
1181
 
 
1182
 
#define DFP_HELPER_IEX(op, size)                                          \
1183
 
void helper_##op(CPUPPCState *env, uint64_t *t, uint64_t *a, uint64_t *b) \
1184
 
{                                                                         \
1185
 
    struct PPC_DFP dfp;                                                   \
1186
 
    uint64_t raw_qnan, raw_snan, raw_inf, max_exp;                        \
1187
 
    int bias;                                                             \
1188
 
    int64_t exp = *((int64_t *)a);                                        \
1189
 
                                                                          \
1190
 
    dfp_prepare_decimal##size(&dfp, 0, b, env);                           \
1191
 
                                                                          \
1192
 
    if ((size) == 64) {                                                   \
1193
 
        max_exp = 767;                                                    \
1194
 
        raw_qnan = 0x1F00;                                                \
1195
 
        raw_snan = 0x1F80;                                                \
1196
 
        raw_inf = 0x1E00;                                                 \
1197
 
        bias = 398;                                                       \
1198
 
    } else if ((size) == 128) {                                           \
1199
 
        max_exp = 12287;                                                  \
1200
 
        raw_qnan = 0x1f000;                                               \
1201
 
        raw_snan = 0x1f800;                                               \
1202
 
        raw_inf = 0x1e000;                                                \
1203
 
        bias = 6176;                                                      \
1204
 
    } else {                                                              \
1205
 
        assert(0);                                                        \
1206
 
    }                                                                     \
1207
 
                                                                          \
1208
 
    if (unlikely((exp < 0) || (exp > max_exp))) {                         \
1209
 
        dfp.t64[0] = dfp.b64[0];                                          \
1210
 
        dfp.t64[1] = dfp.b64[1];                                          \
1211
 
        if (exp == -1) {                                                  \
1212
 
            dfp_set_raw_exp_##size(dfp.t64, raw_inf);                     \
1213
 
        } else if (exp == -3) {                                           \
1214
 
            dfp_set_raw_exp_##size(dfp.t64, raw_snan);                    \
1215
 
        } else {                                                          \
1216
 
            dfp_set_raw_exp_##size(dfp.t64, raw_qnan);                    \
1217
 
        }                                                                 \
1218
 
    } else {                                                              \
1219
 
        dfp.t = dfp.b;                                                    \
1220
 
        if (unlikely(decNumberIsSpecial(&dfp.t))) {                       \
1221
 
            dfp.t.bits &= ~DECSPECIAL;                                    \
1222
 
        }                                                                 \
1223
 
        dfp.t.exponent = exp - bias;                                      \
1224
 
        decimal##size##FromNumber((decimal##size *)dfp.t64, &dfp.t,       \
1225
 
                                  &dfp.context);                          \
1226
 
    }                                                                     \
1227
 
    if (size == 64) {                                                     \
1228
 
        t[0] = dfp.t64[0];                                                \
1229
 
    } else if (size == 128) {                                             \
1230
 
        t[0] = dfp.t64[HI_IDX];                                           \
1231
 
        t[1] = dfp.t64[LO_IDX];                                           \
1232
 
    }                                                                     \
1233
 
}
1234
 
 
1235
 
DFP_HELPER_IEX(diex, 64)
1236
 
DFP_HELPER_IEX(diexq, 128)
1237
 
 
1238
 
static void dfp_clear_lmd_from_g5msb(uint64_t *t)
1239
 
{
1240
 
 
1241
 
    /* The most significant 5 bits of the PowerPC DFP format combine bits  */
1242
 
    /* from the left-most decimal digit (LMD) and the biased exponent.     */
1243
 
    /* This  routine clears the LMD bits while preserving the exponent     */
1244
 
    /*  bits.  See "Figure 80: Encoding of bits 0:4 of the G field for     */
1245
 
    /*  Finite Numbers" in the Power ISA for additional details.           */
1246
 
 
1247
 
    uint64_t g5msb = (*t >> 58) & 0x1F;
1248
 
 
1249
 
    if ((g5msb >> 3) < 3) { /* LMD in [0-7] ? */
1250
 
       *t &= ~(7ULL << 58);
1251
 
    } else {
1252
 
       switch (g5msb & 7) {
1253
 
       case 0:
1254
 
       case 1:
1255
 
           g5msb = 0;
1256
 
           break;
1257
 
       case 2:
1258
 
       case 3:
1259
 
           g5msb = 0x8;
1260
 
           break;
1261
 
       case 4:
1262
 
       case 5:
1263
 
           g5msb = 0x10;
1264
 
           break;
1265
 
       case 6:
1266
 
           g5msb = 0x1E;
1267
 
           break;
1268
 
       case 7:
1269
 
           g5msb = 0x1F;
1270
 
           break;
1271
 
       }
1272
 
 
1273
 
        *t &= ~(0x1fULL << 58);
1274
 
        *t |= (g5msb << 58);
1275
 
    }
1276
 
}
1277
 
 
1278
 
#define DFP_HELPER_SHIFT(op, size, shift_left)                      \
1279
 
void helper_##op(CPUPPCState *env, uint64_t *t, uint64_t *a,        \
1280
 
                 uint32_t sh)                                       \
1281
 
{                                                                   \
1282
 
    struct PPC_DFP dfp;                                             \
1283
 
    unsigned max_digits = ((size) == 64) ? 16 : 34;                 \
1284
 
                                                                    \
1285
 
    dfp_prepare_decimal##size(&dfp, a, 0, env);                     \
1286
 
                                                                    \
1287
 
    if (sh <= max_digits) {                                         \
1288
 
                                                                    \
1289
 
        decNumber shd;                                              \
1290
 
        unsigned special = dfp.a.bits & DECSPECIAL;                 \
1291
 
                                                                    \
1292
 
        if (shift_left) {                                           \
1293
 
            decNumberFromUInt32(&shd, sh);                          \
1294
 
        } else {                                                    \
1295
 
            decNumberFromInt32(&shd, -((int32_t)sh));               \
1296
 
        }                                                           \
1297
 
                                                                    \
1298
 
        dfp.a.bits &= ~DECSPECIAL;                                  \
1299
 
        decNumberShift(&dfp.t, &dfp.a, &shd, &dfp.context);         \
1300
 
                                                                    \
1301
 
        dfp.t.bits |= special;                                      \
1302
 
        if (special && (dfp.t.digits >= max_digits)) {              \
1303
 
            dfp.t.digits = max_digits - 1;                          \
1304
 
        }                                                           \
1305
 
                                                                    \
1306
 
        decimal##size##FromNumber((decimal##size *)dfp.t64, &dfp.t, \
1307
 
                                  &dfp.context);                    \
1308
 
    } else {                                                        \
1309
 
        if ((size) == 64) {                                         \
1310
 
            dfp.t64[0] = dfp.a64[0] & 0xFFFC000000000000ULL;        \
1311
 
            dfp_clear_lmd_from_g5msb(dfp.t64);                      \
1312
 
        } else {                                                    \
1313
 
            dfp.t64[HI_IDX] = dfp.a64[HI_IDX] &                     \
1314
 
                              0xFFFFC00000000000ULL;                \
1315
 
            dfp_clear_lmd_from_g5msb(dfp.t64 + HI_IDX);             \
1316
 
            dfp.t64[LO_IDX] = 0;                                    \
1317
 
        }                                                           \
1318
 
    }                                                               \
1319
 
                                                                    \
1320
 
    if ((size) == 64) {                                             \
1321
 
        t[0] = dfp.t64[0];                                          \
1322
 
    } else {                                                        \
1323
 
        t[0] = dfp.t64[HI_IDX];                                     \
1324
 
        t[1] = dfp.t64[LO_IDX];                                     \
1325
 
    }                                                               \
1326
 
}
1327
 
 
1328
 
DFP_HELPER_SHIFT(dscli, 64, 1)
1329
 
DFP_HELPER_SHIFT(dscliq, 128, 1)
1330
 
DFP_HELPER_SHIFT(dscri, 64, 0)
1331
 
DFP_HELPER_SHIFT(dscriq, 128, 0)