user: 请将这段汇编代码片段转换成等效的C代码：

```asm
<utf_last_valid2>:
  endbr64
  mov    %rdi,%rdx
  movslq %esi,%r8
  add    %rdi,%r8
  cmp    %r8,%rdi
  jae    L112
  mov    %rdi,%r9
  mov    $0x0,%eax
  lea    D1(%rip),%rdi
  jmp    L133
  test   %sil,%sil
  js     L11
  mov    %rdx,%r9
  jmp    L102
L11:
  mov    $0x8,%eax
  cmp    $0xc1,%sil
  jbe    L102
  mov    $0x1,%eax
  cmp    $0xdf,%sil
  jbe    L102
  mov    $0x2,%eax
  cmp    $0xe0,%sil
  je     L102
  mov    $0x3,%eax
  cmp    $0xec,%sil
  jbe    L102
  mov    $0x4,%eax
  cmp    $0xed,%sil
  je     L102
  mov    $0x3,%eax
  cmp    $0xef,%sil
  jbe    L102
  mov    $0x5,%eax
  cmp    $0xf0,%sil
  je     L102
  mov    $0x6,%eax
  cmp    $0xf3,%sil
  jbe    L102
  cmp    $0xf4,%sil
  seta   %al
  movzbl %al,%eax
  add    $0x7,%eax
  jmp    L102
  add    $0xffffff80,%esi
  cmp    $0x3f,%sil
  cmovbe %rdx,%r9
  cmp    $0x40,%sil
  sbb    %eax,%eax
  not    %eax
  and    $0x8,%eax
L102:
  cmp    %rdx,%r8
  je     L97
L133:
  add    $0x1,%rdx
  movzbl -0x1(%rdx),%esi
  cmp    $0x7,%eax
  ja     L97
  mov    %eax,%ecx
  movslq (%rdi,%rcx,4),%rcx
  add    %rdi,%rcx
  notrack jmp *%rcx
  add    $0x60,%esi
  cmp    $0x20,%sil
  sbb    %eax,%eax
  and    $0xfffffff9,%eax
  add    $0x8,%eax
  jmp    L102
  add    $0xffffff80,%esi
  cmp    $0x40,%sil
  sbb    %eax,%eax
  and    $0xfffffff9,%eax
  add    $0x8,%eax
  jmp    L102
  add    $0xffffff80,%esi
  cmp    $0x20,%sil
  sbb    %eax,%eax
  and    $0xfffffff9,%eax
  add    $0x8,%eax
  jmp    L102
  add    $0x70,%esi
  cmp    $0x30,%sil
  sbb    %eax,%eax
  and    $0xfffffffb,%eax
  add    $0x8,%eax
  jmp    L102
  add    $0xffffff80,%esi
  cmp    $0x40,%sil
  sbb    %eax,%eax
  and    $0xfffffffb,%eax
  add    $0x8,%eax
  jmp    L102
  add    $0xffffff80,%esi
  cmp    $0x10,%sil
  sbb    %eax,%eax
  and    $0xfffffffb,%eax
  add    $0x8,%eax
  jmp    L102
L112:
  mov    %rdi,%r9
L97:
  mov    %r9,%rax
  ret
```

assistant: ```c
const char *utf_last_valid2(const char *data, int len) {
  const char *start = data, *end = data + len;
  int state = 0;
  while (data < end) {
    unsigned char octet = *data++;
    switch (state) {
    case 0:
      if (octet <= 0x7F)
        break;
      else if (octet <= 0xC1)
        state = 8;
      else if (octet <= 0xDF)
        state = 1;
      else if (octet == 0xE0)
        state = 2;
      else if (octet <= 0xEC)
        state = 3;
      else if (octet == 0xED)
        state = 4;
      else if (octet <= 0xEF)
        state = 3;
      else if (octet == 0xF0)
        state = 5;
      else if (octet <= 0xF3)
        state = 6;
      else if (octet <= 0xF4)
        state = 7;
      else
        state = 8;
      break;
    case 1:
      if (octet >= 0x80 && octet <= 0xBF)
        state = 0;
      else
        state = 8;
      break;
    case 2:
      if (octet >= 0xA0 && octet <= 0xBF)
        state = 1;
      else
        state = 8;
      break;
    case 3:
      if (octet >= 0x80 && octet <= 0xBF)
        state = 1;
      else
        state = 8;
      break;
    case 4:
      if (octet >= 0x80 && octet <= 0x9F)
        state = 1;
      else
        state = 8;
      break;
    case 5:
      if (octet >= 0x90 && octet <= 0xBF)
        state = 3;
      else
        state = 8;
      break;
    case 6:
      if (octet >= 0x80 && octet <= 0xBF)
        state = 3;
      else
        state = 8;
      break;
    case 7:
      if (octet >= 0x80 && octet <= 0x8F)
        state = 3;
      else
        state = 8;
      break;
    default:
    case 8:
      return start;
    }
    if (state == 0)
      start = data;
  }
  return start;
}
```