// File: /workspace/github_c_makefile_star2_O3/bluecmd[P]fst-example/gtkwave/fastlz.c
// Function: fastlz2_compress
static FASTLZ_INLINE int FASTLZ_COMPRESSOR(const void* input, int length, void* output)
{
  const flzuint8* ip = (const flzuint8*) input;
  const flzuint8* ip_bound = ip + length - 2;
  const flzuint8* ip_limit = ip + length - 12;
  flzuint8* op = (flzuint8*) output;

  const flzuint8* htab[HASH_SIZE];
  const flzuint8** hslot;
  flzuint32 hval;

  flzuint32 copy;

  /* sanity check */
  if(FASTLZ_UNEXPECT_CONDITIONAL(length < 4))
  {
    if(length)
    {
      /* create literal copy only */
      *op++ = length-1;
      ip_bound++;
      while(ip <= ip_bound)
        *op++ = *ip++;
      return length+1;
    }
    else
      return 0;
  }

  /* initializes hash table */
  for (hslot = htab; hslot < htab + HASH_SIZE; hslot++)
    *hslot = ip;

  /* we start with literal copy */
  copy = 2;
  *op++ = MAX_COPY-1;
  *op++ = *ip++;
  *op++ = *ip++;

  /* main loop */
  while(FASTLZ_EXPECT_CONDITIONAL(ip < ip_limit))
  {
    const flzuint8* ref;
    flzuint32 distance;

    /* minimum match length */
    flzuint32 len = 3;

    /* comparison starting-point */
    const flzuint8* anchor = ip;

    /* check for a run */
#if FASTLZ_LEVEL==2
    if(ip[0] == ip[-1] && FASTLZ_READU16(ip-1)==FASTLZ_READU16(ip+1))
    {
      distance = 1;
      /* ip += 3; */ /* scan-build, never used */
      ref = anchor - 1 + 3;
      goto match;
    }
#endif

    /* find potential match */
    HASH_FUNCTION(hval,ip);
    hslot = htab + hval;
    ref = htab[hval];

    /* calculate distance to the match */
    distance = anchor - ref;

    /* update hash table */
    *hslot = anchor;

    /* is this a match? check the first 3 bytes */
    if(distance==0 ||
#if FASTLZ_LEVEL==1
    (distance >= MAX_DISTANCE) ||
#else
    (distance >= MAX_FARDISTANCE) ||
#endif
    *ref++ != *ip++ || *ref++!=*ip++ || *ref++!=*ip++)
      goto literal;

#if FASTLZ_LEVEL==2
    /* far, needs at least 5-byte match */
    if(distance >= MAX_DISTANCE)
    {
      if(*ip++ != *ref++ || *ip++!= *ref++)
        goto literal;
      len += 2;
    }

    match:
#endif

    /* last matched byte */
    ip = anchor + len;

    /* distance is biased */
    distance--;

    if(!distance)
    {
      /* zero distance means a run */
      flzuint8 x = ip[-1];
      while(ip < ip_bound)
        if(*ref++ != x) break; else ip++;
    }
    else
    for(;;)
    {
      /* safe because the outer check against ip limit */
      if(*ref++ != *ip++) break;
      if(*ref++ != *ip++) break;
      if(*ref++ != *ip++) break;
      if(*ref++ != *ip++) break;
      if(*ref++ != *ip++) break;
      if(*ref++ != *ip++) break;
      if(*ref++ != *ip++) break;
      if(*ref++ != *ip++) break;
      while(ip < ip_bound)
        if(*ref++ != *ip++) break;
      break;
    }

    /* if we have copied something, adjust the copy count */
    if(copy)
      /* copy is biased, '0' means 1 byte copy */
      *(op-copy-1) = copy-1;
    else
      /* back, to overwrite the copy count */
      op--;

    /* reset literal counter */
    copy = 0;

    /* length is biased, '1' means a match of 3 bytes */
    ip -= 3;
    len = ip - anchor;

    /* encode the match */
#if FASTLZ_LEVEL==2
    if(distance < MAX_DISTANCE)
    {
      if(len < 7)
      {
        *op++ = (len << 5) + (distance >> 8);
        *op++ = (distance & 255);
      }
      else
      {
        *op++ = (7 << 5) + (distance >> 8);
        for(len-=7; len >= 255; len-= 255)
          *op++ = 255;
        *op++ = len;
        *op++ = (distance & 255);
      }
    }
    else
    {
      /* far away, but not yet in the another galaxy... */
      if(len < 7)
      {
        distance -= MAX_DISTANCE;
        *op++ = (len << 5) + 31;
        *op++ = 255;
        *op++ = distance >> 8;
        *op++ = distance & 255;
      }
      else
      {
        distance -= MAX_DISTANCE;
        *op++ = (7 << 5) + 31;
        for(len-=7; len >= 255; len-= 255)
          *op++ = 255;
        *op++ = len;
        *op++ = 255;
        *op++ = distance >> 8;
        *op++ = distance & 255;
      }
    }
#else

    if(FASTLZ_UNEXPECT_CONDITIONAL(len > MAX_LEN-2))
      while(len > MAX_LEN-2)
      {
        *op++ = (7 << 5) + (distance >> 8);
        *op++ = MAX_LEN - 2 - 7 -2;
        *op++ = (distance & 255);
        len -= MAX_LEN-2;
      }

    if(len < 7)
    {
      *op++ = (len << 5) + (distance >> 8);
      *op++ = (distance & 255);
    }
    else
    {
      *op++ = (7 << 5) + (distance >> 8);
      *op++ = len - 7;
      *op++ = (distance & 255);
    }
#endif

    /* update the hash at match boundary */
    HASH_FUNCTION(hval,ip);
    htab[hval] = ip++;
    HASH_FUNCTION(hval,ip);
    htab[hval] = ip++;

    /* assuming literal copy */
    *op++ = MAX_COPY-1;

    continue;

    literal:
      *op++ = *anchor++;
      ip = anchor;
      copy++;
      if(FASTLZ_UNEXPECT_CONDITIONAL(copy == MAX_COPY))
      {
        copy = 0;
        *op++ = MAX_COPY-1;
      }
  }

  /* left-over as literal copy */
  ip_bound++;
  while(ip <= ip_bound)
  {
    *op++ = *ip++;
    copy++;
    if(copy == MAX_COPY)
    {
      copy = 0;
      *op++ = MAX_COPY-1;
    }
  }

  /* if we have copied something, adjust the copy length */
  if(copy)
    *(op-copy-1) = copy-1;
  else
    op--;

#if FASTLZ_LEVEL==2
  /* marker for fastlz2 */
  *(flzuint8*)output |= (1 << 5);
#endif

  return op - (flzuint8*)output;
}

