From ef0490081fa7ebcda2e1c7adccb05b3a14014cf1 Mon Sep 17 00:00:00 2001 From: Giacomo Travaglini Date: Fri, 13 Oct 2017 10:03:14 +0100 Subject: arm: Add support for armv8 CRC32 instructions This patch introduces the ARM A32/T32/A64 CRC Instructions, which are mandatory since ARMv8.1. The UNPREDICTABLE behaviours are implemented as follows: 1) CRC32(C)X (64 bit) instructions are decoded as Undefined in Aarch32 2) The instructions support predication in Aarch32 3) Using R15(PC) as source/dest operand is permitted in Aarch32 Change-Id: Iaf29b05874e1370c7615da79a07f111ded17b6cc Signed-off-by: Giacomo Travaglini Reviewed-by: Andreas Sandberg Reviewed-by: Nikos Nikoleris Reviewed-by: Giacomo Gabrielli Reviewed-on: https://gem5-review.googlesource.com/5521 Maintainer: Andreas Sandberg --- src/arch/arm/isa/insts/data64.isa | 36 +++++++++++++++++++++++++++++++++++ src/arch/arm/isa/insts/misc.isa | 40 +++++++++++++++++++++++++++++++++++++++ 2 files changed, 76 insertions(+) (limited to 'src/arch/arm/isa/insts') diff --git a/src/arch/arm/isa/insts/data64.isa b/src/arch/arm/isa/insts/data64.isa index 3284d5b2a..d0ee439cb 100644 --- a/src/arch/arm/isa/insts/data64.isa +++ b/src/arch/arm/isa/insts/data64.isa @@ -226,6 +226,42 @@ let {{ "Dest64 = shiftReg64(Op164, Op264, LSR, intWidth)") buildDataXRegInst("rorv", 2, "Dest64 = shiftReg64(Op164, Op264, ROR, intWidth)") + + crcCode = ''' + constexpr uint8_t size_bytes = %(sz)d; + constexpr uint32_t poly = %(polynom)s; + + // Initial value is often a previously evaluated + // crc value hence is always 32bit in CRC32 + uint32_t initial_crc = Op164 & 0xFFFFFFFF; + + uint64_t data = htole(Op264); + auto data_buffer = reinterpret_cast(&data); + + Dest = crc32( + data_buffer, /* Message register */ + initial_crc, /* Initial value of the CRC */ + size_bytes /* Size of the original Message */ + ); + ''' + buildDataXRegInst("crc32b", 2, + crcCode % {"sz": 1, "polynom": "0x04C11DB7"}) + buildDataXRegInst("crc32h", 2, + crcCode % {"sz": 2, "polynom": "0x04C11DB7"}) + buildDataXRegInst("crc32w", 2, + crcCode % {"sz": 4, "polynom": "0x04C11DB7"}) + buildDataXRegInst("crc32x", 2, + crcCode % {"sz": 8, "polynom": "0x04C11DB7"}) + + buildDataXRegInst("crc32cb", 2, + crcCode % {"sz": 1, "polynom": "0x1EDC6F41"}) + buildDataXRegInst("crc32ch", 2, + crcCode % {"sz": 2, "polynom": "0x1EDC6F41"}) + buildDataXRegInst("crc32cw", 2, + crcCode % {"sz": 4, "polynom": "0x1EDC6F41"}) + buildDataXRegInst("crc32cx", 2, + crcCode % {"sz": 8, "polynom": "0x1EDC6F41"}) + buildDataXRegInst("sdiv", 2, ''' int64_t op1 = Op164; int64_t op2 = Op264; diff --git a/src/arch/arm/isa/insts/misc.isa b/src/arch/arm/isa/insts/misc.isa index edeb0f6d3..4681d50a9 100644 --- a/src/arch/arm/isa/insts/misc.isa +++ b/src/arch/arm/isa/insts/misc.isa @@ -136,7 +136,47 @@ let {{ decoder_output += BasicConstructor.subst(eretIop) exec_output += PredOpExecute.subst(eretIop) + crcCode = ''' + constexpr uint8_t size_bytes = %(sz)d; + constexpr uint32_t poly = %(polynom)s; + + uint32_t data = htole(Op2); + auto data_buffer = reinterpret_cast(&data); + + Dest = crc32( + data_buffer, /* Message Register */ + Op1, /* Initial Value of the CRC */ + size_bytes /* Size of the original Message */ + ); + ''' + + def crc32Emit(mnem, implCode, castagnoli, size): + global header_output, decoder_output, exec_output + + if castagnoli: + # crc32c instructions + poly = "0x1EDC6F41" + else: + # crc32 instructions + poly = "0x04C11DB7" + data = {'sz' : size, 'polynom': poly} + + instCode = implCode % data + + crcIop = InstObjParams(mnem, mnem.capitalize(), "RegRegRegOp", + { "code": instCode, + "predicate_test": predicateTest }, []) + header_output += RegRegRegOpDeclare.subst(crcIop) + decoder_output += RegRegRegOpConstructor.subst(crcIop) + exec_output += PredOpExecute.subst(crcIop) + + crc32Emit("crc32b", crcCode, False, 1); + crc32Emit("crc32h", crcCode, False, 2); + crc32Emit("crc32w", crcCode, False, 4); + crc32Emit("crc32cb", crcCode, True, 1); + crc32Emit("crc32ch", crcCode, True, 2); + crc32Emit("crc32cw", crcCode, True, 4); }}; -- cgit v1.2.3