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