user: Translate the below assembly code into C programming language:

```asm
<rcc_clock_init>:
  endbr64
  mov    0x40021000,%rax
  or     $0x1,%rax
  mov    %rax,0x40021000
  mov    0x40021004,%rax
  and    $0xf8ff0000,%eax
  mov    %rax,0x40021004
  mov    0x40021000,%rax
  and    $0xfef6ffff,%eax
  mov    %rax,0x40021000
  mov    0x40021000,%rax
  and    $0xfffbffff,%eax
  mov    %rax,0x40021000
  mov    0x40021004,%rax
  and    $0xff80ffff,%eax
  mov    %rax,0x40021004
  movq   $0x9f0000,0x40021008
  movq   $0x0,-0x10(%rsp)
  movq   $0x0,-0x8(%rsp)
  mov    0x40021000,%rax
  or     $0x10000,%rax
  mov    %rax,0x40021000
  jmp    L61
  nopw   0x0(%rax,%rax,1)
L34:
  mov    -0x10(%rsp),%rax
  cmp    $0x500,%rax
  je     L16
L61:
  mov    0x40021000,%rax
  and    $0x20000,%eax
  mov    %rax,-0x8(%rsp)
  mov    -0x10(%rsp),%rax
  add    $0x1,%rax
  mov    %rax,-0x10(%rsp)
  mov    -0x8(%rsp),%rax
  test   %rax,%rax
  je     L34
L16:
  mov    0x40021000,%rax
  test   $0x20000,%eax
  je     L25
  movq   $0x1,-0x8(%rsp)
  mov    -0x8(%rsp),%rax
  cmp    $0x1,%rax
  je     L42
L29:
  ret
  nopl   0x0(%rax,%rax,1)
L25:
  movq   $0x0,-0x8(%rsp)
  mov    -0x8(%rsp),%rax
  cmp    $0x1,%rax
  jne    L29
L42:
  mov    0x40022000,%rax
  or     $0x10,%rax
  mov    %rax,0x40022000
  mov    0x40022000,%rax
  and    $0xfffffffffffffffc,%rax
  mov    %rax,0x40022000
  mov    0x40022000,%rax
  mov    %rax,0x40022000
  mov    0x40021004,%rax
  mov    %rax,0x40021004
  mov    0x40021004,%rax
  mov    %rax,0x40021004
  mov    0x40021004,%rax
  mov    %rax,0x40021004
  mov    0x40021004,%rax
  and    $0xfffffffffffffffc,%rax
  mov    %rax,0x40021004
  mov    0x40021004,%rax
  or     $0x1,%rax
  mov    %rax,0x40021004
  nopl   0x0(%rax)
L45:
  mov    0x40021004,%rax
  and    $0xc,%eax
  cmp    $0x4,%rax
  jne    L45
  ret
```

assistant: ```c
void rcc_clock_init(void) {
  *((volatile uint32_t *)(((volatile uint32_t)0x40021000) + 0x00)) |= (uint32_t)0x00000001;
  *((volatile uint32_t *)(((volatile uint32_t)0x40021000) + 0x04)) &= (uint32_t)0xF8FF0000;
  *((volatile uint32_t *)(((volatile uint32_t)0x40021000) + 0x00)) &= (uint32_t)0xFEF6FFFF;
  *((volatile uint32_t *)(((volatile uint32_t)0x40021000) + 0x00)) &= (uint32_t)0xFFFBFFFF;
  *((volatile uint32_t *)(((volatile uint32_t)0x40021000) + 0x04)) &= (uint32_t)0xFF80FFFF;
  *((volatile uint32_t *)(((volatile uint32_t)0x40021000) + 0x08)) = 0x009F0000;
  volatile uint32_t StartUpCounter = 0, HSEStatus = 0;
  *((volatile uint32_t *)(((volatile uint32_t)0x40021000) + 0x00)) |= ((uint32_t)((uint32_t)0x00010000));
  do {
    HSEStatus = *((volatile uint32_t *)(((volatile uint32_t)0x40021000) + 0x00)) & ((uint32_t)0x00020000);
    StartUpCounter++;
  } while ((HSEStatus == 0) && (StartUpCounter != ((uint16_t)0x0500)));
  if ((*((volatile uint32_t *)(((volatile uint32_t)0x40021000) + 0x00)) & ((uint32_t)0x00020000)) != 0)
    HSEStatus = (uint32_t)0x01;
  else
    HSEStatus = (uint32_t)0x00;
  if (HSEStatus == (uint32_t)0x01) {
    *((volatile uint32_t *)(((volatile uint32_t)0x40022000) + 0x00)) |= ((uint8_t)0x10);
    *((volatile uint32_t *)(((volatile uint32_t)0x40022000) + 0x00)) &= (uint32_t)((uint32_t) ~((uint8_t)0x03));
    *((volatile uint32_t *)(((volatile uint32_t)0x40022000) + 0x00)) |= (uint32_t)((uint8_t)0x00);
    *((volatile uint32_t *)(((volatile uint32_t)0x40021000) + 0x04)) |= (uint32_t)((uint32_t)0x00000000);
    *((volatile uint32_t *)(((volatile uint32_t)0x40021000) + 0x04)) |= (uint32_t)((uint32_t)0x00000000);
    *((volatile uint32_t *)(((volatile uint32_t)0x40021000) + 0x04)) |= (uint32_t)((uint32_t)0x00000000);
    *((volatile uint32_t *)(((volatile uint32_t)0x40021000) + 0x04)) &= (uint32_t)((uint32_t) ~(((uint32_t)0x00000003)));
    *((volatile uint32_t *)(((volatile uint32_t)0x40021000) + 0x04)) |= (uint32_t)((uint32_t)0x00000001);
    while ((*((volatile uint32_t *)(((volatile uint32_t)0x40021000) + 0x04)) & (uint32_t)((uint32_t)0x0000000C)) != (uint32_t)0x04)
      ;
  } else {
  }
}
```