diff options
author | Mark Cave-Ayland <mark.cave-ayland@ilande.co.uk> | 2019-09-26 19:57:55 +0100 |
---|---|---|
committer | David Gibson <david@gibson.dropbear.id.au> | 2019-10-04 19:08:20 +1000 |
commit | 6a8fbb9bdb7c06b2a73085fd846e22cd3b65242d (patch) | |
tree | 403949c292aa635b1b641d1380163c9eafb132db /target | |
parent | 85164ad4ed9960cac842fa4cc067c6b6699b0994 (diff) |
target/ppc: introduce get_dfp{64,128}() helper functions
The existing functions (now incorrectly) assume that the MSB and LSB of DFP
numbers are stored as consecutive 64-bit words in memory. Instead of accessing
the DFP numbers directly, introduce get_dfp{64,128}() helper functions to ease
the switch to the correct representation.
Signed-off-by: Mark Cave-Ayland <mark.cave-ayland@ilande.co.uk>
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
Message-Id: <20190926185801.11176-2-mark.cave-ayland@ilande.co.uk>
Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
Diffstat (limited to 'target')
-rw-r--r-- | target/ppc/dfp_helper.c | 52 |
1 files changed, 39 insertions, 13 deletions
diff --git a/target/ppc/dfp_helper.c b/target/ppc/dfp_helper.c index 753399177c..e4369ebe9b 100644 --- a/target/ppc/dfp_helper.c +++ b/target/ppc/dfp_helper.c @@ -36,6 +36,17 @@ #define LO_IDX 0 #endif +static void get_dfp64(uint64_t *dst, uint64_t *dfp) +{ + dst[0] = dfp[0]; +} + +static void get_dfp128(uint64_t *dst, uint64_t *dfp) +{ + dst[0] = dfp[HI_IDX]; + dst[1] = dfp[LO_IDX]; +} + struct PPC_DFP { CPUPPCState *env; uint64_t t64[2], a64[2], b64[2]; @@ -129,7 +140,7 @@ static void dfp_prepare_decimal64(struct PPC_DFP *dfp, uint64_t *a, dfp->env = env; if (a) { - dfp->a64[0] = *a; + get_dfp64(dfp->a64, a); decimal64ToNumber((decimal64 *)dfp->a64, &dfp->a); } else { dfp->a64[0] = 0; @@ -137,7 +148,7 @@ static void dfp_prepare_decimal64(struct PPC_DFP *dfp, uint64_t *a, } if (b) { - dfp->b64[0] = *b; + get_dfp64(dfp->b64, b); decimal64ToNumber((decimal64 *)dfp->b64, &dfp->b); } else { dfp->b64[0] = 0; @@ -153,8 +164,7 @@ static void dfp_prepare_decimal128(struct PPC_DFP *dfp, uint64_t *a, dfp->env = env; if (a) { - dfp->a64[0] = a[HI_IDX]; - dfp->a64[1] = a[LO_IDX]; + get_dfp128(dfp->a64, a); decimal128ToNumber((decimal128 *)dfp->a64, &dfp->a); } else { dfp->a64[0] = dfp->a64[1] = 0; @@ -162,8 +172,7 @@ static void dfp_prepare_decimal128(struct PPC_DFP *dfp, uint64_t *a, } if (b) { - dfp->b64[0] = b[HI_IDX]; - dfp->b64[1] = b[LO_IDX]; + get_dfp128(dfp->b64, b); decimal128ToNumber((decimal128 *)dfp->b64, &dfp->b); } else { dfp->b64[0] = dfp->b64[1] = 0; @@ -617,10 +626,12 @@ uint32_t helper_##op(CPUPPCState *env, uint64_t *a, uint64_t *b) \ { \ struct PPC_DFP dfp; \ unsigned k; \ + uint64_t a64; \ \ dfp_prepare_decimal##size(&dfp, 0, b, env); \ \ - k = *a & 0x3F; \ + get_dfp64(&a64, a); \ + k = a64 & 0x3F; \ \ if (unlikely(decNumberIsSpecial(&dfp.b))) { \ dfp.crbf = 1; \ @@ -817,11 +828,15 @@ void helper_##op(CPUPPCState *env, uint64_t *t, uint64_t *a, \ uint64_t *b, uint32_t rmc) \ { \ struct PPC_DFP dfp; \ - int32_t ref_sig = *a & 0x3F; \ + uint64_t a64; \ + int32_t ref_sig; \ int32_t xmax = ((size) == 64) ? 369 : 6111; \ \ dfp_prepare_decimal##size(&dfp, 0, b, env); \ \ + get_dfp64(&a64, a); \ + ref_sig = a64 & 0x3f; \ + \ _dfp_reround(rmc, ref_sig, xmax, &dfp); \ decimal##size##FromNumber((decimal##size *)dfp.t64, &dfp.t, \ &dfp.context); \ @@ -881,7 +896,12 @@ DFP_HELPER_RINT(drintnq, RINTN_PPs, 128) void helper_dctdp(CPUPPCState *env, uint64_t *t, uint64_t *b) { struct PPC_DFP dfp; - uint32_t b_short = *b; + uint64_t b64; + uint32_t b_short; + + get_dfp64(&b64, b); + b_short = (uint32_t)b64; + dfp_prepare_decimal64(&dfp, 0, 0, env); decimal32ToNumber((decimal32 *)&b_short, &dfp.t); decimal64FromNumber((decimal64 *)t, &dfp.t, &dfp.context); @@ -891,8 +911,10 @@ void helper_dctdp(CPUPPCState *env, uint64_t *t, uint64_t *b) void helper_dctqpq(CPUPPCState *env, uint64_t *t, uint64_t *b) { struct PPC_DFP dfp; + uint64_t b64; dfp_prepare_decimal128(&dfp, 0, 0, env); - decimal64ToNumber((decimal64 *)b, &dfp.t); + get_dfp64(&b64, b); + decimal64ToNumber((decimal64 *)&b64, &dfp.t); dfp_check_for_VXSNAN_and_convert_to_QNaN(&dfp); dfp_set_FPRF_from_FRT(&dfp); @@ -940,8 +962,10 @@ void helper_drdpq(CPUPPCState *env, uint64_t *t, uint64_t *b) void helper_##op(CPUPPCState *env, uint64_t *t, uint64_t *b) \ { \ struct PPC_DFP dfp; \ + uint64_t b64; \ dfp_prepare_decimal##size(&dfp, 0, b, env); \ - decNumberFromInt64(&dfp.t, (int64_t)(*b)); \ + get_dfp64(&b64, b); \ + decNumberFromInt64(&dfp.t, (int64_t)b64); \ decimal##size##FromNumber((decimal##size *)dfp.t64, &dfp.t, &dfp.context); \ CFFIX_PPs(&dfp); \ \ @@ -1183,10 +1207,12 @@ static void dfp_set_raw_exp_128(uint64_t *t, uint64_t raw) void helper_##op(CPUPPCState *env, uint64_t *t, uint64_t *a, uint64_t *b) \ { \ struct PPC_DFP dfp; \ - uint64_t raw_qnan, raw_snan, raw_inf, max_exp; \ + uint64_t raw_qnan, raw_snan, raw_inf, max_exp, a64; \ int bias; \ - int64_t exp = *((int64_t *)a); \ + int64_t exp; \ \ + get_dfp64(&a64, a); \ + exp = (int64_t)a64; \ dfp_prepare_decimal##size(&dfp, 0, b, env); \ \ if ((size) == 64) { \ |