// File: DiplIngFrankGerlach[P]MST/./aes/aes.c
// Function: aes_decrypt
void aes_decrypt(const BYTE in[], BYTE out[], const WORD key[], int keysize)
{
	BYTE state[4][4];

	// Copy the input to the state.
	state[0][0] = in[0];
	state[1][0] = in[1];
	state[2][0] = in[2];
	state[3][0] = in[3];
	state[0][1] = in[4];
	state[1][1] = in[5];
	state[2][1] = in[6];
	state[3][1] = in[7];
	state[0][2] = in[8];
	state[1][2] = in[9];
	state[2][2] = in[10];
	state[3][2] = in[11];
	state[0][3] = in[12];
	state[1][3] = in[13];
	state[2][3] = in[14];
	state[3][3] = in[15];

	// Perform the necessary number of rounds. The round key is added first.
	// The last round does not perform the MixColumns step.
	if (keysize > 128) {
		if (keysize > 192) {
			AddRoundKey(state,&key[56]);
			InvShiftRows(state);InvSubBytes(state);AddRoundKey(state,&key[52]);InvMixColumns(state);
			InvShiftRows(state);InvSubBytes(state);AddRoundKey(state,&key[48]);InvMixColumns(state);
		}
		else {
			AddRoundKey(state,&key[48]);
		}
		InvShiftRows(state);InvSubBytes(state);AddRoundKey(state,&key[44]);InvMixColumns(state);
		InvShiftRows(state);InvSubBytes(state);AddRoundKey(state,&key[40]);InvMixColumns(state);
	}
	else {
		AddRoundKey(state,&key[40]);
	}
	InvShiftRows(state);InvSubBytes(state);AddRoundKey(state,&key[36]);InvMixColumns(state);
	InvShiftRows(state);InvSubBytes(state);AddRoundKey(state,&key[32]);InvMixColumns(state);
	InvShiftRows(state);InvSubBytes(state);AddRoundKey(state,&key[28]);InvMixColumns(state);
	InvShiftRows(state);InvSubBytes(state);AddRoundKey(state,&key[24]);InvMixColumns(state);
	InvShiftRows(state);InvSubBytes(state);AddRoundKey(state,&key[20]);InvMixColumns(state);
	InvShiftRows(state);InvSubBytes(state);AddRoundKey(state,&key[16]);InvMixColumns(state);
	InvShiftRows(state);InvSubBytes(state);AddRoundKey(state,&key[12]);InvMixColumns(state);
	InvShiftRows(state);InvSubBytes(state);AddRoundKey(state,&key[8]);InvMixColumns(state);
	InvShiftRows(state);InvSubBytes(state);AddRoundKey(state,&key[4]);InvMixColumns(state);
	InvShiftRows(state);InvSubBytes(state);AddRoundKey(state,&key[0]);

	// Copy the state to the output array.
	out[0] = state[0][0];
	out[1] = state[1][0];
	out[2] = state[2][0];
	out[3] = state[3][0];
	out[4] = state[0][1];
	out[5] = state[1][1];
	out[6] = state[2][1];
	out[7] = state[3][1];
	out[8] = state[0][2];
	out[9] = state[1][2];
	out[10] = state[2][2];
	out[11] = state[3][2];
	out[12] = state[0][3];
	out[13] = state[1][3];
	out[14] = state[2][3];
	out[15] = state[3][3];
}

