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