// File: /workspace/github_cpp_makefile_star2_O1/lemire[P]validateutf8-experiments/benchmarks/hoehrmann.h
// Function: shiftless_validate_dfa_utf8_three(signed char const*, unsigned long)
static inline fastvalidate::error_code
shiftless_validate_dfa_utf8_three(const signed char *c, size_t len) {
  if (len < 32) { // if too small, do not bother
    return shiftless_validate_dfa_utf8(c, len);
  }
  size_t middle_point1 = len / 3;
  // backtrack until we find a leading byte
  while (!is_leading(c[middle_point1])) {
    if (middle_point1 == 0) {
      // we have determined that there is an error
      return fastvalidate::error_code::UTF8_ERROR;
    }
    middle_point1 -= 1;
  }
  size_t middle_point2 = 2 * len / 3;
  // backtrack until we find a leading byte
  while (!is_leading(c[middle_point2])) {
    if (middle_point2 == middle_point1) {
      // we have determined that there is an error
      return fastvalidate::error_code::UTF8_ERROR;
    }
    middle_point2 -= 1;
  }

  uint32_t state1 = 0;
  uint32_t state2 = 0;
  uint32_t state3 = 0;

  const unsigned char *cu1 = (const unsigned char *)c;
  const unsigned char *cu2 = (const unsigned char *)(c + middle_point1);
  const unsigned char *cu3 = (const unsigned char *)(c + middle_point2);
  size_t smallest_run = middle_point1;
  if (middle_point2 - middle_point1 < smallest_run) {
    smallest_run = middle_point2 - middle_point1;
  }
  if (len - middle_point2 < smallest_run) {
    smallest_run = len - middle_point2;
  }
  for (size_t i = 0; i < smallest_run; i++) {
    uint32_t byteval1 = (uint32_t)cu1[i];
    uint32_t byteval2 = (uint32_t)cu2[i];
    uint32_t byteval3 = (uint32_t)cu3[i];

    if ((shiftless_updatestate(&state1, byteval1) == SHIFTLESS_UTF8_REJECT) ||
        (shiftless_updatestate(&state2, byteval2) == SHIFTLESS_UTF8_REJECT) ||
        (shiftless_updatestate(&state3, byteval3) == SHIFTLESS_UTF8_REJECT)) {
      return fastvalidate::error_code::UTF8_ERROR;
    }
  }
  if (middle_point1 > smallest_run) {
    for (size_t i = smallest_run; i < middle_point1; i++) {
      uint32_t byteval1 = (uint32_t)cu1[i];
      if (shiftless_updatestate(&state1, byteval1) == SHIFTLESS_UTF8_REJECT) {
        return fastvalidate::error_code::UTF8_ERROR;
      }
    }
  }
  if (shiftless_updatestate(&state1, 0) == SHIFTLESS_UTF8_REJECT) {
    return fastvalidate::error_code::UTF8_ERROR;
  }

  if (middle_point2 - middle_point1 > smallest_run) {
    for (size_t i = smallest_run; i < middle_point2 - middle_point1; i++) {
      uint32_t byteval2 = (uint32_t)cu2[i];
      if (shiftless_updatestate(&state2, byteval2) == SHIFTLESS_UTF8_REJECT) {
        return fastvalidate::error_code::UTF8_ERROR;
      }
    }
  }
  if (shiftless_updatestate(&state2, 0) == SHIFTLESS_UTF8_REJECT) {
    return fastvalidate::error_code::UTF8_ERROR;
  }

  if (len - middle_point2 > smallest_run) {
    for (size_t i = smallest_run; i < len - middle_point2; i++) {
      uint32_t byteval3 = (uint32_t)cu3[i];
      if (shiftless_updatestate(&state3, byteval3) == SHIFTLESS_UTF8_REJECT) {
        return fastvalidate::error_code::UTF8_ERROR;
      }
    }
  }
  if (shiftless_updatestate(&state3, 0) == SHIFTLESS_UTF8_REJECT) {
    return fastvalidate::error_code::UTF8_ERROR;
  }
  return fastvalidate::error_code::SUCCESS;
}

