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>
master
Mark Cave-Ayland 2019-09-26 19:57:55 +01:00 committed by David Gibson
parent 85164ad4ed
commit 6a8fbb9bdb
1 changed files with 39 additions and 13 deletions

View File

@ -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) { \