Implement the CRC32C instruction according to OSA (Oracle SPARC Architecture) 2011 section 7.19 and set the CRC32C bit in the CFR.
Using QEMU's crc32c.h and bswap.h. Gated behind the crypto CPU feature and disabled for sparc32. Reviewed-by: Philippe Mathieu-Daudé <[email protected]> Tested-by: Philippe Mathieu-Daudé <[email protected]> Signed-off-by: Stian Halseth <[email protected]> --- target/sparc/crypto_helper.c | 21 +++++++++++++++++++++ target/sparc/helper.h | 1 + target/sparc/insns.decode | 1 + target/sparc/translate.c | 4 +++- 4 files changed, 26 insertions(+), 1 deletion(-) diff --git a/target/sparc/crypto_helper.c b/target/sparc/crypto_helper.c index 94377634c5..83409d1aad 100644 --- a/target/sparc/crypto_helper.c +++ b/target/sparc/crypto_helper.c @@ -10,6 +10,8 @@ #include "exec/helper-proto.h" #include "crypto/aes-round.h" #include "crypto/aes.h" +#include "qemu/bswap.h" +#include "qemu/crc32c.h" /* * SPARC four-operand AES round (Section 7.3). @@ -145,3 +147,22 @@ uint64_t helper_aes_kexpand2(uint64_t rs1, uint64_t rs2) { return aes_kexpand(rs1, (uint32_t)rs2); } + +/* + * CRC32C Operation 3-operand (Section 7.19) + * Accumulate CRC32C over the eight bytes of rs2, most significant first. + */ +uint64_t helper_crc32c(uint64_t rs1, uint64_t rs2) +{ + uint8_t buf[8]; + /* IV and result are byte-swapped in the register. */ + uint32_t crc = bswap32((uint32_t)rs1); + + stq_be_p(buf, rs2); + + /* Undo crc32c()'s final inversion for the instruction's raw result. */ + crc = crc32c(crc, buf, sizeof(buf)) ^ UINT32_MAX; + + /* Result lives in the low 32 bits; upper half reads as zero. */ + return (uint64_t)bswap32(crc); +} diff --git a/target/sparc/helper.h b/target/sparc/helper.h index 685b89d9c5..1320f5ebba 100644 --- a/target/sparc/helper.h +++ b/target/sparc/helper.h @@ -133,6 +133,7 @@ DEF_HELPER_FLAGS_3(aes_dround23_l, TCG_CALL_NO_RWG_SE, i64, i64, i64, i64) DEF_HELPER_FLAGS_2(aes_kexpand0, TCG_CALL_NO_RWG_SE, i64, i64, i64) DEF_HELPER_FLAGS_3(aes_kexpand1, TCG_CALL_NO_RWG_SE, i64, i64, i64, i32) DEF_HELPER_FLAGS_2(aes_kexpand2, TCG_CALL_NO_RWG_SE, i64, i64, i64) +DEF_HELPER_FLAGS_2(crc32c, TCG_CALL_NO_RWG_SE, i64, i64, i64) #define VIS_CMPHELPER(name) \ DEF_HELPER_FLAGS_2(f##name##8, TCG_CALL_NO_RWG_SE, \ i64, i64, i64) \ diff --git a/target/sparc/insns.decode b/target/sparc/insns.decode index 96791c7658..05c1e73d7f 100644 --- a/target/sparc/insns.decode +++ b/target/sparc/insns.decode @@ -577,6 +577,7 @@ FCMPEq 10 000 cc:2 110101 ..... 0 0101 0111 ..... \ FPMAXU32 10 ..... 110110 ..... 1 0101 1111 ..... @d_d_d AES_KEXPAND0 10 ..... 110110 ..... 1 0011 0000 ..... @d_d_d AES_KEXPAND2 10 ..... 110110 ..... 1 0011 0001 ..... @d_d_d + CRC32C 10 ..... 110110 ..... 1 0100 0111 ..... @d_d_d FLCMPs 10 000 cc:2 110110 rs1:5 1 0101 0001 rs2:5 FLCMPd 10 000 cc:2 110110 ..... 1 0101 0010 ..... \ diff --git a/target/sparc/translate.c b/target/sparc/translate.c index ad32b53cc3..562bfb506b 100644 --- a/target/sparc/translate.c +++ b/target/sparc/translate.c @@ -111,6 +111,7 @@ # define gen_helper_aes_dround23_l ({ qemu_build_not_reached(); NULL; }) # define gen_helper_aes_kexpand0 ({ qemu_build_not_reached(); NULL; }) # define gen_helper_aes_kexpand2 ({ qemu_build_not_reached(); NULL; }) +# define gen_helper_crc32c ({ qemu_build_not_reached(); NULL; }) #endif #define DISAS_EXIT DISAS_TARGET_0 @@ -3041,7 +3042,7 @@ TRANS(RDSTRAND_STATUS, HYPV, do_rd_special, true, a->rd, do_rdstrand_status) static TCGv do_rdcfr(DisasContext *dc, TCGv dst) { - return tcg_constant_tl(CFR_AES); + return tcg_constant_tl(CFR_AES | CFR_CRC32C); } TRANS(RDCFR, CRYPTO, do_rd_special, true, a->rd, do_rdcfr) @@ -5438,6 +5439,7 @@ TRANS(AES_DROUND01_L, CRYPTO, do_dddd, a, gen_helper_aes_dround01_l) TRANS(AES_DROUND23_L, CRYPTO, do_dddd, a, gen_helper_aes_dround23_l) TRANS(AES_KEXPAND0, CRYPTO, do_ddd, a, gen_helper_aes_kexpand0) TRANS(AES_KEXPAND2, CRYPTO, do_ddd, a, gen_helper_aes_kexpand2) +TRANS(CRC32C, CRYPTO, do_ddd, a, gen_helper_crc32c) /* AES key expansion with RCON selected by the 5-bit immediate in imm */ static bool trans_AES_KEXPAND1(DisasContext *dc, arg_r_r_i_r *a) -- 2.43.0
