// File: /workspace/github_cpp_makefile_star2_O3/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 0x6243
testq %rsi, %rsi
je 0x6357
xorl %eax, %eax
leaq 0x1e3f(%rip), %rdx      # 0x8050
leaq 0x1f38(%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 0x643d
incq %rax
cmpq %rax, %rsi
jne 0x621a
jmp 0x6359
movabsq $-0x5555555555555555, %rcx # imm = 0xAAAAAAAAAAAAAAAB
movq %rsi, %rax
mulq %rcx
shrq %rdx
cmpb $-0x41, (%rdi,%rdx)
jle 0x6261
movq %rdx, %r11
jmp 0x6278
movq %rdx, %r11
subq $0x1, %r11
jb 0x643d
cmpb $-0x40, -0x1(%rdi,%rdx)
movq %r11, %rdx
jl 0x6264
leaq (%rsi,%rsi), %rax
mulq %rcx
shrq %rdx
cmpb $-0x41, (%rdi,%rdx)
jle 0x628d
movq %rdx, %r9
jmp 0x62a4
cmpq %rdx, %r11
je 0x643d
leaq -0x1(%rdx), %r9
cmpb $-0x40, -0x1(%rdi,%rdx)
movq %r9, %rdx
jl 0x628d
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 0x636e
xorl %r15d, %r15d
leaq 0x1d75(%rip), %r12      # 0x8050
leaq 0x1e6e(%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 0x6442
movzbl (%rbx,%r15), %r10d
movzbl (%r10,%r12), %r10d
movl %ebp, %ebp
addq %r10, %rbp
movzbl (%r13,%rbp), %ebp
cmpl $0x10, %ebp
je 0x6442
movzbl (%rcx,%r15), %r10d
movzbl (%r10,%r12), %r10d
movl %r8d, %r8d
addq %r10, %r8
movzbl (%r13,%r8), %r8d
cmpl $0x10, %r8d
je 0x6442
incq %r15
cmpq %r15, %rdx
jne 0x62ea
jmp 0x6376
xorl %ecx, %ecx
leaq 0x1df0(%rip), %rdx      # 0x8150
xorl %eax, %eax
cmpb $0x10, (%rcx,%rdx)
sete %al
jmp 0x6442
xorl %r14d, %r14d
xorl %ebp, %ebp
xorl %r8d, %r8d
cmpq %rdx, %r11
jbe 0x63b3
leaq 0x1cce(%rip), %rax      # 0x8050
leaq 0x1dc7(%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 0x643d
incq %r12
cmpq %r12, %r11
jne 0x638c
movl %r14d, %r10d
leaq 0x1d93(%rip), %rdi      # 0x8150
movl $0x1, %eax
cmpb $0x10, (%r10,%rdi)
je 0x6442
cmpq %rdx, %r9
jbe 0x63fa
leaq 0x1c7b(%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 0x6442
incq %r14
cmpq %r9, %r14
jb 0x63d8
movl %ebp, %r9d
cmpb $0x10, (%r9,%rdi)
je 0x6442
cmpq %rsi, -0x8(%rsp)
jae 0x6435
leaq 0x1c3e(%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 0x6442
incq %rdx
cmpq %rsi, %rdx
jb 0x6412
movl %r8d, %ecx
jmp 0x6359
movl $0x1, %eax
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq