Skip to content

MaxHryshchanka/CourseWorkABC

Repository files navigation

Примечание

Коммит, где добавлял MASK, MATCH и INSN именно в riscv-gnu-toolchain/riscv-binutils перед установкой riscv-gnu-toolchain (о нём чуть позже пойдет речь) можно найти здесь:
https://github.com/MaxGrishenko/riscv-binutils-gdb/commit/d008e51a4bc5593c38d1023f6724b041128b1178

Добавление новых RISC-V ассемблерных команд в gcc

В качестве примера добавим AES: Round Instructions для RISC-V64

  • aes64esm rd rs1 rs2
    Round: ShiftRows, SubBytes, MixColumns
  • aes64es rd rs1 rs2
    Round: ShiftRows, SubBytes
  • aes64dsm rd rs1 rs2
    Round: InvShiftRows, InvSubBytes, InvMixColumn
  • aes64ds rd rs1 rs2
    Round: InvShiftRows, InvSubBytes

Эти инструкции предназначены только для RISC-V64. Они реализуют SubBytes, ShiftRows и MixColumns преобразования AES. Каждая команда round принимает в качестве входных данных два 64-битных регистра, представляющих 128-битное состояние шифра AES и выводит один 64-битный результат, то есть половину следующего состояния round.

RISC-V Opcodes

Для начала нам понадобится официальный git-репозиторий riscv-opcodes

$ git clone https://github.com/riscv/riscv-opcodes.git

В riscv-opcodes/ создадим текстовый файл opcodes-crypto со следующими опкод спецификациями для RISC-V

aes64esm      rd rs1 rs2       31..25=7            14..12=2 6..0=0x2B
aes64es       rd rs1 rs2       31..25=8            14..12=2 6..0=0x2B
aes64dsm      rd rs1 rs2       31..25=9            14..12=2 6..0=0x2B
aes64ds       rd rs1 rs2       31..25=10           14..12=2 6..0=0x2B

Их можно взять с официального git-репозитория https://github.com/riscv/riscv-crypto/blob/master/tools/opcodes-crypto-scalar

Также изменим riscv-opcodes/Makefile для генерации только необходимых нам MASK, MATCH и INSN для наших будущих crypto-команд

SHELL := /bin/sh

CRYPTO_H := ../encoding.h

CRYPTO_OPCODES := opcodes-crypto

$(CRYPTO_H): $(CRYPTO_OPCODES) parse_opcodes encoding.h
	echo "/*" > $@
	echo " * This file is auto-generated by running 'make $@' in" >> $@
	echo " * https://github.com/riscv/riscv-opcodes (`git log -1 --format="format:%h"`)" >> $@
	echo " */" >> $@
	echo >> $@
	cat encoding.h >> $@
	cat $(CRYPTO_OPCODES) | python ./parse_opcodes -c >> $@

.PHONY : install

Теперь спокойно собираем riscv-opcodes

$ sudo make

После успешной сборки появляется ../encoding.h, содержащий необходимые MATCH, MASK и INSN

...
#define MATCH_AES64ESM 0xe00202b
#define MASK_AES64ESM  0xfe00707f
#define MATCH_AES64ES 0x1000202b
#define MASK_AES64ES  0xfe00707f
#define MATCH_AES64DSM 0x1200202b
#define MASK_AES64DSM  0xfe00707f
#define MATCH_AES64DS 0x1400202b
#define MASK_AES64DS  0xfe00707f
...
DECLARE_INSN(aes64esm, MATCH_AES64ESM, MASK_AES64ESM)
DECLARE_INSN(aes64es, MATCH_AES64ES, MASK_AES64ES)
DECLARE_INSN(aes64dsm, MATCH_AES64DSM, MASK_AES64DSM)
DECLARE_INSN(aes64ds, MATCH_AES64DS, MASK_AES64DS)
...

Они понадобятся чуть позже...

RISC-V GNU Compiler Toolchain

Теперь клонируем официальный git-репозиторий riscv-gnu-toolchain

$ git clone --recursive https://github.com/riscv/riscv-gnu-toolchain

Переходим в riscv-gnu-toolchain/riscv-binutils/include/opcode/riscv-opc.h и по аналогии добавляем MATCH, MASK и INSN, которые сгенерировали ранее в ../encoding.h

Переходим в riscv-gnu-toolchain/riscv-binutils/opcodes/riscv-opc.c и по аналогии добавляем

{"aes64esm",    0, INSN_CLASS_C,   "d,s,t",  MATCH_AES64ESM, MASK_AES64ESM, match_opcode, 0 },
{"aes64es",     0, INSN_CLASS_C,   "d,s,t",  MATCH_AES64ES,  MASK_AES64ES,  match_opcode, 0 },
{"aes64dsm",    0, INSN_CLASS_C,   "d,s,t",  MATCH_AES64DSM, MASK_AES64DSM, match_opcode, 0 },
{"aes64ds",     0, INSN_CLASS_C,   "d,s,t",  MATCH_AES64DS,  MASK_AES64DS,  match_opcode, 0 },

Теперь надо собрать наш riscv-gnu-toolchain. Для этого могут понадобиться некоторые стандартные пакеты.

Для Ubuntu использовал

$ sudo apt-get install autoconf automake autotools-dev curl python3 libmpc-dev libmpfr-dev libgmp-dev gawk build-essential bison flex texinfo gperf libtool patchutils bc zlib1g-dev libexpat-dev

Для других дистрибутивов нужные пакеты можно найти на git-репозитории https://github.com/riscv/riscv-gnu-toolchain

Укажем путь, и начнём сборку

$ ./configure --prefix=/opt/riscv
$ sudo make

По умолчанию используется RISC-V64 и Newlib cross-compiler

Тесты

После успешной установки riscv-gnu-toolchain настроим пути

$ export PATH=/opt/riscv/bin:$PATH

Для самого простого теста создадим aes64esm-test.c

#include <stdio.h>

int main() {
    uint64_t a = 1;
    uint64_t b = 2;
    uint64_t c;
    asm volatile("aes64esm %[d], %[s], %[t]\n\t" : [d] "=r" (c) : [s] "r" (a), [t] "r" (b));
}

По аналогии протестируем и остальные команды: aes64ds, aes64es, aes64dsm

Теперь попробуем скомпилировать

$ riscv64-unknown-elf-gcc -o aes64esm-obj aes64esm-test.c

Если нет ошибки "unrecognized opcode", то riscv-gnu-toolchain был собран правильно

Протестируем через object dump то, что инструкция была использована

$ riscv64-unknown-elf-objdump -dC aes64esm-obj > aes64esm.dump
$ grep aes64esm aes64esm.dump

10164: oee7a7ab aes64esm a5,a5,a4

About

Adding new assembler instructions to RISC-V gcc

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published