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