user: What would the C source look like for the assembly code provided here:

```asm
<utf8decode>:
  endbr64
  push   %rbp
  mov    %rsp,%rbp
  mov    %rdi,-0x18(%rbp)
  mov    %rsi,-0x20(%rbp)
  mov    %rdx,-0x28(%rbp)
  mov    -0x18(%rbp),%rax
  movzbl (%rax),%eax
  mov    %al,-0x1(%rbp)
  movzbl -0x1(%rbp),%eax
  test   %al,%al
  js     L178
  mov    -0x28(%rbp),%rax
  movl   $0x1,(%rax)
  movzbl -0x1(%rbp),%eax
  jmp    L108
L178:
  cmpb   $0xc1,-0x1(%rbp)
  jbe    L278
  mov    -0x18(%rbp),%rax
  add    $0x1,%rax
  cmp    %rax,-0x20(%rbp)
  jbe    L48
  mov    -0x18(%rbp),%rax
  add    $0x1,%rax
  movzbl (%rax),%eax
  movsbl %al,%eax
  and    $0xc0,%eax
  cmp    $0x80,%eax
  jne    L48
  cmpb   $0xdf,-0x1(%rbp)
  ja     L74
  mov    -0x28(%rbp),%rax
  movl   $0x2,(%rax)
  mov    -0x18(%rbp),%rax
  movzbl (%rax),%eax
  movsbl %al,%eax
  shl    $0x6,%eax
  and    $0x7c0,%eax
  mov    %eax,%edx
  mov    -0x18(%rbp),%rax
  add    $0x1,%rax
  movzbl (%rax),%eax
  movsbl %al,%eax
  and    $0x3f,%eax
  or     %edx,%eax
  jmp    L108
L74:
  cmpb   $0xe0,-0x1(%rbp)
  jne    L173
  mov    -0x18(%rbp),%rax
  add    $0x1,%rax
  movzbl (%rax),%eax
  cmp    $0x9f,%al
  ja     L91
  jmp    L187
L173:
  cmpb   $0xef,-0x1(%rbp)
  ja     L174
  jmp    L20
L91:
  nop
L20:
  mov    -0x18(%rbp),%rax
  add    $0x2,%rax
  cmp    %rax,-0x20(%rbp)
  jbe    L232
  mov    -0x18(%rbp),%rax
  add    $0x2,%rax
  movzbl (%rax),%eax
  movsbl %al,%eax
  and    $0xc0,%eax
  cmp    $0x80,%eax
  jne    L232
  mov    -0x28(%rbp),%rax
  movl   $0x3,(%rax)
  mov    -0x18(%rbp),%rax
  movzbl (%rax),%eax
  movsbl %al,%eax
  shl    $0xc,%eax
  movzwl %ax,%edx
  mov    -0x18(%rbp),%rax
  add    $0x1,%rax
  movzbl (%rax),%eax
  movsbl %al,%eax
  shl    $0x6,%eax
  and    $0xfc0,%eax
  add    %eax,%edx
  mov    -0x18(%rbp),%rax
  add    $0x2,%rax
  movzbl (%rax),%eax
  movsbl %al,%eax
  and    $0x3f,%eax
  add    %edx,%eax
  jmp    L108
L174:
  cmpb   $0xf0,-0x1(%rbp)
  jne    L180
  mov    -0x18(%rbp),%rax
  add    $0x1,%rax
  movzbl (%rax),%eax
  cmp    $0x8f,%al
  ja     L193
  jmp    L187
L180:
  cmpb   $0xf3,-0x1(%rbp)
  ja     L13
  jmp    L136
L193:
  nop
  jmp    L136
L208:
  nop
L136:
  mov    -0x18(%rbp),%rax
  add    $0x3,%rax
  cmp    %rax,-0x20(%rbp)
  jbe    L8
  mov    -0x18(%rbp),%rax
  add    $0x2,%rax
  movzbl (%rax),%eax
  movsbl %al,%eax
  and    $0xc0,%eax
  cmp    $0x80,%eax
  jne    L8
  mov    -0x18(%rbp),%rax
  add    $0x3,%rax
  movzbl (%rax),%eax
  movsbl %al,%eax
  and    $0xc0,%eax
  cmp    $0x80,%eax
  jne    L8
  mov    -0x28(%rbp),%rax
  movl   $0x4,(%rax)
  mov    -0x18(%rbp),%rax
  movzbl (%rax),%eax
  movsbl %al,%eax
  shl    $0x12,%eax
  and    $0x1c0000,%eax
  mov    %eax,%edx
  mov    -0x18(%rbp),%rax
  add    $0x1,%rax
  movzbl (%rax),%eax
  movsbl %al,%eax
  shl    $0xc,%eax
  and    $0x3f000,%eax
  or     %eax,%edx
  mov    -0x18(%rbp),%rax
  add    $0x2,%rax
  movzbl (%rax),%eax
  movsbl %al,%eax
  shl    $0x6,%eax
  and    $0xfc0,%eax
  add    %eax,%edx
  mov    -0x18(%rbp),%rax
  add    $0x3,%rax
  movzbl (%rax),%eax
  movsbl %al,%eax
  and    $0x3f,%eax
  add    %edx,%eax
  jmp    L108
L13:
  cmpb   $0xf4,-0x1(%rbp)
  jne    L210
  mov    -0x18(%rbp),%rax
  add    $0x1,%rax
  movzbl (%rax),%eax
  cmp    $0x8f,%al
  jbe    L208
  jmp    L187
L278:
  nop
  jmp    L187
L48:
  nop
  jmp    L187
L232:
  nop
  jmp    L187
L8:
  nop
  jmp    L187
L210:
  nop
L187:
  mov    -0x28(%rbp),%rax
  movl   $0x1,(%rax)
  mov    $0xfffd,%eax
L108:
  pop    %rbp
  ret
```

assistant: ```c
unsigned utf8decode(const char *p, const char *end, int *len) {
  unsigned char c = *(unsigned char *)p;
  if (c < 0x80) {
    *len = 1;
    return c;
  } else if (c < 0xc2) {
    goto FAIL;
  }
  if (p + 1 >= end || (p[1] & 0xc0) != 0x80)
    goto FAIL;
  if (c < 0xe0) {
    *len = 2;
    return ((p[0] & 0x1f) << 6) + ((p[1] & 0x3f));
  } else if (c == 0xe0) {
    if (((unsigned char *)p)[1] < 0xa0)
      goto FAIL;
    goto UTF8_3;
  } else if (c < 0xf0) {
  UTF8_3:
    if (p + 2 >= end || (p[2] & 0xc0) != 0x80)
      goto FAIL;
    *len = 3;
    return ((p[0] & 0x0f) << 12) + ((p[1] & 0x3f) << 6) + ((p[2] & 0x3f));
  } else if (c == 0xf0) {
    if (((unsigned char *)p)[1] < 0x90)
      goto FAIL;
    goto UTF8_4;
  } else if (c < 0xf4) {
  UTF8_4:
    if (p + 3 >= end || (p[2] & 0xc0) != 0x80 || (p[3] & 0xc0) != 0x80)
      goto FAIL;
    *len = 4;
    return ((p[0] & 0x07) << 18) + ((p[1] & 0x3f) << 12) + ((p[2] & 0x3f) << 6) + ((p[3] & 0x3f));
  } else if (c == 0xf4) {
    if (((unsigned char *)p)[1] > 0x8f)
      goto FAIL;
    goto UTF8_4;
  } else {
  FAIL:
    *len = 1;
    return 0xfffd;
  }
}
```