diff options
-rw-r--r-- | target-ppc/dfp_helper.c | 68 | ||||
-rw-r--r-- | target-ppc/helper.h | 2 | ||||
-rw-r--r-- | target-ppc/translate.c | 4 |
3 files changed, 74 insertions, 0 deletions
diff --git a/target-ppc/dfp_helper.c b/target-ppc/dfp_helper.c index 8c8ee795c7..adb9763192 100644 --- a/target-ppc/dfp_helper.c +++ b/target-ppc/dfp_helper.c @@ -1152,3 +1152,71 @@ void helper_##op(CPUPPCState *env, uint64_t *t, uint64_t *b) \ DFP_HELPER_XEX(dxex, 64) DFP_HELPER_XEX(dxexq, 128) + +static void dfp_set_raw_exp_64(uint64_t *t, uint64_t raw) +{ + *t &= 0x8003ffffffffffffULL; + *t |= (raw << (63-13)); +} + +static void dfp_set_raw_exp_128(uint64_t *t, uint64_t raw) +{ + t[HI_IDX] &= 0x80003fffffffffffULL; + t[HI_IDX] |= (raw << (63-17)); +} + +#define DFP_HELPER_IEX(op, size) \ +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; \ + int bias; \ + int64_t exp = *((int64_t *)a); \ + \ + dfp_prepare_decimal##size(&dfp, 0, b, env); \ + \ + if ((size) == 64) { \ + max_exp = 767; \ + raw_qnan = 0x1F00; \ + raw_snan = 0x1F80; \ + raw_inf = 0x1E00; \ + bias = 398; \ + } else if ((size) == 128) { \ + max_exp = 12287; \ + raw_qnan = 0x1f000; \ + raw_snan = 0x1f800; \ + raw_inf = 0x1e000; \ + bias = 6176; \ + } else { \ + assert(0); \ + } \ + \ + if (unlikely((exp < 0) || (exp > max_exp))) { \ + dfp.t64[0] = dfp.b64[0]; \ + dfp.t64[1] = dfp.b64[1]; \ + if (exp == -1) { \ + dfp_set_raw_exp_##size(dfp.t64, raw_inf); \ + } else if (exp == -3) { \ + dfp_set_raw_exp_##size(dfp.t64, raw_snan); \ + } else { \ + dfp_set_raw_exp_##size(dfp.t64, raw_qnan); \ + } \ + } else { \ + dfp.t = dfp.b; \ + if (unlikely(decNumberIsSpecial(&dfp.t))) { \ + dfp.t.bits &= ~DECSPECIAL; \ + } \ + dfp.t.exponent = exp - bias; \ + decimal##size##FromNumber((decimal##size *)dfp.t64, &dfp.t, \ + &dfp.context); \ + } \ + 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_IEX(diex, 64) +DFP_HELPER_IEX(diexq, 128) diff --git a/target-ppc/helper.h b/target-ppc/helper.h index b99ca809a9..435a1c0924 100644 --- a/target-ppc/helper.h +++ b/target-ppc/helper.h @@ -660,3 +660,5 @@ DEF_HELPER_4(denbcd, void, env, fprp, fprp, i32) DEF_HELPER_4(denbcdq, void, env, fprp, fprp, i32) DEF_HELPER_3(dxex, void, env, fprp, fprp) DEF_HELPER_3(dxexq, void, env, fprp, fprp) +DEF_HELPER_4(diex, void, env, fprp, fprp, fprp) +DEF_HELPER_4(diexq, void, env, fprp, fprp, fprp) diff --git a/target-ppc/translate.c b/target-ppc/translate.c index 4cc93dff48..da71e925ec 100644 --- a/target-ppc/translate.c +++ b/target-ppc/translate.c @@ -8400,6 +8400,8 @@ GEN_DFP_T_FPR_I32_Rc(denbcd, rB, SP) GEN_DFP_T_FPR_I32_Rc(denbcdq, rB, SP) GEN_DFP_T_B_Rc(dxex) GEN_DFP_T_B_Rc(dxexq) +GEN_DFP_T_A_B_Rc(diex) +GEN_DFP_T_A_B_Rc(diexq) /*** SPE extension ***/ /* Register moves */ @@ -11371,6 +11373,8 @@ GEN_DFP_S_T_B_Rc(denbcd, 0x02, 0x1a), GEN_DFP_S_Tp_Bp_Rc(denbcdq, 0x02, 0x1a), GEN_DFP_T_B_Rc(dxex, 0x02, 0x0b), GEN_DFP_T_Bp_Rc(dxexq, 0x02, 0x0b), +GEN_DFP_T_A_B_Rc(diex, 0x02, 0x1b), +GEN_DFP_Tp_A_Bp_Rc(diexq, 0x02, 0x1b), #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) |