1fcf5ef2aSThomas Huth /*
2fcf5ef2aSThomas Huth * PowerPC Decimal Floating Point (DPF) emulation helpers for QEMU.
3fcf5ef2aSThomas Huth *
4fcf5ef2aSThomas Huth * Copyright (c) 2014 IBM Corporation.
5fcf5ef2aSThomas Huth *
6fcf5ef2aSThomas Huth * This library is free software; you can redistribute it and/or
7fcf5ef2aSThomas Huth * modify it under the terms of the GNU Lesser General Public
8fcf5ef2aSThomas Huth * License as published by the Free Software Foundation; either
96bd039cdSChetan Pant * version 2.1 of the License, or (at your option) any later version.
10fcf5ef2aSThomas Huth *
11fcf5ef2aSThomas Huth * This library is distributed in the hope that it will be useful,
12fcf5ef2aSThomas Huth * but WITHOUT ANY WARRANTY; without even the implied warranty of
13fcf5ef2aSThomas Huth * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14fcf5ef2aSThomas Huth * Lesser General Public License for more details.
15fcf5ef2aSThomas Huth *
16fcf5ef2aSThomas Huth * You should have received a copy of the GNU Lesser General Public
17fcf5ef2aSThomas Huth * License along with this library; if not, see <http://www.gnu.org/licenses/>.
18fcf5ef2aSThomas Huth */
19fcf5ef2aSThomas Huth
20fcf5ef2aSThomas Huth #include "qemu/osdep.h"
21fcf5ef2aSThomas Huth #include "cpu.h"
22fcf5ef2aSThomas Huth #include "exec/helper-proto.h"
23fcf5ef2aSThomas Huth
24fcf5ef2aSThomas Huth #define DECNUMDIGITS 34
25fcf5ef2aSThomas Huth #include "libdecnumber/decContext.h"
26fcf5ef2aSThomas Huth #include "libdecnumber/decNumber.h"
27fcf5ef2aSThomas Huth #include "libdecnumber/dpd/decimal32.h"
28fcf5ef2aSThomas Huth #include "libdecnumber/dpd/decimal64.h"
29fcf5ef2aSThomas Huth #include "libdecnumber/dpd/decimal128.h"
30fcf5ef2aSThomas Huth
31fcf5ef2aSThomas Huth
get_dfp64(ppc_vsr_t * dst,ppc_fprp_t * dfp)3264b8574eSMark Cave-Ayland static void get_dfp64(ppc_vsr_t *dst, ppc_fprp_t *dfp)
336a8fbb9bSMark Cave-Ayland {
3464b8574eSMark Cave-Ayland dst->VsrD(1) = dfp->VsrD(0);
356a8fbb9bSMark Cave-Ayland }
366a8fbb9bSMark Cave-Ayland
get_dfp128(ppc_vsr_t * dst,ppc_fprp_t * dfp)3764b8574eSMark Cave-Ayland static void get_dfp128(ppc_vsr_t *dst, ppc_fprp_t *dfp)
386a8fbb9bSMark Cave-Ayland {
3964b8574eSMark Cave-Ayland dst->VsrD(0) = dfp[0].VsrD(0);
4064b8574eSMark Cave-Ayland dst->VsrD(1) = dfp[1].VsrD(0);
416a8fbb9bSMark Cave-Ayland }
426a8fbb9bSMark Cave-Ayland
set_dfp64(ppc_fprp_t * dfp,ppc_vsr_t * src)4364b8574eSMark Cave-Ayland static void set_dfp64(ppc_fprp_t *dfp, ppc_vsr_t *src)
4433432d77SMark Cave-Ayland {
4534f760baSVíctor Colombo dfp[0].VsrD(0) = src->VsrD(1);
4634f760baSVíctor Colombo dfp[0].VsrD(1) = 0ULL;
4733432d77SMark Cave-Ayland }
4833432d77SMark Cave-Ayland
set_dfp128(ppc_fprp_t * dfp,ppc_vsr_t * src)4964b8574eSMark Cave-Ayland static void set_dfp128(ppc_fprp_t *dfp, ppc_vsr_t *src)
5033432d77SMark Cave-Ayland {
5164b8574eSMark Cave-Ayland dfp[0].VsrD(0) = src->VsrD(0);
5264b8574eSMark Cave-Ayland dfp[1].VsrD(0) = src->VsrD(1);
5334f760baSVíctor Colombo dfp[0].VsrD(1) = 0ULL;
5434f760baSVíctor Colombo dfp[1].VsrD(1) = 0ULL;
5533432d77SMark Cave-Ayland }
5633432d77SMark Cave-Ayland
set_dfp128_to_avr(ppc_avr_t * dst,ppc_vsr_t * src)57328747f3SLuis Pires static void set_dfp128_to_avr(ppc_avr_t *dst, ppc_vsr_t *src)
58328747f3SLuis Pires {
59328747f3SLuis Pires *dst = *src;
60328747f3SLuis Pires }
61328747f3SLuis Pires
62fcf5ef2aSThomas Huth struct PPC_DFP {
63fcf5ef2aSThomas Huth CPUPPCState *env;
6464b8574eSMark Cave-Ayland ppc_vsr_t vt, va, vb;
65fcf5ef2aSThomas Huth decNumber t, a, b;
66fcf5ef2aSThomas Huth decContext context;
67fcf5ef2aSThomas Huth uint8_t crbf;
68fcf5ef2aSThomas Huth };
69fcf5ef2aSThomas Huth
dfp_prepare_rounding_mode(decContext * context,uint64_t fpscr)70fcf5ef2aSThomas Huth static void dfp_prepare_rounding_mode(decContext *context, uint64_t fpscr)
71fcf5ef2aSThomas Huth {
72fcf5ef2aSThomas Huth enum rounding rnd;
73fcf5ef2aSThomas Huth
74a2735cf4SPaul A. Clarke switch ((fpscr & FP_DRN) >> FPSCR_DRN0) {
75fcf5ef2aSThomas Huth case 0:
76fcf5ef2aSThomas Huth rnd = DEC_ROUND_HALF_EVEN;
77fcf5ef2aSThomas Huth break;
78fcf5ef2aSThomas Huth case 1:
79fcf5ef2aSThomas Huth rnd = DEC_ROUND_DOWN;
80fcf5ef2aSThomas Huth break;
81fcf5ef2aSThomas Huth case 2:
82fcf5ef2aSThomas Huth rnd = DEC_ROUND_CEILING;
83fcf5ef2aSThomas Huth break;
84fcf5ef2aSThomas Huth case 3:
85fcf5ef2aSThomas Huth rnd = DEC_ROUND_FLOOR;
86fcf5ef2aSThomas Huth break;
87fcf5ef2aSThomas Huth case 4:
88fcf5ef2aSThomas Huth rnd = DEC_ROUND_HALF_UP;
89fcf5ef2aSThomas Huth break;
90fcf5ef2aSThomas Huth case 5:
91fcf5ef2aSThomas Huth rnd = DEC_ROUND_HALF_DOWN;
92fcf5ef2aSThomas Huth break;
93fcf5ef2aSThomas Huth case 6:
94fcf5ef2aSThomas Huth rnd = DEC_ROUND_UP;
95fcf5ef2aSThomas Huth break;
96fcf5ef2aSThomas Huth case 7:
97fcf5ef2aSThomas Huth rnd = DEC_ROUND_05UP;
98fcf5ef2aSThomas Huth break;
99fcf5ef2aSThomas Huth default:
100fcf5ef2aSThomas Huth g_assert_not_reached();
101fcf5ef2aSThomas Huth }
102fcf5ef2aSThomas Huth
103fcf5ef2aSThomas Huth decContextSetRounding(context, rnd);
104fcf5ef2aSThomas Huth }
105fcf5ef2aSThomas Huth
dfp_set_round_mode_from_immediate(uint8_t r,uint8_t rmc,struct PPC_DFP * dfp)106fcf5ef2aSThomas Huth static void dfp_set_round_mode_from_immediate(uint8_t r, uint8_t rmc,
107fcf5ef2aSThomas Huth struct PPC_DFP *dfp)
108fcf5ef2aSThomas Huth {
109fcf5ef2aSThomas Huth enum rounding rnd;
110fcf5ef2aSThomas Huth if (r == 0) {
111fcf5ef2aSThomas Huth switch (rmc & 3) {
112fcf5ef2aSThomas Huth case 0:
113fcf5ef2aSThomas Huth rnd = DEC_ROUND_HALF_EVEN;
114fcf5ef2aSThomas Huth break;
115fcf5ef2aSThomas Huth case 1:
116fcf5ef2aSThomas Huth rnd = DEC_ROUND_DOWN;
117fcf5ef2aSThomas Huth break;
118fcf5ef2aSThomas Huth case 2:
119fcf5ef2aSThomas Huth rnd = DEC_ROUND_HALF_UP;
120fcf5ef2aSThomas Huth break;
121fcf5ef2aSThomas Huth case 3: /* use FPSCR rounding mode */
122fcf5ef2aSThomas Huth return;
123fcf5ef2aSThomas Huth default:
124a1a65aadSPierrick Bouvier g_assert_not_reached();
125fcf5ef2aSThomas Huth }
126fcf5ef2aSThomas Huth } else { /* r == 1 */
127fcf5ef2aSThomas Huth switch (rmc & 3) {
128fcf5ef2aSThomas Huth case 0:
129fcf5ef2aSThomas Huth rnd = DEC_ROUND_CEILING;
130fcf5ef2aSThomas Huth break;
131fcf5ef2aSThomas Huth case 1:
132fcf5ef2aSThomas Huth rnd = DEC_ROUND_FLOOR;
133fcf5ef2aSThomas Huth break;
134fcf5ef2aSThomas Huth case 2:
135fcf5ef2aSThomas Huth rnd = DEC_ROUND_UP;
136fcf5ef2aSThomas Huth break;
137fcf5ef2aSThomas Huth case 3:
138fcf5ef2aSThomas Huth rnd = DEC_ROUND_HALF_DOWN;
139fcf5ef2aSThomas Huth break;
140fcf5ef2aSThomas Huth default:
141a1a65aadSPierrick Bouvier g_assert_not_reached();
142fcf5ef2aSThomas Huth }
143fcf5ef2aSThomas Huth }
144fcf5ef2aSThomas Huth decContextSetRounding(&dfp->context, rnd);
145fcf5ef2aSThomas Huth }
146fcf5ef2aSThomas Huth
dfp_prepare_decimal64(struct PPC_DFP * dfp,ppc_fprp_t * a,ppc_fprp_t * b,CPUPPCState * env)147d9acba31SMark Cave-Ayland static void dfp_prepare_decimal64(struct PPC_DFP *dfp, ppc_fprp_t *a,
148d9acba31SMark Cave-Ayland ppc_fprp_t *b, CPUPPCState *env)
149fcf5ef2aSThomas Huth {
150fcf5ef2aSThomas Huth decContextDefault(&dfp->context, DEC_INIT_DECIMAL64);
151fcf5ef2aSThomas Huth dfp_prepare_rounding_mode(&dfp->context, env->fpscr);
152fcf5ef2aSThomas Huth dfp->env = env;
153fcf5ef2aSThomas Huth
154fcf5ef2aSThomas Huth if (a) {
15564b8574eSMark Cave-Ayland get_dfp64(&dfp->va, a);
15664b8574eSMark Cave-Ayland decimal64ToNumber((decimal64 *)&dfp->va.VsrD(1), &dfp->a);
157fcf5ef2aSThomas Huth } else {
15864b8574eSMark Cave-Ayland dfp->va.VsrD(1) = 0;
159fcf5ef2aSThomas Huth decNumberZero(&dfp->a);
160fcf5ef2aSThomas Huth }
161fcf5ef2aSThomas Huth
162fcf5ef2aSThomas Huth if (b) {
16364b8574eSMark Cave-Ayland get_dfp64(&dfp->vb, b);
16464b8574eSMark Cave-Ayland decimal64ToNumber((decimal64 *)&dfp->vb.VsrD(1), &dfp->b);
165fcf5ef2aSThomas Huth } else {
16664b8574eSMark Cave-Ayland dfp->vb.VsrD(1) = 0;
167fcf5ef2aSThomas Huth decNumberZero(&dfp->b);
168fcf5ef2aSThomas Huth }
169fcf5ef2aSThomas Huth }
170fcf5ef2aSThomas Huth
dfp_prepare_decimal128(struct PPC_DFP * dfp,ppc_fprp_t * a,ppc_fprp_t * b,CPUPPCState * env)171d9acba31SMark Cave-Ayland static void dfp_prepare_decimal128(struct PPC_DFP *dfp, ppc_fprp_t *a,
172d9acba31SMark Cave-Ayland ppc_fprp_t *b, CPUPPCState *env)
173fcf5ef2aSThomas Huth {
174fcf5ef2aSThomas Huth decContextDefault(&dfp->context, DEC_INIT_DECIMAL128);
175fcf5ef2aSThomas Huth dfp_prepare_rounding_mode(&dfp->context, env->fpscr);
176fcf5ef2aSThomas Huth dfp->env = env;
177fcf5ef2aSThomas Huth
178fcf5ef2aSThomas Huth if (a) {
17964b8574eSMark Cave-Ayland get_dfp128(&dfp->va, a);
18064b8574eSMark Cave-Ayland decimal128ToNumber((decimal128 *)&dfp->va, &dfp->a);
181fcf5ef2aSThomas Huth } else {
18264b8574eSMark Cave-Ayland dfp->va.VsrD(0) = dfp->va.VsrD(1) = 0;
183fcf5ef2aSThomas Huth decNumberZero(&dfp->a);
184fcf5ef2aSThomas Huth }
185fcf5ef2aSThomas Huth
186fcf5ef2aSThomas Huth if (b) {
18764b8574eSMark Cave-Ayland get_dfp128(&dfp->vb, b);
18864b8574eSMark Cave-Ayland decimal128ToNumber((decimal128 *)&dfp->vb, &dfp->b);
189fcf5ef2aSThomas Huth } else {
19064b8574eSMark Cave-Ayland dfp->vb.VsrD(0) = dfp->vb.VsrD(1) = 0;
191fcf5ef2aSThomas Huth decNumberZero(&dfp->b);
192fcf5ef2aSThomas Huth }
193fcf5ef2aSThomas Huth }
194fcf5ef2aSThomas Huth
dfp_finalize_decimal64(struct PPC_DFP * dfp)195474c2e93SMark Cave-Ayland static void dfp_finalize_decimal64(struct PPC_DFP *dfp)
196474c2e93SMark Cave-Ayland {
19764b8574eSMark Cave-Ayland decimal64FromNumber((decimal64 *)&dfp->vt.VsrD(1), &dfp->t, &dfp->context);
198474c2e93SMark Cave-Ayland }
199474c2e93SMark Cave-Ayland
dfp_finalize_decimal128(struct PPC_DFP * dfp)200474c2e93SMark Cave-Ayland static void dfp_finalize_decimal128(struct PPC_DFP *dfp)
201474c2e93SMark Cave-Ayland {
20264b8574eSMark Cave-Ayland decimal128FromNumber((decimal128 *)&dfp->vt, &dfp->t, &dfp->context);
203474c2e93SMark Cave-Ayland }
204474c2e93SMark Cave-Ayland
dfp_set_FPSCR_flag(struct PPC_DFP * dfp,uint64_t flag,uint64_t enabled)205fcf5ef2aSThomas Huth static void dfp_set_FPSCR_flag(struct PPC_DFP *dfp, uint64_t flag,
206fcf5ef2aSThomas Huth uint64_t enabled)
207fcf5ef2aSThomas Huth {
208fcf5ef2aSThomas Huth dfp->env->fpscr |= (flag | FP_FX);
209fcf5ef2aSThomas Huth if (dfp->env->fpscr & enabled) {
210fcf5ef2aSThomas Huth dfp->env->fpscr |= FP_FEX;
211fcf5ef2aSThomas Huth }
212fcf5ef2aSThomas Huth }
213fcf5ef2aSThomas Huth
dfp_set_FPRF_from_FRT_with_context(struct PPC_DFP * dfp,decContext * context)214fcf5ef2aSThomas Huth static void dfp_set_FPRF_from_FRT_with_context(struct PPC_DFP *dfp,
215fcf5ef2aSThomas Huth decContext *context)
216fcf5ef2aSThomas Huth {
217fcf5ef2aSThomas Huth uint64_t fprf = 0;
218fcf5ef2aSThomas Huth
219fcf5ef2aSThomas Huth /* construct FPRF */
220fcf5ef2aSThomas Huth switch (decNumberClass(&dfp->t, context)) {
221fcf5ef2aSThomas Huth case DEC_CLASS_SNAN:
222fcf5ef2aSThomas Huth fprf = 0x01;
223fcf5ef2aSThomas Huth break;
224fcf5ef2aSThomas Huth case DEC_CLASS_QNAN:
225fcf5ef2aSThomas Huth fprf = 0x11;
226fcf5ef2aSThomas Huth break;
227fcf5ef2aSThomas Huth case DEC_CLASS_NEG_INF:
228fcf5ef2aSThomas Huth fprf = 0x09;
229fcf5ef2aSThomas Huth break;
230fcf5ef2aSThomas Huth case DEC_CLASS_NEG_NORMAL:
231fcf5ef2aSThomas Huth fprf = 0x08;
232fcf5ef2aSThomas Huth break;
233fcf5ef2aSThomas Huth case DEC_CLASS_NEG_SUBNORMAL:
234fcf5ef2aSThomas Huth fprf = 0x18;
235fcf5ef2aSThomas Huth break;
236fcf5ef2aSThomas Huth case DEC_CLASS_NEG_ZERO:
237fcf5ef2aSThomas Huth fprf = 0x12;
238fcf5ef2aSThomas Huth break;
239fcf5ef2aSThomas Huth case DEC_CLASS_POS_ZERO:
240fcf5ef2aSThomas Huth fprf = 0x02;
241fcf5ef2aSThomas Huth break;
242fcf5ef2aSThomas Huth case DEC_CLASS_POS_SUBNORMAL:
243fcf5ef2aSThomas Huth fprf = 0x14;
244fcf5ef2aSThomas Huth break;
245fcf5ef2aSThomas Huth case DEC_CLASS_POS_NORMAL:
246fcf5ef2aSThomas Huth fprf = 0x04;
247fcf5ef2aSThomas Huth break;
248fcf5ef2aSThomas Huth case DEC_CLASS_POS_INF:
249fcf5ef2aSThomas Huth fprf = 0x05;
250fcf5ef2aSThomas Huth break;
251fcf5ef2aSThomas Huth default:
252*52d9ffd8SPierrick Bouvier g_assert_not_reached();
253fcf5ef2aSThomas Huth }
2545c94dd38SPaul A. Clarke dfp->env->fpscr &= ~FP_FPRF;
2555c94dd38SPaul A. Clarke dfp->env->fpscr |= (fprf << FPSCR_FPRF);
256fcf5ef2aSThomas Huth }
257fcf5ef2aSThomas Huth
dfp_set_FPRF_from_FRT(struct PPC_DFP * dfp)258fcf5ef2aSThomas Huth static void dfp_set_FPRF_from_FRT(struct PPC_DFP *dfp)
259fcf5ef2aSThomas Huth {
260fcf5ef2aSThomas Huth dfp_set_FPRF_from_FRT_with_context(dfp, &dfp->context);
261fcf5ef2aSThomas Huth }
262fcf5ef2aSThomas Huth
dfp_set_FPRF_from_FRT_short(struct PPC_DFP * dfp)263fcf5ef2aSThomas Huth static void dfp_set_FPRF_from_FRT_short(struct PPC_DFP *dfp)
264fcf5ef2aSThomas Huth {
265fcf5ef2aSThomas Huth decContext shortContext;
266fcf5ef2aSThomas Huth decContextDefault(&shortContext, DEC_INIT_DECIMAL32);
267fcf5ef2aSThomas Huth dfp_set_FPRF_from_FRT_with_context(dfp, &shortContext);
268fcf5ef2aSThomas Huth }
269fcf5ef2aSThomas Huth
dfp_set_FPRF_from_FRT_long(struct PPC_DFP * dfp)270fcf5ef2aSThomas Huth static void dfp_set_FPRF_from_FRT_long(struct PPC_DFP *dfp)
271fcf5ef2aSThomas Huth {
272fcf5ef2aSThomas Huth decContext longContext;
273fcf5ef2aSThomas Huth decContextDefault(&longContext, DEC_INIT_DECIMAL64);
274fcf5ef2aSThomas Huth dfp_set_FPRF_from_FRT_with_context(dfp, &longContext);
275fcf5ef2aSThomas Huth }
276fcf5ef2aSThomas Huth
dfp_check_for_OX(struct PPC_DFP * dfp)277fcf5ef2aSThomas Huth static void dfp_check_for_OX(struct PPC_DFP *dfp)
278fcf5ef2aSThomas Huth {
279fcf5ef2aSThomas Huth if (dfp->context.status & DEC_Overflow) {
280fcf5ef2aSThomas Huth dfp_set_FPSCR_flag(dfp, FP_OX, FP_OE);
281fcf5ef2aSThomas Huth }
282fcf5ef2aSThomas Huth }
283fcf5ef2aSThomas Huth
dfp_check_for_UX(struct PPC_DFP * dfp)284fcf5ef2aSThomas Huth static void dfp_check_for_UX(struct PPC_DFP *dfp)
285fcf5ef2aSThomas Huth {
286fcf5ef2aSThomas Huth if (dfp->context.status & DEC_Underflow) {
287fcf5ef2aSThomas Huth dfp_set_FPSCR_flag(dfp, FP_UX, FP_UE);
288fcf5ef2aSThomas Huth }
289fcf5ef2aSThomas Huth }
290fcf5ef2aSThomas Huth
dfp_check_for_XX(struct PPC_DFP * dfp)291fcf5ef2aSThomas Huth static void dfp_check_for_XX(struct PPC_DFP *dfp)
292fcf5ef2aSThomas Huth {
293fcf5ef2aSThomas Huth if (dfp->context.status & DEC_Inexact) {
294fcf5ef2aSThomas Huth dfp_set_FPSCR_flag(dfp, FP_XX | FP_FI, FP_XE);
295fcf5ef2aSThomas Huth }
296fcf5ef2aSThomas Huth }
297fcf5ef2aSThomas Huth
dfp_check_for_ZX(struct PPC_DFP * dfp)298fcf5ef2aSThomas Huth static void dfp_check_for_ZX(struct PPC_DFP *dfp)
299fcf5ef2aSThomas Huth {
300fcf5ef2aSThomas Huth if (dfp->context.status & DEC_Division_by_zero) {
301fcf5ef2aSThomas Huth dfp_set_FPSCR_flag(dfp, FP_ZX, FP_ZE);
302fcf5ef2aSThomas Huth }
303fcf5ef2aSThomas Huth }
304fcf5ef2aSThomas Huth
dfp_check_for_VXSNAN(struct PPC_DFP * dfp)305fcf5ef2aSThomas Huth static void dfp_check_for_VXSNAN(struct PPC_DFP *dfp)
306fcf5ef2aSThomas Huth {
307fcf5ef2aSThomas Huth if (dfp->context.status & DEC_Invalid_operation) {
308fcf5ef2aSThomas Huth if (decNumberIsSNaN(&dfp->a) || decNumberIsSNaN(&dfp->b)) {
309fcf5ef2aSThomas Huth dfp_set_FPSCR_flag(dfp, FP_VX | FP_VXSNAN, FP_VE);
310fcf5ef2aSThomas Huth }
311fcf5ef2aSThomas Huth }
312fcf5ef2aSThomas Huth }
313fcf5ef2aSThomas Huth
dfp_check_for_VXSNAN_and_convert_to_QNaN(struct PPC_DFP * dfp)314fcf5ef2aSThomas Huth static void dfp_check_for_VXSNAN_and_convert_to_QNaN(struct PPC_DFP *dfp)
315fcf5ef2aSThomas Huth {
316fcf5ef2aSThomas Huth if (decNumberIsSNaN(&dfp->t)) {
317fcf5ef2aSThomas Huth dfp->t.bits &= ~DECSNAN;
318fcf5ef2aSThomas Huth dfp->t.bits |= DECNAN;
319fcf5ef2aSThomas Huth dfp_set_FPSCR_flag(dfp, FP_VX | FP_VXSNAN, FP_VE);
320fcf5ef2aSThomas Huth }
321fcf5ef2aSThomas Huth }
322fcf5ef2aSThomas Huth
dfp_check_for_VXISI(struct PPC_DFP * dfp,int testForSameSign)323fcf5ef2aSThomas Huth static void dfp_check_for_VXISI(struct PPC_DFP *dfp, int testForSameSign)
324fcf5ef2aSThomas Huth {
325fcf5ef2aSThomas Huth if (dfp->context.status & DEC_Invalid_operation) {
326fcf5ef2aSThomas Huth if (decNumberIsInfinite(&dfp->a) && decNumberIsInfinite(&dfp->b)) {
327fcf5ef2aSThomas Huth int same = decNumberClass(&dfp->a, &dfp->context) ==
328fcf5ef2aSThomas Huth decNumberClass(&dfp->b, &dfp->context);
329fcf5ef2aSThomas Huth if ((same && testForSameSign) || (!same && !testForSameSign)) {
330fcf5ef2aSThomas Huth dfp_set_FPSCR_flag(dfp, FP_VX | FP_VXISI, FP_VE);
331fcf5ef2aSThomas Huth }
332fcf5ef2aSThomas Huth }
333fcf5ef2aSThomas Huth }
334fcf5ef2aSThomas Huth }
335fcf5ef2aSThomas Huth
dfp_check_for_VXISI_add(struct PPC_DFP * dfp)336fcf5ef2aSThomas Huth static void dfp_check_for_VXISI_add(struct PPC_DFP *dfp)
337fcf5ef2aSThomas Huth {
338fcf5ef2aSThomas Huth dfp_check_for_VXISI(dfp, 0);
339fcf5ef2aSThomas Huth }
340fcf5ef2aSThomas Huth
dfp_check_for_VXISI_subtract(struct PPC_DFP * dfp)341fcf5ef2aSThomas Huth static void dfp_check_for_VXISI_subtract(struct PPC_DFP *dfp)
342fcf5ef2aSThomas Huth {
343fcf5ef2aSThomas Huth dfp_check_for_VXISI(dfp, 1);
344fcf5ef2aSThomas Huth }
345fcf5ef2aSThomas Huth
dfp_check_for_VXIMZ(struct PPC_DFP * dfp)346fcf5ef2aSThomas Huth static void dfp_check_for_VXIMZ(struct PPC_DFP *dfp)
347fcf5ef2aSThomas Huth {
348fcf5ef2aSThomas Huth if (dfp->context.status & DEC_Invalid_operation) {
349fcf5ef2aSThomas Huth if ((decNumberIsInfinite(&dfp->a) && decNumberIsZero(&dfp->b)) ||
350fcf5ef2aSThomas Huth (decNumberIsInfinite(&dfp->b) && decNumberIsZero(&dfp->a))) {
351fcf5ef2aSThomas Huth dfp_set_FPSCR_flag(dfp, FP_VX | FP_VXIMZ, FP_VE);
352fcf5ef2aSThomas Huth }
353fcf5ef2aSThomas Huth }
354fcf5ef2aSThomas Huth }
355fcf5ef2aSThomas Huth
dfp_check_for_VXZDZ(struct PPC_DFP * dfp)356fcf5ef2aSThomas Huth static void dfp_check_for_VXZDZ(struct PPC_DFP *dfp)
357fcf5ef2aSThomas Huth {
358fcf5ef2aSThomas Huth if (dfp->context.status & DEC_Division_undefined) {
359fcf5ef2aSThomas Huth dfp_set_FPSCR_flag(dfp, FP_VX | FP_VXZDZ, FP_VE);
360fcf5ef2aSThomas Huth }
361fcf5ef2aSThomas Huth }
362fcf5ef2aSThomas Huth
dfp_check_for_VXIDI(struct PPC_DFP * dfp)363fcf5ef2aSThomas Huth static void dfp_check_for_VXIDI(struct PPC_DFP *dfp)
364fcf5ef2aSThomas Huth {
365fcf5ef2aSThomas Huth if (dfp->context.status & DEC_Invalid_operation) {
366fcf5ef2aSThomas Huth if (decNumberIsInfinite(&dfp->a) && decNumberIsInfinite(&dfp->b)) {
367fcf5ef2aSThomas Huth dfp_set_FPSCR_flag(dfp, FP_VX | FP_VXIDI, FP_VE);
368fcf5ef2aSThomas Huth }
369fcf5ef2aSThomas Huth }
370fcf5ef2aSThomas Huth }
371fcf5ef2aSThomas Huth
dfp_check_for_VXVC(struct PPC_DFP * dfp)372fcf5ef2aSThomas Huth static void dfp_check_for_VXVC(struct PPC_DFP *dfp)
373fcf5ef2aSThomas Huth {
374fcf5ef2aSThomas Huth if (decNumberIsNaN(&dfp->a) || decNumberIsNaN(&dfp->b)) {
375fcf5ef2aSThomas Huth dfp_set_FPSCR_flag(dfp, FP_VX | FP_VXVC, FP_VE);
376fcf5ef2aSThomas Huth }
377fcf5ef2aSThomas Huth }
378fcf5ef2aSThomas Huth
dfp_check_for_VXCVI(struct PPC_DFP * dfp)379fcf5ef2aSThomas Huth static void dfp_check_for_VXCVI(struct PPC_DFP *dfp)
380fcf5ef2aSThomas Huth {
381fcf5ef2aSThomas Huth if ((dfp->context.status & DEC_Invalid_operation) &&
382fcf5ef2aSThomas Huth (!decNumberIsSNaN(&dfp->a)) &&
383fcf5ef2aSThomas Huth (!decNumberIsSNaN(&dfp->b))) {
384fcf5ef2aSThomas Huth dfp_set_FPSCR_flag(dfp, FP_VX | FP_VXCVI, FP_VE);
385fcf5ef2aSThomas Huth }
386fcf5ef2aSThomas Huth }
387fcf5ef2aSThomas Huth
dfp_set_CRBF_from_T(struct PPC_DFP * dfp)388fcf5ef2aSThomas Huth static void dfp_set_CRBF_from_T(struct PPC_DFP *dfp)
389fcf5ef2aSThomas Huth {
390fcf5ef2aSThomas Huth if (decNumberIsNaN(&dfp->t)) {
391fcf5ef2aSThomas Huth dfp->crbf = 1;
392fcf5ef2aSThomas Huth } else if (decNumberIsZero(&dfp->t)) {
393fcf5ef2aSThomas Huth dfp->crbf = 2;
394fcf5ef2aSThomas Huth } else if (decNumberIsNegative(&dfp->t)) {
395fcf5ef2aSThomas Huth dfp->crbf = 8;
396fcf5ef2aSThomas Huth } else {
397fcf5ef2aSThomas Huth dfp->crbf = 4;
398fcf5ef2aSThomas Huth }
399fcf5ef2aSThomas Huth }
400fcf5ef2aSThomas Huth
dfp_set_FPCC_from_CRBF(struct PPC_DFP * dfp)401fcf5ef2aSThomas Huth static void dfp_set_FPCC_from_CRBF(struct PPC_DFP *dfp)
402fcf5ef2aSThomas Huth {
4035c94dd38SPaul A. Clarke dfp->env->fpscr &= ~FP_FPCC;
4045c94dd38SPaul A. Clarke dfp->env->fpscr |= (dfp->crbf << FPSCR_FPCC);
405fcf5ef2aSThomas Huth }
406fcf5ef2aSThomas Huth
dfp_makeQNaN(decNumber * dn)407fcf5ef2aSThomas Huth static inline void dfp_makeQNaN(decNumber *dn)
408fcf5ef2aSThomas Huth {
409fcf5ef2aSThomas Huth dn->bits &= ~DECSPECIAL;
410fcf5ef2aSThomas Huth dn->bits |= DECNAN;
411fcf5ef2aSThomas Huth }
412fcf5ef2aSThomas Huth
dfp_get_digit(decNumber * dn,int n)413fcf5ef2aSThomas Huth static inline int dfp_get_digit(decNumber *dn, int n)
414fcf5ef2aSThomas Huth {
415fcf5ef2aSThomas Huth assert(DECDPUN == 3);
416fcf5ef2aSThomas Huth int unit = n / DECDPUN;
417fcf5ef2aSThomas Huth int dig = n % DECDPUN;
418fcf5ef2aSThomas Huth switch (dig) {
419fcf5ef2aSThomas Huth case 0:
420fcf5ef2aSThomas Huth return dn->lsu[unit] % 10;
421fcf5ef2aSThomas Huth case 1:
422fcf5ef2aSThomas Huth return (dn->lsu[unit] / 10) % 10;
423fcf5ef2aSThomas Huth case 2:
424fcf5ef2aSThomas Huth return dn->lsu[unit] / 100;
425fcf5ef2aSThomas Huth }
426fcf5ef2aSThomas Huth g_assert_not_reached();
427fcf5ef2aSThomas Huth }
428fcf5ef2aSThomas Huth
429fcf5ef2aSThomas Huth #define DFP_HELPER_TAB(op, dnop, postprocs, size) \
430d9acba31SMark Cave-Ayland void helper_##op(CPUPPCState *env, ppc_fprp_t *t, ppc_fprp_t *a, \
431d9acba31SMark Cave-Ayland ppc_fprp_t *b) \
432fcf5ef2aSThomas Huth { \
433fcf5ef2aSThomas Huth struct PPC_DFP dfp; \
434fcf5ef2aSThomas Huth dfp_prepare_decimal##size(&dfp, a, b, env); \
435fcf5ef2aSThomas Huth dnop(&dfp.t, &dfp.a, &dfp.b, &dfp.context); \
436474c2e93SMark Cave-Ayland dfp_finalize_decimal##size(&dfp); \
437fcf5ef2aSThomas Huth postprocs(&dfp); \
438f6d4c423SMark Cave-Ayland set_dfp##size(t, &dfp.vt); \
439fcf5ef2aSThomas Huth }
440fcf5ef2aSThomas Huth
ADD_PPs(struct PPC_DFP * dfp)441fcf5ef2aSThomas Huth static void ADD_PPs(struct PPC_DFP *dfp)
442fcf5ef2aSThomas Huth {
443fcf5ef2aSThomas Huth dfp_set_FPRF_from_FRT(dfp);
444fcf5ef2aSThomas Huth dfp_check_for_OX(dfp);
445fcf5ef2aSThomas Huth dfp_check_for_UX(dfp);
446fcf5ef2aSThomas Huth dfp_check_for_XX(dfp);
447fcf5ef2aSThomas Huth dfp_check_for_VXSNAN(dfp);
448fcf5ef2aSThomas Huth dfp_check_for_VXISI_add(dfp);
449fcf5ef2aSThomas Huth }
450fcf5ef2aSThomas Huth
451afdc9310SLuis Pires DFP_HELPER_TAB(DADD, decNumberAdd, ADD_PPs, 64)
452afdc9310SLuis Pires DFP_HELPER_TAB(DADDQ, decNumberAdd, ADD_PPs, 128)
453fcf5ef2aSThomas Huth
SUB_PPs(struct PPC_DFP * dfp)454fcf5ef2aSThomas Huth static void SUB_PPs(struct PPC_DFP *dfp)
455fcf5ef2aSThomas Huth {
456fcf5ef2aSThomas Huth dfp_set_FPRF_from_FRT(dfp);
457fcf5ef2aSThomas Huth dfp_check_for_OX(dfp);
458fcf5ef2aSThomas Huth dfp_check_for_UX(dfp);
459fcf5ef2aSThomas Huth dfp_check_for_XX(dfp);
460fcf5ef2aSThomas Huth dfp_check_for_VXSNAN(dfp);
461fcf5ef2aSThomas Huth dfp_check_for_VXISI_subtract(dfp);
462fcf5ef2aSThomas Huth }
463fcf5ef2aSThomas Huth
464afdc9310SLuis Pires DFP_HELPER_TAB(DSUB, decNumberSubtract, SUB_PPs, 64)
465afdc9310SLuis Pires DFP_HELPER_TAB(DSUBQ, decNumberSubtract, SUB_PPs, 128)
466fcf5ef2aSThomas Huth
MUL_PPs(struct PPC_DFP * dfp)467fcf5ef2aSThomas Huth static void MUL_PPs(struct PPC_DFP *dfp)
468fcf5ef2aSThomas Huth {
469fcf5ef2aSThomas Huth dfp_set_FPRF_from_FRT(dfp);
470fcf5ef2aSThomas Huth dfp_check_for_OX(dfp);
471fcf5ef2aSThomas Huth dfp_check_for_UX(dfp);
472fcf5ef2aSThomas Huth dfp_check_for_XX(dfp);
473fcf5ef2aSThomas Huth dfp_check_for_VXSNAN(dfp);
474fcf5ef2aSThomas Huth dfp_check_for_VXIMZ(dfp);
475fcf5ef2aSThomas Huth }
476fcf5ef2aSThomas Huth
477afdc9310SLuis Pires DFP_HELPER_TAB(DMUL, decNumberMultiply, MUL_PPs, 64)
478afdc9310SLuis Pires DFP_HELPER_TAB(DMULQ, decNumberMultiply, MUL_PPs, 128)
479fcf5ef2aSThomas Huth
DIV_PPs(struct PPC_DFP * dfp)480fcf5ef2aSThomas Huth static void DIV_PPs(struct PPC_DFP *dfp)
481fcf5ef2aSThomas Huth {
482fcf5ef2aSThomas Huth dfp_set_FPRF_from_FRT(dfp);
483fcf5ef2aSThomas Huth dfp_check_for_OX(dfp);
484fcf5ef2aSThomas Huth dfp_check_for_UX(dfp);
485fcf5ef2aSThomas Huth dfp_check_for_ZX(dfp);
486fcf5ef2aSThomas Huth dfp_check_for_XX(dfp);
487fcf5ef2aSThomas Huth dfp_check_for_VXSNAN(dfp);
488fcf5ef2aSThomas Huth dfp_check_for_VXZDZ(dfp);
489fcf5ef2aSThomas Huth dfp_check_for_VXIDI(dfp);
490fcf5ef2aSThomas Huth }
491fcf5ef2aSThomas Huth
492afdc9310SLuis Pires DFP_HELPER_TAB(DDIV, decNumberDivide, DIV_PPs, 64)
493afdc9310SLuis Pires DFP_HELPER_TAB(DDIVQ, decNumberDivide, DIV_PPs, 128)
494fcf5ef2aSThomas Huth
495fcf5ef2aSThomas Huth #define DFP_HELPER_BF_AB(op, dnop, postprocs, size) \
496d9acba31SMark Cave-Ayland uint32_t helper_##op(CPUPPCState *env, ppc_fprp_t *a, ppc_fprp_t *b) \
497fcf5ef2aSThomas Huth { \
498fcf5ef2aSThomas Huth struct PPC_DFP dfp; \
499fcf5ef2aSThomas Huth dfp_prepare_decimal##size(&dfp, a, b, env); \
500fcf5ef2aSThomas Huth dnop(&dfp.t, &dfp.a, &dfp.b, &dfp.context); \
501474c2e93SMark Cave-Ayland dfp_finalize_decimal##size(&dfp); \
502fcf5ef2aSThomas Huth postprocs(&dfp); \
503fcf5ef2aSThomas Huth return dfp.crbf; \
504fcf5ef2aSThomas Huth }
505fcf5ef2aSThomas Huth
CMPU_PPs(struct PPC_DFP * dfp)506fcf5ef2aSThomas Huth static void CMPU_PPs(struct PPC_DFP *dfp)
507fcf5ef2aSThomas Huth {
508fcf5ef2aSThomas Huth dfp_set_CRBF_from_T(dfp);
509fcf5ef2aSThomas Huth dfp_set_FPCC_from_CRBF(dfp);
510fcf5ef2aSThomas Huth dfp_check_for_VXSNAN(dfp);
511fcf5ef2aSThomas Huth }
512fcf5ef2aSThomas Huth
51385c38a46SLuis Pires DFP_HELPER_BF_AB(DCMPU, decNumberCompare, CMPU_PPs, 64)
51485c38a46SLuis Pires DFP_HELPER_BF_AB(DCMPUQ, decNumberCompare, CMPU_PPs, 128)
515fcf5ef2aSThomas Huth
CMPO_PPs(struct PPC_DFP * dfp)516fcf5ef2aSThomas Huth static void CMPO_PPs(struct PPC_DFP *dfp)
517fcf5ef2aSThomas Huth {
518fcf5ef2aSThomas Huth dfp_set_CRBF_from_T(dfp);
519fcf5ef2aSThomas Huth dfp_set_FPCC_from_CRBF(dfp);
520fcf5ef2aSThomas Huth dfp_check_for_VXSNAN(dfp);
521fcf5ef2aSThomas Huth dfp_check_for_VXVC(dfp);
522fcf5ef2aSThomas Huth }
523fcf5ef2aSThomas Huth
52485c38a46SLuis Pires DFP_HELPER_BF_AB(DCMPO, decNumberCompare, CMPO_PPs, 64)
52585c38a46SLuis Pires DFP_HELPER_BF_AB(DCMPOQ, decNumberCompare, CMPO_PPs, 128)
526fcf5ef2aSThomas Huth
527fcf5ef2aSThomas Huth #define DFP_HELPER_TSTDC(op, size) \
528d9acba31SMark Cave-Ayland uint32_t helper_##op(CPUPPCState *env, ppc_fprp_t *a, uint32_t dcm) \
529fcf5ef2aSThomas Huth { \
530fcf5ef2aSThomas Huth struct PPC_DFP dfp; \
531fcf5ef2aSThomas Huth int match = 0; \
532fcf5ef2aSThomas Huth \
533fcf5ef2aSThomas Huth dfp_prepare_decimal##size(&dfp, a, 0, env); \
534fcf5ef2aSThomas Huth \
535fcf5ef2aSThomas Huth match |= (dcm & 0x20) && decNumberIsZero(&dfp.a); \
536fcf5ef2aSThomas Huth match |= (dcm & 0x10) && decNumberIsSubnormal(&dfp.a, &dfp.context); \
537fcf5ef2aSThomas Huth match |= (dcm & 0x08) && decNumberIsNormal(&dfp.a, &dfp.context); \
538fcf5ef2aSThomas Huth match |= (dcm & 0x04) && decNumberIsInfinite(&dfp.a); \
539fcf5ef2aSThomas Huth match |= (dcm & 0x02) && decNumberIsQNaN(&dfp.a); \
540fcf5ef2aSThomas Huth match |= (dcm & 0x01) && decNumberIsSNaN(&dfp.a); \
541fcf5ef2aSThomas Huth \
542fcf5ef2aSThomas Huth if (decNumberIsNegative(&dfp.a)) { \
543fcf5ef2aSThomas Huth dfp.crbf = match ? 0xA : 0x8; \
544fcf5ef2aSThomas Huth } else { \
545fcf5ef2aSThomas Huth dfp.crbf = match ? 0x2 : 0x0; \
546fcf5ef2aSThomas Huth } \
547fcf5ef2aSThomas Huth \
548fcf5ef2aSThomas Huth dfp_set_FPCC_from_CRBF(&dfp); \
549fcf5ef2aSThomas Huth return dfp.crbf; \
550fcf5ef2aSThomas Huth }
551fcf5ef2aSThomas Huth
55287bc8e52SLuis Pires DFP_HELPER_TSTDC(DTSTDC, 64)
55387bc8e52SLuis Pires DFP_HELPER_TSTDC(DTSTDCQ, 128)
554fcf5ef2aSThomas Huth
555fcf5ef2aSThomas Huth #define DFP_HELPER_TSTDG(op, size) \
556d9acba31SMark Cave-Ayland uint32_t helper_##op(CPUPPCState *env, ppc_fprp_t *a, uint32_t dcm) \
557fcf5ef2aSThomas Huth { \
558fcf5ef2aSThomas Huth struct PPC_DFP dfp; \
559fcf5ef2aSThomas Huth int minexp, maxexp, nzero_digits, nzero_idx, is_negative, is_zero, \
560fcf5ef2aSThomas Huth is_extreme_exp, is_subnormal, is_normal, leftmost_is_nonzero, \
561fcf5ef2aSThomas Huth match; \
562fcf5ef2aSThomas Huth \
563fcf5ef2aSThomas Huth dfp_prepare_decimal##size(&dfp, a, 0, env); \
564fcf5ef2aSThomas Huth \
565fcf5ef2aSThomas Huth if ((size) == 64) { \
566fcf5ef2aSThomas Huth minexp = -398; \
567fcf5ef2aSThomas Huth maxexp = 369; \
568fcf5ef2aSThomas Huth nzero_digits = 16; \
569fcf5ef2aSThomas Huth nzero_idx = 5; \
570fcf5ef2aSThomas Huth } else if ((size) == 128) { \
571fcf5ef2aSThomas Huth minexp = -6176; \
572fcf5ef2aSThomas Huth maxexp = 6111; \
573fcf5ef2aSThomas Huth nzero_digits = 34; \
574fcf5ef2aSThomas Huth nzero_idx = 11; \
575fcf5ef2aSThomas Huth } \
576fcf5ef2aSThomas Huth \
577fcf5ef2aSThomas Huth is_negative = decNumberIsNegative(&dfp.a); \
578fcf5ef2aSThomas Huth is_zero = decNumberIsZero(&dfp.a); \
579fcf5ef2aSThomas Huth is_extreme_exp = (dfp.a.exponent == maxexp) || \
580fcf5ef2aSThomas Huth (dfp.a.exponent == minexp); \
581fcf5ef2aSThomas Huth is_subnormal = decNumberIsSubnormal(&dfp.a, &dfp.context); \
582fcf5ef2aSThomas Huth is_normal = decNumberIsNormal(&dfp.a, &dfp.context); \
583fcf5ef2aSThomas Huth leftmost_is_nonzero = (dfp.a.digits == nzero_digits) && \
584fcf5ef2aSThomas Huth (dfp.a.lsu[nzero_idx] != 0); \
585fcf5ef2aSThomas Huth match = 0; \
586fcf5ef2aSThomas Huth \
587fcf5ef2aSThomas Huth match |= (dcm & 0x20) && is_zero && !is_extreme_exp; \
588fcf5ef2aSThomas Huth match |= (dcm & 0x10) && is_zero && is_extreme_exp; \
589fcf5ef2aSThomas Huth match |= (dcm & 0x08) && \
590fcf5ef2aSThomas Huth (is_subnormal || (is_normal && is_extreme_exp)); \
591fcf5ef2aSThomas Huth match |= (dcm & 0x04) && is_normal && !is_extreme_exp && \
592fcf5ef2aSThomas Huth !leftmost_is_nonzero; \
593fcf5ef2aSThomas Huth match |= (dcm & 0x02) && is_normal && !is_extreme_exp && \
594fcf5ef2aSThomas Huth leftmost_is_nonzero; \
595fcf5ef2aSThomas Huth match |= (dcm & 0x01) && decNumberIsSpecial(&dfp.a); \
596fcf5ef2aSThomas Huth \
597fcf5ef2aSThomas Huth if (is_negative) { \
598fcf5ef2aSThomas Huth dfp.crbf = match ? 0xA : 0x8; \
599fcf5ef2aSThomas Huth } else { \
600fcf5ef2aSThomas Huth dfp.crbf = match ? 0x2 : 0x0; \
601fcf5ef2aSThomas Huth } \
602fcf5ef2aSThomas Huth \
603fcf5ef2aSThomas Huth dfp_set_FPCC_from_CRBF(&dfp); \
604fcf5ef2aSThomas Huth return dfp.crbf; \
605fcf5ef2aSThomas Huth }
606fcf5ef2aSThomas Huth
60787bc8e52SLuis Pires DFP_HELPER_TSTDG(DTSTDG, 64)
60887bc8e52SLuis Pires DFP_HELPER_TSTDG(DTSTDGQ, 128)
609fcf5ef2aSThomas Huth
610fcf5ef2aSThomas Huth #define DFP_HELPER_TSTEX(op, size) \
611d9acba31SMark Cave-Ayland uint32_t helper_##op(CPUPPCState *env, ppc_fprp_t *a, ppc_fprp_t *b) \
612fcf5ef2aSThomas Huth { \
613fcf5ef2aSThomas Huth struct PPC_DFP dfp; \
614fcf5ef2aSThomas Huth int expa, expb, a_is_special, b_is_special; \
615fcf5ef2aSThomas Huth \
616fcf5ef2aSThomas Huth dfp_prepare_decimal##size(&dfp, a, b, env); \
617fcf5ef2aSThomas Huth \
618fcf5ef2aSThomas Huth expa = dfp.a.exponent; \
619fcf5ef2aSThomas Huth expb = dfp.b.exponent; \
620fcf5ef2aSThomas Huth a_is_special = decNumberIsSpecial(&dfp.a); \
621fcf5ef2aSThomas Huth b_is_special = decNumberIsSpecial(&dfp.b); \
622fcf5ef2aSThomas Huth \
623fcf5ef2aSThomas Huth if (a_is_special || b_is_special) { \
624fcf5ef2aSThomas Huth int atype = a_is_special ? (decNumberIsNaN(&dfp.a) ? 4 : 2) : 1; \
625fcf5ef2aSThomas Huth int btype = b_is_special ? (decNumberIsNaN(&dfp.b) ? 4 : 2) : 1; \
626fcf5ef2aSThomas Huth dfp.crbf = (atype ^ btype) ? 0x1 : 0x2; \
627fcf5ef2aSThomas Huth } else if (expa < expb) { \
628fcf5ef2aSThomas Huth dfp.crbf = 0x8; \
629fcf5ef2aSThomas Huth } else if (expa > expb) { \
630fcf5ef2aSThomas Huth dfp.crbf = 0x4; \
631fcf5ef2aSThomas Huth } else { \
632fcf5ef2aSThomas Huth dfp.crbf = 0x2; \
633fcf5ef2aSThomas Huth } \
634fcf5ef2aSThomas Huth \
635fcf5ef2aSThomas Huth dfp_set_FPCC_from_CRBF(&dfp); \
636fcf5ef2aSThomas Huth return dfp.crbf; \
637fcf5ef2aSThomas Huth }
638fcf5ef2aSThomas Huth
63985c38a46SLuis Pires DFP_HELPER_TSTEX(DTSTEX, 64)
64085c38a46SLuis Pires DFP_HELPER_TSTEX(DTSTEXQ, 128)
641fcf5ef2aSThomas Huth
642fcf5ef2aSThomas Huth #define DFP_HELPER_TSTSF(op, size) \
643d9acba31SMark Cave-Ayland uint32_t helper_##op(CPUPPCState *env, ppc_fprp_t *a, ppc_fprp_t *b) \
644fcf5ef2aSThomas Huth { \
645fcf5ef2aSThomas Huth struct PPC_DFP dfp; \
646fcf5ef2aSThomas Huth unsigned k; \
64764b8574eSMark Cave-Ayland ppc_vsr_t va; \
648fcf5ef2aSThomas Huth \
649fcf5ef2aSThomas Huth dfp_prepare_decimal##size(&dfp, 0, b, env); \
650fcf5ef2aSThomas Huth \
65164b8574eSMark Cave-Ayland get_dfp64(&va, a); \
65264b8574eSMark Cave-Ayland k = va.VsrD(1) & 0x3F; \
653fcf5ef2aSThomas Huth \
654fcf5ef2aSThomas Huth if (unlikely(decNumberIsSpecial(&dfp.b))) { \
655fcf5ef2aSThomas Huth dfp.crbf = 1; \
656fcf5ef2aSThomas Huth } else if (k == 0) { \
657fcf5ef2aSThomas Huth dfp.crbf = 4; \
658fcf5ef2aSThomas Huth } else if (unlikely(decNumberIsZero(&dfp.b))) { \
659fcf5ef2aSThomas Huth /* Zero has no sig digits */ \
660fcf5ef2aSThomas Huth dfp.crbf = 4; \
661fcf5ef2aSThomas Huth } else { \
662fcf5ef2aSThomas Huth unsigned nsd = dfp.b.digits; \
663fcf5ef2aSThomas Huth if (k < nsd) { \
664fcf5ef2aSThomas Huth dfp.crbf = 8; \
665fcf5ef2aSThomas Huth } else if (k > nsd) { \
666fcf5ef2aSThomas Huth dfp.crbf = 4; \
667fcf5ef2aSThomas Huth } else { \
668fcf5ef2aSThomas Huth dfp.crbf = 2; \
669fcf5ef2aSThomas Huth } \
670fcf5ef2aSThomas Huth } \
671fcf5ef2aSThomas Huth \
672fcf5ef2aSThomas Huth dfp_set_FPCC_from_CRBF(&dfp); \
673fcf5ef2aSThomas Huth return dfp.crbf; \
674fcf5ef2aSThomas Huth }
675fcf5ef2aSThomas Huth
67685c38a46SLuis Pires DFP_HELPER_TSTSF(DTSTSF, 64)
67785c38a46SLuis Pires DFP_HELPER_TSTSF(DTSTSFQ, 128)
678fcf5ef2aSThomas Huth
679fcf5ef2aSThomas Huth #define DFP_HELPER_TSTSFI(op, size) \
680d9acba31SMark Cave-Ayland uint32_t helper_##op(CPUPPCState *env, uint32_t a, ppc_fprp_t *b) \
681fcf5ef2aSThomas Huth { \
682fcf5ef2aSThomas Huth struct PPC_DFP dfp; \
683fcf5ef2aSThomas Huth unsigned uim; \
684fcf5ef2aSThomas Huth \
685fcf5ef2aSThomas Huth dfp_prepare_decimal##size(&dfp, 0, b, env); \
686fcf5ef2aSThomas Huth \
687fcf5ef2aSThomas Huth uim = a & 0x3F; \
688fcf5ef2aSThomas Huth \
689fcf5ef2aSThomas Huth if (unlikely(decNumberIsSpecial(&dfp.b))) { \
690fcf5ef2aSThomas Huth dfp.crbf = 1; \
691fcf5ef2aSThomas Huth } else if (uim == 0) { \
692fcf5ef2aSThomas Huth dfp.crbf = 4; \
693fcf5ef2aSThomas Huth } else if (unlikely(decNumberIsZero(&dfp.b))) { \
694fcf5ef2aSThomas Huth /* Zero has no sig digits */ \
695fcf5ef2aSThomas Huth dfp.crbf = 4; \
696fcf5ef2aSThomas Huth } else { \
697fcf5ef2aSThomas Huth unsigned nsd = dfp.b.digits; \
698fcf5ef2aSThomas Huth if (uim < nsd) { \
699fcf5ef2aSThomas Huth dfp.crbf = 8; \
700fcf5ef2aSThomas Huth } else if (uim > nsd) { \
701fcf5ef2aSThomas Huth dfp.crbf = 4; \
702fcf5ef2aSThomas Huth } else { \
703fcf5ef2aSThomas Huth dfp.crbf = 2; \
704fcf5ef2aSThomas Huth } \
705fcf5ef2aSThomas Huth } \
706fcf5ef2aSThomas Huth \
707fcf5ef2aSThomas Huth dfp_set_FPCC_from_CRBF(&dfp); \
708fcf5ef2aSThomas Huth return dfp.crbf; \
709fcf5ef2aSThomas Huth }
710fcf5ef2aSThomas Huth
71185c38a46SLuis Pires DFP_HELPER_TSTSFI(DTSTSFI, 64)
71285c38a46SLuis Pires DFP_HELPER_TSTSFI(DTSTSFIQ, 128)
713fcf5ef2aSThomas Huth
QUA_PPs(struct PPC_DFP * dfp)714fcf5ef2aSThomas Huth static void QUA_PPs(struct PPC_DFP *dfp)
715fcf5ef2aSThomas Huth {
716fcf5ef2aSThomas Huth dfp_set_FPRF_from_FRT(dfp);
717fcf5ef2aSThomas Huth dfp_check_for_XX(dfp);
718fcf5ef2aSThomas Huth dfp_check_for_VXSNAN(dfp);
719fcf5ef2aSThomas Huth dfp_check_for_VXCVI(dfp);
720fcf5ef2aSThomas Huth }
721fcf5ef2aSThomas Huth
dfp_quantize(uint8_t rmc,struct PPC_DFP * dfp)722fcf5ef2aSThomas Huth static void dfp_quantize(uint8_t rmc, struct PPC_DFP *dfp)
723fcf5ef2aSThomas Huth {
724fcf5ef2aSThomas Huth dfp_set_round_mode_from_immediate(0, rmc, dfp);
725fcf5ef2aSThomas Huth decNumberQuantize(&dfp->t, &dfp->b, &dfp->a, &dfp->context);
726fcf5ef2aSThomas Huth if (decNumberIsSNaN(&dfp->a)) {
727fcf5ef2aSThomas Huth dfp->t = dfp->a;
728fcf5ef2aSThomas Huth dfp_makeQNaN(&dfp->t);
729fcf5ef2aSThomas Huth } else if (decNumberIsSNaN(&dfp->b)) {
730fcf5ef2aSThomas Huth dfp->t = dfp->b;
731fcf5ef2aSThomas Huth dfp_makeQNaN(&dfp->t);
732fcf5ef2aSThomas Huth } else if (decNumberIsQNaN(&dfp->a)) {
733fcf5ef2aSThomas Huth dfp->t = dfp->a;
734fcf5ef2aSThomas Huth } else if (decNumberIsQNaN(&dfp->b)) {
735fcf5ef2aSThomas Huth dfp->t = dfp->b;
736fcf5ef2aSThomas Huth }
737fcf5ef2aSThomas Huth }
738fcf5ef2aSThomas Huth
739fcf5ef2aSThomas Huth #define DFP_HELPER_QUAI(op, size) \
740d9acba31SMark Cave-Ayland void helper_##op(CPUPPCState *env, ppc_fprp_t *t, ppc_fprp_t *b, \
741fcf5ef2aSThomas Huth uint32_t te, uint32_t rmc) \
742fcf5ef2aSThomas Huth { \
743fcf5ef2aSThomas Huth struct PPC_DFP dfp; \
744fcf5ef2aSThomas Huth \
745fcf5ef2aSThomas Huth dfp_prepare_decimal##size(&dfp, 0, b, env); \
746fcf5ef2aSThomas Huth \
747fcf5ef2aSThomas Huth decNumberFromUInt32(&dfp.a, 1); \
748fcf5ef2aSThomas Huth dfp.a.exponent = (int32_t)((int8_t)(te << 3) >> 3); \
749fcf5ef2aSThomas Huth \
750fcf5ef2aSThomas Huth dfp_quantize(rmc, &dfp); \
751474c2e93SMark Cave-Ayland dfp_finalize_decimal##size(&dfp); \
752fcf5ef2aSThomas Huth QUA_PPs(&dfp); \
753fcf5ef2aSThomas Huth \
754f6d4c423SMark Cave-Ayland set_dfp##size(t, &dfp.vt); \
755fcf5ef2aSThomas Huth }
756fcf5ef2aSThomas Huth
75778464edbSLuis Pires DFP_HELPER_QUAI(DQUAI, 64)
75878464edbSLuis Pires DFP_HELPER_QUAI(DQUAIQ, 128)
759fcf5ef2aSThomas Huth
760fcf5ef2aSThomas Huth #define DFP_HELPER_QUA(op, size) \
761d9acba31SMark Cave-Ayland void helper_##op(CPUPPCState *env, ppc_fprp_t *t, ppc_fprp_t *a, \
762d9acba31SMark Cave-Ayland ppc_fprp_t *b, uint32_t rmc) \
763fcf5ef2aSThomas Huth { \
764fcf5ef2aSThomas Huth struct PPC_DFP dfp; \
765fcf5ef2aSThomas Huth \
766fcf5ef2aSThomas Huth dfp_prepare_decimal##size(&dfp, a, b, env); \
767fcf5ef2aSThomas Huth \
768fcf5ef2aSThomas Huth dfp_quantize(rmc, &dfp); \
769474c2e93SMark Cave-Ayland dfp_finalize_decimal##size(&dfp); \
770fcf5ef2aSThomas Huth QUA_PPs(&dfp); \
771fcf5ef2aSThomas Huth \
772f6d4c423SMark Cave-Ayland set_dfp##size(t, &dfp.vt); \
773fcf5ef2aSThomas Huth }
774fcf5ef2aSThomas Huth
775a8f4bce6SLuis Pires DFP_HELPER_QUA(DQUA, 64)
776a8f4bce6SLuis Pires DFP_HELPER_QUA(DQUAQ, 128)
777fcf5ef2aSThomas Huth
_dfp_reround(uint8_t rmc,int32_t ref_sig,int32_t xmax,struct PPC_DFP * dfp)778fcf5ef2aSThomas Huth static void _dfp_reround(uint8_t rmc, int32_t ref_sig, int32_t xmax,
779fcf5ef2aSThomas Huth struct PPC_DFP *dfp)
780fcf5ef2aSThomas Huth {
781fcf5ef2aSThomas Huth int msd_orig, msd_rslt;
782fcf5ef2aSThomas Huth
783fcf5ef2aSThomas Huth if (unlikely((ref_sig == 0) || (dfp->b.digits <= ref_sig))) {
784fcf5ef2aSThomas Huth dfp->t = dfp->b;
785fcf5ef2aSThomas Huth if (decNumberIsSNaN(&dfp->b)) {
786fcf5ef2aSThomas Huth dfp_makeQNaN(&dfp->t);
787fcf5ef2aSThomas Huth dfp_set_FPSCR_flag(dfp, FP_VX | FP_VXSNAN, FPSCR_VE);
788fcf5ef2aSThomas Huth }
789fcf5ef2aSThomas Huth return;
790fcf5ef2aSThomas Huth }
791fcf5ef2aSThomas Huth
792fcf5ef2aSThomas Huth /* Reround is equivalent to quantizing b with 1**E(n) where */
793fcf5ef2aSThomas Huth /* n = exp(b) + numDigits(b) - reference_significance. */
794fcf5ef2aSThomas Huth
795fcf5ef2aSThomas Huth decNumberFromUInt32(&dfp->a, 1);
796fcf5ef2aSThomas Huth dfp->a.exponent = dfp->b.exponent + dfp->b.digits - ref_sig;
797fcf5ef2aSThomas Huth
798fcf5ef2aSThomas Huth if (unlikely(dfp->a.exponent > xmax)) {
799fcf5ef2aSThomas Huth dfp->t.digits = 0;
800fcf5ef2aSThomas Huth dfp->t.bits &= ~DECNEG;
801fcf5ef2aSThomas Huth dfp_makeQNaN(&dfp->t);
802fcf5ef2aSThomas Huth dfp_set_FPSCR_flag(dfp, FP_VX | FP_VXCVI, FPSCR_VE);
803fcf5ef2aSThomas Huth return;
804fcf5ef2aSThomas Huth }
805fcf5ef2aSThomas Huth
806fcf5ef2aSThomas Huth dfp_quantize(rmc, dfp);
807fcf5ef2aSThomas Huth
808fcf5ef2aSThomas Huth msd_orig = dfp_get_digit(&dfp->b, dfp->b.digits-1);
809fcf5ef2aSThomas Huth msd_rslt = dfp_get_digit(&dfp->t, dfp->t.digits-1);
810fcf5ef2aSThomas Huth
811fcf5ef2aSThomas Huth /* If the quantization resulted in rounding up to the next magnitude, */
812fcf5ef2aSThomas Huth /* then we need to shift the significand and adjust the exponent. */
813fcf5ef2aSThomas Huth
814fcf5ef2aSThomas Huth if (unlikely((msd_orig == 9) && (msd_rslt == 1))) {
815fcf5ef2aSThomas Huth
816fcf5ef2aSThomas Huth decNumber negone;
817fcf5ef2aSThomas Huth
818fcf5ef2aSThomas Huth decNumberFromInt32(&negone, -1);
819fcf5ef2aSThomas Huth decNumberShift(&dfp->t, &dfp->t, &negone, &dfp->context);
820fcf5ef2aSThomas Huth dfp->t.exponent++;
821fcf5ef2aSThomas Huth
822fcf5ef2aSThomas Huth if (unlikely(dfp->t.exponent > xmax)) {
823fcf5ef2aSThomas Huth dfp_makeQNaN(&dfp->t);
824fcf5ef2aSThomas Huth dfp->t.digits = 0;
825fcf5ef2aSThomas Huth dfp_set_FPSCR_flag(dfp, FP_VX | FP_VXCVI, FP_VE);
826fcf5ef2aSThomas Huth /* Inhibit XX in this case */
827fcf5ef2aSThomas Huth decContextClearStatus(&dfp->context, DEC_Inexact);
828fcf5ef2aSThomas Huth }
829fcf5ef2aSThomas Huth }
830fcf5ef2aSThomas Huth }
831fcf5ef2aSThomas Huth
832fcf5ef2aSThomas Huth #define DFP_HELPER_RRND(op, size) \
833d9acba31SMark Cave-Ayland void helper_##op(CPUPPCState *env, ppc_fprp_t *t, ppc_fprp_t *a, \
834d9acba31SMark Cave-Ayland ppc_fprp_t *b, uint32_t rmc) \
835fcf5ef2aSThomas Huth { \
836fcf5ef2aSThomas Huth struct PPC_DFP dfp; \
83764b8574eSMark Cave-Ayland ppc_vsr_t va; \
8386a8fbb9bSMark Cave-Ayland int32_t ref_sig; \
839fcf5ef2aSThomas Huth int32_t xmax = ((size) == 64) ? 369 : 6111; \
840fcf5ef2aSThomas Huth \
841fcf5ef2aSThomas Huth dfp_prepare_decimal##size(&dfp, 0, b, env); \
842fcf5ef2aSThomas Huth \
84364b8574eSMark Cave-Ayland get_dfp64(&va, a); \
84464b8574eSMark Cave-Ayland ref_sig = va.VsrD(1) & 0x3f; \
8456a8fbb9bSMark Cave-Ayland \
846fcf5ef2aSThomas Huth _dfp_reround(rmc, ref_sig, xmax, &dfp); \
847474c2e93SMark Cave-Ayland dfp_finalize_decimal##size(&dfp); \
848fcf5ef2aSThomas Huth QUA_PPs(&dfp); \
849fcf5ef2aSThomas Huth \
850f6d4c423SMark Cave-Ayland set_dfp##size(t, &dfp.vt); \
851fcf5ef2aSThomas Huth }
852fcf5ef2aSThomas Huth
853a8f4bce6SLuis Pires DFP_HELPER_RRND(DRRND, 64)
854a8f4bce6SLuis Pires DFP_HELPER_RRND(DRRNDQ, 128)
855fcf5ef2aSThomas Huth
856fcf5ef2aSThomas Huth #define DFP_HELPER_RINT(op, postprocs, size) \
857d9acba31SMark Cave-Ayland void helper_##op(CPUPPCState *env, ppc_fprp_t *t, ppc_fprp_t *b, \
858fcf5ef2aSThomas Huth uint32_t r, uint32_t rmc) \
859fcf5ef2aSThomas Huth { \
860fcf5ef2aSThomas Huth struct PPC_DFP dfp; \
861fcf5ef2aSThomas Huth \
862fcf5ef2aSThomas Huth dfp_prepare_decimal##size(&dfp, 0, b, env); \
863fcf5ef2aSThomas Huth \
864fcf5ef2aSThomas Huth dfp_set_round_mode_from_immediate(r, rmc, &dfp); \
865fcf5ef2aSThomas Huth decNumberToIntegralExact(&dfp.t, &dfp.b, &dfp.context); \
866474c2e93SMark Cave-Ayland dfp_finalize_decimal##size(&dfp); \
867fcf5ef2aSThomas Huth postprocs(&dfp); \
868fcf5ef2aSThomas Huth \
869f6d4c423SMark Cave-Ayland set_dfp##size(t, &dfp.vt); \
870fcf5ef2aSThomas Huth }
871fcf5ef2aSThomas Huth
RINTX_PPs(struct PPC_DFP * dfp)872fcf5ef2aSThomas Huth static void RINTX_PPs(struct PPC_DFP *dfp)
873fcf5ef2aSThomas Huth {
874fcf5ef2aSThomas Huth dfp_set_FPRF_from_FRT(dfp);
875fcf5ef2aSThomas Huth dfp_check_for_XX(dfp);
876fcf5ef2aSThomas Huth dfp_check_for_VXSNAN(dfp);
877fcf5ef2aSThomas Huth }
878fcf5ef2aSThomas Huth
87978464edbSLuis Pires DFP_HELPER_RINT(DRINTX, RINTX_PPs, 64)
88078464edbSLuis Pires DFP_HELPER_RINT(DRINTXQ, RINTX_PPs, 128)
881fcf5ef2aSThomas Huth
RINTN_PPs(struct PPC_DFP * dfp)882fcf5ef2aSThomas Huth static void RINTN_PPs(struct PPC_DFP *dfp)
883fcf5ef2aSThomas Huth {
884fcf5ef2aSThomas Huth dfp_set_FPRF_from_FRT(dfp);
885fcf5ef2aSThomas Huth dfp_check_for_VXSNAN(dfp);
886fcf5ef2aSThomas Huth }
887fcf5ef2aSThomas Huth
88878464edbSLuis Pires DFP_HELPER_RINT(DRINTN, RINTN_PPs, 64)
88978464edbSLuis Pires DFP_HELPER_RINT(DRINTNQ, RINTN_PPs, 128)
890fcf5ef2aSThomas Huth
helper_DCTDP(CPUPPCState * env,ppc_fprp_t * t,ppc_fprp_t * b)891c8ef4d1eSLuis Pires void helper_DCTDP(CPUPPCState *env, ppc_fprp_t *t, ppc_fprp_t *b)
892fcf5ef2aSThomas Huth {
893fcf5ef2aSThomas Huth struct PPC_DFP dfp;
89464b8574eSMark Cave-Ayland ppc_vsr_t vb;
8956a8fbb9bSMark Cave-Ayland uint32_t b_short;
8966a8fbb9bSMark Cave-Ayland
89764b8574eSMark Cave-Ayland get_dfp64(&vb, b);
89864b8574eSMark Cave-Ayland b_short = (uint32_t)vb.VsrD(1);
8996a8fbb9bSMark Cave-Ayland
900fcf5ef2aSThomas Huth dfp_prepare_decimal64(&dfp, 0, 0, env);
901fcf5ef2aSThomas Huth decimal32ToNumber((decimal32 *)&b_short, &dfp.t);
902474c2e93SMark Cave-Ayland dfp_finalize_decimal64(&dfp);
90364b8574eSMark Cave-Ayland set_dfp64(t, &dfp.vt);
904fcf5ef2aSThomas Huth dfp_set_FPRF_from_FRT(&dfp);
905fcf5ef2aSThomas Huth }
906fcf5ef2aSThomas Huth
helper_DCTQPQ(CPUPPCState * env,ppc_fprp_t * t,ppc_fprp_t * b)907c8ef4d1eSLuis Pires void helper_DCTQPQ(CPUPPCState *env, ppc_fprp_t *t, ppc_fprp_t *b)
908fcf5ef2aSThomas Huth {
909fcf5ef2aSThomas Huth struct PPC_DFP dfp;
91064b8574eSMark Cave-Ayland ppc_vsr_t vb;
911fcf5ef2aSThomas Huth dfp_prepare_decimal128(&dfp, 0, 0, env);
91264b8574eSMark Cave-Ayland get_dfp64(&vb, b);
91364b8574eSMark Cave-Ayland decimal64ToNumber((decimal64 *)&vb.VsrD(1), &dfp.t);
914fcf5ef2aSThomas Huth
915fcf5ef2aSThomas Huth dfp_check_for_VXSNAN_and_convert_to_QNaN(&dfp);
916fcf5ef2aSThomas Huth dfp_set_FPRF_from_FRT(&dfp);
917fcf5ef2aSThomas Huth
918474c2e93SMark Cave-Ayland dfp_finalize_decimal128(&dfp);
91964b8574eSMark Cave-Ayland set_dfp128(t, &dfp.vt);
920fcf5ef2aSThomas Huth }
921fcf5ef2aSThomas Huth
helper_DRSP(CPUPPCState * env,ppc_fprp_t * t,ppc_fprp_t * b)922c8ef4d1eSLuis Pires void helper_DRSP(CPUPPCState *env, ppc_fprp_t *t, ppc_fprp_t *b)
923fcf5ef2aSThomas Huth {
924fcf5ef2aSThomas Huth struct PPC_DFP dfp;
925fcf5ef2aSThomas Huth uint32_t t_short = 0;
92664b8574eSMark Cave-Ayland ppc_vsr_t vt;
927fcf5ef2aSThomas Huth dfp_prepare_decimal64(&dfp, 0, b, env);
928fcf5ef2aSThomas Huth decimal32FromNumber((decimal32 *)&t_short, &dfp.b, &dfp.context);
929fcf5ef2aSThomas Huth decimal32ToNumber((decimal32 *)&t_short, &dfp.t);
930fcf5ef2aSThomas Huth
931fcf5ef2aSThomas Huth dfp_set_FPRF_from_FRT_short(&dfp);
932fcf5ef2aSThomas Huth dfp_check_for_OX(&dfp);
933fcf5ef2aSThomas Huth dfp_check_for_UX(&dfp);
934fcf5ef2aSThomas Huth dfp_check_for_XX(&dfp);
935fcf5ef2aSThomas Huth
93664b8574eSMark Cave-Ayland vt.VsrD(1) = (uint64_t)t_short;
93764b8574eSMark Cave-Ayland set_dfp64(t, &vt);
938fcf5ef2aSThomas Huth }
939fcf5ef2aSThomas Huth
helper_DRDPQ(CPUPPCState * env,ppc_fprp_t * t,ppc_fprp_t * b)940c8ef4d1eSLuis Pires void helper_DRDPQ(CPUPPCState *env, ppc_fprp_t *t, ppc_fprp_t *b)
941fcf5ef2aSThomas Huth {
942fcf5ef2aSThomas Huth struct PPC_DFP dfp;
943fcf5ef2aSThomas Huth dfp_prepare_decimal128(&dfp, 0, b, env);
94464b8574eSMark Cave-Ayland decimal64FromNumber((decimal64 *)&dfp.vt.VsrD(1), &dfp.b, &dfp.context);
94564b8574eSMark Cave-Ayland decimal64ToNumber((decimal64 *)&dfp.vt.VsrD(1), &dfp.t);
946fcf5ef2aSThomas Huth
947fcf5ef2aSThomas Huth dfp_check_for_VXSNAN_and_convert_to_QNaN(&dfp);
948fcf5ef2aSThomas Huth dfp_set_FPRF_from_FRT_long(&dfp);
949fcf5ef2aSThomas Huth dfp_check_for_OX(&dfp);
950fcf5ef2aSThomas Huth dfp_check_for_UX(&dfp);
951fcf5ef2aSThomas Huth dfp_check_for_XX(&dfp);
952fcf5ef2aSThomas Huth
95364b8574eSMark Cave-Ayland dfp.vt.VsrD(0) = dfp.vt.VsrD(1) = 0;
954474c2e93SMark Cave-Ayland dfp_finalize_decimal64(&dfp);
95564b8574eSMark Cave-Ayland set_dfp128(t, &dfp.vt);
956fcf5ef2aSThomas Huth }
957fcf5ef2aSThomas Huth
958fcf5ef2aSThomas Huth #define DFP_HELPER_CFFIX(op, size) \
959d9acba31SMark Cave-Ayland void helper_##op(CPUPPCState *env, ppc_fprp_t *t, ppc_fprp_t *b) \
960fcf5ef2aSThomas Huth { \
961fcf5ef2aSThomas Huth struct PPC_DFP dfp; \
96264b8574eSMark Cave-Ayland ppc_vsr_t vb; \
963fcf5ef2aSThomas Huth dfp_prepare_decimal##size(&dfp, 0, b, env); \
96464b8574eSMark Cave-Ayland get_dfp64(&vb, b); \
96564b8574eSMark Cave-Ayland decNumberFromInt64(&dfp.t, (int64_t)vb.VsrD(1)); \
966474c2e93SMark Cave-Ayland dfp_finalize_decimal##size(&dfp); \
967fcf5ef2aSThomas Huth CFFIX_PPs(&dfp); \
968fcf5ef2aSThomas Huth \
969f6d4c423SMark Cave-Ayland set_dfp##size(t, &dfp.vt); \
970fcf5ef2aSThomas Huth }
971fcf5ef2aSThomas Huth
CFFIX_PPs(struct PPC_DFP * dfp)972fcf5ef2aSThomas Huth static void CFFIX_PPs(struct PPC_DFP *dfp)
973fcf5ef2aSThomas Huth {
974fcf5ef2aSThomas Huth dfp_set_FPRF_from_FRT(dfp);
975fcf5ef2aSThomas Huth dfp_check_for_XX(dfp);
976fcf5ef2aSThomas Huth }
977fcf5ef2aSThomas Huth
978c8ef4d1eSLuis Pires DFP_HELPER_CFFIX(DCFFIX, 64)
979c8ef4d1eSLuis Pires DFP_HELPER_CFFIX(DCFFIXQ, 128)
980fcf5ef2aSThomas Huth
helper_DCFFIXQQ(CPUPPCState * env,ppc_fprp_t * t,ppc_avr_t * b)981d39b2cc7SLuis Pires void helper_DCFFIXQQ(CPUPPCState *env, ppc_fprp_t *t, ppc_avr_t *b)
982d39b2cc7SLuis Pires {
983d39b2cc7SLuis Pires struct PPC_DFP dfp;
984d39b2cc7SLuis Pires
985d39b2cc7SLuis Pires dfp_prepare_decimal128(&dfp, NULL, NULL, env);
986d39b2cc7SLuis Pires decNumberFromInt128(&dfp.t, (uint64_t)b->VsrD(1), (int64_t)b->VsrD(0));
987d39b2cc7SLuis Pires dfp_finalize_decimal128(&dfp);
988d39b2cc7SLuis Pires CFFIX_PPs(&dfp);
989d39b2cc7SLuis Pires
990d39b2cc7SLuis Pires set_dfp128(t, &dfp.vt);
991d39b2cc7SLuis Pires }
992d39b2cc7SLuis Pires
993fcf5ef2aSThomas Huth #define DFP_HELPER_CTFIX(op, size) \
994d9acba31SMark Cave-Ayland void helper_##op(CPUPPCState *env, ppc_fprp_t *t, ppc_fprp_t *b) \
995fcf5ef2aSThomas Huth { \
996fcf5ef2aSThomas Huth struct PPC_DFP dfp; \
997fcf5ef2aSThomas Huth dfp_prepare_decimal##size(&dfp, 0, b, env); \
998fcf5ef2aSThomas Huth \
999fcf5ef2aSThomas Huth if (unlikely(decNumberIsSpecial(&dfp.b))) { \
1000fcf5ef2aSThomas Huth uint64_t invalid_flags = FP_VX | FP_VXCVI; \
1001fcf5ef2aSThomas Huth if (decNumberIsInfinite(&dfp.b)) { \
100264b8574eSMark Cave-Ayland dfp.vt.VsrD(1) = decNumberIsNegative(&dfp.b) ? INT64_MIN : \
100364b8574eSMark Cave-Ayland INT64_MAX; \
1004fcf5ef2aSThomas Huth } else { /* NaN */ \
100564b8574eSMark Cave-Ayland dfp.vt.VsrD(1) = INT64_MIN; \
1006fcf5ef2aSThomas Huth if (decNumberIsSNaN(&dfp.b)) { \
1007fcf5ef2aSThomas Huth invalid_flags |= FP_VXSNAN; \
1008fcf5ef2aSThomas Huth } \
1009fcf5ef2aSThomas Huth } \
1010fcf5ef2aSThomas Huth dfp_set_FPSCR_flag(&dfp, invalid_flags, FP_VE); \
1011fcf5ef2aSThomas Huth } else if (unlikely(decNumberIsZero(&dfp.b))) { \
101264b8574eSMark Cave-Ayland dfp.vt.VsrD(1) = 0; \
1013fcf5ef2aSThomas Huth } else { \
1014fcf5ef2aSThomas Huth decNumberToIntegralExact(&dfp.b, &dfp.b, &dfp.context); \
101564b8574eSMark Cave-Ayland dfp.vt.VsrD(1) = decNumberIntegralToInt64(&dfp.b, &dfp.context); \
1016fcf5ef2aSThomas Huth if (decContextTestStatus(&dfp.context, DEC_Invalid_operation)) { \
101764b8574eSMark Cave-Ayland dfp.vt.VsrD(1) = decNumberIsNegative(&dfp.b) ? INT64_MIN : \
101864b8574eSMark Cave-Ayland INT64_MAX; \
1019fcf5ef2aSThomas Huth dfp_set_FPSCR_flag(&dfp, FP_VX | FP_VXCVI, FP_VE); \
1020fcf5ef2aSThomas Huth } else { \
1021fcf5ef2aSThomas Huth dfp_check_for_XX(&dfp); \
1022fcf5ef2aSThomas Huth } \
1023fcf5ef2aSThomas Huth } \
1024fcf5ef2aSThomas Huth \
102564b8574eSMark Cave-Ayland set_dfp64(t, &dfp.vt); \
1026fcf5ef2aSThomas Huth }
1027fcf5ef2aSThomas Huth
1028c8ef4d1eSLuis Pires DFP_HELPER_CTFIX(DCTFIX, 64)
1029c8ef4d1eSLuis Pires DFP_HELPER_CTFIX(DCTFIXQ, 128)
1030fcf5ef2aSThomas Huth
helper_DCTFIXQQ(CPUPPCState * env,ppc_avr_t * t,ppc_fprp_t * b)1031328747f3SLuis Pires void helper_DCTFIXQQ(CPUPPCState *env, ppc_avr_t *t, ppc_fprp_t *b)
1032328747f3SLuis Pires {
1033328747f3SLuis Pires struct PPC_DFP dfp;
1034328747f3SLuis Pires dfp_prepare_decimal128(&dfp, 0, b, env);
1035328747f3SLuis Pires
1036328747f3SLuis Pires if (unlikely(decNumberIsSpecial(&dfp.b))) {
1037328747f3SLuis Pires uint64_t invalid_flags = FP_VX | FP_VXCVI;
1038328747f3SLuis Pires if (decNumberIsInfinite(&dfp.b)) {
1039328747f3SLuis Pires if (decNumberIsNegative(&dfp.b)) {
1040328747f3SLuis Pires dfp.vt.VsrD(0) = INT64_MIN;
1041328747f3SLuis Pires dfp.vt.VsrD(1) = 0;
1042328747f3SLuis Pires } else {
1043328747f3SLuis Pires dfp.vt.VsrD(0) = INT64_MAX;
1044328747f3SLuis Pires dfp.vt.VsrD(1) = UINT64_MAX;
1045328747f3SLuis Pires }
1046328747f3SLuis Pires } else { /* NaN */
1047328747f3SLuis Pires dfp.vt.VsrD(0) = INT64_MIN;
1048328747f3SLuis Pires dfp.vt.VsrD(1) = 0;
1049328747f3SLuis Pires if (decNumberIsSNaN(&dfp.b)) {
1050328747f3SLuis Pires invalid_flags |= FP_VXSNAN;
1051328747f3SLuis Pires }
1052328747f3SLuis Pires }
1053328747f3SLuis Pires dfp_set_FPSCR_flag(&dfp, invalid_flags, FP_VE);
1054328747f3SLuis Pires } else if (unlikely(decNumberIsZero(&dfp.b))) {
1055328747f3SLuis Pires dfp.vt.VsrD(0) = 0;
1056328747f3SLuis Pires dfp.vt.VsrD(1) = 0;
1057328747f3SLuis Pires } else {
1058328747f3SLuis Pires decNumberToIntegralExact(&dfp.b, &dfp.b, &dfp.context);
1059328747f3SLuis Pires decNumberIntegralToInt128(&dfp.b, &dfp.context,
1060328747f3SLuis Pires &dfp.vt.VsrD(1), &dfp.vt.VsrD(0));
1061328747f3SLuis Pires if (decContextTestStatus(&dfp.context, DEC_Invalid_operation)) {
1062328747f3SLuis Pires if (decNumberIsNegative(&dfp.b)) {
1063328747f3SLuis Pires dfp.vt.VsrD(0) = INT64_MIN;
1064328747f3SLuis Pires dfp.vt.VsrD(1) = 0;
1065328747f3SLuis Pires } else {
1066328747f3SLuis Pires dfp.vt.VsrD(0) = INT64_MAX;
1067328747f3SLuis Pires dfp.vt.VsrD(1) = UINT64_MAX;
1068328747f3SLuis Pires }
1069328747f3SLuis Pires dfp_set_FPSCR_flag(&dfp, FP_VX | FP_VXCVI, FP_VE);
1070328747f3SLuis Pires } else {
1071328747f3SLuis Pires dfp_check_for_XX(&dfp);
1072328747f3SLuis Pires }
1073328747f3SLuis Pires }
1074328747f3SLuis Pires
1075328747f3SLuis Pires set_dfp128_to_avr(t, &dfp.vt);
1076328747f3SLuis Pires }
1077328747f3SLuis Pires
dfp_set_bcd_digit_64(ppc_vsr_t * t,uint8_t digit,unsigned n)10781ea80bf7SMark Cave-Ayland static inline void dfp_set_bcd_digit_64(ppc_vsr_t *t, uint8_t digit,
1079fcf5ef2aSThomas Huth unsigned n)
1080fcf5ef2aSThomas Huth {
10811ea80bf7SMark Cave-Ayland t->VsrD(1) |= ((uint64_t)(digit & 0xF) << (n << 2));
1082fcf5ef2aSThomas Huth }
1083fcf5ef2aSThomas Huth
dfp_set_bcd_digit_128(ppc_vsr_t * t,uint8_t digit,unsigned n)10841ea80bf7SMark Cave-Ayland static inline void dfp_set_bcd_digit_128(ppc_vsr_t *t, uint8_t digit,
1085fcf5ef2aSThomas Huth unsigned n)
1086fcf5ef2aSThomas Huth {
10871ea80bf7SMark Cave-Ayland t->VsrD((n & 0x10) ? 0 : 1) |=
1088fcf5ef2aSThomas Huth ((uint64_t)(digit & 0xF) << ((n & 15) << 2));
1089fcf5ef2aSThomas Huth }
1090fcf5ef2aSThomas Huth
dfp_set_sign_64(ppc_vsr_t * t,uint8_t sgn)10911ea80bf7SMark Cave-Ayland static inline void dfp_set_sign_64(ppc_vsr_t *t, uint8_t sgn)
1092fcf5ef2aSThomas Huth {
10931ea80bf7SMark Cave-Ayland t->VsrD(1) <<= 4;
10941ea80bf7SMark Cave-Ayland t->VsrD(1) |= (sgn & 0xF);
1095fcf5ef2aSThomas Huth }
1096fcf5ef2aSThomas Huth
dfp_set_sign_128(ppc_vsr_t * t,uint8_t sgn)10971ea80bf7SMark Cave-Ayland static inline void dfp_set_sign_128(ppc_vsr_t *t, uint8_t sgn)
1098fcf5ef2aSThomas Huth {
10991ea80bf7SMark Cave-Ayland t->VsrD(0) <<= 4;
11001ea80bf7SMark Cave-Ayland t->VsrD(0) |= (t->VsrD(1) >> 60);
11011ea80bf7SMark Cave-Ayland t->VsrD(1) <<= 4;
11021ea80bf7SMark Cave-Ayland t->VsrD(1) |= (sgn & 0xF);
1103fcf5ef2aSThomas Huth }
1104fcf5ef2aSThomas Huth
1105fcf5ef2aSThomas Huth #define DFP_HELPER_DEDPD(op, size) \
1106d9acba31SMark Cave-Ayland void helper_##op(CPUPPCState *env, ppc_fprp_t *t, ppc_fprp_t *b, \
1107d9acba31SMark Cave-Ayland uint32_t sp) \
1108fcf5ef2aSThomas Huth { \
1109fcf5ef2aSThomas Huth struct PPC_DFP dfp; \
1110fcf5ef2aSThomas Huth uint8_t digits[34]; \
1111fcf5ef2aSThomas Huth int i, N; \
1112fcf5ef2aSThomas Huth \
1113fcf5ef2aSThomas Huth dfp_prepare_decimal##size(&dfp, 0, b, env); \
1114fcf5ef2aSThomas Huth \
1115fcf5ef2aSThomas Huth decNumberGetBCD(&dfp.b, digits); \
111664b8574eSMark Cave-Ayland dfp.vt.VsrD(0) = dfp.vt.VsrD(1) = 0; \
1117fcf5ef2aSThomas Huth N = dfp.b.digits; \
1118fcf5ef2aSThomas Huth \
1119fcf5ef2aSThomas Huth for (i = 0; (i < N) && (i < (size)/4); i++) { \
11201ea80bf7SMark Cave-Ayland dfp_set_bcd_digit_##size(&dfp.vt, digits[N - i - 1], i); \
1121fcf5ef2aSThomas Huth } \
1122fcf5ef2aSThomas Huth \
1123fcf5ef2aSThomas Huth if (sp & 2) { \
1124fcf5ef2aSThomas Huth uint8_t sgn; \
1125fcf5ef2aSThomas Huth \
1126fcf5ef2aSThomas Huth if (decNumberIsNegative(&dfp.b)) { \
1127fcf5ef2aSThomas Huth sgn = 0xD; \
1128fcf5ef2aSThomas Huth } else { \
1129fcf5ef2aSThomas Huth sgn = ((sp & 1) ? 0xF : 0xC); \
1130fcf5ef2aSThomas Huth } \
11311ea80bf7SMark Cave-Ayland dfp_set_sign_##size(&dfp.vt, sgn); \
1132fcf5ef2aSThomas Huth } \
1133fcf5ef2aSThomas Huth \
1134f6d4c423SMark Cave-Ayland set_dfp##size(t, &dfp.vt); \
1135fcf5ef2aSThomas Huth }
1136fcf5ef2aSThomas Huth
1137a2329747SLuis Pires DFP_HELPER_DEDPD(DDEDPD, 64)
1138a2329747SLuis Pires DFP_HELPER_DEDPD(DDEDPDQ, 128)
1139fcf5ef2aSThomas Huth
dfp_get_bcd_digit_64(ppc_vsr_t * t,unsigned n)11401ea80bf7SMark Cave-Ayland static inline uint8_t dfp_get_bcd_digit_64(ppc_vsr_t *t, unsigned n)
1141fcf5ef2aSThomas Huth {
11421ea80bf7SMark Cave-Ayland return t->VsrD(1) >> ((n << 2) & 63) & 15;
1143fcf5ef2aSThomas Huth }
1144fcf5ef2aSThomas Huth
dfp_get_bcd_digit_128(ppc_vsr_t * t,unsigned n)11451ea80bf7SMark Cave-Ayland static inline uint8_t dfp_get_bcd_digit_128(ppc_vsr_t *t, unsigned n)
1146fcf5ef2aSThomas Huth {
11471ea80bf7SMark Cave-Ayland return t->VsrD((n & 0x10) ? 0 : 1) >> ((n << 2) & 63) & 15;
1148fcf5ef2aSThomas Huth }
1149fcf5ef2aSThomas Huth
dfp_invalid_op_vxcvi_64(struct PPC_DFP * dfp)11503ecec4c0SVíctor Colombo static inline void dfp_invalid_op_vxcvi_64(struct PPC_DFP *dfp)
11513ecec4c0SVíctor Colombo {
11523ecec4c0SVíctor Colombo /* TODO: fpscr is incorrectly not being saved to env */
11533ecec4c0SVíctor Colombo dfp_set_FPSCR_flag(dfp, FP_VX | FP_VXCVI, FPSCR_VE);
11543ecec4c0SVíctor Colombo if ((dfp->env->fpscr & FP_VE) == 0) {
11553ecec4c0SVíctor Colombo dfp->vt.VsrD(1) = 0x7c00000000000000; /* QNaN */
11563ecec4c0SVíctor Colombo }
11573ecec4c0SVíctor Colombo }
11583ecec4c0SVíctor Colombo
11593ecec4c0SVíctor Colombo
dfp_invalid_op_vxcvi_128(struct PPC_DFP * dfp)11603ecec4c0SVíctor Colombo static inline void dfp_invalid_op_vxcvi_128(struct PPC_DFP *dfp)
11613ecec4c0SVíctor Colombo {
11623ecec4c0SVíctor Colombo /* TODO: fpscr is incorrectly not being saved to env */
11633ecec4c0SVíctor Colombo dfp_set_FPSCR_flag(dfp, FP_VX | FP_VXCVI, FPSCR_VE);
11643ecec4c0SVíctor Colombo if ((dfp->env->fpscr & FP_VE) == 0) {
11653ecec4c0SVíctor Colombo dfp->vt.VsrD(0) = 0x7c00000000000000; /* QNaN */
11663ecec4c0SVíctor Colombo dfp->vt.VsrD(1) = 0x0;
11673ecec4c0SVíctor Colombo }
11683ecec4c0SVíctor Colombo }
11693ecec4c0SVíctor Colombo
1170fcf5ef2aSThomas Huth #define DFP_HELPER_ENBCD(op, size) \
1171d9acba31SMark Cave-Ayland void helper_##op(CPUPPCState *env, ppc_fprp_t *t, ppc_fprp_t *b, \
1172d9acba31SMark Cave-Ayland uint32_t s) \
1173fcf5ef2aSThomas Huth { \
1174fcf5ef2aSThomas Huth struct PPC_DFP dfp; \
1175fcf5ef2aSThomas Huth uint8_t digits[32]; \
1176fcf5ef2aSThomas Huth int n = 0, offset = 0, sgn = 0, nonzero = 0; \
1177fcf5ef2aSThomas Huth \
1178fcf5ef2aSThomas Huth dfp_prepare_decimal##size(&dfp, 0, b, env); \
1179fcf5ef2aSThomas Huth \
1180fcf5ef2aSThomas Huth decNumberZero(&dfp.t); \
1181fcf5ef2aSThomas Huth \
1182fcf5ef2aSThomas Huth if (s) { \
11831ea80bf7SMark Cave-Ayland uint8_t sgnNibble = dfp_get_bcd_digit_##size(&dfp.vb, offset++); \
1184fcf5ef2aSThomas Huth switch (sgnNibble) { \
1185fcf5ef2aSThomas Huth case 0xD: \
1186fcf5ef2aSThomas Huth case 0xB: \
1187fcf5ef2aSThomas Huth sgn = 1; \
1188fcf5ef2aSThomas Huth break; \
1189fcf5ef2aSThomas Huth case 0xC: \
1190fcf5ef2aSThomas Huth case 0xF: \
1191fcf5ef2aSThomas Huth case 0xA: \
1192fcf5ef2aSThomas Huth case 0xE: \
1193fcf5ef2aSThomas Huth sgn = 0; \
1194fcf5ef2aSThomas Huth break; \
1195fcf5ef2aSThomas Huth default: \
11963ecec4c0SVíctor Colombo dfp_invalid_op_vxcvi_##size(&dfp); \
11973ecec4c0SVíctor Colombo set_dfp##size(t, &dfp.vt); \
1198fcf5ef2aSThomas Huth return; \
1199fcf5ef2aSThomas Huth } \
1200fcf5ef2aSThomas Huth } \
1201fcf5ef2aSThomas Huth \
1202fcf5ef2aSThomas Huth while (offset < (size) / 4) { \
1203fcf5ef2aSThomas Huth n++; \
12041ea80bf7SMark Cave-Ayland digits[(size) / 4 - n] = dfp_get_bcd_digit_##size(&dfp.vb, \
120564b8574eSMark Cave-Ayland offset++); \
1206fcf5ef2aSThomas Huth if (digits[(size) / 4 - n] > 10) { \
12073ecec4c0SVíctor Colombo dfp_invalid_op_vxcvi_##size(&dfp); \
12083ecec4c0SVíctor Colombo set_dfp##size(t, &dfp.vt); \
1209fcf5ef2aSThomas Huth return; \
1210fcf5ef2aSThomas Huth } else { \
1211fcf5ef2aSThomas Huth nonzero |= (digits[(size) / 4 - n] > 0); \
1212fcf5ef2aSThomas Huth } \
1213fcf5ef2aSThomas Huth } \
1214fcf5ef2aSThomas Huth \
1215fcf5ef2aSThomas Huth if (nonzero) { \
1216fcf5ef2aSThomas Huth decNumberSetBCD(&dfp.t, digits + ((size) / 4) - n, n); \
1217fcf5ef2aSThomas Huth } \
1218fcf5ef2aSThomas Huth \
1219fcf5ef2aSThomas Huth if (s && sgn) { \
1220fcf5ef2aSThomas Huth dfp.t.bits |= DECNEG; \
1221fcf5ef2aSThomas Huth } \
1222474c2e93SMark Cave-Ayland dfp_finalize_decimal##size(&dfp); \
1223fcf5ef2aSThomas Huth dfp_set_FPRF_from_FRT(&dfp); \
1224f6d4c423SMark Cave-Ayland set_dfp##size(t, &dfp.vt); \
1225fcf5ef2aSThomas Huth }
1226fcf5ef2aSThomas Huth
1227a2329747SLuis Pires DFP_HELPER_ENBCD(DENBCD, 64)
1228a2329747SLuis Pires DFP_HELPER_ENBCD(DENBCDQ, 128)
1229fcf5ef2aSThomas Huth
1230fcf5ef2aSThomas Huth #define DFP_HELPER_XEX(op, size) \
1231d9acba31SMark Cave-Ayland void helper_##op(CPUPPCState *env, ppc_fprp_t *t, ppc_fprp_t *b) \
1232fcf5ef2aSThomas Huth { \
1233fcf5ef2aSThomas Huth struct PPC_DFP dfp; \
123464b8574eSMark Cave-Ayland ppc_vsr_t vt; \
1235fcf5ef2aSThomas Huth \
1236fcf5ef2aSThomas Huth dfp_prepare_decimal##size(&dfp, 0, b, env); \
1237fcf5ef2aSThomas Huth \
1238fcf5ef2aSThomas Huth if (unlikely(decNumberIsSpecial(&dfp.b))) { \
1239fcf5ef2aSThomas Huth if (decNumberIsInfinite(&dfp.b)) { \
124064b8574eSMark Cave-Ayland vt.VsrD(1) = -1; \
1241fcf5ef2aSThomas Huth } else if (decNumberIsSNaN(&dfp.b)) { \
124264b8574eSMark Cave-Ayland vt.VsrD(1) = -3; \
1243fcf5ef2aSThomas Huth } else if (decNumberIsQNaN(&dfp.b)) { \
124464b8574eSMark Cave-Ayland vt.VsrD(1) = -2; \
1245fcf5ef2aSThomas Huth } else { \
1246*52d9ffd8SPierrick Bouvier g_assert_not_reached(); \
1247fcf5ef2aSThomas Huth } \
124864b8574eSMark Cave-Ayland set_dfp64(t, &vt); \
1249fcf5ef2aSThomas Huth } else { \
1250fcf5ef2aSThomas Huth if ((size) == 64) { \
125164b8574eSMark Cave-Ayland vt.VsrD(1) = dfp.b.exponent + 398; \
1252fcf5ef2aSThomas Huth } else if ((size) == 128) { \
125364b8574eSMark Cave-Ayland vt.VsrD(1) = dfp.b.exponent + 6176; \
1254fcf5ef2aSThomas Huth } else { \
1255*52d9ffd8SPierrick Bouvier g_assert_not_reached(); \
1256fcf5ef2aSThomas Huth } \
125764b8574eSMark Cave-Ayland set_dfp64(t, &vt); \
1258fcf5ef2aSThomas Huth } \
1259fcf5ef2aSThomas Huth }
1260fcf5ef2aSThomas Huth
1261c8ef4d1eSLuis Pires DFP_HELPER_XEX(DXEX, 64)
1262c8ef4d1eSLuis Pires DFP_HELPER_XEX(DXEXQ, 128)
1263fcf5ef2aSThomas Huth
dfp_set_raw_exp_64(ppc_vsr_t * t,uint64_t raw)12641ea80bf7SMark Cave-Ayland static void dfp_set_raw_exp_64(ppc_vsr_t *t, uint64_t raw)
1265fcf5ef2aSThomas Huth {
12661ea80bf7SMark Cave-Ayland t->VsrD(1) &= 0x8003ffffffffffffULL;
12671ea80bf7SMark Cave-Ayland t->VsrD(1) |= (raw << (63 - 13));
1268fcf5ef2aSThomas Huth }
1269fcf5ef2aSThomas Huth
dfp_set_raw_exp_128(ppc_vsr_t * t,uint64_t raw)12701ea80bf7SMark Cave-Ayland static void dfp_set_raw_exp_128(ppc_vsr_t *t, uint64_t raw)
1271fcf5ef2aSThomas Huth {
12721ea80bf7SMark Cave-Ayland t->VsrD(0) &= 0x80003fffffffffffULL;
12731ea80bf7SMark Cave-Ayland t->VsrD(0) |= (raw << (63 - 17));
1274fcf5ef2aSThomas Huth }
1275fcf5ef2aSThomas Huth
1276fcf5ef2aSThomas Huth #define DFP_HELPER_IEX(op, size) \
1277d9acba31SMark Cave-Ayland void helper_##op(CPUPPCState *env, ppc_fprp_t *t, ppc_fprp_t *a, \
1278d9acba31SMark Cave-Ayland ppc_fprp_t *b) \
1279fcf5ef2aSThomas Huth { \
1280fcf5ef2aSThomas Huth struct PPC_DFP dfp; \
128164b8574eSMark Cave-Ayland uint64_t raw_qnan, raw_snan, raw_inf, max_exp; \
128264b8574eSMark Cave-Ayland ppc_vsr_t va; \
1283fcf5ef2aSThomas Huth int bias; \
12846a8fbb9bSMark Cave-Ayland int64_t exp; \
1285fcf5ef2aSThomas Huth \
128664b8574eSMark Cave-Ayland get_dfp64(&va, a); \
128764b8574eSMark Cave-Ayland exp = (int64_t)va.VsrD(1); \
1288fcf5ef2aSThomas Huth dfp_prepare_decimal##size(&dfp, 0, b, env); \
1289fcf5ef2aSThomas Huth \
1290fcf5ef2aSThomas Huth if ((size) == 64) { \
1291fcf5ef2aSThomas Huth max_exp = 767; \
1292fcf5ef2aSThomas Huth raw_qnan = 0x1F00; \
1293fcf5ef2aSThomas Huth raw_snan = 0x1F80; \
1294fcf5ef2aSThomas Huth raw_inf = 0x1E00; \
1295fcf5ef2aSThomas Huth bias = 398; \
1296fcf5ef2aSThomas Huth } else if ((size) == 128) { \
1297fcf5ef2aSThomas Huth max_exp = 12287; \
1298fcf5ef2aSThomas Huth raw_qnan = 0x1f000; \
1299fcf5ef2aSThomas Huth raw_snan = 0x1f800; \
1300fcf5ef2aSThomas Huth raw_inf = 0x1e000; \
1301fcf5ef2aSThomas Huth bias = 6176; \
1302fcf5ef2aSThomas Huth } else { \
1303*52d9ffd8SPierrick Bouvier g_assert_not_reached(); \
1304fcf5ef2aSThomas Huth } \
1305fcf5ef2aSThomas Huth \
1306fcf5ef2aSThomas Huth if (unlikely((exp < 0) || (exp > max_exp))) { \
130764b8574eSMark Cave-Ayland dfp.vt.VsrD(0) = dfp.vb.VsrD(0); \
130864b8574eSMark Cave-Ayland dfp.vt.VsrD(1) = dfp.vb.VsrD(1); \
1309fcf5ef2aSThomas Huth if (exp == -1) { \
13101ea80bf7SMark Cave-Ayland dfp_set_raw_exp_##size(&dfp.vt, raw_inf); \
1311fcf5ef2aSThomas Huth } else if (exp == -3) { \
13121ea80bf7SMark Cave-Ayland dfp_set_raw_exp_##size(&dfp.vt, raw_snan); \
1313fcf5ef2aSThomas Huth } else { \
13141ea80bf7SMark Cave-Ayland dfp_set_raw_exp_##size(&dfp.vt, raw_qnan); \
1315fcf5ef2aSThomas Huth } \
1316fcf5ef2aSThomas Huth } else { \
1317fcf5ef2aSThomas Huth dfp.t = dfp.b; \
1318fcf5ef2aSThomas Huth if (unlikely(decNumberIsSpecial(&dfp.t))) { \
1319fcf5ef2aSThomas Huth dfp.t.bits &= ~DECSPECIAL; \
1320fcf5ef2aSThomas Huth } \
1321fcf5ef2aSThomas Huth dfp.t.exponent = exp - bias; \
1322474c2e93SMark Cave-Ayland dfp_finalize_decimal##size(&dfp); \
1323fcf5ef2aSThomas Huth } \
1324f6d4c423SMark Cave-Ayland set_dfp##size(t, &dfp.vt); \
1325fcf5ef2aSThomas Huth }
1326fcf5ef2aSThomas Huth
1327afdc9310SLuis Pires DFP_HELPER_IEX(DIEX, 64)
1328afdc9310SLuis Pires DFP_HELPER_IEX(DIEXQ, 128)
1329fcf5ef2aSThomas Huth
dfp_clear_lmd_from_g5msb(uint64_t * t)1330fcf5ef2aSThomas Huth static void dfp_clear_lmd_from_g5msb(uint64_t *t)
1331fcf5ef2aSThomas Huth {
1332fcf5ef2aSThomas Huth
1333fcf5ef2aSThomas Huth /* The most significant 5 bits of the PowerPC DFP format combine bits */
1334fcf5ef2aSThomas Huth /* from the left-most decimal digit (LMD) and the biased exponent. */
1335fcf5ef2aSThomas Huth /* This routine clears the LMD bits while preserving the exponent */
1336fcf5ef2aSThomas Huth /* bits. See "Figure 80: Encoding of bits 0:4 of the G field for */
1337fcf5ef2aSThomas Huth /* Finite Numbers" in the Power ISA for additional details. */
1338fcf5ef2aSThomas Huth
1339fcf5ef2aSThomas Huth uint64_t g5msb = (*t >> 58) & 0x1F;
1340fcf5ef2aSThomas Huth
1341fcf5ef2aSThomas Huth if ((g5msb >> 3) < 3) { /* LMD in [0-7] ? */
1342fcf5ef2aSThomas Huth *t &= ~(7ULL << 58);
1343fcf5ef2aSThomas Huth } else {
1344fcf5ef2aSThomas Huth switch (g5msb & 7) {
1345fcf5ef2aSThomas Huth case 0:
1346fcf5ef2aSThomas Huth case 1:
1347fcf5ef2aSThomas Huth g5msb = 0;
1348fcf5ef2aSThomas Huth break;
1349fcf5ef2aSThomas Huth case 2:
1350fcf5ef2aSThomas Huth case 3:
1351fcf5ef2aSThomas Huth g5msb = 0x8;
1352fcf5ef2aSThomas Huth break;
1353fcf5ef2aSThomas Huth case 4:
1354fcf5ef2aSThomas Huth case 5:
1355fcf5ef2aSThomas Huth g5msb = 0x10;
1356fcf5ef2aSThomas Huth break;
1357fcf5ef2aSThomas Huth case 6:
1358fcf5ef2aSThomas Huth g5msb = 0x1E;
1359fcf5ef2aSThomas Huth break;
1360fcf5ef2aSThomas Huth case 7:
1361fcf5ef2aSThomas Huth g5msb = 0x1F;
1362fcf5ef2aSThomas Huth break;
1363fcf5ef2aSThomas Huth }
1364fcf5ef2aSThomas Huth
1365fcf5ef2aSThomas Huth *t &= ~(0x1fULL << 58);
1366fcf5ef2aSThomas Huth *t |= (g5msb << 58);
1367fcf5ef2aSThomas Huth }
1368fcf5ef2aSThomas Huth }
1369fcf5ef2aSThomas Huth
1370fcf5ef2aSThomas Huth #define DFP_HELPER_SHIFT(op, size, shift_left) \
1371d9acba31SMark Cave-Ayland void helper_##op(CPUPPCState *env, ppc_fprp_t *t, ppc_fprp_t *a, \
1372fcf5ef2aSThomas Huth uint32_t sh) \
1373fcf5ef2aSThomas Huth { \
1374fcf5ef2aSThomas Huth struct PPC_DFP dfp; \
1375fcf5ef2aSThomas Huth unsigned max_digits = ((size) == 64) ? 16 : 34; \
1376fcf5ef2aSThomas Huth \
1377fcf5ef2aSThomas Huth dfp_prepare_decimal##size(&dfp, a, 0, env); \
1378fcf5ef2aSThomas Huth \
1379fcf5ef2aSThomas Huth if (sh <= max_digits) { \
1380fcf5ef2aSThomas Huth \
1381fcf5ef2aSThomas Huth decNumber shd; \
1382fcf5ef2aSThomas Huth unsigned special = dfp.a.bits & DECSPECIAL; \
1383fcf5ef2aSThomas Huth \
1384fcf5ef2aSThomas Huth if (shift_left) { \
1385fcf5ef2aSThomas Huth decNumberFromUInt32(&shd, sh); \
1386fcf5ef2aSThomas Huth } else { \
1387fcf5ef2aSThomas Huth decNumberFromInt32(&shd, -((int32_t)sh)); \
1388fcf5ef2aSThomas Huth } \
1389fcf5ef2aSThomas Huth \
1390fcf5ef2aSThomas Huth dfp.a.bits &= ~DECSPECIAL; \
1391fcf5ef2aSThomas Huth decNumberShift(&dfp.t, &dfp.a, &shd, &dfp.context); \
1392fcf5ef2aSThomas Huth \
1393fcf5ef2aSThomas Huth dfp.t.bits |= special; \
1394fcf5ef2aSThomas Huth if (special && (dfp.t.digits >= max_digits)) { \
1395fcf5ef2aSThomas Huth dfp.t.digits = max_digits - 1; \
1396fcf5ef2aSThomas Huth } \
1397fcf5ef2aSThomas Huth \
1398474c2e93SMark Cave-Ayland dfp_finalize_decimal##size(&dfp); \
1399fcf5ef2aSThomas Huth } else { \
1400fcf5ef2aSThomas Huth if ((size) == 64) { \
140164b8574eSMark Cave-Ayland dfp.vt.VsrD(1) = dfp.va.VsrD(1) & \
140264b8574eSMark Cave-Ayland 0xFFFC000000000000ULL; \
140364b8574eSMark Cave-Ayland dfp_clear_lmd_from_g5msb(&dfp.vt.VsrD(1)); \
1404fcf5ef2aSThomas Huth } else { \
140564b8574eSMark Cave-Ayland dfp.vt.VsrD(0) = dfp.va.VsrD(0) & \
1406fcf5ef2aSThomas Huth 0xFFFFC00000000000ULL; \
140764b8574eSMark Cave-Ayland dfp_clear_lmd_from_g5msb(&dfp.vt.VsrD(0)); \
140864b8574eSMark Cave-Ayland dfp.vt.VsrD(1) = 0; \
1409fcf5ef2aSThomas Huth } \
1410fcf5ef2aSThomas Huth } \
1411fcf5ef2aSThomas Huth \
1412f6d4c423SMark Cave-Ayland set_dfp##size(t, &dfp.vt); \
1413fcf5ef2aSThomas Huth }
1414fcf5ef2aSThomas Huth
1415a2329747SLuis Pires DFP_HELPER_SHIFT(DSCLI, 64, 1)
1416a2329747SLuis Pires DFP_HELPER_SHIFT(DSCLIQ, 128, 1)
1417a2329747SLuis Pires DFP_HELPER_SHIFT(DSCRI, 64, 0)
1418a2329747SLuis Pires DFP_HELPER_SHIFT(DSCRIQ, 128, 0)
141938d3690bSMatheus Ferst
helper_CDTBCD(target_ulong s)14206b924d4aSMatheus Ferst target_ulong helper_CDTBCD(target_ulong s)
14216b924d4aSMatheus Ferst {
14226b924d4aSMatheus Ferst uint64_t res = 0;
14236b924d4aSMatheus Ferst uint32_t dec32, declets;
14246b924d4aSMatheus Ferst uint8_t bcd[6];
14256b924d4aSMatheus Ferst int i, w, sh;
14266b924d4aSMatheus Ferst decNumber a;
14276b924d4aSMatheus Ferst
14286b924d4aSMatheus Ferst for (w = 1; w >= 0; w--) {
14296b924d4aSMatheus Ferst res <<= 32;
14306b924d4aSMatheus Ferst declets = extract64(s, 32 * w, 20);
14316b924d4aSMatheus Ferst if (declets) {
14326b924d4aSMatheus Ferst /* decimal32 with zero exponent and word "w" declets */
14336b924d4aSMatheus Ferst dec32 = (0x225ULL << 20) | declets;
14346b924d4aSMatheus Ferst decimal32ToNumber((decimal32 *)&dec32, &a);
14356b924d4aSMatheus Ferst decNumberGetBCD(&a, bcd);
14366b924d4aSMatheus Ferst for (i = 0; i < a.digits; i++) {
14376b924d4aSMatheus Ferst sh = 4 * (a.digits - 1 - i);
14386b924d4aSMatheus Ferst res |= (uint64_t)bcd[i] << sh;
14396b924d4aSMatheus Ferst }
14406b924d4aSMatheus Ferst }
14416b924d4aSMatheus Ferst }
14426b924d4aSMatheus Ferst
14436b924d4aSMatheus Ferst return res;
14446b924d4aSMatheus Ferst }
14456b924d4aSMatheus Ferst
helper_CBCDTD(target_ulong s)144638d3690bSMatheus Ferst target_ulong helper_CBCDTD(target_ulong s)
144738d3690bSMatheus Ferst {
144838d3690bSMatheus Ferst uint64_t res = 0;
144938d3690bSMatheus Ferst uint32_t dec32;
145038d3690bSMatheus Ferst uint8_t bcd[6];
145138d3690bSMatheus Ferst int w, i, offs;
145238d3690bSMatheus Ferst decNumber a;
145338d3690bSMatheus Ferst decContext context;
145438d3690bSMatheus Ferst
145538d3690bSMatheus Ferst decContextDefault(&context, DEC_INIT_DECIMAL32);
145638d3690bSMatheus Ferst
145738d3690bSMatheus Ferst for (w = 1; w >= 0; w--) {
145838d3690bSMatheus Ferst res <<= 32;
145938d3690bSMatheus Ferst decNumberZero(&a);
146038d3690bSMatheus Ferst /* Extract each BCD field of word "w" */
146138d3690bSMatheus Ferst for (i = 5; i >= 0; i--) {
146238d3690bSMatheus Ferst offs = 4 * (5 - i) + 32 * w;
146338d3690bSMatheus Ferst bcd[i] = extract64(s, offs, 4);
146438d3690bSMatheus Ferst if (bcd[i] > 9) {
146538d3690bSMatheus Ferst /*
146638d3690bSMatheus Ferst * If the field value is greater than 9, the results are
146738d3690bSMatheus Ferst * undefined. We could use a fixed value like 0 or 9, but
146838d3690bSMatheus Ferst * an and with 9 seems to better match the hardware behavior.
146938d3690bSMatheus Ferst */
147038d3690bSMatheus Ferst bcd[i] &= 9;
147138d3690bSMatheus Ferst }
147238d3690bSMatheus Ferst }
147338d3690bSMatheus Ferst
147438d3690bSMatheus Ferst /* Create a decNumber with the BCD values and convert to decimal32 */
147538d3690bSMatheus Ferst decNumberSetBCD(&a, bcd, 6);
147638d3690bSMatheus Ferst decimal32FromNumber((decimal32 *)&dec32, &a, &context);
147738d3690bSMatheus Ferst
147838d3690bSMatheus Ferst /* Extract the two declets from the decimal32 value */
147938d3690bSMatheus Ferst res |= dec32 & 0xfffff;
148038d3690bSMatheus Ferst }
148138d3690bSMatheus Ferst
148238d3690bSMatheus Ferst return res;
148338d3690bSMatheus Ferst }
1484