.include "HDL50001_pcf.inc"

.alias SP  39
.alias IDX  4
.alias AA   0
.alias BB   1
.alias KI   2
.alias ENC  3	/* запрошена операция шифрования или расшифровывания */

.global gost_encdec

.data

Sblock:
    /* Определяем тестовые S-блоки в соответствии с ГОСТ Р 34.11-94 */
    .quad 0x35F7C1B6E08D29A4
    .quad 0x95701832AFD6C4BE
    .quad 0xB9067CFE243AD185
    .quad 0x352BC64EF9801AD7
    .quad 0x2B30E9A48DF517B6
    .quad 0xEFC95863D1270AB4
    .quad 0xC2867EA095F314BD
    .quad 0xC8B6E3294A750DF1

Keys:
    .long 0x1EADBEAF
    .long 0x2EADBEAF
    .long 0x3EADBEAF
    .long 0x4EADBEAF
    .long 0x5EADBEAF
    .long 0x6EADBEAF
    .long 0x7EADBEAF
Keys_last:
    .long 0x8EADBEAF

.text

gost_encdec:
enc :=	rdl #SP, 4
	rdl #SP, 8
	rdl #SP, 12

	setl #ENC, @3
	setl #AA, @3
	setl #BB, @3

	getl Sblock
	setl #32, @1

	je @enc, gost_enc.prologue
	jne @enc, gost_dec.prologue
complete

gost_enc.prologue:
	setl #IDX, 0
	jmp load_key1_24
complete

gost_dec.prologue:
	setl #IDX, 32
	jmp load_key25_32
complete

load_key1_24:
kp := 	getl Keys
	getl #IDX

	and  @1, 7		/* Ограничиваем Ki пределами [0..7] */
	mull @1, 4		/* Смещение до Ki */
	addl @kp, @1		/* Ki = kp + i*4 */
	rdl @1
	setl #KI, @1

	jmp round
complete

load_key25_32:
kp := 	getl Keys_last
i :=	getl #IDX

	subl @i, 25		/* Ограничиваем Ki пределами [7..0] */
	mull @1, 4		/* Смещение до Ki */
	subl @kp, @1		/* Отсчитываем ключ с конца: Ki = kp - i*4 */
	rdl @1
	setl #KI, @1

	jmp round
complete

round:
	/* Сохраняем в коммутатор 8 значений Sblock */
s0 :=	rdq  #32
s1 :=	rdq  #32, 8
s2 :=	rdq  #32, 16
s3 :=	rdq  #32, 24
s4 :=	rdq  #32, 32
s5 :=	rdq  #32, 40
s6 :=	rdq  #32, 48
s7 :=	rdq  #32, 56

	getl #KI
	getl #AA
axk :=	xor  @1, @2		/* Сложение Ai + Ki по mod 2 */

	/* Разбиваем на 4-х битную подпоследовательность */
	slrl @axk, 4
	slrl @axk, 8
	slrl @axk, 12
	slrl @axk, 16
	slrl @axk, 20
	slrl @axk, 24
	slrl @axk, 28
	/* Получаем индекс для каждой подпоследовательности */
	and @axk, 0xf
	and @8, 0xf
	and @8, 0xf
	and @8, 0xf
	and @8, 0xf
	and @8, 0xf
	and @8, 0xf
	and @8, 0xf
	mull @8, 4
	mull @8, 4
	mull @8, 4
	mull @8, 4
	mull @8, 4
	mull @8, 4
	mull @8, 4
	mull @8, 4
	/* Получаем значение по индексу */
	slrq @s0, @8
	slrq @s1, @8
	slrq @s2, @8
	slrq @s3, @8
	slrq @s4, @8
	slrq @s5, @8
	slrq @s6, @8
	slrq @s7, @8
	and  @8, 0xf
	and  @8, 0xf
	and  @8, 0xf
	and  @8, 0xf
	and  @8, 0xf
	and  @8, 0xf
	and  @8, 0xf
	and  @8, 0xf
	/* Склеиваем подпоследовательности */
	slll @7, 4
	slll @7, 8
	slll @7, 12
	slll @7, 16
	slll @7, 20
	slll @7, 24
	slll @7, 28
	or   @15, @7
	or   @1, @7
	or   @1, @7
	or   @1, @7
	or   @1, @7
	or   @1, @7
	or   @1, @7

	roll @1, 11		/* Циклический сдвиг влево на 11 бит */
	getl #BB
	xor  @1, @2		/* Bi ^ f(Ai,Ki) */
	setl #BB, #AA		/* Bi+1 = Ai */
	setl #AA, @2		/* Ai+1 = Bi ^ f(Ai,Ki) */

	/* HACK */
	getl #IDX
	subl @1, 1
/*	addl @1, 1 */
	setl #IDX, @1

	subl @2, 25
/*	subl @3, 33 */
	subl @3, 1
	jl   @2, load_key1_24
	jge  @3, load_key25_32
/*	je   @3, return */
	js   @6, return
complete

return:
	getl #AA
	getl #BB
	rdl #SP
	jmp @1
complete
