diff options
author | Tom Musta <tommusta@gmail.com> | 2014-04-21 15:55:17 -0500 |
---|---|---|
committer | Alexander Graf <agraf@suse.de> | 2014-06-16 13:24:32 +0200 |
commit | 7796676fddc9f6b035c6a9fd872258b53c7d8644 (patch) | |
tree | 53e9a3c100051ec1a0084c0c5dbf01a107f3730b /target-ppc | |
parent | bea0dd7912ee91c0219f143db7bb8350fade98c4 (diff) |
target-ppc: Introduce DFP Decode DPD to BCD
Add emulation of the Power PC Decimal Floating Point Decode
Densely Packed Decimal to Binary Coded Decimal instructions
ddedpd[q][.].
Signed-off-by: Tom Musta <tommusta@gmail.com>
Signed-off-by: Alexander Graf <agraf@suse.de>
Diffstat (limited to 'target-ppc')
-rw-r--r-- | target-ppc/dfp_helper.c | 66 | ||||
-rw-r--r-- | target-ppc/helper.h | 2 | ||||
-rw-r--r-- | target-ppc/translate.c | 4 |
3 files changed, 72 insertions, 0 deletions
diff --git a/target-ppc/dfp_helper.c b/target-ppc/dfp_helper.c index 24de5a7770..df40da7ca9 100644 --- a/target-ppc/dfp_helper.c +++ b/target-ppc/dfp_helper.c @@ -983,3 +983,69 @@ void helper_##op(CPUPPCState *env, uint64_t *t, uint64_t *b) \ DFP_HELPER_CTFIX(dctfix, 64) DFP_HELPER_CTFIX(dctfixq, 128) + +static inline void dfp_set_bcd_digit_64(uint64_t *t, uint8_t digit, + unsigned n) +{ + *t |= ((uint64_t)(digit & 0xF) << (n << 2)); +} + +static inline void dfp_set_bcd_digit_128(uint64_t *t, uint8_t digit, + unsigned n) +{ + t[(n & 0x10) ? HI_IDX : LO_IDX] |= + ((uint64_t)(digit & 0xF) << ((n & 15) << 2)); +} + +static inline void dfp_set_sign_64(uint64_t *t, uint8_t sgn) +{ + *t <<= 4; + *t |= (sgn & 0xF); +} + +static inline void dfp_set_sign_128(uint64_t *t, uint8_t sgn) +{ + t[HI_IDX] <<= 4; + t[HI_IDX] |= (t[LO_IDX] >> 60); + t[LO_IDX] <<= 4; + t[LO_IDX] |= (sgn & 0xF); +} + +#define DFP_HELPER_DEDPD(op, size) \ +void helper_##op(CPUPPCState *env, uint64_t *t, uint64_t *b, uint32_t sp) \ +{ \ + struct PPC_DFP dfp; \ + uint8_t digits[34]; \ + int i, N; \ + \ + dfp_prepare_decimal##size(&dfp, 0, b, env); \ + \ + decNumberGetBCD(&dfp.b, digits); \ + dfp.t64[0] = dfp.t64[1] = 0; \ + N = dfp.b.digits; \ + \ + for (i = 0; (i < N) && (i < (size)/4); i++) { \ + dfp_set_bcd_digit_##size(dfp.t64, digits[N-i-1], i); \ + } \ + \ + if (sp & 2) { \ + uint8_t sgn; \ + \ + if (decNumberIsNegative(&dfp.b)) { \ + sgn = 0xD; \ + } else { \ + sgn = ((sp & 1) ? 0xF : 0xC); \ + } \ + dfp_set_sign_##size(dfp.t64, sgn); \ + } \ + \ + 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_DEDPD(ddedpd, 64) +DFP_HELPER_DEDPD(ddedpdq, 128) diff --git a/target-ppc/helper.h b/target-ppc/helper.h index 69c0a1d8e3..d4e73f26cb 100644 --- a/target-ppc/helper.h +++ b/target-ppc/helper.h @@ -654,3 +654,5 @@ DEF_HELPER_3(dcffix, void, env, fprp, fprp) DEF_HELPER_3(dcffixq, void, env, fprp, fprp) 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) diff --git a/target-ppc/translate.c b/target-ppc/translate.c index 9b1dca5416..2588ddb548 100644 --- a/target-ppc/translate.c +++ b/target-ppc/translate.c @@ -8394,6 +8394,8 @@ GEN_DFP_T_B_Rc(dcffix) GEN_DFP_T_B_Rc(dcffixq) 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) /*** SPE extension ***/ /* Register moves */ @@ -11359,6 +11361,8 @@ GEN_DFP_T_B_Rc(dcffix, 0x02, 0x19), GEN_DFP_Tp_B_Rc(dcffixq, 0x02, 0x19), 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), #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) |