diff options
| author | Richard Henderson <richard.henderson@linaro.org> | 2021-11-09 07:18:33 +0100 |
|---|---|---|
| committer | Richard Henderson <richard.henderson@linaro.org> | 2021-11-09 07:18:33 +0100 |
| commit | f10e7b9f6fc18be390b3bc189e04b5147eb8dbf8 (patch) | |
| tree | 760292c2ddc22c5b75653c5d5dc7ae4ca6d8d729 /target/ppc/dfp_helper.c | |
| parent | 114f3c8cc427333dbae331dfd2ecae64676b087e (diff) | |
| parent | 71e6fae3a994ab5c69e37d6a52a30c840883fbfb (diff) | |
| download | focaccia-qemu-f10e7b9f6fc18be390b3bc189e04b5147eb8dbf8.tar.gz focaccia-qemu-f10e7b9f6fc18be390b3bc189e04b5147eb8dbf8.zip | |
Merge remote-tracking branch 'remotes/dgibson/tags/ppc-for-6.2-20211109' into staging
ppc patch queue for 2021-11-09 Here's the latest set of ppc related patches for qemu-6.2, which I hope will squeeze in just barely before the hard freeze. This set includes a change to MAINTAINERS moving maintainership of ppc from myself and Greg Kurz to Cédric le Goater and Daniel Henrique Barboza. So, I expect this to be my last pull request as ppc maintainer. It's been great, but it's time I moved onto other things. Apart from that, this patchset is mostly a lot of updates to TCG implementations of ISA 3.1 (POWER10) instructions from the El Dorado team. There are also a handful of other fixes. # gpg: Signature made Tue 09 Nov 2021 05:14:33 AM CET # gpg: using RSA key 75F46586AE61A66CC44E87DC6C38CACA20D9B392 # gpg: Good signature from "David Gibson <david@gibson.dropbear.id.au>" [full] # gpg: aka "David Gibson (kernel.org) <dwg@kernel.org>" [unknown] # gpg: aka "David Gibson (Red Hat) <dgibson@redhat.com>" [full] # gpg: aka "David Gibson (ozlabs.org) <dgibson@ozlabs.org>" [full] * remotes/dgibson/tags/ppc-for-6.2-20211109: (54 commits) spapr_numa.c: FORM2 table handle nodes with no distance info target/ppc, hw/ppc: Change maintainers target/ppc: cntlzdm/cnttzdm implementation without brcond target/ppc: Implement lxvkq instruction target/ppc: Implement xxblendvb/xxblendvh/xxblendvw/xxblendvd instructions target/ppc: implemented XXSPLTIDP instruction target/ppc: Implemented XXSPLTIW using decodetree target/ppc: implemented XXSPLTI32DX target/ppc: moved XXSPLTIB to using decodetree target/ppc: moved XXSPLTW to using decodetree target/ppc: added the instructions PLXVP and PSTXVP target/ppc: added the instructions PLXV and PSTXV target/ppc: added the instructions LXVPX and STXVPX target/ppc: added the instructions LXVP and STXVP target/ppc: moved stxvx and lxvx from legacy to decodtree target/ppc: moved stxv and lxv from legacy to decodtree target/ppc: receive high/low as argument in get/set_cpu_vsr target/ppc: Introduce REQUIRE_VSX macro target/ppc: Implement Vector Extract Double to VSR using GPR index insns target/ppc: Move vinsertb/vinserth/vinsertw/vinsertd to decodetree ... Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
Diffstat (limited to 'target/ppc/dfp_helper.c')
| -rw-r--r-- | target/ppc/dfp_helper.c | 168 |
1 files changed, 116 insertions, 52 deletions
diff --git a/target/ppc/dfp_helper.c b/target/ppc/dfp_helper.c index 07341a69f5..0d01ac3de0 100644 --- a/target/ppc/dfp_helper.c +++ b/target/ppc/dfp_helper.c @@ -51,6 +51,11 @@ static void set_dfp128(ppc_fprp_t *dfp, ppc_vsr_t *src) dfp[1].VsrD(0) = src->VsrD(1); } +static void set_dfp128_to_avr(ppc_avr_t *dst, ppc_vsr_t *src) +{ + *dst = *src; +} + struct PPC_DFP { CPUPPCState *env; ppc_vsr_t vt, va, vb; @@ -440,8 +445,8 @@ static void ADD_PPs(struct PPC_DFP *dfp) dfp_check_for_VXISI_add(dfp); } -DFP_HELPER_TAB(dadd, decNumberAdd, ADD_PPs, 64) -DFP_HELPER_TAB(daddq, decNumberAdd, ADD_PPs, 128) +DFP_HELPER_TAB(DADD, decNumberAdd, ADD_PPs, 64) +DFP_HELPER_TAB(DADDQ, decNumberAdd, ADD_PPs, 128) static void SUB_PPs(struct PPC_DFP *dfp) { @@ -453,8 +458,8 @@ static void SUB_PPs(struct PPC_DFP *dfp) dfp_check_for_VXISI_subtract(dfp); } -DFP_HELPER_TAB(dsub, decNumberSubtract, SUB_PPs, 64) -DFP_HELPER_TAB(dsubq, decNumberSubtract, SUB_PPs, 128) +DFP_HELPER_TAB(DSUB, decNumberSubtract, SUB_PPs, 64) +DFP_HELPER_TAB(DSUBQ, decNumberSubtract, SUB_PPs, 128) static void MUL_PPs(struct PPC_DFP *dfp) { @@ -466,8 +471,8 @@ static void MUL_PPs(struct PPC_DFP *dfp) dfp_check_for_VXIMZ(dfp); } -DFP_HELPER_TAB(dmul, decNumberMultiply, MUL_PPs, 64) -DFP_HELPER_TAB(dmulq, decNumberMultiply, MUL_PPs, 128) +DFP_HELPER_TAB(DMUL, decNumberMultiply, MUL_PPs, 64) +DFP_HELPER_TAB(DMULQ, decNumberMultiply, MUL_PPs, 128) static void DIV_PPs(struct PPC_DFP *dfp) { @@ -481,8 +486,8 @@ static void DIV_PPs(struct PPC_DFP *dfp) dfp_check_for_VXIDI(dfp); } -DFP_HELPER_TAB(ddiv, decNumberDivide, DIV_PPs, 64) -DFP_HELPER_TAB(ddivq, decNumberDivide, DIV_PPs, 128) +DFP_HELPER_TAB(DDIV, decNumberDivide, DIV_PPs, 64) +DFP_HELPER_TAB(DDIVQ, decNumberDivide, DIV_PPs, 128) #define DFP_HELPER_BF_AB(op, dnop, postprocs, size) \ uint32_t helper_##op(CPUPPCState *env, ppc_fprp_t *a, ppc_fprp_t *b) \ @@ -502,8 +507,8 @@ static void CMPU_PPs(struct PPC_DFP *dfp) dfp_check_for_VXSNAN(dfp); } -DFP_HELPER_BF_AB(dcmpu, decNumberCompare, CMPU_PPs, 64) -DFP_HELPER_BF_AB(dcmpuq, decNumberCompare, CMPU_PPs, 128) +DFP_HELPER_BF_AB(DCMPU, decNumberCompare, CMPU_PPs, 64) +DFP_HELPER_BF_AB(DCMPUQ, decNumberCompare, CMPU_PPs, 128) static void CMPO_PPs(struct PPC_DFP *dfp) { @@ -513,8 +518,8 @@ static void CMPO_PPs(struct PPC_DFP *dfp) dfp_check_for_VXVC(dfp); } -DFP_HELPER_BF_AB(dcmpo, decNumberCompare, CMPO_PPs, 64) -DFP_HELPER_BF_AB(dcmpoq, decNumberCompare, CMPO_PPs, 128) +DFP_HELPER_BF_AB(DCMPO, decNumberCompare, CMPO_PPs, 64) +DFP_HELPER_BF_AB(DCMPOQ, decNumberCompare, CMPO_PPs, 128) #define DFP_HELPER_TSTDC(op, size) \ uint32_t helper_##op(CPUPPCState *env, ppc_fprp_t *a, uint32_t dcm) \ @@ -541,8 +546,8 @@ uint32_t helper_##op(CPUPPCState *env, ppc_fprp_t *a, uint32_t dcm) \ return dfp.crbf; \ } -DFP_HELPER_TSTDC(dtstdc, 64) -DFP_HELPER_TSTDC(dtstdcq, 128) +DFP_HELPER_TSTDC(DTSTDC, 64) +DFP_HELPER_TSTDC(DTSTDCQ, 128) #define DFP_HELPER_TSTDG(op, size) \ uint32_t helper_##op(CPUPPCState *env, ppc_fprp_t *a, uint32_t dcm) \ @@ -596,8 +601,8 @@ uint32_t helper_##op(CPUPPCState *env, ppc_fprp_t *a, uint32_t dcm) \ return dfp.crbf; \ } -DFP_HELPER_TSTDG(dtstdg, 64) -DFP_HELPER_TSTDG(dtstdgq, 128) +DFP_HELPER_TSTDG(DTSTDG, 64) +DFP_HELPER_TSTDG(DTSTDGQ, 128) #define DFP_HELPER_TSTEX(op, size) \ uint32_t helper_##op(CPUPPCState *env, ppc_fprp_t *a, ppc_fprp_t *b) \ @@ -628,8 +633,8 @@ uint32_t helper_##op(CPUPPCState *env, ppc_fprp_t *a, ppc_fprp_t *b) \ return dfp.crbf; \ } -DFP_HELPER_TSTEX(dtstex, 64) -DFP_HELPER_TSTEX(dtstexq, 128) +DFP_HELPER_TSTEX(DTSTEX, 64) +DFP_HELPER_TSTEX(DTSTEXQ, 128) #define DFP_HELPER_TSTSF(op, size) \ uint32_t helper_##op(CPUPPCState *env, ppc_fprp_t *a, ppc_fprp_t *b) \ @@ -665,8 +670,8 @@ uint32_t helper_##op(CPUPPCState *env, ppc_fprp_t *a, ppc_fprp_t *b) \ return dfp.crbf; \ } -DFP_HELPER_TSTSF(dtstsf, 64) -DFP_HELPER_TSTSF(dtstsfq, 128) +DFP_HELPER_TSTSF(DTSTSF, 64) +DFP_HELPER_TSTSF(DTSTSFQ, 128) #define DFP_HELPER_TSTSFI(op, size) \ uint32_t helper_##op(CPUPPCState *env, uint32_t a, ppc_fprp_t *b) \ @@ -700,8 +705,8 @@ uint32_t helper_##op(CPUPPCState *env, uint32_t a, ppc_fprp_t *b) \ return dfp.crbf; \ } -DFP_HELPER_TSTSFI(dtstsfi, 64) -DFP_HELPER_TSTSFI(dtstsfiq, 128) +DFP_HELPER_TSTSFI(DTSTSFI, 64) +DFP_HELPER_TSTSFI(DTSTSFIQ, 128) static void QUA_PPs(struct PPC_DFP *dfp) { @@ -746,8 +751,8 @@ void helper_##op(CPUPPCState *env, ppc_fprp_t *t, ppc_fprp_t *b, \ set_dfp##size(t, &dfp.vt); \ } -DFP_HELPER_QUAI(dquai, 64) -DFP_HELPER_QUAI(dquaiq, 128) +DFP_HELPER_QUAI(DQUAI, 64) +DFP_HELPER_QUAI(DQUAIQ, 128) #define DFP_HELPER_QUA(op, size) \ void helper_##op(CPUPPCState *env, ppc_fprp_t *t, ppc_fprp_t *a, \ @@ -764,8 +769,8 @@ void helper_##op(CPUPPCState *env, ppc_fprp_t *t, ppc_fprp_t *a, \ set_dfp##size(t, &dfp.vt); \ } -DFP_HELPER_QUA(dqua, 64) -DFP_HELPER_QUA(dquaq, 128) +DFP_HELPER_QUA(DQUA, 64) +DFP_HELPER_QUA(DQUAQ, 128) static void _dfp_reround(uint8_t rmc, int32_t ref_sig, int32_t xmax, struct PPC_DFP *dfp) @@ -842,8 +847,8 @@ void helper_##op(CPUPPCState *env, ppc_fprp_t *t, ppc_fprp_t *a, \ set_dfp##size(t, &dfp.vt); \ } -DFP_HELPER_RRND(drrnd, 64) -DFP_HELPER_RRND(drrndq, 128) +DFP_HELPER_RRND(DRRND, 64) +DFP_HELPER_RRND(DRRNDQ, 128) #define DFP_HELPER_RINT(op, postprocs, size) \ void helper_##op(CPUPPCState *env, ppc_fprp_t *t, ppc_fprp_t *b, \ @@ -868,8 +873,8 @@ static void RINTX_PPs(struct PPC_DFP *dfp) dfp_check_for_VXSNAN(dfp); } -DFP_HELPER_RINT(drintx, RINTX_PPs, 64) -DFP_HELPER_RINT(drintxq, RINTX_PPs, 128) +DFP_HELPER_RINT(DRINTX, RINTX_PPs, 64) +DFP_HELPER_RINT(DRINTXQ, RINTX_PPs, 128) static void RINTN_PPs(struct PPC_DFP *dfp) { @@ -877,10 +882,10 @@ static void RINTN_PPs(struct PPC_DFP *dfp) dfp_check_for_VXSNAN(dfp); } -DFP_HELPER_RINT(drintn, RINTN_PPs, 64) -DFP_HELPER_RINT(drintnq, RINTN_PPs, 128) +DFP_HELPER_RINT(DRINTN, RINTN_PPs, 64) +DFP_HELPER_RINT(DRINTNQ, RINTN_PPs, 128) -void helper_dctdp(CPUPPCState *env, ppc_fprp_t *t, ppc_fprp_t *b) +void helper_DCTDP(CPUPPCState *env, ppc_fprp_t *t, ppc_fprp_t *b) { struct PPC_DFP dfp; ppc_vsr_t vb; @@ -896,7 +901,7 @@ void helper_dctdp(CPUPPCState *env, ppc_fprp_t *t, ppc_fprp_t *b) dfp_set_FPRF_from_FRT(&dfp); } -void helper_dctqpq(CPUPPCState *env, ppc_fprp_t *t, ppc_fprp_t *b) +void helper_DCTQPQ(CPUPPCState *env, ppc_fprp_t *t, ppc_fprp_t *b) { struct PPC_DFP dfp; ppc_vsr_t vb; @@ -911,7 +916,7 @@ void helper_dctqpq(CPUPPCState *env, ppc_fprp_t *t, ppc_fprp_t *b) set_dfp128(t, &dfp.vt); } -void helper_drsp(CPUPPCState *env, ppc_fprp_t *t, ppc_fprp_t *b) +void helper_DRSP(CPUPPCState *env, ppc_fprp_t *t, ppc_fprp_t *b) { struct PPC_DFP dfp; uint32_t t_short = 0; @@ -929,7 +934,7 @@ void helper_drsp(CPUPPCState *env, ppc_fprp_t *t, ppc_fprp_t *b) set_dfp64(t, &vt); } -void helper_drdpq(CPUPPCState *env, ppc_fprp_t *t, ppc_fprp_t *b) +void helper_DRDPQ(CPUPPCState *env, ppc_fprp_t *t, ppc_fprp_t *b) { struct PPC_DFP dfp; dfp_prepare_decimal128(&dfp, 0, b, env); @@ -967,8 +972,20 @@ static void CFFIX_PPs(struct PPC_DFP *dfp) dfp_check_for_XX(dfp); } -DFP_HELPER_CFFIX(dcffix, 64) -DFP_HELPER_CFFIX(dcffixq, 128) +DFP_HELPER_CFFIX(DCFFIX, 64) +DFP_HELPER_CFFIX(DCFFIXQ, 128) + +void helper_DCFFIXQQ(CPUPPCState *env, ppc_fprp_t *t, ppc_avr_t *b) +{ + struct PPC_DFP dfp; + + dfp_prepare_decimal128(&dfp, NULL, NULL, env); + decNumberFromInt128(&dfp.t, (uint64_t)b->VsrD(1), (int64_t)b->VsrD(0)); + dfp_finalize_decimal128(&dfp); + CFFIX_PPs(&dfp); + + set_dfp128(t, &dfp.vt); +} #define DFP_HELPER_CTFIX(op, size) \ void helper_##op(CPUPPCState *env, ppc_fprp_t *t, ppc_fprp_t *b) \ @@ -1005,8 +1022,55 @@ void helper_##op(CPUPPCState *env, ppc_fprp_t *t, ppc_fprp_t *b) \ set_dfp64(t, &dfp.vt); \ } -DFP_HELPER_CTFIX(dctfix, 64) -DFP_HELPER_CTFIX(dctfixq, 128) +DFP_HELPER_CTFIX(DCTFIX, 64) +DFP_HELPER_CTFIX(DCTFIXQ, 128) + +void helper_DCTFIXQQ(CPUPPCState *env, ppc_avr_t *t, ppc_fprp_t *b) +{ + struct PPC_DFP dfp; + dfp_prepare_decimal128(&dfp, 0, b, env); + + if (unlikely(decNumberIsSpecial(&dfp.b))) { + uint64_t invalid_flags = FP_VX | FP_VXCVI; + if (decNumberIsInfinite(&dfp.b)) { + if (decNumberIsNegative(&dfp.b)) { + dfp.vt.VsrD(0) = INT64_MIN; + dfp.vt.VsrD(1) = 0; + } else { + dfp.vt.VsrD(0) = INT64_MAX; + dfp.vt.VsrD(1) = UINT64_MAX; + } + } else { /* NaN */ + dfp.vt.VsrD(0) = INT64_MIN; + dfp.vt.VsrD(1) = 0; + if (decNumberIsSNaN(&dfp.b)) { + invalid_flags |= FP_VXSNAN; + } + } + dfp_set_FPSCR_flag(&dfp, invalid_flags, FP_VE); + } else if (unlikely(decNumberIsZero(&dfp.b))) { + dfp.vt.VsrD(0) = 0; + dfp.vt.VsrD(1) = 0; + } else { + decNumberToIntegralExact(&dfp.b, &dfp.b, &dfp.context); + decNumberIntegralToInt128(&dfp.b, &dfp.context, + &dfp.vt.VsrD(1), &dfp.vt.VsrD(0)); + if (decContextTestStatus(&dfp.context, DEC_Invalid_operation)) { + if (decNumberIsNegative(&dfp.b)) { + dfp.vt.VsrD(0) = INT64_MIN; + dfp.vt.VsrD(1) = 0; + } else { + dfp.vt.VsrD(0) = INT64_MAX; + dfp.vt.VsrD(1) = UINT64_MAX; + } + dfp_set_FPSCR_flag(&dfp, FP_VX | FP_VXCVI, FP_VE); + } else { + dfp_check_for_XX(&dfp); + } + } + + set_dfp128_to_avr(t, &dfp.vt); +} static inline void dfp_set_bcd_digit_64(ppc_vsr_t *t, uint8_t digit, unsigned n) @@ -1067,8 +1131,8 @@ void helper_##op(CPUPPCState *env, ppc_fprp_t *t, ppc_fprp_t *b, \ set_dfp##size(t, &dfp.vt); \ } -DFP_HELPER_DEDPD(ddedpd, 64) -DFP_HELPER_DEDPD(ddedpdq, 128) +DFP_HELPER_DEDPD(DDEDPD, 64) +DFP_HELPER_DEDPD(DDEDPDQ, 128) static inline uint8_t dfp_get_bcd_digit_64(ppc_vsr_t *t, unsigned n) { @@ -1135,8 +1199,8 @@ void helper_##op(CPUPPCState *env, ppc_fprp_t *t, ppc_fprp_t *b, \ set_dfp##size(t, &dfp.vt); \ } -DFP_HELPER_ENBCD(denbcd, 64) -DFP_HELPER_ENBCD(denbcdq, 128) +DFP_HELPER_ENBCD(DENBCD, 64) +DFP_HELPER_ENBCD(DENBCDQ, 128) #define DFP_HELPER_XEX(op, size) \ void helper_##op(CPUPPCState *env, ppc_fprp_t *t, ppc_fprp_t *b) \ @@ -1169,8 +1233,8 @@ void helper_##op(CPUPPCState *env, ppc_fprp_t *t, ppc_fprp_t *b) \ } \ } -DFP_HELPER_XEX(dxex, 64) -DFP_HELPER_XEX(dxexq, 128) +DFP_HELPER_XEX(DXEX, 64) +DFP_HELPER_XEX(DXEXQ, 128) static void dfp_set_raw_exp_64(ppc_vsr_t *t, uint64_t raw) { @@ -1235,8 +1299,8 @@ void helper_##op(CPUPPCState *env, ppc_fprp_t *t, ppc_fprp_t *a, \ set_dfp##size(t, &dfp.vt); \ } -DFP_HELPER_IEX(diex, 64) -DFP_HELPER_IEX(diexq, 128) +DFP_HELPER_IEX(DIEX, 64) +DFP_HELPER_IEX(DIEXQ, 128) static void dfp_clear_lmd_from_g5msb(uint64_t *t) { @@ -1323,7 +1387,7 @@ void helper_##op(CPUPPCState *env, ppc_fprp_t *t, ppc_fprp_t *a, \ set_dfp##size(t, &dfp.vt); \ } -DFP_HELPER_SHIFT(dscli, 64, 1) -DFP_HELPER_SHIFT(dscliq, 128, 1) -DFP_HELPER_SHIFT(dscri, 64, 0) -DFP_HELPER_SHIFT(dscriq, 128, 0) +DFP_HELPER_SHIFT(DSCLI, 64, 1) +DFP_HELPER_SHIFT(DSCLIQ, 128, 1) +DFP_HELPER_SHIFT(DSCRI, 64, 0) +DFP_HELPER_SHIFT(DSCRIQ, 128, 0) |