// Assembly:
pushq %rbp
pushq %r15
pushq %r14
pushq %r13
pushq %r12
pushq %rbx
cmpq $0x1f, %rsi
ja 0x6350
testq %rsi, %rsi
je 0x6464
xorl %eax, %eax
leaq 0x1d32(%rip), %rdx      # 0x8050
leaq 0x1e2b(%rip), %r8       # 0x8150
xorl %ecx, %ecx
movzbl (%rdi,%rax), %r9d
movzbl (%r9,%rdx), %r9d
addq %rcx, %r9
movzbl (%r8,%r9), %ecx
cmpq $0x10, %rcx
je 0x654a
incq %rax
cmpq %rax, %rsi
jne 0x6327
jmp 0x6466
movabsq $-0x5555555555555555, %rcx # imm = 0xAAAAAAAAAAAAAAAB
movq %rsi, %rax
mulq %rcx
shrq %rdx
cmpb $-0x41, (%rdi,%rdx)
jle 0x636e
movq %rdx, %r11
jmp 0x6385
movq %rdx, %r11
subq $0x1, %r11
jb 0x654a
cmpb $-0x40, -0x1(%rdi,%rdx)
movq %r11, %rdx
jl 0x6371
leaq (%rsi,%rsi), %rax
mulq %rcx
shrq %rdx
cmpb $-0x41, (%rdi,%rdx)
jle 0x639a
movq %rdx, %r9
jmp 0x63b1
cmpq %rdx, %r11
je 0x654a
leaq -0x1(%rdx), %r9
cmpb $-0x40, -0x1(%rdi,%rdx)
movq %r9, %rdx
jl 0x639a
leaq (%rdi,%r11), %rbx
leaq (%rdi,%r9), %rcx
subq %r9, %rsi
subq %r11, %r9
cmpq %r11, %r9
movq %r11, %rdx
cmovbq %r9, %rdx
cmpq %rdx, %rsi
movq %rdx, -0x8(%rsp)
cmovbq %rsi, %rdx
testq %rdx, %rdx
je 0x647b
xorl %r15d, %r15d
leaq 0x1c68(%rip), %r12      # 0x8050
leaq 0x1d61(%rip), %r13      # 0x8150
xorl %r8d, %r8d
xorl %ebp, %ebp
xorl %r14d, %r14d
movzbl (%rdi,%r15), %eax
movzbl (%rax,%r12), %eax
movl %r14d, %r14d
addq %rax, %r14
movzbl (%r13,%r14), %r14d
movl $0x1, %eax
cmpl $0x10, %r14d
je 0x654f
movzbl (%rbx,%r15), %r10d
movzbl (%r10,%r12), %r10d
movl %ebp, %ebp
addq %r10, %rbp
movzbl (%r13,%rbp), %ebp
cmpl $0x10, %ebp
je 0x654f
movzbl (%rcx,%r15), %r10d
movzbl (%r10,%r12), %r10d
movl %r8d, %r8d
addq %r10, %r8
movzbl (%r13,%r8), %r8d
cmpl $0x10, %r8d
je 0x654f
incq %r15
cmpq %r15, %rdx
jne 0x63f7
jmp 0x6483
xorl %ecx, %ecx
leaq 0x1ce3(%rip), %rdx      # 0x8150
xorl %eax, %eax
cmpb $0x10, (%rcx,%rdx)
sete %al
jmp 0x654f
xorl %r14d, %r14d
xorl %ebp, %ebp
xorl %r8d, %r8d
cmpq %rdx, %r11
jbe 0x64c0
leaq 0x1bc1(%rip), %rax      # 0x8050
leaq 0x1cba(%rip), %r15      # 0x8150
movq %rdx, %r12
movzbl (%rdi,%r12), %r10d
movzbl (%r10,%rax), %r10d
movl %r14d, %r14d
addq %r10, %r14
movzbl (%r15,%r14), %r14d
cmpl $0x10, %r14d
je 0x654a
incq %r12
cmpq %r12, %r11
jne 0x6499
movl %r14d, %r10d
leaq 0x1c86(%rip), %rdi      # 0x8150
movl $0x1, %eax
cmpb $0x10, (%r10,%rdi)
je 0x654f
cmpq %rdx, %r9
jbe 0x6507
leaq 0x1b6e(%rip), %r11      # 0x8050
movq %rdx, %r14
movzbl (%rbx,%r14), %r10d
movzbl (%r10,%r11), %r10d
movl %ebp, %r15d
addq %r10, %r15
movzbl (%rdi,%r15), %ebp
cmpl $0x10, %ebp
je 0x654f
incq %r14
cmpq %r9, %r14
jb 0x64e5
movl %ebp, %r9d
cmpb $0x10, (%r9,%rdi)
je 0x654f
cmpq %rsi, -0x8(%rsp)
jae 0x6542
leaq 0x1b31(%rip), %r9       # 0x8050
movzbl (%rcx,%rdx), %r10d
movzbl (%r10,%r9), %r10d
movl %r8d, %r8d
addq %r10, %r8
movzbl (%rdi,%r8), %r8d
cmpl $0x10, %r8d
je 0x654f
incq %rdx
cmpq %rsi, %rdx
jb 0x651f
movl %r8d, %ecx
jmp 0x6466
movl $0x1, %eax
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq