target-ppc: Introduce DFP Shift Significand
Add emulation of the PowerPC Decimal Floating Point Shift Significand Left Immediate (dscli[q][.]) and DFP Shift Significant Right Immediate (dscri[q][.]) instructions. Signed-off-by: Tom Musta <tommusta@gmail.com> Signed-off-by: Alexander Graf <agraf@suse.de>
This commit is contained in:
parent
297666eba0
commit
804e654a56
|
@ -1220,3 +1220,98 @@ void helper_##op(CPUPPCState *env, uint64_t *t, uint64_t *a, uint64_t *b) \
|
||||||
|
|
||||||
DFP_HELPER_IEX(diex, 64)
|
DFP_HELPER_IEX(diex, 64)
|
||||||
DFP_HELPER_IEX(diexq, 128)
|
DFP_HELPER_IEX(diexq, 128)
|
||||||
|
|
||||||
|
static void dfp_clear_lmd_from_g5msb(uint64_t *t)
|
||||||
|
{
|
||||||
|
|
||||||
|
/* The most significant 5 bits of the PowerPC DFP format combine bits */
|
||||||
|
/* from the left-most decimal digit (LMD) and the biased exponent. */
|
||||||
|
/* This routine clears the LMD bits while preserving the exponent */
|
||||||
|
/* bits. See "Figure 80: Encoding of bits 0:4 of the G field for */
|
||||||
|
/* Finite Numbers" in the Power ISA for additional details. */
|
||||||
|
|
||||||
|
uint64_t g5msb = (*t >> 58) & 0x1F;
|
||||||
|
|
||||||
|
if ((g5msb >> 3) < 3) { /* LMD in [0-7] ? */
|
||||||
|
*t &= ~(7ULL << 58);
|
||||||
|
} else {
|
||||||
|
switch (g5msb & 7) {
|
||||||
|
case 0:
|
||||||
|
case 1:
|
||||||
|
g5msb = 0;
|
||||||
|
break;
|
||||||
|
case 2:
|
||||||
|
case 3:
|
||||||
|
g5msb = 0x8;
|
||||||
|
break;
|
||||||
|
case 4:
|
||||||
|
case 5:
|
||||||
|
g5msb = 0x10;
|
||||||
|
break;
|
||||||
|
case 6:
|
||||||
|
g5msb = 0x1E;
|
||||||
|
break;
|
||||||
|
case 7:
|
||||||
|
g5msb = 0x1F;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
*t &= ~(0x1fULL << 58);
|
||||||
|
*t |= (g5msb << 58);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#define DFP_HELPER_SHIFT(op, size, shift_left) \
|
||||||
|
void helper_##op(CPUPPCState *env, uint64_t *t, uint64_t *a, \
|
||||||
|
uint32_t sh) \
|
||||||
|
{ \
|
||||||
|
struct PPC_DFP dfp; \
|
||||||
|
unsigned max_digits = ((size) == 64) ? 16 : 34; \
|
||||||
|
\
|
||||||
|
dfp_prepare_decimal##size(&dfp, a, 0, env); \
|
||||||
|
\
|
||||||
|
if (sh <= max_digits) { \
|
||||||
|
\
|
||||||
|
decNumber shd; \
|
||||||
|
unsigned special = dfp.a.bits & DECSPECIAL; \
|
||||||
|
\
|
||||||
|
if (shift_left) { \
|
||||||
|
decNumberFromUInt32(&shd, sh); \
|
||||||
|
} else { \
|
||||||
|
decNumberFromInt32(&shd, -((int32_t)sh)); \
|
||||||
|
} \
|
||||||
|
\
|
||||||
|
dfp.a.bits &= ~DECSPECIAL; \
|
||||||
|
decNumberShift(&dfp.t, &dfp.a, &shd, &dfp.context); \
|
||||||
|
\
|
||||||
|
dfp.t.bits |= special; \
|
||||||
|
if (special && (dfp.t.digits >= max_digits)) { \
|
||||||
|
dfp.t.digits = max_digits - 1; \
|
||||||
|
} \
|
||||||
|
\
|
||||||
|
decimal##size##FromNumber((decimal##size *)dfp.t64, &dfp.t, \
|
||||||
|
&dfp.context); \
|
||||||
|
} else { \
|
||||||
|
if ((size) == 64) { \
|
||||||
|
dfp.t64[0] = dfp.a64[0] & 0xFFFC000000000000ULL; \
|
||||||
|
dfp_clear_lmd_from_g5msb(dfp.t64); \
|
||||||
|
} else { \
|
||||||
|
dfp.t64[HI_IDX] = dfp.a64[HI_IDX] & \
|
||||||
|
0xFFFFC00000000000ULL; \
|
||||||
|
dfp_clear_lmd_from_g5msb(dfp.t64 + HI_IDX); \
|
||||||
|
dfp.t64[LO_IDX] = 0; \
|
||||||
|
} \
|
||||||
|
} \
|
||||||
|
\
|
||||||
|
if ((size) == 64) { \
|
||||||
|
t[0] = dfp.t64[0]; \
|
||||||
|
} else { \
|
||||||
|
t[0] = dfp.t64[HI_IDX]; \
|
||||||
|
t[1] = dfp.t64[LO_IDX]; \
|
||||||
|
} \
|
||||||
|
}
|
||||||
|
|
||||||
|
DFP_HELPER_SHIFT(dscli, 64, 1)
|
||||||
|
DFP_HELPER_SHIFT(dscliq, 128, 1)
|
||||||
|
DFP_HELPER_SHIFT(dscri, 64, 0)
|
||||||
|
DFP_HELPER_SHIFT(dscriq, 128, 0)
|
||||||
|
|
|
@ -662,3 +662,7 @@ DEF_HELPER_3(dxex, void, env, fprp, fprp)
|
||||||
DEF_HELPER_3(dxexq, void, env, fprp, fprp)
|
DEF_HELPER_3(dxexq, void, env, fprp, fprp)
|
||||||
DEF_HELPER_4(diex, void, env, fprp, fprp, fprp)
|
DEF_HELPER_4(diex, void, env, fprp, fprp, fprp)
|
||||||
DEF_HELPER_4(diexq, void, env, fprp, fprp, fprp)
|
DEF_HELPER_4(diexq, void, env, fprp, fprp, fprp)
|
||||||
|
DEF_HELPER_4(dscri, void, env, fprp, fprp, i32)
|
||||||
|
DEF_HELPER_4(dscriq, void, env, fprp, fprp, i32)
|
||||||
|
DEF_HELPER_4(dscli, void, env, fprp, fprp, i32)
|
||||||
|
DEF_HELPER_4(dscliq, void, env, fprp, fprp, i32)
|
||||||
|
|
|
@ -8402,6 +8402,11 @@ GEN_DFP_T_B_Rc(dxex)
|
||||||
GEN_DFP_T_B_Rc(dxexq)
|
GEN_DFP_T_B_Rc(dxexq)
|
||||||
GEN_DFP_T_A_B_Rc(diex)
|
GEN_DFP_T_A_B_Rc(diex)
|
||||||
GEN_DFP_T_A_B_Rc(diexq)
|
GEN_DFP_T_A_B_Rc(diexq)
|
||||||
|
GEN_DFP_T_FPR_I32_Rc(dscli, rA, DCM)
|
||||||
|
GEN_DFP_T_FPR_I32_Rc(dscliq, rA, DCM)
|
||||||
|
GEN_DFP_T_FPR_I32_Rc(dscri, rA, DCM)
|
||||||
|
GEN_DFP_T_FPR_I32_Rc(dscriq, rA, DCM)
|
||||||
|
|
||||||
/*** SPE extension ***/
|
/*** SPE extension ***/
|
||||||
/* Register moves */
|
/* Register moves */
|
||||||
|
|
||||||
|
@ -11375,6 +11380,11 @@ GEN_DFP_T_B_Rc(dxex, 0x02, 0x0b),
|
||||||
GEN_DFP_T_Bp_Rc(dxexq, 0x02, 0x0b),
|
GEN_DFP_T_Bp_Rc(dxexq, 0x02, 0x0b),
|
||||||
GEN_DFP_T_A_B_Rc(diex, 0x02, 0x1b),
|
GEN_DFP_T_A_B_Rc(diex, 0x02, 0x1b),
|
||||||
GEN_DFP_Tp_A_Bp_Rc(diexq, 0x02, 0x1b),
|
GEN_DFP_Tp_A_Bp_Rc(diexq, 0x02, 0x1b),
|
||||||
|
GEN_DFP_T_A_SH_Rc(dscli, 0x02, 0x02),
|
||||||
|
GEN_DFP_Tp_Ap_SH_Rc(dscliq, 0x02, 0x02),
|
||||||
|
GEN_DFP_T_A_SH_Rc(dscri, 0x02, 0x03),
|
||||||
|
GEN_DFP_Tp_Ap_SH_Rc(dscriq, 0x02, 0x03),
|
||||||
|
|
||||||
#undef GEN_SPE
|
#undef GEN_SPE
|
||||||
#define GEN_SPE(name0, name1, opc2, opc3, inval0, inval1, type) \
|
#define GEN_SPE(name0, name1, opc2, opc3, inval0, inval1, type) \
|
||||||
GEN_OPCODE_DUAL(name0##_##name1, 0x04, opc2, opc3, inval0, inval1, type, PPC_NONE)
|
GEN_OPCODE_DUAL(name0##_##name1, 0x04, opc2, opc3, inval0, inval1, type, PPC_NONE)
|
||||||
|
|
Loading…
Reference in New Issue