target-arm: Add support for AArch32 ARMv8 CRC32 instructions
Add support for AArch32 CRC32 and CRC32C instructions added in ARMv8 and add a CPU feature flag to enable these instructions. The CRC32-C implementation used is the built-in qemu implementation and The CRC-32 implementation is from zlib. This requires adding zlib to LIBS to ensure it is linked for the linux-user binary. Signed-off-by: Will Newton <will.newton@linaro.org> Reviewed-by: Peter Maydell <peter.maydell@linaro.org> Message-id: 1393411566-24104-3-git-send-email-will.newton@linaro.org Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
This commit is contained in:
parent
0956ff5a4e
commit
eb0ecd5ad9
2
configure
vendored
2
configure
vendored
@ -1657,7 +1657,7 @@ EOF
|
||||
"Make sure to have the zlib libs and headers installed."
|
||||
fi
|
||||
fi
|
||||
libs_softmmu="$libs_softmmu -lz"
|
||||
LIBS="$LIBS -lz"
|
||||
|
||||
##########################################
|
||||
# libseccomp check
|
||||
|
@ -924,6 +924,7 @@ static void arm_any_initfn(Object *obj)
|
||||
set_feature(&cpu->env, ARM_FEATURE_THUMB2EE);
|
||||
set_feature(&cpu->env, ARM_FEATURE_ARM_DIV);
|
||||
set_feature(&cpu->env, ARM_FEATURE_V7MP);
|
||||
set_feature(&cpu->env, ARM_FEATURE_CRC);
|
||||
#ifdef TARGET_AARCH64
|
||||
set_feature(&cpu->env, ARM_FEATURE_AARCH64);
|
||||
#endif
|
||||
|
@ -626,6 +626,7 @@ enum arm_features {
|
||||
ARM_FEATURE_AARCH64, /* supports 64 bit mode */
|
||||
ARM_FEATURE_V8_AES, /* implements AES part of v8 Crypto Extensions */
|
||||
ARM_FEATURE_CBAR, /* has cp15 CBAR */
|
||||
ARM_FEATURE_CRC, /* ARMv8 CRC instructions */
|
||||
};
|
||||
|
||||
static inline int arm_feature(CPUARMState *env, int feature)
|
||||
|
@ -5,6 +5,8 @@
|
||||
#include "sysemu/arch_init.h"
|
||||
#include "sysemu/sysemu.h"
|
||||
#include "qemu/bitops.h"
|
||||
#include "qemu/crc32c.h"
|
||||
#include <zlib.h> /* For crc32 */
|
||||
|
||||
#ifndef CONFIG_USER_ONLY
|
||||
static inline int get_phys_addr(CPUARMState *env, uint32_t address,
|
||||
@ -4703,3 +4705,40 @@ int arm_rmode_to_sf(int rmode)
|
||||
}
|
||||
return rmode;
|
||||
}
|
||||
|
||||
static void crc_init_buffer(uint8_t *buf, uint32_t val, uint32_t bytes)
|
||||
{
|
||||
memset(buf, 0, 4);
|
||||
|
||||
if (bytes == 1) {
|
||||
buf[0] = val & 0xff;
|
||||
} else if (bytes == 2) {
|
||||
buf[0] = val & 0xff;
|
||||
buf[1] = (val >> 8) & 0xff;
|
||||
} else {
|
||||
buf[0] = val & 0xff;
|
||||
buf[1] = (val >> 8) & 0xff;
|
||||
buf[2] = (val >> 16) & 0xff;
|
||||
buf[3] = (val >> 24) & 0xff;
|
||||
}
|
||||
}
|
||||
|
||||
uint32_t HELPER(crc32)(uint32_t acc, uint32_t val, uint32_t bytes)
|
||||
{
|
||||
uint8_t buf[4];
|
||||
|
||||
crc_init_buffer(buf, val, bytes);
|
||||
|
||||
/* zlib crc32 converts the accumulator and output to one's complement. */
|
||||
return crc32(acc ^ 0xffffffff, buf, bytes) ^ 0xffffffff;
|
||||
}
|
||||
|
||||
uint32_t HELPER(crc32c)(uint32_t acc, uint32_t val, uint32_t bytes)
|
||||
{
|
||||
uint8_t buf[4];
|
||||
|
||||
crc_init_buffer(buf, val, bytes);
|
||||
|
||||
/* Linux crc32c converts the output to one's complement. */
|
||||
return crc32c(acc, buf, bytes) ^ 0xffffffff;
|
||||
}
|
||||
|
@ -499,6 +499,9 @@ DEF_HELPER_3(neon_qzip32, void, env, i32, i32)
|
||||
DEF_HELPER_4(crypto_aese, void, env, i32, i32, i32)
|
||||
DEF_HELPER_4(crypto_aesmc, void, env, i32, i32, i32)
|
||||
|
||||
DEF_HELPER_FLAGS_3(crc32, TCG_CALL_NO_RWG_SE, i32, i32, i32, i32)
|
||||
DEF_HELPER_FLAGS_3(crc32c, TCG_CALL_NO_RWG_SE, i32, i32, i32, i32)
|
||||
|
||||
#ifdef TARGET_AARCH64
|
||||
#include "helper-a64.h"
|
||||
#endif
|
||||
|
@ -7561,6 +7561,36 @@ static void disas_arm_insn(CPUARMState * env, DisasContext *s)
|
||||
store_reg(s, 14, tmp2);
|
||||
gen_bx(s, tmp);
|
||||
break;
|
||||
case 0x4:
|
||||
{
|
||||
/* crc32/crc32c */
|
||||
uint32_t c = extract32(insn, 8, 4);
|
||||
|
||||
/* Check this CPU supports ARMv8 CRC instructions.
|
||||
* op1 == 3 is UNPREDICTABLE but handle as UNDEFINED.
|
||||
* Bits 8, 10 and 11 should be zero.
|
||||
*/
|
||||
if (!arm_feature(env, ARM_FEATURE_CRC) || op1 == 0x3 ||
|
||||
(c & 0xd) != 0) {
|
||||
goto illegal_op;
|
||||
}
|
||||
|
||||
rn = extract32(insn, 16, 4);
|
||||
rd = extract32(insn, 12, 4);
|
||||
|
||||
tmp = load_reg(s, rn);
|
||||
tmp2 = load_reg(s, rm);
|
||||
tmp3 = tcg_const_i32(1 << op1);
|
||||
if (c & 0x2) {
|
||||
gen_helper_crc32c(tmp, tmp, tmp2, tmp3);
|
||||
} else {
|
||||
gen_helper_crc32(tmp, tmp, tmp2, tmp3);
|
||||
}
|
||||
tcg_temp_free_i32(tmp2);
|
||||
tcg_temp_free_i32(tmp3);
|
||||
store_reg(s, rd, tmp);
|
||||
break;
|
||||
}
|
||||
case 0x5: /* saturating add/subtract */
|
||||
ARCH(5TE);
|
||||
rd = (insn >> 12) & 0xf;
|
||||
@ -9145,6 +9175,32 @@ static int disas_thumb2_insn(CPUARMState *env, DisasContext *s, uint16_t insn_hw
|
||||
case 0x18: /* clz */
|
||||
gen_helper_clz(tmp, tmp);
|
||||
break;
|
||||
case 0x20:
|
||||
case 0x21:
|
||||
case 0x22:
|
||||
case 0x28:
|
||||
case 0x29:
|
||||
case 0x2a:
|
||||
{
|
||||
/* crc32/crc32c */
|
||||
uint32_t sz = op & 0x3;
|
||||
uint32_t c = op & 0x8;
|
||||
|
||||
if (!arm_feature(env, ARM_FEATURE_CRC)) {
|
||||
goto illegal_op;
|
||||
}
|
||||
|
||||
tmp2 = load_reg(s, rm);
|
||||
tmp3 = tcg_const_i32(1 << sz);
|
||||
if (c) {
|
||||
gen_helper_crc32c(tmp, tmp, tmp2, tmp3);
|
||||
} else {
|
||||
gen_helper_crc32(tmp, tmp, tmp2, tmp3);
|
||||
}
|
||||
tcg_temp_free_i32(tmp2);
|
||||
tcg_temp_free_i32(tmp3);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
goto illegal_op;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user