aboutsummaryrefslogtreecommitdiff
path: root/riscv/insns/aesdsm.h
blob: d57e50e54d0e1c4c2e8e16150b7dd54533d4986b (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60

#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);

}