aboutsummaryrefslogtreecommitdiff
path: root/riscv/insns/aes64dsm.h
diff options
context:
space:
mode:
authorBen Marshall <ben.marshall@bristol.ac.uk>2021-02-18 13:27:35 +0000
committerBen Marshall <ben.marshall@bristol.ac.uk>2021-02-18 13:27:35 +0000
commitda7748e6d88c75559e8f3c09067a502fe950136e (patch)
treea0d7a9151682bdc4f26431c79624fef6c8957fbc /riscv/insns/aes64dsm.h
parent5730d12167e0a0834d14b6332a4dd31d673bf73b (diff)
downloadspike-da7748e6d88c75559e8f3c09067a502fe950136e.zip
spike-da7748e6d88c75559e8f3c09067a502fe950136e.tar.gz
spike-da7748e6d88c75559e8f3c09067a502fe950136e.tar.bz2
scalar-crypto: Fix decoding of RV64 AES instructions.
Historically, one could uniquely decode any RISC-V instruction based on the instruciton to decode, plus a MATCH and MASK pair. The scalar crypto extension adds instructions for accelerating the AES algorithm which work very differently on RV32 and RV64. However, they overlap in terms of opcodes. The instructions are always mutually exclusive, and so it makes sense to overlap them this way to save encoding space. This exposed a problem, where previously Spike assumed the decoder function was something like: > decode(instr_word, MATCH, MASK) Now it needed to be > decode(instr_word, MATCH, MASK, current_xlen) To get around this in the initial implementation, the instructions which shared opcodes were implemented in the same *.h file - e.g. aesds.h contained an implementation of aes32dsi, and aes64ds. We detected xlen in the file, and executed the appropriate instruction logic. This worked fine for our limited set of benchmarks. After more extensive testing, we found that Spike has an optimisation which changes the order in which it tries to decode instructions based on past instructions. Running more extensive tests exposed the fact that the decoding logic could still not unambiguously decode the instructions. Hence, more substantial changes were needed to tell spike that an instruction is RV32 or RV64 only. These changes have been implemented as part of - riscv/encoding.h - disasm/disasm.cc - riscv/processor.cc/h Basically, every instr_desc_t has an extra field which marks which base architecture the instruction can be exectuted on. This bitfield can be altered for particular instructions. The changes to riscv/insns/* simply split out the previously combined instructions into a separate header files. On branch scalar-crypto-fix Changes to be committed: modified: disasm/disasm.cc modified: riscv/encoding.h new file: riscv/insns/aes32dsi.h new file: riscv/insns/aes32dsmi.h new file: riscv/insns/aes32esi.h new file: riscv/insns/aes32esmi.h new file: riscv/insns/aes64ds.h new file: riscv/insns/aes64dsm.h new file: riscv/insns/aes64es.h new file: riscv/insns/aes64esm.h deleted: riscv/insns/aesds.h deleted: riscv/insns/aesdsm.h deleted: riscv/insns/aeses.h deleted: riscv/insns/aesesm.h modified: riscv/processor.cc modified: riscv/processor.h modified: riscv/riscv.mk.in
Diffstat (limited to 'riscv/insns/aes64dsm.h')
-rw-r--r--riscv/insns/aes64dsm.h29
1 files changed, 29 insertions, 0 deletions
diff --git a/riscv/insns/aes64dsm.h b/riscv/insns/aes64dsm.h
new file mode 100644
index 0000000..617a965
--- /dev/null
+++ b/riscv/insns/aes64dsm.h
@@ -0,0 +1,29 @@
+
+#include "aes_common.h"
+
+require_rv64;
+require_extension('K');
+
+uint64_t temp = AES_INVSHIFROWS_LO(RS1,RS2);
+
+ temp = (
+ ((uint64_t)AES_DEC_SBOX[(temp >> 0) & 0xFF] << 0) |
+ ((uint64_t)AES_DEC_SBOX[(temp >> 8) & 0xFF] << 8) |
+ ((uint64_t)AES_DEC_SBOX[(temp >> 16) & 0xFF] << 16) |
+ ((uint64_t)AES_DEC_SBOX[(temp >> 24) & 0xFF] << 24) |
+ ((uint64_t)AES_DEC_SBOX[(temp >> 32) & 0xFF] << 32) |
+ ((uint64_t)AES_DEC_SBOX[(temp >> 40) & 0xFF] << 40) |
+ ((uint64_t)AES_DEC_SBOX[(temp >> 48) & 0xFF] << 48) |
+ ((uint64_t)AES_DEC_SBOX[(temp >> 56) & 0xFF] << 56)
+);
+
+uint32_t col_0 = temp & 0xFFFFFFFF;
+uint32_t col_1 = temp >> 32 ;
+
+ col_0 = AES_INVMIXCOLUMN(col_0);
+ col_1 = AES_INVMIXCOLUMN(col_1);
+
+uint64_t result= ((uint64_t)col_1 << 32) | col_0;
+
+WRITE_RD(result);
+