// File: /workspace/github_cpp_makefile_star2_O3/lemire[P]validateutf8-experiments/benchmarks/hoehrmann.h
// Function: shiftless_validate_dfa_utf8_quad(signed char const*, unsigned long)
static inline fastvalidate::error_code
shiftless_validate_dfa_utf8_quad(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 / 4;
  // 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 = len / 2;
  // 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;
  }
  size_t middle_point3 = len / 2;
  // backtrack until we find a leading byte
  while (!is_leading(c[middle_point3])) {
    if (middle_point3 == middle_point2) {
      // we have determined that there is an error
      return fastvalidate::error_code::UTF8_ERROR;
    }
    middle_point3 -= 1;
  }
  uint32_t state1 = 0;
  uint32_t state2 = 0;
  uint32_t state3 = 0;
  uint32_t state4 = 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);
  const unsigned char *cu4 = (const unsigned char *)(c + middle_point3);

  size_t smallest_run = middle_point1;
  if (middle_point2 - middle_point1 < smallest_run) {
    smallest_run = middle_point2 - middle_point1;
  }
  if (middle_point3 - middle_point2 < smallest_run) {
    smallest_run = middle_point3 - middle_point2;
  }
  if (len - middle_point3 < smallest_run) {
    smallest_run = len - middle_point3;
  }
  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];
    uint32_t byteval4 = (uint32_t)cu4[i];

    if ((shiftless_updatestate(&state1, byteval1) == SHIFTLESS_UTF8_REJECT) ||
        (shiftless_updatestate(&state2, byteval2) == SHIFTLESS_UTF8_REJECT) ||
        (shiftless_updatestate(&state3, byteval3) == SHIFTLESS_UTF8_REJECT) ||
        (shiftless_updatestate(&state4, byteval4) == SHIFTLESS_UTF8_REJECT)) {
      return fastvalidate::error_code::UTF8_ERROR;
    }
  }
  if (middle_point1 > smallest_run) {
    for (size_t i = smallest_run; i < middle_point1 - smallest_run; 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 (middle_point3 - middle_point2 > smallest_run) {
    for (size_t i = smallest_run; i < middle_point3 - 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;
  }

  if (len - middle_point3 > smallest_run) {
    for (size_t i = smallest_run; i < len - middle_point3; i++) {
      uint32_t byteval4 = (uint32_t)cu4[i];
      if (shiftless_updatestate(&state4, byteval4) == SHIFTLESS_UTF8_REJECT) {
        return fastvalidate::error_code::UTF8_ERROR;
      }
    }
  }
  if (shiftless_updatestate(&state4, 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 0x64a1
testq %rsi, %rsi
je 0x65e1
xorl %eax, %eax
leaq 0x1be1(%rip), %rdx      # 0x8050
leaq 0x1cda(%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 0x6783
incq %rax
cmpq %rax, %rsi
jne 0x6478
jmp 0x65e3
movq %rsi, %rax
shrq $0x2, %rax
cmpb $-0x41, (%rdi,%rax)
jle 0x64b3
movq %rax, %rbx
jmp 0x64ca
movq %rax, %rbx
subq $0x1, %rbx
jb 0x6783
cmpb $-0x40, -0x1(%rdi,%rax)
movq %rbx, %rax
jl 0x64b6
movq %rsi, %rcx
shrq %rcx
movb (%rdi,%rcx), %r8b
cmpb $-0x41, %r8b
jle 0x65f8
movq %rcx, %r14
leaq (%rdi,%rbx), %rax
movq %rax, -0x10(%rsp)
leaq (%rdi,%r14), %rax
movq %rax, -0x18(%rsp)
leaq (%rdi,%rcx), %rax
movq %rax, -0x20(%rsp)
subq %rcx, %rsi
subq %r14, %rcx
subq %rbx, %r14
cmpq %rbx, %r14
movq %rbx, %r8
cmovbq %r14, %r8
cmpq %r8, %rcx
cmovbq %rcx, %r8
cmpq %r8, %rsi
movq %r8, -0x8(%rsp)
cmovbq %rsi, %r8
testq %r8, %r8
je 0x6655
xorl %edx, %edx
leaq 0x1b1c(%rip), %r11      # 0x8050
leaq 0x1c15(%rip), %r15      # 0x8150
xorl %r9d, %r9d
xorl %ebp, %ebp
xorl %r12d, %r12d
xorl %r13d, %r13d
movzbl (%rdi,%rdx), %eax
movzbl (%rax,%r11), %eax
movl %r13d, %r13d
addq %rax, %r13
movzbl (%r15,%r13), %r13d
movl $0x1, %eax
cmpl $0x10, %r13d
je 0x6788
movq -0x10(%rsp), %r10
movzbl (%r10,%rdx), %r10d
movzbl (%r10,%r11), %r10d
movl %r12d, %r12d
addq %r10, %r12
movzbl (%r15,%r12), %r12d
cmpl $0x10, %r12d
je 0x6788
movq -0x18(%rsp), %r10
movzbl (%r10,%rdx), %r10d
movzbl (%r10,%r11), %r10d
movl %ebp, %ebp
addq %r10, %rbp
movzbl (%r15,%rbp), %ebp
cmpl $0x10, %ebp
je 0x6788
movq -0x20(%rsp), %r10
movzbl (%r10,%rdx), %r10d
movzbl (%r10,%r11), %r10d
movl %r9d, %r9d
addq %r10, %r9
movzbl (%r15,%r9), %r9d
cmpl $0x10, %r9d
je 0x6788
incq %rdx
cmpq %rdx, %r8
jne 0x6546
jmp 0x6660
xorl %ecx, %ecx
leaq 0x1b66(%rip), %rdx      # 0x8150
xorl %eax, %eax
cmpb $0x10, (%rcx,%rdx)
sete %al
jmp 0x6788
movq %rcx, %r9
subq %rbx, %r9
leaq -0x1(%rdi), %r10
xorl %edx, %edx
movl $0x1, %eax
cmpq %rdx, %r9
je 0x6788
incq %rdx
cmpb $-0x41, (%r10,%rcx)
leaq -0x1(%r10), %r10
jle 0x6609
movq %rcx, %r14
subq %rdx, %r14
cmpb $-0x41, %r8b
jg 0x64e1
negq %rdx
testq %rdx, %rdx
je 0x6788
leaq -0x1(%rcx), %r8
incq %rdx
cmpb $-0x40, -0x1(%rdi,%rcx)
movq %r8, %rcx
jl 0x6633
movq %r8, %rcx
jmp 0x64e1
xorl %r13d, %r13d
xorl %r12d, %r12d
xorl %ebp, %ebp
xorl %r9d, %r9d
movq %rbx, %rax
subq %r8, %rax
jbe 0x66ad
cmpq %rax, %r8
jae 0x66ad
subq %r8, %rbx
subq %r8, %rbx
addq %r8, %rdi
xorl %eax, %eax
leaq 0x19d1(%rip), %rdx      # 0x8050
leaq 0x1aca(%rip), %r11      # 0x8150
movzbl (%rdi,%rax), %r10d
movzbl (%r10,%rdx), %r10d
movl %r13d, %r15d
addq %r10, %r15
movzbl (%r11,%r15), %r13d
cmpl $0x10, %r13d
je 0x6783
incq %rax
cmpq %rax, %rbx
jne 0x6686
movl %r13d, %edx
leaq 0x1a99(%rip), %rdi      # 0x8150
movl $0x1, %eax
cmpb $0x10, (%rdx,%rdi)
je 0x6788
cmpq %r8, %r14
jbe 0x6701
leaq 0x197e(%rip), %rdx      # 0x8050
movq %r8, %r11
movq -0x10(%rsp), %r10
movzbl (%r10,%r11), %r10d
movzbl (%r10,%rdx), %r10d
movl %r12d, %ebx
addq %r10, %rbx
movzbl (%rdi,%rbx), %r12d
cmpl $0x10, %r12d
je 0x6788
incq %r11
cmpq %r14, %r11
jb 0x66d5
movl %r12d, %edx
cmpb $0x10, (%rdx,%rdi)
je 0x6788
cmpq %r8, %rcx
jbe 0x673e
leaq 0x193a(%rip), %rdx      # 0x8050
movq %r8, %r11
movq -0x18(%rsp), %r10
movzbl (%r10,%r11), %r10d
movzbl (%r10,%rdx), %r10d
movl %ebp, %ebx
addq %r10, %rbx
movzbl (%rdi,%rbx), %ebp
cmpl $0x10, %ebp
je 0x6788
incq %r11
cmpq %rcx, %r11
jb 0x6719
movl %ebp, %ecx
cmpb $0x10, (%rcx,%rdi)
je 0x6788
cmpq %rsi, -0x8(%rsp)
jae 0x677b
leaq 0x18fc(%rip), %rcx      # 0x8050
movq -0x20(%rsp), %rdx
movzbl (%rdx,%r8), %edx
movzbl (%rdx,%rcx), %edx
movl %r9d, %r9d
addq %rdx, %r9
movzbl (%rdi,%r9), %r9d
cmpl $0x10, %r9d
je 0x6788
incq %r8
cmpq %rsi, %r8
jb 0x6754
movl %r9d, %ecx
jmp 0x65e3
movl $0x1, %eax
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq