Skip to content

Commit

Permalink
target-ppc: Introduce DFP Encode BCD to DPD
Browse files Browse the repository at this point in the history
Add emulation of the PowerPC Decimal Floating Point Encode Binary
Coded Decimal to Densely Packed Decimal instructions denbcd[q][.].

Signed-off-by: Tom Musta <tommusta@gmail.com>
Signed-off-by: Alexander Graf <agraf@suse.de>
  • Loading branch information
Tom Musta authored and agraf committed Jun 16, 2014
1 parent 7796676 commit 013c3ac
Show file tree
Hide file tree
Showing 3 changed files with 78 additions and 0 deletions.
72 changes: 72 additions & 0 deletions target-ppc/dfp_helper.c
Expand Up @@ -1049,3 +1049,75 @@ void helper_##op(CPUPPCState *env, uint64_t *t, uint64_t *b, uint32_t sp) \

DFP_HELPER_DEDPD(ddedpd, 64)
DFP_HELPER_DEDPD(ddedpdq, 128)

static inline uint8_t dfp_get_bcd_digit_64(uint64_t *t, unsigned n)
{
return *t >> ((n << 2) & 63) & 15;
}

static inline uint8_t dfp_get_bcd_digit_128(uint64_t *t, unsigned n)
{
return t[(n & 0x10) ? HI_IDX : LO_IDX] >> ((n << 2) & 63) & 15;
}

#define DFP_HELPER_ENBCD(op, size) \
void helper_##op(CPUPPCState *env, uint64_t *t, uint64_t *b, uint32_t s) \
{ \
struct PPC_DFP dfp; \
uint8_t digits[32]; \
int n = 0, offset = 0, sgn = 0, nonzero = 0; \
\
dfp_prepare_decimal##size(&dfp, 0, b, env); \
\
decNumberZero(&dfp.t); \
\
if (s) { \
uint8_t sgnNibble = dfp_get_bcd_digit_##size(dfp.b64, offset++); \
switch (sgnNibble) { \
case 0xD: \
case 0xB: \
sgn = 1; \
break; \
case 0xC: \
case 0xF: \
case 0xA: \
case 0xE: \
sgn = 0; \
break; \
default: \
dfp_set_FPSCR_flag(&dfp, FP_VX | FP_VXCVI, FPSCR_VE); \
return; \
} \
} \
\
while (offset < (size)/4) { \
n++; \
digits[(size)/4-n] = dfp_get_bcd_digit_##size(dfp.b64, offset++); \
if (digits[(size)/4-n] > 10) { \
dfp_set_FPSCR_flag(&dfp, FP_VX | FP_VXCVI, FPSCR_VE); \
return; \
} else { \
nonzero |= (digits[(size)/4-n] > 0); \
} \
} \
\
if (nonzero) { \
decNumberSetBCD(&dfp.t, digits+((size)/4)-n, n); \
} \
\
if (s && sgn) { \
dfp.t.bits |= DECNEG; \
} \
decimal##size##FromNumber((decimal##size *)dfp.t64, &dfp.t, \
&dfp.context); \
dfp_set_FPRF_from_FRT(&dfp); \
if ((size) == 64) { \
t[0] = dfp.t64[0]; \
} else if ((size) == 128) { \
t[0] = dfp.t64[HI_IDX]; \
t[1] = dfp.t64[LO_IDX]; \
} \
}

DFP_HELPER_ENBCD(denbcd, 64)
DFP_HELPER_ENBCD(denbcdq, 128)
2 changes: 2 additions & 0 deletions target-ppc/helper.h
Expand Up @@ -656,3 +656,5 @@ DEF_HELPER_3(dctfix, void, env, fprp, fprp)
DEF_HELPER_3(dctfixq, void, env, fprp, fprp)
DEF_HELPER_4(ddedpd, void, env, fprp, fprp, i32)
DEF_HELPER_4(ddedpdq, void, env, fprp, fprp, i32)
DEF_HELPER_4(denbcd, void, env, fprp, fprp, i32)
DEF_HELPER_4(denbcdq, void, env, fprp, fprp, i32)
4 changes: 4 additions & 0 deletions target-ppc/translate.c
Expand Up @@ -8396,6 +8396,8 @@ GEN_DFP_T_B_Rc(dctfix)
GEN_DFP_T_B_Rc(dctfixq)
GEN_DFP_T_FPR_I32_Rc(ddedpd, rB, SP)
GEN_DFP_T_FPR_I32_Rc(ddedpdq, rB, SP)
GEN_DFP_T_FPR_I32_Rc(denbcd, rB, SP)
GEN_DFP_T_FPR_I32_Rc(denbcdq, rB, SP)
/*** SPE extension ***/
/* Register moves */

Expand Down Expand Up @@ -11363,6 +11365,8 @@ GEN_DFP_T_B_Rc(dctfix, 0x02, 0x09),
GEN_DFP_T_Bp_Rc(dctfixq, 0x02, 0x09),
GEN_DFP_SP_T_B_Rc(ddedpd, 0x02, 0x0a),
GEN_DFP_SP_Tp_Bp_Rc(ddedpdq, 0x02, 0x0a),
GEN_DFP_S_T_B_Rc(denbcd, 0x02, 0x1a),
GEN_DFP_S_Tp_Bp_Rc(denbcdq, 0x02, 0x1a),
#undef GEN_SPE
#define GEN_SPE(name0, name1, opc2, opc3, inval0, inval1, type) \
GEN_OPCODE_DUAL(name0##_##name1, 0x04, opc2, opc3, inval0, inval1, type, PPC_NONE)
Expand Down

0 comments on commit 013c3ac

Please sign in to comment.