This patch adds a new helper file to the PowerPC implementation (dfp_helper.c). This first version of the file declares a structure that will be used by various Decimal Floating Point (DFP) instructions. It also implements utilities that will initialize such a structure for either a long, 64-bit DFP instruction with two operands, or an extended, 128-bit (aka quad) DFP instruction with two operands.
Since there is not yet any code that invokes these utilities, a temporary pointer array is declared; this avoids 'defined but not used' warnings and thus preserves build bisection. Signed-off-by: Tom Musta <tommu...@gmail.com> --- target-ppc/Makefile.objs | 1 + target-ppc/dfp_helper.c | 111 ++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 112 insertions(+), 0 deletions(-) create mode 100644 target-ppc/dfp_helper.c diff --git a/target-ppc/Makefile.objs b/target-ppc/Makefile.objs index 3cb23e0..a7ae392 100644 --- a/target-ppc/Makefile.objs +++ b/target-ppc/Makefile.objs @@ -6,6 +6,7 @@ obj-$(TARGET_PPC64) += mmu-hash64.o arch_dump.o endif obj-$(CONFIG_KVM) += kvm.o kvm_ppc.o obj-$(call lnot,$(CONFIG_KVM)) += kvm-stub.o +obj-y += dfp_helper.o obj-y += excp_helper.o obj-y += fpu_helper.o obj-y += int_helper.o diff --git a/target-ppc/dfp_helper.c b/target-ppc/dfp_helper.c new file mode 100644 index 0000000..3c5988a --- /dev/null +++ b/target-ppc/dfp_helper.c @@ -0,0 +1,111 @@ +/* + * PowerPC Decimal Floating Point (DPF) emulation helpers for QEMU. + * + * Copyright (c) 2014 Tom Musta + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, see <http://www.gnu.org/licenses/>. + */ + +#include "cpu.h" +#include "helper.h" + +#define DECNUMDIGITS 34 +#include "libdecnumber/decContext.h" +#include "libdecnumber/decNumber.h" +#include "libdecnumber/decDouble.h" +#include "libdecnumber/dpd/decimal64.h" +#include "libdecnumber/dpd/decimal128.h" + +#if defined(HOST_WORDS_BIGENDIAN) +#define HI_IDX 0 +#define LO_IDX 1 +#else +#define HI_IDX 1 +#define LO_IDX 0 +#endif + +struct PPC_DFP { + CPUPPCState *env; + uint64_t t64[2], a64[2], b64[2]; + decNumber t, a, b; + decContext context; + uint8_t crbf; +}; + +static void ppc_dfp_prepare_rounding_mode(decContext *context, uint64_t fpscr) +{ + enum rounding rnd; + + switch ((fpscr >> 32) & 0x7) { + case 0: + rnd = DEC_ROUND_HALF_EVEN; + break; + case 1: + rnd = DEC_ROUND_DOWN; + break; + case 2: + rnd = DEC_ROUND_CEILING; + break; + case 3: + rnd = DEC_ROUND_FLOOR; + break; + case 4: + rnd = DEC_ROUND_HALF_UP; + break; + case 5: + rnd = DEC_ROUND_HALF_DOWN; + break; + case 6: + rnd = DEC_ROUND_UP; + break; + case 7: + rnd = DEC_ROUND_05UP; + break; + } + + decContextSetRounding(context, rnd); +} + +static void ppc_dfp_prepare_decimal64_fra_frb(struct PPC_DFP *dfp, uint64_t *a, + uint64_t *b, CPUPPCState *env) +{ + decContextDefault(&dfp->context, DEC_INIT_DECIMAL64); + ppc_dfp_prepare_rounding_mode(&dfp->context, env->fpscr); + dfp->a64[0] = *a; + dfp->b64[0] = *b; + decimal64ToNumber((decimal64 *)dfp->a64, &dfp->a); + decimal64ToNumber((decimal64 *)dfp->b64, &dfp->b); + dfp->env = env; +} + +static void ppc_dfp_prepare_decimal128_fra_frb(struct PPC_DFP *dfp, uint64_t *a, + uint64_t *b, CPUPPCState *env) +{ + decContextDefault(&dfp->context, DEC_INIT_DECIMAL128); + ppc_dfp_prepare_rounding_mode(&dfp->context, env->fpscr); + dfp->a64[0] = a[HI_IDX]; + dfp->a64[1] = a[LO_IDX]; + dfp->b64[0] = b[HI_IDX]; + dfp->b64[1] = b[LO_IDX]; + dfp->env = env; + decimal128ToNumber((decimal128 *)dfp->a64, &dfp->a); + decimal128ToNumber((decimal128 *)dfp->b64, &dfp->b); +} + +void *_TmpAvoidDefinedButNotUsedWarnings_[] = { + (void *)ppc_dfp_prepare_decimal64_fra_frb, + (void *)ppc_dfp_prepare_decimal128_fra_frb, +}; + + -- 1.7.1