aboutsummaryrefslogtreecommitdiff
path: root/riscv
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
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')
-rw-r--r--riscv/encoding.h63
-rw-r--r--riscv/insns/aes32dsi.h18
-rw-r--r--riscv/insns/aes32dsmi.h23
-rw-r--r--riscv/insns/aes32esi.h18
-rw-r--r--riscv/insns/aes32esmi.h23
-rw-r--r--riscv/insns/aes64ds.h21
-rw-r--r--riscv/insns/aes64dsm.h29
-rw-r--r--riscv/insns/aes64es.h21
-rw-r--r--riscv/insns/aes64esm.h29
-rw-r--r--riscv/insns/aesds.h47
-rw-r--r--riscv/insns/aesdsm.h60
-rw-r--r--riscv/insns/aeses.h47
-rw-r--r--riscv/insns/aesesm.h61
-rw-r--r--riscv/processor.cc20
-rw-r--r--riscv/processor.h10
-rw-r--r--riscv/riscv.mk.in12
16 files changed, 264 insertions, 238 deletions
diff --git a/riscv/encoding.h b/riscv/encoding.h
index 160dc29..eb0c49b 100644
--- a/riscv/encoding.h
+++ b/riscv/encoding.h
@@ -967,14 +967,28 @@
#define MATCH_AES64IM 0x30001013
#define MASK_AES64KS2 0xfe00707f
#define MATCH_AES64KS2 0x7e000033
-#define MASK_AESESM 0x3e00707f
-#define MATCH_AESESM 0x36000033
-#define MASK_AESES 0x3e00707f
-#define MATCH_AESES 0x32000033
-#define MASK_AESDSM 0x3e00707f
-#define MATCH_AESDSM 0x3e000033
-#define MASK_AESDS 0x3e00707f
-#define MATCH_AESDS 0x3a000033
+#define MASK_AES32ESMI 0x3e007fff
+#define MATCH_AES32ESMI 0x36000033
+#define MASK_AES32ESI 0x3e007fff
+#define MATCH_AES32ESI 0x32000033
+#define MASK_AES32DSMI 0x3e007fff
+#define MATCH_AES32DSMI 0x3e000033
+#define MASK_AES32DSI 0x3e007fff
+#define MATCH_AES32DSI 0x3a000033
+#define MASK_AES64KS1I 0xff00707f
+#define MATCH_AES64KS1I 0x31001013
+#define MASK_AES64IM 0xfff0707f
+#define MATCH_AES64IM 0x30001013
+#define MASK_AES64KS2 0xfe00707f
+#define MATCH_AES64KS2 0x7e000033
+#define MASK_AES64ESM 0xfe00707f
+#define MATCH_AES64ESM 0x36000033
+#define MASK_AES64ES 0xfe00707f
+#define MATCH_AES64ES 0x32000033
+#define MASK_AES64DSM 0xfe00707f
+#define MATCH_AES64DSM 0x3e000033
+#define MASK_AES64DS 0xfe00707f
+#define MATCH_AES64DS 0x3a000033
#define MASK_SHA512SUM0 0xfff0707f
#define MATCH_SHA512SUM0 0x10401013
#define MASK_SHA512SUM1 0xfff0707f
@@ -2746,10 +2760,25 @@ DECLARE_INSN(sm4ks, MATCH_SM4KS, MASK_SM4KS)
DECLARE_INSN(aes64ks1i, MATCH_AES64KS1I, MASK_AES64KS1I)
DECLARE_INSN(aes64ks2, MATCH_AES64KS2, MASK_AES64KS2)
DECLARE_INSN(aes64im, MATCH_AES64IM, MASK_AES64IM)
-DECLARE_INSN(aesesm, MATCH_AESESM, MASK_AESESM)
-DECLARE_INSN(aeses, MATCH_AESES, MASK_AESES)
-DECLARE_INSN(aesdsm, MATCH_AESDSM, MASK_AESDSM)
-DECLARE_INSN(aesds, MATCH_AESDS, MASK_AESDS)
+DECLARE_INSN(aes64es, MATCH_AES64ES, MASK_AES64ES)
+DECLARE_INSN(aes64esm, MATCH_AES64ESM, MASK_AES64ESM)
+DECLARE_INSN(aes64ds, MATCH_AES64DS, MASK_AES64DS)
+DECLARE_INSN(aes64dsm, MATCH_AES64DSM, MASK_AES64DSM)
+DECLARE_RV64_ONLY(aes64ks1i)
+DECLARE_RV64_ONLY(aes64ks2)
+DECLARE_RV64_ONLY(aes64im)
+DECLARE_RV64_ONLY(aes64es)
+DECLARE_RV64_ONLY(aes64esm)
+DECLARE_RV64_ONLY(aes64ds)
+DECLARE_RV64_ONLY(aes64dsm)
+DECLARE_INSN(aes32esi, MATCH_AES32ESI, MASK_AES32ESI)
+DECLARE_INSN(aes32esmi, MATCH_AES32ESMI, MASK_AES32ESMI)
+DECLARE_INSN(aes32dsi, MATCH_AES32DSI, MASK_AES32DSI)
+DECLARE_INSN(aes32dsmi, MATCH_AES32DSMI, MASK_AES32DSMI)
+DECLARE_RV32_ONLY(aes32esi)
+DECLARE_RV32_ONLY(aes32esmi)
+DECLARE_RV32_ONLY(aes32dsi)
+DECLARE_RV32_ONLY(aes32dsmi)
DECLARE_INSN(sha256sig0, MATCH_SHA256SIG0, MASK_SHA256SIG0)
DECLARE_INSN(sha256sig1, MATCH_SHA256SIG1, MASK_SHA256SIG1)
DECLARE_INSN(sha256sum0, MATCH_SHA256SUM0, MASK_SHA256SUM0)
@@ -2762,10 +2791,20 @@ DECLARE_INSN(sha512sig1l, MATCH_SHA512SIG1L, MASK_SHA512SIG1L)
DECLARE_INSN(sha512sig1h, MATCH_SHA512SIG1H, MASK_SHA512SIG1H)
DECLARE_INSN(sha512sum0r, MATCH_SHA512SUM0R, MASK_SHA512SUM0R)
DECLARE_INSN(sha512sum1r, MATCH_SHA512SUM1R, MASK_SHA512SUM1R)
+DECLARE_RV32_ONLY(sha512sig0l)
+DECLARE_RV32_ONLY(sha512sig0h)
+DECLARE_RV32_ONLY(sha512sig1l)
+DECLARE_RV32_ONLY(sha512sig1h)
+DECLARE_RV32_ONLY(sha512sum0r)
+DECLARE_RV32_ONLY(sha512sum1r)
DECLARE_INSN(sha512sig0, MATCH_SHA512SIG0, MASK_SHA512SIG0)
DECLARE_INSN(sha512sig1, MATCH_SHA512SIG1, MASK_SHA512SIG1)
DECLARE_INSN(sha512sum0, MATCH_SHA512SUM0, MASK_SHA512SUM0)
DECLARE_INSN(sha512sum1, MATCH_SHA512SUM1, MASK_SHA512SUM1)
+DECLARE_RV64_ONLY(sha512sig0)
+DECLARE_RV64_ONLY(sha512sig1)
+DECLARE_RV64_ONLY(sha512sum0)
+DECLARE_RV64_ONLY(sha512sum1)
DECLARE_INSN(pollentropy, MATCH_POLLENTROPY, MASK_POLLENTROPY)
DECLARE_INSN(getnoise, MATCH_GETNOISE, MASK_GETNOISE)
DECLARE_INSN(ecall, MATCH_ECALL, MASK_ECALL)
diff --git a/riscv/insns/aes32dsi.h b/riscv/insns/aes32dsi.h
new file mode 100644
index 0000000..07d0363
--- /dev/null
+++ b/riscv/insns/aes32dsi.h
@@ -0,0 +1,18 @@
+
+#include "aes_common.h"
+
+require_rv32;
+require_extension('K');
+require(RD == 0); // Additional decoding required for RV32
+
+uint8_t bs = insn.bs();
+
+uint8_t t0 = RS2 >> (8*bs);
+uint8_t x = AES_DEC_SBOX[t0];
+uint32_t u = x;
+
+u = (u << (8*bs)) | (u >> (32-8*bs));
+
+uint64_t rd = insn.rs1(); // RD sourced from RS1 field.
+WRITE_REG(rd, u ^ RS1);
+
diff --git a/riscv/insns/aes32dsmi.h b/riscv/insns/aes32dsmi.h
new file mode 100644
index 0000000..6d157ac
--- /dev/null
+++ b/riscv/insns/aes32dsmi.h
@@ -0,0 +1,23 @@
+
+#include "aes_common.h"
+
+require_rv32;
+require_extension('K');
+require(RD == 0); // Additional decoding required for RV32
+
+uint8_t bs = insn.bs();
+
+uint8_t t0 = RS2 >> (8*bs);
+uint8_t x = AES_DEC_SBOX[t0];
+uint32_t u ;
+
+u = (AES_GFMUL(x,0xb) << 24) |
+ (AES_GFMUL(x,0xd) << 16) |
+ (AES_GFMUL(x,0x9) << 8) |
+ (AES_GFMUL(x,0xe) << 0) ;
+
+u = (u << (8*bs)) | (u >> (32-8*bs));
+
+uint64_t rd = insn.rs1(); // RD sourced from RS1 field.
+WRITE_REG(rd, u ^ RS1);
+
diff --git a/riscv/insns/aes32esi.h b/riscv/insns/aes32esi.h
new file mode 100644
index 0000000..e24124d
--- /dev/null
+++ b/riscv/insns/aes32esi.h
@@ -0,0 +1,18 @@
+
+#include "aes_common.h"
+
+require_rv32;
+require_extension('K');
+require(RD == 0); // Additional decoding required for RV32
+
+uint8_t bs = insn.bs();
+
+uint8_t t0 = RS2 >> (8*bs);
+uint8_t x = AES_ENC_SBOX[t0];
+uint32_t u = x;
+
+u = (u << (8*bs)) | (u >> (32-8*bs));
+
+uint64_t rd = insn.rs1(); // RD sourced from RS1 field.
+WRITE_REG(rd, u ^ RS1);
+
diff --git a/riscv/insns/aes32esmi.h b/riscv/insns/aes32esmi.h
new file mode 100644
index 0000000..9768201
--- /dev/null
+++ b/riscv/insns/aes32esmi.h
@@ -0,0 +1,23 @@
+
+#include "aes_common.h"
+
+require_rv32;
+require_extension('K');
+require(RD == 0); // Additional decoding required for RV32
+
+uint8_t bs = insn.bs();
+
+uint8_t t0 = RS2 >> (8*bs);
+uint8_t x = AES_ENC_SBOX[t0];
+uint32_t u ;
+
+u = (AES_GFMUL(x,3) << 24) |
+ ( x << 16) |
+ ( x << 8) |
+ (AES_GFMUL(x,2) << 0) ;
+
+u = (u << (8*bs)) | (u >> (32-8*bs));
+
+uint64_t rd = insn.rs1(); // RD sourced from RS1 field.
+WRITE_REG(rd, u ^ RS1);
+
diff --git a/riscv/insns/aes64ds.h b/riscv/insns/aes64ds.h
new file mode 100644
index 0000000..05fadca
--- /dev/null
+++ b/riscv/insns/aes64ds.h
@@ -0,0 +1,21 @@
+
+#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)
+);
+
+WRITE_RD(temp);
+
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);
+
diff --git a/riscv/insns/aes64es.h b/riscv/insns/aes64es.h
new file mode 100644
index 0000000..a34436d
--- /dev/null
+++ b/riscv/insns/aes64es.h
@@ -0,0 +1,21 @@
+
+#include "aes_common.h"
+
+require_rv64;
+require_extension('K');
+
+uint64_t temp = AES_SHIFROWS_LO(RS1,RS2);
+
+ temp = (
+ ((uint64_t)AES_ENC_SBOX[(temp >> 0) & 0xFF] << 0) |
+ ((uint64_t)AES_ENC_SBOX[(temp >> 8) & 0xFF] << 8) |
+ ((uint64_t)AES_ENC_SBOX[(temp >> 16) & 0xFF] << 16) |
+ ((uint64_t)AES_ENC_SBOX[(temp >> 24) & 0xFF] << 24) |
+ ((uint64_t)AES_ENC_SBOX[(temp >> 32) & 0xFF] << 32) |
+ ((uint64_t)AES_ENC_SBOX[(temp >> 40) & 0xFF] << 40) |
+ ((uint64_t)AES_ENC_SBOX[(temp >> 48) & 0xFF] << 48) |
+ ((uint64_t)AES_ENC_SBOX[(temp >> 56) & 0xFF] << 56)
+);
+
+WRITE_RD(temp);
+
diff --git a/riscv/insns/aes64esm.h b/riscv/insns/aes64esm.h
new file mode 100644
index 0000000..a41667b
--- /dev/null
+++ b/riscv/insns/aes64esm.h
@@ -0,0 +1,29 @@
+
+#include "aes_common.h"
+
+require_rv64;
+require_extension('K');
+
+uint64_t temp = AES_SHIFROWS_LO(RS1,RS2);
+
+ temp = (
+ ((uint64_t)AES_ENC_SBOX[(temp >> 0) & 0xFF] << 0) |
+ ((uint64_t)AES_ENC_SBOX[(temp >> 8) & 0xFF] << 8) |
+ ((uint64_t)AES_ENC_SBOX[(temp >> 16) & 0xFF] << 16) |
+ ((uint64_t)AES_ENC_SBOX[(temp >> 24) & 0xFF] << 24) |
+ ((uint64_t)AES_ENC_SBOX[(temp >> 32) & 0xFF] << 32) |
+ ((uint64_t)AES_ENC_SBOX[(temp >> 40) & 0xFF] << 40) |
+ ((uint64_t)AES_ENC_SBOX[(temp >> 48) & 0xFF] << 48) |
+ ((uint64_t)AES_ENC_SBOX[(temp >> 56) & 0xFF] << 56)
+);
+
+uint32_t col_0 = temp & 0xFFFFFFFF;
+uint32_t col_1 = temp >> 32 ;
+
+ col_0 = AES_MIXCOLUMN(col_0);
+ col_1 = AES_MIXCOLUMN(col_1);
+
+uint64_t result= ((uint64_t)col_1 << 32) | col_0;
+
+WRITE_RD(result);
+
diff --git a/riscv/insns/aesds.h b/riscv/insns/aesds.h
deleted file mode 100644
index 3fdc07a..0000000
--- a/riscv/insns/aesds.h
+++ /dev/null
@@ -1,47 +0,0 @@
-
-#include "aes_common.h"
-
-// The encodings for the RV32 and RV64 AES instructions overlap, as they
-// are mutually exclusive. They have rather different functionality.
-
-if(xlen == 32) {
- // Execute the RV32 aes32dsi instruction
-
- require_rv32;
- require_extension('K');
- require(RD == 0); // Additional decoding required for RV32
-
- uint8_t bs = insn.bs();
-
- uint8_t t0 = RS2 >> (8*bs);
- uint8_t x = AES_DEC_SBOX[t0];
- uint32_t u = x;
-
- u = (u << (8*bs)) | (u >> (32-8*bs));
-
- uint64_t rd = insn.rs1(); // RD sourced from RS1 field.
- WRITE_REG(rd, u ^ RS1);
-
-} else {
- // Execute the RV64 aes64ds instruction
-
- require(insn.bs() == 0);
- 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)
- );
-
- WRITE_RD(temp);
-
-}
diff --git a/riscv/insns/aesdsm.h b/riscv/insns/aesdsm.h
deleted file mode 100644
index d57e50e..0000000
--- a/riscv/insns/aesdsm.h
+++ /dev/null
@@ -1,60 +0,0 @@
-
-#include "aes_common.h"
-
-// The encodings for the RV32 and RV64 AES instructions overlap, as they
-// are mutually exclusive. They have rather different functionality.
-
-if(xlen == 32) {
- // Execute the RV32 aes32dsmi instruction
-
- require_rv32;
- require_extension('K');
- require(RD == 0); // Additional decoding required for RV32
-
- uint8_t bs = insn.bs();
-
- uint8_t t0 = RS2 >> (8*bs);
- uint8_t x = AES_DEC_SBOX[t0];
- uint32_t u ;
-
- u = (AES_GFMUL(x,0xb) << 24) |
- (AES_GFMUL(x,0xd) << 16) |
- (AES_GFMUL(x,0x9) << 8) |
- (AES_GFMUL(x,0xe) << 0) ;
-
- u = (u << (8*bs)) | (u >> (32-8*bs));
-
- uint64_t rd = insn.rs1(); // RD sourced from RS1 field.
- WRITE_REG(rd, u ^ RS1);
-
-} else {
- // Execute the RV64 aes64dsm instruction
-
- require(insn.bs() == 0);
- 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);
-
-}
diff --git a/riscv/insns/aeses.h b/riscv/insns/aeses.h
deleted file mode 100644
index 635fc54..0000000
--- a/riscv/insns/aeses.h
+++ /dev/null
@@ -1,47 +0,0 @@
-
-#include "aes_common.h"
-
-// The encodings for the RV32 and RV64 AES instructions overlap, as they
-// are mutually exclusive. They have rather different functionality.
-
-if(xlen == 32) {
- // Execute the RV32 aes32esi instruction
-
- require_rv32;
- require_extension('K');
- require(RD == 0); // Additional decoding required for RV32
-
- uint8_t bs = insn.bs();
-
- uint8_t t0 = RS2 >> (8*bs);
- uint8_t x = AES_ENC_SBOX[t0];
- uint32_t u = x;
-
- u = (u << (8*bs)) | (u >> (32-8*bs));
-
- uint64_t rd = insn.rs1(); // RD sourced from RS1 field.
- WRITE_REG(rd, u ^ RS1);
-
-} else {
- // Execute the RV64 aes64es instruction
-
- require(insn.bs() == 0);
- require_rv64;
- require_extension('K');
-
- uint64_t temp = AES_SHIFROWS_LO(RS1,RS2);
-
- temp = (
- ((uint64_t)AES_ENC_SBOX[(temp >> 0) & 0xFF] << 0) |
- ((uint64_t)AES_ENC_SBOX[(temp >> 8) & 0xFF] << 8) |
- ((uint64_t)AES_ENC_SBOX[(temp >> 16) & 0xFF] << 16) |
- ((uint64_t)AES_ENC_SBOX[(temp >> 24) & 0xFF] << 24) |
- ((uint64_t)AES_ENC_SBOX[(temp >> 32) & 0xFF] << 32) |
- ((uint64_t)AES_ENC_SBOX[(temp >> 40) & 0xFF] << 40) |
- ((uint64_t)AES_ENC_SBOX[(temp >> 48) & 0xFF] << 48) |
- ((uint64_t)AES_ENC_SBOX[(temp >> 56) & 0xFF] << 56)
- );
-
- WRITE_RD(temp);
-
-}
diff --git a/riscv/insns/aesesm.h b/riscv/insns/aesesm.h
deleted file mode 100644
index 4b0d6c7..0000000
--- a/riscv/insns/aesesm.h
+++ /dev/null
@@ -1,61 +0,0 @@
-
-#include "aes_common.h"
-
-// The encodings for the RV32 and RV64 AES instructions overlap, as they
-// are mutually exclusive. They have rather different functionality.
-
-if(xlen == 32) {
- // Execute the RV32 aes32esmi instruction
-
- require_rv32;
- require_extension('K');
- require(RD == 0); // Additional decoding required for RV32
-
- uint8_t bs = insn.bs();
-
- uint8_t t0 = RS2 >> (8*bs);
- uint8_t x = AES_ENC_SBOX[t0];
- uint32_t u ;
-
- u = (AES_GFMUL(x,3) << 24) |
- ( x << 16) |
- ( x << 8) |
- (AES_GFMUL(x,2) << 0) ;
-
- u = (u << (8*bs)) | (u >> (32-8*bs));
-
- uint64_t rd = insn.rs1(); // RD sourced from RS1 field.
- WRITE_REG(rd, u ^ RS1);
-
-} else {
- // Execute the RV64 aes64esm instruction
-
- require(insn.bs() == 0);
- require_rv64;
- require_extension('K');
-
- uint64_t temp = AES_SHIFROWS_LO(RS1,RS2);
-
- temp = (
- ((uint64_t)AES_ENC_SBOX[(temp >> 0) & 0xFF] << 0) |
- ((uint64_t)AES_ENC_SBOX[(temp >> 8) & 0xFF] << 8) |
- ((uint64_t)AES_ENC_SBOX[(temp >> 16) & 0xFF] << 16) |
- ((uint64_t)AES_ENC_SBOX[(temp >> 24) & 0xFF] << 24) |
- ((uint64_t)AES_ENC_SBOX[(temp >> 32) & 0xFF] << 32) |
- ((uint64_t)AES_ENC_SBOX[(temp >> 40) & 0xFF] << 40) |
- ((uint64_t)AES_ENC_SBOX[(temp >> 48) & 0xFF] << 48) |
- ((uint64_t)AES_ENC_SBOX[(temp >> 56) & 0xFF] << 56)
- );
-
- uint32_t col_0 = temp & 0xFFFFFFFF;
- uint32_t col_1 = temp >> 32 ;
-
- col_0 = AES_MIXCOLUMN(col_0);
- col_1 = AES_MIXCOLUMN(col_1);
-
- uint64_t result= ((uint64_t)col_1 << 32) | col_0;
-
- WRITE_RD(result);
-
-}
-
diff --git a/riscv/processor.cc b/riscv/processor.cc
index e00bc85..687ea6a 100644
--- a/riscv/processor.cc
+++ b/riscv/processor.cc
@@ -1786,13 +1786,17 @@ insn_func_t processor_t::decode_insn(insn_t insn)
size_t idx = insn.bits() % OPCODE_CACHE_SIZE;
insn_desc_t desc = opcode_cache[idx];
- if (unlikely(insn.bits() != desc.match)) {
+ archen_t current_arch = xlen >> 5;
+ bool insn_valid_for_arch = (desc.archen & current_arch) != 0;
+
+ if (unlikely(insn.bits() != desc.match || insn_valid_for_arch == false)) {
// fall back to linear search
insn_desc_t* p = &instructions[0];
- while ((insn.bits() & p->mask) != p->match)
+ while ((insn.bits() & p->mask) != p->match ||
+ (p->archen & current_arch) == 0)
p++;
desc = *p;
-
+
if (p->mask != 0 && p > &instructions[0]) {
if (p->match != (p-1)->match && p->match != (p+1)->match) {
// move to front of opcode list to reduce miss penalty
@@ -1850,12 +1854,18 @@ void processor_t::register_extension(extension_t* x)
void processor_t::register_base_instructions()
{
#define DECLARE_INSN(name, match, mask) \
- insn_bits_t name##_match = (match), name##_mask = (mask);
+ insn_bits_t name##_match = (match), name##_mask = (mask); \
+ archen_t name##_arch_en = ARCHEN_ANY;
+ #define DECLARE_RV32_ONLY(name) {name##_arch_en=ARCHEN_RV32_ONLY;}
+ #define DECLARE_RV64_ONLY(name) {name##_arch_en=ARCHEN_RV64_ONLY;}
+
#include "encoding.h"
+ #undef DECLARE_RV64_INSN
+ #undef DECLARE_RV32_INSN
#undef DECLARE_INSN
#define DEFINE_INSN(name) \
- REGISTER_INSN(this, name, name##_match, name##_mask)
+ REGISTER_INSN(this, name, name##_match, name##_mask, name##_arch_en)
#include "insn_list.h"
#undef DEFINE_INSN
diff --git a/riscv/processor.h b/riscv/processor.h
index 7fb5103..89e889f 100644
--- a/riscv/processor.h
+++ b/riscv/processor.h
@@ -23,12 +23,18 @@ class trap_t;
class extension_t;
class disassembler_t;
+typedef char archen_t;
+const archen_t ARCHEN_RV32_ONLY=1;
+const archen_t ARCHEN_RV64_ONLY=2;
+const archen_t ARCHEN_ANY =7;
+
struct insn_desc_t
{
insn_bits_t match;
insn_bits_t mask;
insn_func_t rv32;
insn_func_t rv64;
+ char archen; // 0x7=all arches, 0x2=rv64 only, 0x1=rv32 only etc
};
// regnum, data
@@ -549,9 +555,9 @@ public:
reg_t illegal_instruction(processor_t* p, insn_t insn, reg_t pc);
-#define REGISTER_INSN(proc, name, match, mask) \
+#define REGISTER_INSN(proc, name, match, mask, archen) \
extern reg_t rv32_##name(processor_t*, insn_t, reg_t); \
extern reg_t rv64_##name(processor_t*, insn_t, reg_t); \
- proc->register_insn((insn_desc_t){match, mask, rv32_##name, rv64_##name});
+ proc->register_insn((insn_desc_t){match, mask, rv32_##name, rv64_##name,archen});
#endif
diff --git a/riscv/riscv.mk.in b/riscv/riscv.mk.in
index d19e9f6..a301a36 100644
--- a/riscv/riscv.mk.in
+++ b/riscv/riscv.mk.in
@@ -434,10 +434,14 @@ riscv_insn_ext_b = \
# Scalar Crypto ISE
riscv_insn_ext_k = \
- aesds \
- aesdsm \
- aeses \
- aesesm \
+ aes32dsi \
+ aes32dsmi \
+ aes32esi \
+ aes32esmi \
+ aes64ds \
+ aes64dsm \
+ aes64es \
+ aes64esm \
aes64ks1i \
aes64ks2 \
aes64im \