xref: /openbmc/qemu/target/ppc/dfp_helper.c (revision a1a65aad)
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         assert(0); /* should never get here */
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             assert(0);                                         \
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             assert(0);                                         \
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         assert(0);                                                        \
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