// Assembly:
pushq %rbp
movq %rsp, %rbp
pushq %r15
pushq %r14
pushq %r13
pushq %r12
pushq %rbx
subq $0x10038, %rsp          # imm = 0x10038
movl %esi, %eax
movslq %esi, %rcx
leaq (%rdi,%rcx), %rsi
cmpl $0x4, %ecx
jl 0x527c
leaq (%rdi,%rcx), %r12
addq $-0x2, %r12
leaq (%rdi,%rcx), %r9
addq $-0xc, %r9
movq $-0x8, %rcx
movq %rdi, -0x10058(%rbp,%rcx)
addq $0x8, %rcx
cmpq $0xfff8, %rcx           # imm = 0xFFF8
jb 0x4e2f
movq %rsi, -0x58(%rbp)
movb $0x1f, (%rdx)
movb (%rdi), %cl
movb %cl, 0x1(%rdx)
movb 0x1(%rdi), %cl
addq $0x2, %rdi
leaq 0x3(%rdx), %r8
movq %rdx, -0x48(%rbp)
movb %cl, 0x2(%rdx)
cmpl $0xf, %eax
jl 0x5275
movl $0x2, %eax
movq %r8, %rbx
movq %rdi, %rcx
movq %r9, -0x50(%rbp)
movq %r12, -0x60(%rbp)
movb (%rcx), %dl
cmpb -0x1(%rcx), %dl
jne 0x4ec6
movzwl 0x1(%rcx), %edx
cmpw %dx, -0x1(%rcx)
jne 0x4eca
leaq 0x2(%rcx), %rdx
leaq 0x3(%rcx), %r13
movl $0x1, %r15d
xorl %r11d, %r11d
cmpq %r12, %r13
jae 0x501c
movb 0x2(%rcx), %sil
cmpb %sil, (%rdx)
jne 0x501c
incq %rdx
incq %r13
cmpq %r12, %r13
jb 0x4ead
jmp 0x501c
movzwl 0x1(%rcx), %edx
movzwl (%rcx), %esi
leaq 0x1(%rcx), %rdi
xorl %esi, %edx
shrl $0x3, %esi
xorl %edx, %esi
andl $0x1fff, %esi           # imm = 0x1FFF
movq -0x10060(%rbp,%rsi,8), %r8
movl %ecx, %r15d
subl %r8d, %r15d
movq %rcx, -0x10060(%rbp,%rsi,8)
leal -0x11ffd(%r15), %edx
cmpl $0xfffee004, %edx       # imm = 0xFFFEE004
jb 0x4f4b
movb (%r8), %dl
cmpb (%rcx), %dl
jne 0x4f4b
movb 0x1(%r8), %dl
cmpb (%rdi), %dl
jne 0x4f4b
movb 0x2(%r8), %dl
cmpb 0x2(%rcx), %dl
jne 0x4f4b
leaq 0x3(%r8), %rdx
cmpl $0x1fff, %r15d          # imm = 0x1FFF
jb 0x4f66
movb 0x3(%rcx), %sil
cmpb (%rdx), %sil
jne 0x4f4b
movb 0x4(%rcx), %dl
cmpb 0x4(%r8), %dl
jne 0x4f4b
addq $0x5, %r8
leaq 0x5(%rcx), %rsi
leal -0x1(%r15), %r11d
movq %r8, %rdx
jmp 0x4f79
movb (%rcx), %cl
leaq 0x1(%rbx), %r8
movb %cl, (%rbx)
incl %eax
cmpl $0x20, %eax
je 0x5006
movq %r8, %rbx
jmp 0x51ff
leaq 0x3(%rcx), %r13
movl %r15d, %r11d
movq %r13, %rsi
decl %r11d
je 0x4e97
movb (%rdx), %dil
cmpb (%rsi), %dil
jne 0x4fe9
movb 0x1(%rdx), %dil
cmpb 0x1(%rsi), %dil
jne 0x4fee
movb 0x2(%rdx), %dil
cmpb 0x2(%rsi), %dil
jne 0x4ff4
movb 0x3(%rdx), %dil
cmpb 0x3(%rsi), %dil
jne 0x4ffa
movb 0x4(%rdx), %dil
cmpb 0x4(%rsi), %dil
jne 0x5000
movb 0x5(%rdx), %dil
cmpb 0x5(%rsi), %dil
jne 0x500f
movb 0x6(%rdx), %dil
cmpb 0x6(%rsi), %dil
jne 0x5015
movb 0x7(%rdx), %dil
leaq 0x8(%rsi), %r13
cmpb 0x7(%rsi), %dil
jne 0x501c
addq $0x8, %rdx
cmpq %r12, %r13
jae 0x501c
movb (%rdx), %dil
incq %rdx
leaq 0x1(%r13), %rsi
cmpb (%r13), %dil
movq %rsi, %r13
je 0x4fcf
jmp 0x5019
incq %rsi
jmp 0x5019
addq $0x2, %rsi
jmp 0x5019
addq $0x3, %rsi
jmp 0x5019
addq $0x4, %rsi
jmp 0x5019
addq $0x5, %rsi
jmp 0x5019
addq $0x2, %rbx
jmp 0x51f6
addq $0x6, %rsi
jmp 0x5019
addq $0x7, %rsi
movq %rsi, %r13
testl %eax, %eax
je 0x502d
leal -0x1(%rax), %edx
movl %eax, %eax
notq %rax
movb %dl, (%rax,%rbx)
jmp 0x5030
decq %rbx
leaq -0x3(%r13), %r10
movq %r10, %rax
subq %rcx, %rax
cmpl $0x1ffe, %r11d          # imm = 0x1FFE
ja 0x5062
cmpl $0x6, %eax
ja 0x508d
shll $0x5, %eax
movl %r11d, %ecx
shrl $0x8, %ecx
orl %eax, %ecx
movb %cl, (%rbx)
movb %r11b, 0x1(%rbx)
addq $0x2, %rbx
jmp 0x51ae
leal 0xe000(%r15), %edx
cmpl $0x6, %eax
ja 0x511f
shlb $0x5, %al
orb $0x1f, %al
movb %al, (%rbx)
movb $-0x1, 0x1(%rbx)
movb %dh, 0x2(%rbx)
movb %r15b, 0x3(%rbx)
addq $0x4, %rbx
jmp 0x51ae
movq %r10, -0x38(%rbp)
movl %r11d, %edx
shrl $0x8, %edx
orb $-0x20, %dl
movb %dl, (%rbx)
addl $-0x7, %eax
leaq 0x1(%rbx), %r14
cmpl $0xff, %eax
jb 0x510b
movl %r13d, %eax
subl %ecx, %eax
movq %rax, -0x40(%rbp)
leal -0x109(%rax), %r15d
movl $0x80808081, %eax       # imm = 0x80808081
imulq %rax, %r15
shrq $0x27, %r15
leaq 0x1(%r15), %rdx
movq %r14, %rdi
movl $0xff, %esi
movl %r11d, -0x2c(%rbp)
callq 0x2190
movl -0x2c(%rbp), %r11d
movq -0x50(%rbp), %r9
movl %r15d, %eax
shll $0x8, %eax
movl %r15d, %ecx
subl %eax, %ecx
movq -0x40(%rbp), %rax
addl %ecx, %eax
addl $0xfffffef7, %eax       # imm = 0xFFFFFEF7
addq %r15, %r14
leaq (%rbx,%r15), %rcx
addq $0x2, %rcx
movq %r14, %rbx
movq %rcx, %r14
movq -0x38(%rbp), %r10
movb %al, (%r14)
movb %r11b, 0x2(%rbx)
addq $0x3, %rbx
jmp 0x51ae
movl %edx, -0x2c(%rbp)
movb $-0x1, (%rbx)
addl $-0x7, %eax
leaq 0x1(%rbx), %r14
cmpl $0xff, %eax
jb 0x5199
movl %r13d, %eax
subl %ecx, %eax
movq %rax, -0x40(%rbp)
leal -0x109(%rax), %r12d
movl $0x80808081, %eax       # imm = 0x80808081
imulq %rax, %r12
shrq $0x27, %r12
movq %r10, -0x38(%rbp)
leaq 0x1(%r12), %rdx
movq %r14, %rdi
movl $0xff, %esi
callq 0x2190
movq -0x38(%rbp), %r10
movq -0x50(%rbp), %r9
movl %r12d, %eax
shll $0x8, %eax
movl %r12d, %ecx
subl %eax, %ecx
movq -0x40(%rbp), %rax
addl %ecx, %eax
addl $0xfffffef7, %eax       # imm = 0xFFFFFEF7
addq %r12, %r14
leaq (%rbx,%r12), %rcx
addq $0x2, %rcx
movq -0x60(%rbp), %r12
movq %r14, %rbx
movq %rcx, %r14
movb %al, (%r14)
movb $-0x1, 0x2(%rbx)
movl -0x2c(%rbp), %eax
movb %ah, 0x3(%rbx)
movb %r15b, 0x4(%rbx)
addq $0x5, %rbx
movq %rbx, %r8
movzwl -0x3(%r13), %eax
leaq -0x2(%r13), %rcx
movzwl -0x2(%r13), %esi
movl %eax, %edi
shrl $0x3, %edi
xorl %esi, %eax
xorl %edi, %eax
movl $0x1fff, %edx           # imm = 0x1FFF
andl %edx, %eax
movq %r10, -0x10060(%rbp,%rax,8)
movq %r13, %rdi
decq %rdi
movzwl -0x1(%r13), %eax
xorl %esi, %eax
shrl $0x3, %esi
xorl %eax, %esi
andl %edx, %esi
movq %rcx, -0x10060(%rbp,%rsi,8)
incq %rbx
movb $0x1f, (%r8)
xorl %eax, %eax
movq %rbx, %r8
movq %rdi, %rcx
cmpq %r9, %rdi
jb 0x4e7e
movq -0x58(%rbp), %rsi
decq %rsi
cmpq %rsi, %rdi
jbe 0x521d
movq -0x48(%rbp), %rdx
jmp 0x5245
movq -0x48(%rbp), %rdx
movb (%rdi), %cl
movb %cl, (%r8)
incl %eax
cmpl $0x20, %eax
je 0x5232
incq %r8
jmp 0x523d
movb $0x1f, 0x1(%r8)
addq $0x2, %r8
xorl %eax, %eax
incq %rdi
cmpq %rsi, %rdi
jbe 0x5221
testl %eax, %eax
je 0x5257
leal -0x1(%rax), %ecx
movl %eax, %eax
notq %rax
movb %cl, (%rax,%r8)
jmp 0x525a
decq %r8
orb $0x20, (%rdx)
subl %edx, %r8d
movl %r8d, %eax
addq $0x10038, %rsp          # imm = 0x10038
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq
movl $0x2, %eax
jmp 0x520b
testl %eax, %eax
je 0x52a3
leal -0x1(%rax), %ecx
movb %cl, (%rdx)
decq %rsi
cmpq %rdi, %rsi
jb 0x529f
incq %rdx
movb (%rdi), %cl
incq %rdi
movb %cl, (%rdx)
incq %rdx
cmpq %rsi, %rdi
jbe 0x5290
incl %eax
jmp 0x5263
xorl %eax, %eax
jmp 0x5263