diff options
author | Matheus Ferst <matheus.ferst@eldorado.org.br> | 2021-06-01 16:35:25 -0300 |
---|---|---|
committer | David Gibson <david@gibson.dropbear.id.au> | 2021-06-03 18:10:31 +1000 |
commit | 89ccd7dc3fbce4a46679f282b47789e34fc3528a (patch) | |
tree | 424d78d6090b706319f083a106e20914fe4feb7d /target/ppc/int_helper.c | |
parent | 9a14365eeb0d8b0e9d69692c34cdce76b9505189 (diff) |
target/ppc: Implement cfuged instruction
Signed-off-by: Matheus Ferst <matheus.ferst@eldorado.org.br>
Message-Id: <20210601193528.2533031-12-matheus.ferst@eldorado.org.br>
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
Signed-off-by: David Gibson <david@gibson.dropbear.id.au>
Diffstat (limited to 'target/ppc/int_helper.c')
-rw-r--r-- | target/ppc/int_helper.c | 62 |
1 files changed, 62 insertions, 0 deletions
diff --git a/target/ppc/int_helper.c b/target/ppc/int_helper.c index 41f8477d4b..efa833ef64 100644 --- a/target/ppc/int_helper.c +++ b/target/ppc/int_helper.c @@ -320,6 +320,68 @@ target_ulong helper_popcntb(target_ulong val) } #endif +uint64_t helper_cfuged(uint64_t src, uint64_t mask) +{ + /* + * Instead of processing the mask bit-by-bit from the most significant to + * the least significant bit, as described in PowerISA, we'll handle it in + * blocks of 'n' zeros/ones from LSB to MSB. To avoid the decision to use + * ctz or cto, we negate the mask at the end of the loop. + */ + target_ulong m, left = 0, right = 0; + unsigned int n, i = 64; + bool bit = false; /* tracks if we are processing zeros or ones */ + + if (mask == 0 || mask == -1) { + return src; + } + + /* Processes the mask in blocks, from LSB to MSB */ + while (i) { + /* Find how many bits we should take */ + n = ctz64(mask); + if (n > i) { + n = i; + } + + /* + * Extracts 'n' trailing bits of src and put them on the leading 'n' + * bits of 'right' or 'left', pushing down the previously extracted + * values. + */ + m = (1ll << n) - 1; + if (bit) { + right = ror64(right | (src & m), n); + } else { + left = ror64(left | (src & m), n); + } + + /* + * Discards the processed bits from 'src' and 'mask'. Note that we are + * removing 'n' trailing zeros from 'mask', but the logical shift will + * add 'n' leading zeros back, so the population count of 'mask' is kept + * the same. + */ + src >>= n; + mask >>= n; + i -= n; + bit = !bit; + mask = ~mask; + } + + /* + * At the end, right was ror'ed ctpop(mask) times. To put it back in place, + * we'll shift it more 64-ctpop(mask) times. + */ + if (bit) { + n = ctpop64(mask); + } else { + n = 64 - ctpop64(mask); + } + + return left | (right >> n); +} + /*****************************************************************************/ /* PowerPC 601 specific instructions (POWER bridge) */ target_ulong helper_div(CPUPPCState *env, target_ulong arg1, target_ulong arg2) |