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 <giacomo.travaglini@arm.com>
Reviewed-by: Andreas Sandberg <andreas.sandberg@arm.com>
Reviewed-by: Nikos Nikoleris <nikos.nikoleris@arm.com>
Reviewed-by: Giacomo Gabrielli <giacomo.gabrielli@arm.com>
Reviewed-on: https://gem5-review.googlesource.com/5521
Maintainer: Andreas Sandberg <andreas.sandberg@arm.com>
This commit is contained in:
Giacomo Travaglini
2017-10-13 10:03:14 +01:00
committed by Andreas Sandberg
parent f0f04ddd70
commit ef0490081f
8 changed files with 231 additions and 4 deletions

View File

@@ -1,6 +1,6 @@
// -*- mode:c++ -*-
// Copyright (c) 2010-2013 ARM Limited
// Copyright (c) 2010-2013,2017 ARM Limited
// All rights reserved
//
// The license below extends only to copyright in the software and shall
@@ -72,6 +72,7 @@ format DataOp {
0x3: decode OPCODE {
0x9: ArmBlxReg::armBlxReg();
}
0x4: Crc32::crc32();
0x5: ArmSatAddSub::armSatAddSub();
0x6: ArmERet::armERet();
0x7: decode OPCODE_22 {

View File

@@ -1202,6 +1202,22 @@ namespace Aarch64
return new Asrv64(machInst, rdzr, rn, rm);
case 0xb:
return new Rorv64(machInst, rdzr, rn, rm);
case 0x10:
return new Crc32b64(machInst, rdzr, rn, rm);
case 0x11:
return new Crc32h64(machInst, rdzr, rn, rm);
case 0x12:
return new Crc32w64(machInst, rdzr, rn, rm);
case 0x13:
return new Crc32x64(machInst, rdzr, rn, rm);
case 0x14:
return new Crc32cb64(machInst, rdzr, rn, rm);
case 0x15:
return new Crc32ch64(machInst, rdzr, rn, rm);
case 0x16:
return new Crc32cw64(machInst, rdzr, rn, rm);
case 0x17:
return new Crc32cx64(machInst, rdzr, rn, rm);
default:
return new Unknown64(machInst);
}

View File

@@ -1,4 +1,4 @@
// Copyright (c) 2010 ARM Limited
// Copyright (c) 2010,2017 ARM Limited
// All rights reserved
//
// The license below extends only to copyright in the software and shall
@@ -788,7 +788,7 @@ def format Thumb32DataProcReg() {{
}
}
} else if (bits(op1, 3, 2) == 0x2 && bits(op2, 3, 2) == 0x2) {
const uint32_t op1 = bits(machInst, 21, 20);
const uint32_t op1 = bits(machInst, 22, 20);
const uint32_t op2 = bits(machInst, 5, 4);
const IntRegIndex rd =
(IntRegIndex)(uint32_t)bits(machInst, 11, 8);
@@ -832,6 +832,27 @@ def format Thumb32DataProcReg() {{
if (op2 == 0) {
return new Clz(machInst, rd, rm);
}
break;
case 0x4:
switch (op2) {
case 0x0:
return new Crc32b(machInst, rd, rn, rm);
case 0x1:
return new Crc32h(machInst, rd, rn, rm);
case 0x2:
return new Crc32w(machInst, rd, rn, rm);
}
break;
case 0x5:
switch (op2) {
case 0x0:
return new Crc32cb(machInst, rd, rn, rm);
case 0x1:
return new Crc32ch(machInst, rd, rn, rm);
case 0x2:
return new Crc32cw(machInst, rd, rn, rm);
}
break;
}
}
return new Unknown(machInst);

View File

@@ -38,6 +38,37 @@
// Authors: Gabe Black
// Giacomo Gabrielli
def format Crc32() {{
decode_block = '''
{
const IntRegIndex rm = (IntRegIndex)(uint32_t)bits(machInst, 3, 0);
const IntRegIndex rn = (IntRegIndex)(uint32_t)bits(machInst, 19, 16);
const IntRegIndex rd = (IntRegIndex)(uint32_t)bits(machInst, 15, 12);
uint8_t c_poly = bits(machInst, 9);
uint8_t sz = bits(machInst, 22, 21);
uint8_t crc_select = (c_poly << 2) | sz;
switch(crc_select) {
case 0x0:
return new Crc32b(machInst, rd, rn, rm);
case 0x1:
return new Crc32h(machInst, rd, rn, rm);
case 0x2:
return new Crc32w(machInst, rd, rn, rm);
case 0x4:
return new Crc32cb(machInst, rd, rn, rm);
case 0x5:
return new Crc32ch(machInst, rd, rn, rm);
case 0x6:
return new Crc32cw(machInst, rd, rn, rm);
default:
return new Unknown(machInst);
}
}
'''
}};
def format ArmERet() {{
decode_block = "return new Eret(machInst);"
}};

View File

@@ -1,6 +1,6 @@
// -*- mode:c++ -*-
// Copyright (c) 2010, 2012 ARM Limited
// Copyright (c) 2010, 2012, 2017 ARM Limited
// All rights reserved
//
// The license below extends only to copyright in the software and shall
@@ -95,6 +95,7 @@ output exec {{
#include "arch/arm/utility.hh"
#include "arch/generic/memhelpers.hh"
#include "base/condcodes.hh"
#include "base/crc.hh"
#include "cpu/base.hh"
#include "sim/pseudo_inst.hh"
#if defined(linux)

View File

@@ -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<uint8_t*>(&data);
Dest = crc32<poly>(
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;

View File

@@ -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<uint8_t*>(&data);
Dest = crc32<poly>(
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);
}};