// File: /workspace/github_c_makefile_star2_O1/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 $0x10028, %rsp          # imm = 0x10028
movl %esi, %eax
movslq %esi, %rcx
leaq (%rdi,%rcx), %rsi
cmpl $0x4, %ecx
jl 0x33d7
leaq (%rdi,%rcx), %r8
addq $-0x2, %r8
leaq (%rdi,%rcx), %r9
addq $-0xc, %r9
movq $-0x8, %rcx
movq %rdi, -0x10048(%rbp,%rcx)
addq $0x8, %rcx
cmpq $0xfff8, %rcx           # imm = 0xFFF8
jb 0x2f56
movq %rsi, -0x50(%rbp)
movb $0x1f, (%rdx)
movb (%rdi), %cl
movb %cl, 0x1(%rdx)
movb 0x1(%rdi), %sil
addq $0x2, %rdi
leaq 0x3(%rdx), %rcx
movq %rdx, -0x38(%rbp)
movb %sil, 0x2(%rdx)
cmpl $0xf, %eax
jl 0x336d
movl $0x2, %eax
movl $0x1fff, %r10d          # imm = 0x1FFF
movq %rcx, %rbx
movq %rdi, %r13
movq %r8, -0x48(%rbp)
movq %r9, -0x40(%rbp)
movb (%r13), %cl
cmpb -0x1(%r13), %cl
jne 0x3079
movzwl -0x1(%r13), %ecx
cmpw 0x1(%r13), %cx
jne 0x3079
leaq 0x2(%r13), %rcx
movl $0x3, %r14d
movl $0x1, %r15d
addq %r13, %r14
movl %r15d, %r12d
decl %r12d
je 0x3129
movb (%rcx), %dl
cmpb (%r14), %dl
jne 0x3143
movb 0x1(%rcx), %dl
cmpb 0x1(%r14), %dl
jne 0x3148
movb 0x2(%rcx), %dl
cmpb 0x2(%r14), %dl
jne 0x314e
movb 0x3(%rcx), %dl
cmpb 0x3(%r14), %dl
jne 0x3154
movb 0x4(%rcx), %dl
cmpb 0x4(%r14), %dl
jne 0x315a
movb 0x5(%rcx), %dl
cmpb 0x5(%r14), %dl
jne 0x3160
movb 0x6(%rcx), %dl
cmpb 0x6(%r14), %dl
jne 0x3166
movb 0x7(%rcx), %sil
leaq 0x8(%r14), %rdx
cmpb 0x7(%r14), %sil
jne 0x316c
addq $0x8, %rcx
cmpq %r8, %rdx
jae 0x316c
movb (%rcx), %sil
incq %rcx
leaq 0x1(%rdx), %r14
cmpb (%rdx), %sil
movq %r14, %rdx
je 0x3059
jmp 0x316f
movzwl (%r13), %ecx
leaq 0x1(%r13), %rdi
movl %ecx, %esi
shrl $0x3, %esi
xorw 0x1(%r13), %si
xorl %ecx, %esi
andl $0x1fff, %esi           # imm = 0x1FFF
movq -0x10050(%rbp,%rsi,8), %rdx
movl %r13d, %r15d
subl %edx, %r15d
movq %r13, -0x10050(%rbp,%rsi,8)
leal -0x11ffd(%r15), %ecx
cmpl $0xfffee004, %ecx       # imm = 0xFFFEE004
jb 0x310c
movb (%rdx), %cl
cmpb (%r13), %cl
jne 0x310c
movb 0x1(%rdx), %cl
cmpb (%rdi), %cl
jne 0x310c
movb 0x2(%rdx), %cl
cmpb 0x2(%r13), %cl
jne 0x310c
leaq 0x3(%rdx), %rcx
movl $0x3, %r14d
cmpl $0x1fff, %r15d          # imm = 0x1FFF
jb 0x2fdb
movb 0x3(%r13), %sil
cmpb (%rcx), %sil
jne 0x310c
movb 0x4(%r13), %cl
cmpb 0x4(%rdx), %cl
jne 0x310c
addq $0x5, %rdx
movl $0x5, %r14d
movq %rdx, %rcx
jmp 0x2fdb
movb (%r13), %dl
leaq 0x1(%rbx), %rcx
movb %dl, (%rbx)
incl %eax
cmpl $0x20, %eax
je 0x3367
movq %rcx, %rbx
jmp 0x3359
cmpq %r8, %r14
jae 0x316f
movb -0x1(%r14), %dl
cmpb %dl, (%rcx)
jne 0x316f
incq %rcx
incq %r14
cmpq %r8, %r14
jb 0x3132
jmp 0x316f
incq %r14
jmp 0x316f
addq $0x2, %r14
jmp 0x316f
addq $0x3, %r14
jmp 0x316f
addq $0x4, %r14
jmp 0x316f
addq $0x5, %r14
jmp 0x316f
addq $0x6, %r14
jmp 0x316f
addq $0x7, %r14
jmp 0x316f
movq %rdx, %r14
testl %eax, %eax
je 0x3180
leal -0x1(%rax), %ecx
movl %eax, %eax
notq %rax
movb %cl, (%rax,%rbx)
jmp 0x3183
decq %rbx
leaq -0x3(%r14), %r11
movq %r11, %rax
subq %r13, %rax
cmpl $0x1ffe, %r12d          # imm = 0x1FFE
ja 0x31b5
cmpl $0x6, %eax
ja 0x31e0
shll $0x5, %eax
movl %r12d, %ecx
shrl $0x8, %ecx
orl %eax, %ecx
movb %cl, (%rbx)
movb %r12b, 0x1(%rbx)
addq $0x2, %rbx
jmp 0x330c
leal 0xe000(%r15), %ecx
cmpl $0x6, %eax
ja 0x3276
shlb $0x5, %al
orb $0x1f, %al
movb %al, (%rbx)
movb $-0x1, 0x1(%rbx)
movb %ch, 0x2(%rbx)
movb %r15b, 0x3(%rbx)
addq $0x4, %rbx
jmp 0x330c
movl %r12d, %ecx
shrl $0x8, %ecx
orb $-0x20, %cl
movb %cl, (%rbx)
addl $-0x7, %eax
leaq 0x1(%rbx), %rdi
cmpl $0xff, %eax
jb 0x3267
movl $0xfffffef7, %eax       # imm = 0xFFFFFEF7
addl %r14d, %eax
subl %r13d, %eax
movabsq $0x101010101010102, %rcx # imm = 0x101010101010102
mulq %rcx
incq %rdx
movl $0xff, %esi
movq %r11, %r15
callq 0x2190
movq %r15, %r11
movl $0x1fff, %r10d          # imm = 0x1FFF
movq -0x40(%rbp), %r9
movq -0x48(%rbp), %r8
movl %r14d, %eax
subl %r13d, %eax
leal -0x109(%rax), %ecx
movl $0x80808081, %edx       # imm = 0x80808081
imulq %rdx, %rcx
shrq $0x27, %rcx
movl %ecx, %edx
leaq (%rbx,%rcx), %rdi
addq $0x2, %rdi
addq %rcx, %rbx
incq %rbx
shll $0x8, %ecx
subl %ecx, %edx
addl %edx, %eax
addl $0xfffffef7, %eax       # imm = 0xFFFFFEF7
movb %al, (%rdi)
movb %r12b, 0x2(%rbx)
addq $0x3, %rbx
jmp 0x330c
movb $-0x1, (%rbx)
addl $-0x7, %eax
leaq 0x1(%rbx), %rdi
cmpl $0xff, %eax
jb 0x32fb
movl $0xfffffef7, %eax       # imm = 0xFFFFFEF7
addl %r14d, %eax
subl %r13d, %eax
movl %ecx, -0x2c(%rbp)
movabsq $0x101010101010102, %rcx # imm = 0x101010101010102
mulq %rcx
incq %rdx
movl $0xff, %esi
movq %r11, %r12
callq 0x2190
movq %r12, %r11
movl $0x1fff, %r10d          # imm = 0x1FFF
movq -0x40(%rbp), %r9
movq -0x48(%rbp), %r8
movl %r14d, %eax
subl %r13d, %eax
leal -0x109(%rax), %ecx
movl $0x80808081, %edx       # imm = 0x80808081
imulq %rdx, %rcx
shrq $0x27, %rcx
movl %ecx, %edx
leaq (%rbx,%rcx), %rdi
addq $0x2, %rdi
addq %rcx, %rbx
incq %rbx
shll $0x8, %ecx
subl %ecx, %edx
movl -0x2c(%rbp), %ecx
addl %edx, %eax
addl $0xfffffef7, %eax       # imm = 0xFFFFFEF7
movb %al, (%rdi)
movb $-0x1, 0x2(%rbx)
movb %ch, 0x3(%rbx)
movb %r15b, 0x4(%rbx)
addq $0x5, %rbx
movq %rbx, %rcx
movzwl -0x3(%r14), %eax
leaq -0x2(%r14), %rdx
movzwl -0x2(%r14), %esi
movl %eax, %edi
shrl $0x3, %edi
xorl %esi, %eax
xorl %edi, %eax
andl %r10d, %eax
movq %r11, -0x10050(%rbp,%rax,8)
movq %r14, %rdi
decq %rdi
movzwl -0x1(%r14), %eax
xorl %esi, %eax
shrl $0x3, %esi
xorl %eax, %esi
andl %r10d, %esi
movq %rdx, -0x10050(%rbp,%rsi,8)
incq %rbx
movb $0x1f, (%rcx)
xorl %eax, %eax
movq %rbx, %rcx
movq %rdi, %r13
cmpq %r9, %rdi
jb 0x2fad
jmp 0x3372
addq $0x2, %rbx
jmp 0x3351
movl $0x2, %eax
movq -0x50(%rbp), %r8
decq %r8
cmpq %r8, %rdi
jbe 0x3384
movq -0x38(%rbp), %rsi
jmp 0x33aa
movq -0x38(%rbp), %rsi
movb (%rdi), %dl
movb %dl, (%rcx)
incl %eax
cmpl $0x20, %eax
je 0x3398
incq %rcx
jmp 0x33a2
movb $0x1f, 0x1(%rcx)
addq $0x2, %rcx
xorl %eax, %eax
incq %rdi
cmpq %r8, %rdi
jbe 0x3388
testl %eax, %eax
je 0x33bb
leal -0x1(%rax), %edx
movl %eax, %eax
notq %rax
movb %dl, (%rax,%rcx)
jmp 0x33be
decq %rcx
orb $0x20, (%rsi)
subl %esi, %ecx
movl %ecx, %eax
addq $0x10028, %rsp          # imm = 0x10028
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq
testl %eax, %eax
je 0x33fe
leal -0x1(%rax), %ecx
movb %cl, (%rdx)
decq %rsi
cmpq %rdi, %rsi
jb 0x33fa
incq %rdx
movb (%rdi), %cl
incq %rdi
movb %cl, (%rdx)
incq %rdx
cmpq %rsi, %rdi
jbe 0x33eb
incl %eax
jmp 0x33c5
xorl %eax, %eax
jmp 0x33c5