mirror of
https://github.com/qemu/qemu.git
synced 2026-07-08 17:56:38 +00:00
target/mips: add Octeon CRC COP2 helpers
Add helper support for the Octeon COP2 CRC register interface. This covers normal and reflected CRC state handling, byte/halfword/word/ doubleword/variable-width update selectors, and the reflected IV readback operation. Register moves that can be represented as direct TCG loads/stores do not need helpers. Add only the side-effecting CRC helper implementation here. Signed-off-by: James Hilliard <james.hilliard1@gmail.com> Reviewed-by: Richard Henderson <richard.henderson@linaro.org> Message-ID: <20260608-mips-octeon-missing-insns-v2-v16-3-daef7a0d8b04@gmail.com> Signed-off-by: Philippe Mathieu-Daudé <philmd@oss.qualcomm.com>
This commit is contained in:
committed by
Philippe Mathieu-Daudé
parent
3bbe7ae19e
commit
e1ac6b2775
@@ -25,6 +25,20 @@ DEF_HELPER_3(crc32, tl, tl, tl, i32)
|
||||
DEF_HELPER_3(crc32c, tl, tl, tl, i32)
|
||||
DEF_HELPER_FLAGS_4(rotx, TCG_CALL_NO_RWG_SE, tl, tl, i32, i32, i32)
|
||||
|
||||
/* Octeon COP2 selector operation helpers. */
|
||||
DEF_HELPER_1(octeon_cp2_mf_crc_iv_reflect, i64, env)
|
||||
DEF_HELPER_2(octeon_cp2_mt_crc_write_iv_reflect, void, env, i64)
|
||||
DEF_HELPER_2(octeon_cp2_mt_crc_write_byte, void, env, i64)
|
||||
DEF_HELPER_2(octeon_cp2_mt_crc_write_half, void, env, i64)
|
||||
DEF_HELPER_2(octeon_cp2_mt_crc_write_word, void, env, i64)
|
||||
DEF_HELPER_2(octeon_cp2_mt_crc_write_byte_reflect, void, env, i64)
|
||||
DEF_HELPER_2(octeon_cp2_mt_crc_write_half_reflect, void, env, i64)
|
||||
DEF_HELPER_2(octeon_cp2_mt_crc_write_word_reflect, void, env, i64)
|
||||
DEF_HELPER_2(octeon_cp2_mt_crc_write_dword, void, env, i64)
|
||||
DEF_HELPER_2(octeon_cp2_mt_crc_write_var, void, env, i64)
|
||||
DEF_HELPER_2(octeon_cp2_mt_crc_write_dword_reflect, void, env, i64)
|
||||
DEF_HELPER_2(octeon_cp2_mt_crc_write_var_reflect, void, env, i64)
|
||||
|
||||
/* microMIPS functions */
|
||||
DEF_HELPER_4(lwm, void, env, tl, tl, i32)
|
||||
DEF_HELPER_4(swm, void, env, tl, tl, i32)
|
||||
|
||||
@@ -14,3 +14,134 @@
|
||||
#include "crypto/sm4.h"
|
||||
#include "qemu/bitops.h"
|
||||
#include "qemu/host-utils.h"
|
||||
|
||||
static uint32_t octeon_crc_reflect32_by_byte(uint32_t v)
|
||||
{
|
||||
return bswap32(revbit32(v));
|
||||
}
|
||||
|
||||
static uint32_t octeon_crc_state_reflect(const MIPSOcteonCryptoState *crypto)
|
||||
{
|
||||
return octeon_crc_reflect32_by_byte(crypto->crc_iv);
|
||||
}
|
||||
|
||||
static void octeon_crc_set_state_reflect(MIPSOcteonCryptoState *crypto,
|
||||
uint32_t state)
|
||||
{
|
||||
crypto->crc_iv = octeon_crc_reflect32_by_byte(state);
|
||||
}
|
||||
|
||||
static void octeon_crc_update_normal(MIPSOcteonCryptoState *crypto,
|
||||
uint64_t value, unsigned int bytes)
|
||||
{
|
||||
uint32_t crc = crypto->crc_iv;
|
||||
uint32_t poly = crypto->crc_poly;
|
||||
|
||||
for (unsigned int i = 0; i < bytes; i++) {
|
||||
uint8_t byte = value >> ((bytes - 1 - i) * 8);
|
||||
|
||||
crc ^= (uint32_t)byte << 24;
|
||||
for (int bit = 0; bit < 8; bit++) {
|
||||
if (crc & 0x80000000U) {
|
||||
crc = (crc << 1) ^ poly;
|
||||
} else {
|
||||
crc <<= 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
crypto->crc_iv = crc;
|
||||
}
|
||||
|
||||
static void octeon_crc_update_reflect(MIPSOcteonCryptoState *crypto,
|
||||
uint64_t value, unsigned int bytes)
|
||||
{
|
||||
uint32_t crc = octeon_crc_state_reflect(crypto);
|
||||
uint32_t poly = bswap32(crypto->crc_poly);
|
||||
|
||||
for (unsigned int i = 0; i < bytes; i++) {
|
||||
uint8_t byte = value >> ((bytes - 1 - i) * 8);
|
||||
|
||||
crc ^= byte;
|
||||
for (int bit = 0; bit < 8; bit++) {
|
||||
if (crc & 1U) {
|
||||
crc = (crc >> 1) ^ poly;
|
||||
} else {
|
||||
crc >>= 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
octeon_crc_set_state_reflect(crypto, crc);
|
||||
}
|
||||
|
||||
uint64_t helper_octeon_cp2_mf_crc_iv_reflect(CPUMIPSState *env)
|
||||
{
|
||||
return octeon_crc_reflect32_by_byte(env->octeon_crypto.crc_iv);
|
||||
}
|
||||
|
||||
void helper_octeon_cp2_mt_crc_write_iv_reflect(CPUMIPSState *env,
|
||||
uint64_t value)
|
||||
{
|
||||
env->octeon_crypto.crc_iv =
|
||||
octeon_crc_reflect32_by_byte((uint32_t)value);
|
||||
}
|
||||
|
||||
void helper_octeon_cp2_mt_crc_write_byte(CPUMIPSState *env, uint64_t value)
|
||||
{
|
||||
octeon_crc_update_normal(&env->octeon_crypto, value, 1);
|
||||
}
|
||||
|
||||
void helper_octeon_cp2_mt_crc_write_half(CPUMIPSState *env, uint64_t value)
|
||||
{
|
||||
octeon_crc_update_normal(&env->octeon_crypto, value, 2);
|
||||
}
|
||||
|
||||
void helper_octeon_cp2_mt_crc_write_word(CPUMIPSState *env, uint64_t value)
|
||||
{
|
||||
octeon_crc_update_normal(&env->octeon_crypto, value, 4);
|
||||
}
|
||||
|
||||
void helper_octeon_cp2_mt_crc_write_dword(CPUMIPSState *env, uint64_t value)
|
||||
{
|
||||
octeon_crc_update_normal(&env->octeon_crypto, value, 8);
|
||||
}
|
||||
|
||||
void helper_octeon_cp2_mt_crc_write_var(CPUMIPSState *env, uint64_t value)
|
||||
{
|
||||
MIPSOcteonCryptoState *crypto = &env->octeon_crypto;
|
||||
|
||||
octeon_crc_update_normal(crypto, value, MIN(8U, crypto->crc_len & 0xf));
|
||||
}
|
||||
|
||||
void helper_octeon_cp2_mt_crc_write_byte_reflect(CPUMIPSState *env,
|
||||
uint64_t value)
|
||||
{
|
||||
octeon_crc_update_reflect(&env->octeon_crypto, value, 1);
|
||||
}
|
||||
|
||||
void helper_octeon_cp2_mt_crc_write_half_reflect(CPUMIPSState *env,
|
||||
uint64_t value)
|
||||
{
|
||||
octeon_crc_update_reflect(&env->octeon_crypto, value, 2);
|
||||
}
|
||||
|
||||
void helper_octeon_cp2_mt_crc_write_word_reflect(CPUMIPSState *env,
|
||||
uint64_t value)
|
||||
{
|
||||
octeon_crc_update_reflect(&env->octeon_crypto, value, 4);
|
||||
}
|
||||
|
||||
void helper_octeon_cp2_mt_crc_write_dword_reflect(CPUMIPSState *env,
|
||||
uint64_t value)
|
||||
{
|
||||
octeon_crc_update_reflect(&env->octeon_crypto, value, 8);
|
||||
}
|
||||
|
||||
void helper_octeon_cp2_mt_crc_write_var_reflect(CPUMIPSState *env,
|
||||
uint64_t value)
|
||||
{
|
||||
MIPSOcteonCryptoState *crypto = &env->octeon_crypto;
|
||||
|
||||
octeon_crc_update_reflect(crypto, value, MIN(8U, crypto->crc_len & 0xf));
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user