// File: /workspace/github_cpp_makefile_star2_O1/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 0x65ae
testq %rsi, %rsi
je 0x6725
xorl %eax, %eax
leaq 0x1ad4(%rip), %rdx      # 0x8050
leaq 0x1bcd(%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 0x686b
incq %rax
cmpq %rax, %rsi
jne 0x6585
jmp 0x6727
movq %rsi, %rax
shrq $0x2, %rax
cmpb $-0x41, (%rdi,%rax)
jle 0x65c0
movq %rax, %r14
jmp 0x65d7
movq %rax, %r14
subq $0x1, %r14
jb 0x686b
cmpb $-0x40, -0x1(%rdi,%rax)
movq %r14, %rax
jl 0x65c3
movq %rsi, %rax
shrq %rax
cmpb $-0x41, (%rdi,%rax)
movq %rax, %rbx
jg 0x6600
movq %rax, %rcx
cmpq %rcx, %r14
je 0x686b
leaq -0x1(%rcx), %rbx
cmpb $-0x41, -0x1(%rdi,%rcx)
movq %rbx, %rcx
jle 0x65e9
cmpb $-0x41, (%rdi,%rax)
jle 0x660b
movq %rax, %r8
jmp 0x6622
cmpq %rax, %rbx
je 0x686b
leaq -0x1(%rax), %r8
cmpb $-0x40, -0x1(%rdi,%rax)
movq %r8, %rax
jl 0x660b
leaq (%rdi,%r14), %rax
movq %rax, -0x10(%rsp)
leaq (%rdi,%rbx), %rax
movq %rax, -0x18(%rsp)
leaq (%rdi,%r8), %rax
movq %rax, -0x20(%rsp)
subq %r8, %rsi
subq %rbx, %r8
subq %r14, %rbx
cmpq %r14, %rbx
movq %r14, %rax
cmovbq %rbx, %rax
cmpq %rax, %r8
cmovbq %r8, %rax
cmpq %rax, %rsi
movq %rax, %rdx
cmovbq %rsi, %rdx
testq %rdx, %rdx
movq %rax, -0x8(%rsp)
je 0x673c
xorl %ecx, %ecx
leaq 0x19d8(%rip), %r11      # 0x8050
leaq 0x1ad1(%rip), %r15      # 0x8150
xorl %r9d, %r9d
xorl %ebp, %ebp
xorl %r12d, %r12d
xorl %r13d, %r13d
movzbl (%rdi,%rcx), %eax
movzbl (%rax,%r11), %eax
movl %r13d, %r13d
addq %rax, %r13
movzbl (%r15,%r13), %r13d
movl $0x1, %eax
cmpl $0x10, %r13d
je 0x6870
movq -0x10(%rsp), %r10
movzbl (%r10,%rcx), %r10d
movzbl (%r10,%r11), %r10d
movl %r12d, %r12d
addq %r10, %r12
movzbl (%r15,%r12), %r12d
cmpl $0x10, %r12d
je 0x6870
movq -0x18(%rsp), %r10
movzbl (%r10,%rcx), %r10d
movzbl (%r10,%r11), %r10d
movl %ebp, %ebp
addq %r10, %rbp
movzbl (%r15,%rbp), %ebp
cmpl $0x10, %ebp
je 0x6870
movq -0x20(%rsp), %r10
movzbl (%r10,%rcx), %r10d
movzbl (%r10,%r11), %r10d
movl %r9d, %r9d
addq %r10, %r9
movzbl (%r15,%r9), %r9d
cmpl $0x10, %r9d
je 0x6870
incq %rcx
cmpq %rcx, %rdx
jne 0x668a
jmp 0x6747
xorl %ecx, %ecx
leaq 0x1a22(%rip), %rdx      # 0x8150
xorl %eax, %eax
cmpb $0x10, (%rcx,%rdx)
sete %al
jmp 0x6870
xorl %r13d, %r13d
xorl %r12d, %r12d
xorl %ebp, %ebp
xorl %r9d, %r9d
movq %r14, %rax
subq %rdx, %rax
jbe 0x6794
cmpq %rax, %rdx
jae 0x6794
subq %rdx, %r14
subq %rdx, %r14
addq %rdx, %rdi
xorl %eax, %eax
leaq 0x18ea(%rip), %rcx      # 0x8050
leaq 0x19e3(%rip), %r11      # 0x8150
movzbl (%rdi,%rax), %r10d
movzbl (%r10,%rcx), %r10d
movl %r13d, %r15d
addq %r10, %r15
movzbl (%r11,%r15), %r13d
cmpl $0x10, %r13d
je 0x686b
incq %rax
cmpq %rax, %r14
jne 0x676d
movl %r13d, %ecx
leaq 0x19b2(%rip), %rdi      # 0x8150
movl $0x1, %eax
cmpb $0x10, (%rcx,%rdi)
je 0x6870
cmpq %rdx, %rbx
jbe 0x67e8
leaq 0x1897(%rip), %rcx      # 0x8050
movq %rdx, %r11
movq -0x10(%rsp), %r10
movzbl (%r10,%r11), %r10d
movzbl (%r10,%rcx), %r10d
movl %r12d, %r14d
addq %r10, %r14
movzbl (%rdi,%r14), %r12d
cmpl $0x10, %r12d
je 0x6870
incq %r11
cmpq %rbx, %r11
jb 0x67bc
movl %r12d, %ecx
cmpb $0x10, (%rcx,%rdi)
je 0x6870
cmpq %rdx, %r8
jbe 0x6825
leaq 0x1853(%rip), %rcx      # 0x8050
movq %rdx, %r11
movq -0x18(%rsp), %r10
movzbl (%r10,%r11), %r10d
movzbl (%r10,%rcx), %r10d
movl %ebp, %ebx
addq %r10, %rbx
movzbl (%rdi,%rbx), %ebp
cmpl $0x10, %ebp
je 0x6870
incq %r11
cmpq %r8, %r11
jb 0x6800
movl %ebp, %ecx
cmpb $0x10, (%rcx,%rdi)
je 0x6870
cmpq %rsi, -0x8(%rsp)
jae 0x6863
leaq 0x1815(%rip), %rcx      # 0x8050
movq -0x20(%rsp), %r8
movzbl (%r8,%rdx), %r8d
movzbl (%r8,%rcx), %r8d
movl %r9d, %r9d
addq %r8, %r9
movzbl (%rdi,%r9), %r9d
cmpl $0x10, %r9d
je 0x6870
incq %rdx
cmpq %rsi, %rdx
jb 0x683b
movl %r9d, %ecx
jmp 0x6727
movl $0x1, %eax
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq