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