user: Converte this assembly snippet into its equivalent C code:

```asm
<fast_validate>:
  endbr64
  mov    %rdi,%rcx
  movzbl (%rdi),%eax
  test   %al,%al
  je     L90
  mov    $0x10000,%edi
  mov    $0x800,%r8d
  jmp    L57
L38:
  test   $0x1e,%al
  je     L90
  movzbl 0x1(%rcx),%eax
  and    $0xffffffc0,%eax
  cmp    $0x80,%al
  je     L71
L90:
  mov    %rcx,%rax
  ret
L71:
  lea    0x1(%rcx),%rdx
L60:
  lea    0x1(%rdx),%rcx
  movzbl 0x1(%rdx),%eax
  test   %al,%al
  je     L90
L57:
  mov    %rcx,%rdx
  test   %al,%al
  jns    L60
  mov    %eax,%edx
  mov    %eax,%esi
  and    $0xffffffe0,%esi
  cmp    $0xc0,%sil
  je     L38
  and    $0xfffffff0,%eax
  cmp    $0xe0,%al
  je     L86
  mov    %edx,%eax
  and    $0xfffffff8,%eax
  cmp    $0xf0,%al
  jne    L90
  mov    %edx,%esi
  and    $0x7,%esi
  lea    0x1(%rcx),%rdx
  movzbl 0x1(%rcx),%eax
  mov    %eax,%r9d
  and    $0xffffffc0,%r9d
  cmp    $0x80,%r9b
  jne    L90
  shl    $0x6,%esi
  and    $0x3f,%eax
  or     %eax,%esi
  mov    %edi,%r10d
L162:
  movzbl 0x1(%rdx),%eax
  mov    %eax,%r9d
  and    $0xffffffc0,%r9d
  cmp    $0x80,%r9b
  jne    L90
  shl    $0x6,%esi
  and    $0x3f,%eax
  or     %eax,%esi
  movzbl 0x2(%rdx),%eax
  mov    %eax,%r9d
  and    $0xffffffc0,%r9d
  cmp    $0x80,%r9b
  jne    L90
  shl    $0x6,%esi
  and    $0x3f,%eax
  or     %esi,%eax
  cmp    $0x10ffff,%eax
  ja     L90
  cmp    %eax,%r10d
  ja     L90
  mov    %eax,%esi
  and    $0xfffff800,%esi
  cmp    $0xd800,%esi
  je     L90
  lea    -0xfdd0(%rax),%esi
  cmp    $0x1f,%esi
  jbe    L90
  and    $0xfffe,%eax
  cmp    $0xfffe,%eax
  je     L90
  add    $0x2,%rdx
  jmp    L60
L86:
  mov    %edx,%esi
  and    $0xf,%esi
  mov    %rcx,%rdx
  mov    %r8d,%r10d
  jmp    L162
```

assistant: ```c
const char *fast_validate(const char *str) {
  unsigned int val = 0;
  unsigned int min = 0;
  const char *p;
  for (p = str; *p; p++) {
    if (*(unsigned char *)p < 128)
      ;
    else {
      const char *last;
      last = p;
      if ((*(unsigned char *)p & 0xe0) == 0xc0) {
        if ((*(unsigned char *)p & 0x1e) == 0)
          goto error;
        p++;
        if ((*(unsigned char *)p & 0xc0) != 0x80)
          goto error;
      } else {
        if ((*(unsigned char *)p & 0xf0) == 0xe0) {
          min = (1 << 11);
          val = *(unsigned char *)p & 0x0f;
          goto TWO_REMAINING;
        } else if ((*(unsigned char *)p & 0xf8) == 0xf0) {
          min = (1 << 16);
          val = *(unsigned char *)p & 0x07;
        } else
          goto error;
        p++;
        do {
          if ((*(unsigned char *)p & 0xc0) != 0x80)
            goto error;
          val <<= 6;
          val |= (*(unsigned char *)p) & 0x3f;
        } while (0);
      TWO_REMAINING:
        p++;
        do {
          if ((*(unsigned char *)p & 0xc0) != 0x80)
            goto error;
          val <<= 6;
          val |= (*(unsigned char *)p) & 0x3f;
        } while (0);
        p++;
        do {
          if ((*(unsigned char *)p & 0xc0) != 0x80)
            goto error;
          val <<= 6;
          val |= (*(unsigned char *)p) & 0x3f;
        } while (0);
        if (val < min)
          goto error;
        if (!((val) < 0x110000 && (((val)&0xFFFFF800) != 0xD800) && ((val) < 0xFDD0 || (val) > 0xFDEF) && ((val)&0xFFFE) != 0xFFFE))
          goto error;
      }
      continue;
    error:
      return last;
    }
  }
  return p;
}
```