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:
committed by
Andreas Sandberg
parent
f0f04ddd70
commit
ef0490081f
@@ -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 {
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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);"
|
||||
}};
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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);
|
||||
|
||||
}};
|
||||
|
||||
|
||||
81
src/base/crc.hh
Normal file
81
src/base/crc.hh
Normal file
@@ -0,0 +1,81 @@
|
||||
/*
|
||||
* Copyright (c) 2017 ARM Limited
|
||||
* All rights reserved
|
||||
*
|
||||
* The license below extends only to copyright in the software and shall
|
||||
* not be construed as granting a license to any other intellectual
|
||||
* property including but not limited to intellectual property relating
|
||||
* to a hardware implementation of the functionality of the software
|
||||
* licensed hereunder. You may use the software subject to the license
|
||||
* terms below provided that you ensure that this notice is replicated
|
||||
* unmodified and in its entirety in all distributions of the software,
|
||||
* modified or unmodified, in source code or in binary form.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are
|
||||
* met: redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer;
|
||||
* redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution;
|
||||
* neither the name of the copyright holders nor the names of its
|
||||
* contributors may be used to endorse or promote products derived from
|
||||
* this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
* Authors: Giacomo Travaglini
|
||||
*/
|
||||
|
||||
#ifndef __BASE_CRC_HH__
|
||||
#define __BASE_CRC_HH__
|
||||
|
||||
#include "base/bitfield.hh"
|
||||
|
||||
/**
|
||||
* Evaluate the CRC32 of the first size bytes of a data buffer,
|
||||
* using a specific polynomium and an initial value.
|
||||
* The crc is accomplished by reversing the input, the initial value
|
||||
* and the output (remainder).
|
||||
*
|
||||
* @param data: Input data buffer pointer
|
||||
* @param crc: Initial value of the checksum
|
||||
* @param size: Number of bytes
|
||||
*
|
||||
* @return 32-bit remainder of the checksum
|
||||
*/
|
||||
template <uint32_t Poly>
|
||||
uint32_t
|
||||
crc32(const uint8_t* data, uint32_t crc, std::size_t size)
|
||||
{
|
||||
uint32_t byte = 0;
|
||||
|
||||
crc = reverseBits(crc);
|
||||
for (auto i = 0; i < size; i++) {
|
||||
byte = data[i];
|
||||
|
||||
// 32-bit reverse
|
||||
byte = reverseBits(byte);
|
||||
for (auto j = 0; j <= 7; j++) {
|
||||
if ((int)(crc ^ byte) < 0) {
|
||||
crc = (crc << 1) ^ Poly;
|
||||
} else {
|
||||
crc = crc << 1;
|
||||
}
|
||||
byte = byte << 1;
|
||||
}
|
||||
}
|
||||
return reverseBits(crc);
|
||||
}
|
||||
|
||||
#endif // __BASE_CRC_HH__
|
||||
Reference in New Issue
Block a user