user: Please show me the C implementation that matches the assembly code listed below:

```asm
<setup_aeskey>:
  endbr64
  push   %rbp
  mov    %rsp,%rbp
  sub    $0x50,%rsp
  mov    %edi,-0x44(%rbp)
  mov    %esi,-0x48(%rbp)
  mov    %rdx,-0x50(%rbp)
  mov    %fs:0x28,%rax
  mov    %rax,-0x8(%rbp)
  xor    %eax,%eax
  cmpq   $0x0,-0x50(%rbp)
  je     L19
  movq   $0x19009060,-0x30(%rbp)
  movq   $0x10009090,-0x28(%rbp)
  movq   $0x100090c0,-0x20(%rbp)
  movq   $0x100090f0,-0x18(%rbp)
  mov    -0x50(%rbp),%rax
  mov    %rax,-0x40(%rbp)
  mov    $0x10009000,%eax
  mov    (%rax),%eax
  and    $0xfd7fffff,%eax
  mov    %eax,%ecx
  mov    -0x48(%rbp),%eax
  shl    $0x17,%eax
  mov    $0x10009000,%edx
  or     %ecx,%eax
  mov    %eax,(%rdx)
  cmpl   $0x3,-0x44(%rbp)
  jle    L60
  cmpl   $0x3f,-0x44(%rbp)
  jg     L69
  mov    $0x10009011,%eax
  mov    (%rax),%eax
  and    $0xffffffc0,%eax
  or     -0x44(%rbp),%eax
  mov    $0x10009011,%edx
  or     $0x80,%al
  mov    %eax,(%rdx)
  mov    $0x10009108,%edx
  mov    -0x40(%rbp),%rax
  mov    (%rax),%eax
  mov    %eax,(%rdx)
  mov    $0x10009108,%edx
  mov    -0x40(%rbp),%rax
  mov    0x4(%rax),%eax
  mov    %eax,(%rdx)
  mov    $0x10009108,%edx
  mov    -0x40(%rbp),%rax
  mov    0x8(%rax),%eax
  mov    %eax,(%rdx)
  mov    $0x10009108,%edx
  mov    -0x40(%rbp),%rax
  mov    0xc(%rax),%eax
  mov    %eax,(%rdx)
  jmp    L13
L60:
  mov    -0x44(%rbp),%eax
  cltq
  mov    -0x30(%rbp,%rax,8),%rax
  mov    %rax,-0x38(%rbp)
  mov    -0x48(%rbp),%eax
  and    $0x4,%eax
  test   %eax,%eax
  je     L77
  mov    -0x40(%rbp),%rax
  mov    0xc(%rax),%edx
  mov    -0x38(%rbp),%rax
  mov    %edx,(%rax)
  mov    -0x38(%rbp),%rax
  lea    0x4(%rax),%rdx
  mov    -0x40(%rbp),%rax
  mov    0x8(%rax),%eax
  mov    %eax,(%rdx)
  mov    -0x38(%rbp),%rax
  lea    0x8(%rax),%rdx
  mov    -0x40(%rbp),%rax
  mov    0x4(%rax),%eax
  mov    %eax,(%rdx)
  mov    -0x38(%rbp),%rax
  lea    0xc(%rax),%rdx
  mov    -0x40(%rbp),%rax
  mov    (%rax),%eax
  mov    %eax,(%rdx)
  jmp    L13
L77:
  mov    -0x40(%rbp),%rax
  mov    (%rax),%edx
  mov    -0x38(%rbp),%rax
  mov    %edx,(%rax)
  mov    -0x38(%rbp),%rax
  lea    0x4(%rax),%rdx
  mov    -0x40(%rbp),%rax
  mov    0x4(%rax),%eax
  mov    %eax,(%rdx)
  mov    -0x38(%rbp),%rax
  lea    0x8(%rax),%rdx
  mov    -0x40(%rbp),%rax
  mov    0x8(%rax),%eax
  mov    %eax,(%rdx)
  mov    -0x38(%rbp),%rax
  lea    0xc(%rax),%rdx
  mov    -0x40(%rbp),%rax
  mov    0xc(%rax),%eax
  mov    %eax,(%rdx)
  jmp    L13
L19:
  nop
  jmp    L13
L69:
  nop
L13:
  mov    -0x8(%rbp),%rax
  sub    %fs:0x28,%rax
  je     L85
  call   <__stack_chk_fail@plt>
L85:
  leave
  ret
```

assistant: ```c
void setup_aeskey(uint_fast8_t keyno, int value, void *key) {
  if (!key)
    return;
  volatile uint32_t *aes_regs[] = {(volatile uint32_t *)0x19009060, (volatile uint32_t *)0x10009090, (volatile uint32_t *)0x100090C0, (volatile uint32_t *)0x100090F0};
  uint32_t *_key = (uint32_t *)key;
  *((volatile uint32_t *)0x10009000) = (*((volatile uint32_t *)0x10009000) & ~(0x00800000 | 0x02000000)) | (value << 23);
  if (keyno > 3) {
    if (keyno > 0x3F)
      return;
    *((volatile uint8_t *)0x10009011) = (*((volatile uint8_t *)0x10009011) >> 6 << 6) | (uint8_t)keyno | 0x80;
    *((volatile uint32_t *)0x10009108) = _key[0];
    *((volatile uint32_t *)0x10009108) = _key[1];
    *((volatile uint32_t *)0x10009108) = _key[2];
    *((volatile uint32_t *)0x10009108) = _key[3];
  } else {
    volatile uint32_t *aes_reg = aes_regs[keyno];
    if (value & 0x4) {
      aes_reg[0] = _key[3];
      aes_reg[1] = _key[2];
      aes_reg[2] = _key[1];
      aes_reg[3] = _key[0];
    } else {
      aes_reg[0] = _key[0];
      aes_reg[1] = _key[1];
      aes_reg[2] = _key[2];
      aes_reg[3] = _key[3];
    }
  }
}
```