// Assembly:
pushq %rbp
movq %rsp, %rbp
subq $0x30, %rsp
movq %rdi, -0x8(%rbp)
movq %rsi, -0x10(%rbp)
movq %rdx, -0x18(%rbp)
movl %ecx, -0x1c(%rbp)
movq -0x8(%rbp), %rax
movb (%rax), %al
movb %al, -0x30(%rbp)
movq -0x8(%rbp), %rax
movb 0x1(%rax), %al
movb %al, -0x2c(%rbp)
movq -0x8(%rbp), %rax
movb 0x2(%rax), %al
movb %al, -0x28(%rbp)
movq -0x8(%rbp), %rax
movb 0x3(%rax), %al
movb %al, -0x24(%rbp)
movq -0x8(%rbp), %rax
movb 0x4(%rax), %al
movb %al, -0x2f(%rbp)
movq -0x8(%rbp), %rax
movb 0x5(%rax), %al
movb %al, -0x2b(%rbp)
movq -0x8(%rbp), %rax
movb 0x6(%rax), %al
movb %al, -0x27(%rbp)
movq -0x8(%rbp), %rax
movb 0x7(%rax), %al
movb %al, -0x23(%rbp)
movq -0x8(%rbp), %rax
movb 0x8(%rax), %al
movb %al, -0x2e(%rbp)
movq -0x8(%rbp), %rax
movb 0x9(%rax), %al
movb %al, -0x2a(%rbp)
movq -0x8(%rbp), %rax
movb 0xa(%rax), %al
movb %al, -0x26(%rbp)
movq -0x8(%rbp), %rax
movb 0xb(%rax), %al
movb %al, -0x22(%rbp)
movq -0x8(%rbp), %rax
movb 0xc(%rax), %al
movb %al, -0x2d(%rbp)
movq -0x8(%rbp), %rax
movb 0xd(%rax), %al
movb %al, -0x29(%rbp)
movq -0x8(%rbp), %rax
movb 0xe(%rax), %al
movb %al, -0x25(%rbp)
movq -0x8(%rbp), %rax
movb 0xf(%rax), %al
movb %al, -0x21(%rbp)
cmpl $0x80, -0x1c(%rbp)
jle 0x2dd4
cmpl $0xc0, -0x1c(%rbp)
jle 0x2d60
leaq -0x30(%rbp), %rdi
movq -0x18(%rbp), %rsi
addq $0xe0, %rsi
callq 0x3c10
leaq -0x30(%rbp), %rdi
callq 0x4570
leaq -0x30(%rbp), %rdi
callq 0x4140
leaq -0x30(%rbp), %rdi
movq -0x18(%rbp), %rsi
addq $0xd0, %rsi
callq 0x3c10
leaq -0x30(%rbp), %rdi
callq 0x4d40
leaq -0x30(%rbp), %rdi
callq 0x4570
leaq -0x30(%rbp), %rdi
callq 0x4140
leaq -0x30(%rbp), %rdi
movq -0x18(%rbp), %rsi
addq $0xc0, %rsi
callq 0x3c10
leaq -0x30(%rbp), %rdi
callq 0x4d40
jmp 0x2d74
leaq -0x30(%rbp), %rdi
movq -0x18(%rbp), %rsi
addq $0xc0, %rsi
callq 0x3c10
leaq -0x30(%rbp), %rdi
callq 0x4570
leaq -0x30(%rbp), %rdi
callq 0x4140
leaq -0x30(%rbp), %rdi
movq -0x18(%rbp), %rsi
addq $0xb0, %rsi
callq 0x3c10
leaq -0x30(%rbp), %rdi
callq 0x4d40
leaq -0x30(%rbp), %rdi
callq 0x4570
leaq -0x30(%rbp), %rdi
callq 0x4140
leaq -0x30(%rbp), %rdi
movq -0x18(%rbp), %rsi
addq $0xa0, %rsi
callq 0x3c10
leaq -0x30(%rbp), %rdi
callq 0x4d40
jmp 0x2de8
leaq -0x30(%rbp), %rdi
movq -0x18(%rbp), %rsi
addq $0xa0, %rsi
callq 0x3c10
leaq -0x30(%rbp), %rdi
callq 0x4570
leaq -0x30(%rbp), %rdi
callq 0x4140
leaq -0x30(%rbp), %rdi
movq -0x18(%rbp), %rsi
addq $0x90, %rsi
callq 0x3c10
leaq -0x30(%rbp), %rdi
callq 0x4d40
leaq -0x30(%rbp), %rdi
callq 0x4570
leaq -0x30(%rbp), %rdi
callq 0x4140
leaq -0x30(%rbp), %rdi
movq -0x18(%rbp), %rsi
addq $0x80, %rsi
callq 0x3c10
leaq -0x30(%rbp), %rdi
callq 0x4d40
leaq -0x30(%rbp), %rdi
callq 0x4570
leaq -0x30(%rbp), %rdi
callq 0x4140
leaq -0x30(%rbp), %rdi
movq -0x18(%rbp), %rsi
addq $0x70, %rsi
callq 0x3c10
leaq -0x30(%rbp), %rdi
callq 0x4d40
leaq -0x30(%rbp), %rdi
callq 0x4570
leaq -0x30(%rbp), %rdi
callq 0x4140
leaq -0x30(%rbp), %rdi
movq -0x18(%rbp), %rsi
addq $0x60, %rsi
callq 0x3c10
leaq -0x30(%rbp), %rdi
callq 0x4d40
leaq -0x30(%rbp), %rdi
callq 0x4570
leaq -0x30(%rbp), %rdi
callq 0x4140
leaq -0x30(%rbp), %rdi
movq -0x18(%rbp), %rsi
addq $0x50, %rsi
callq 0x3c10
leaq -0x30(%rbp), %rdi
callq 0x4d40
leaq -0x30(%rbp), %rdi
callq 0x4570
leaq -0x30(%rbp), %rdi
callq 0x4140
leaq -0x30(%rbp), %rdi
movq -0x18(%rbp), %rsi
addq $0x40, %rsi
callq 0x3c10
leaq -0x30(%rbp), %rdi
callq 0x4d40
leaq -0x30(%rbp), %rdi
callq 0x4570
leaq -0x30(%rbp), %rdi
callq 0x4140
leaq -0x30(%rbp), %rdi
movq -0x18(%rbp), %rsi
addq $0x30, %rsi
callq 0x3c10
leaq -0x30(%rbp), %rdi
callq 0x4d40
leaq -0x30(%rbp), %rdi
callq 0x4570
leaq -0x30(%rbp), %rdi
callq 0x4140
leaq -0x30(%rbp), %rdi
movq -0x18(%rbp), %rsi
addq $0x20, %rsi
callq 0x3c10
leaq -0x30(%rbp), %rdi
callq 0x4d40
leaq -0x30(%rbp), %rdi
callq 0x4570
leaq -0x30(%rbp), %rdi
callq 0x4140
leaq -0x30(%rbp), %rdi
movq -0x18(%rbp), %rsi
addq $0x10, %rsi
callq 0x3c10
leaq -0x30(%rbp), %rdi
callq 0x4d40
leaq -0x30(%rbp), %rdi
callq 0x4570
leaq -0x30(%rbp), %rdi
callq 0x4140
leaq -0x30(%rbp), %rdi
movq -0x18(%rbp), %rsi
callq 0x3c10
movb -0x30(%rbp), %cl
movq -0x10(%rbp), %rax
movb %cl, (%rax)
movb -0x2c(%rbp), %cl
movq -0x10(%rbp), %rax
movb %cl, 0x1(%rax)
movb -0x28(%rbp), %cl
movq -0x10(%rbp), %rax
movb %cl, 0x2(%rax)
movb -0x24(%rbp), %cl
movq -0x10(%rbp), %rax
movb %cl, 0x3(%rax)
movb -0x2f(%rbp), %cl
movq -0x10(%rbp), %rax
movb %cl, 0x4(%rax)
movb -0x2b(%rbp), %cl
movq -0x10(%rbp), %rax
movb %cl, 0x5(%rax)
movb -0x27(%rbp), %cl
movq -0x10(%rbp), %rax
movb %cl, 0x6(%rax)
movb -0x23(%rbp), %cl
movq -0x10(%rbp), %rax
movb %cl, 0x7(%rax)
movb -0x2e(%rbp), %cl
movq -0x10(%rbp), %rax
movb %cl, 0x8(%rax)
movb -0x2a(%rbp), %cl
movq -0x10(%rbp), %rax
movb %cl, 0x9(%rax)
movb -0x26(%rbp), %cl
movq -0x10(%rbp), %rax
movb %cl, 0xa(%rax)
movb -0x22(%rbp), %cl
movq -0x10(%rbp), %rax
movb %cl, 0xb(%rax)
movb -0x2d(%rbp), %cl
movq -0x10(%rbp), %rax
movb %cl, 0xc(%rax)
movb -0x29(%rbp), %cl
movq -0x10(%rbp), %rax
movb %cl, 0xd(%rax)
movb -0x25(%rbp), %cl
movq -0x10(%rbp), %rax
movb %cl, 0xe(%rax)
movb -0x21(%rbp), %cl
movq -0x10(%rbp), %rax
movb %cl, 0xf(%rax)
addq $0x30, %rsp
popq %rbp
retq
nop