// File: twekkel[P]mzpq/libzpaq.cpp
// Function: libzpaq::LZBuffer::write_match(unsigned int, unsigned int)
void LZBuffer::write_match(unsigned len, unsigned off) {

  // mm,mmm,n,ll,r,q[mmmmm-8] = match n*4+ll, offset ((q-1)<<rb)+r+1
  if (level==1) {
    assert(len>=minMatch && len<=maxMatch);
    assert(off>0);
    assert(len>=4);
    assert(rb>=0 && rb<=8);
    int ll=lg(len)-1;
    assert(ll>=2);
    off+=(1<<rb)-1;
    int lo=lg(off)-1-rb;
    assert(lo>=0 && lo<=23);
    putb((lo+8)>>3, 2);// mm
    putb(lo&7, 3);     // mmm
    while (--ll>=2) {  // n
      putb(1, 1);
      putb((len>>ll)&1, 1);
    }
    putb(0, 1);
    putb(len&3, 2);    // ll
    putb(off, rb);     // r
    putb(off>>rb, lo); // q
  }

  // x[2]:len[6] off[x-1] 
  else {
    assert(level==2);
    assert(minMatch>=1 && minMatch<=64);
    --off;
    while (len>0) {  // Split long matches to len1=minMatch..minMatch+63
      const unsigned len1=len>minMatch*2+63 ? minMatch+63 :
          len>minMatch+63 ? len-minMatch : len;
      assert(wpos<BUFSIZE-5);
      assert(len1>=minMatch && len1<minMatch+64);
      if (off<(1<<16)) {
        put(64+len1-minMatch);
        put(off>>8);
        put(off);
      }
      else if (off<(1<<24)) {
        put(128+len1-minMatch);
        put(off>>16);
        put(off>>8);
        put(off);
      }
      else {
        put(192+len1-minMatch);
        put(off>>24);
        put(off>>16);
        put(off>>8);
        put(off);
      }
      len-=len1;
    }
  }
}

// Assembly:
pushq %rbp
movq %rsp, %rbp
subq $0x30, %rsp
movq %rdi, -0x8(%rbp)
movl %esi, -0xc(%rbp)
movl %edx, -0x10(%rbp)
movq -0x8(%rbp), %rax
movq %rax, -0x28(%rbp)
cmpl $0x1, 0x2c(%rax)
jne 0x23b9c
movl -0xc(%rbp), %edi
callq 0x226a0
movl %eax, %ecx
movq -0x28(%rbp), %rax
subl $0x1, %ecx
movl %ecx, -0x14(%rbp)
movl 0x68(%rax), %ecx
movl $0x1, %eax
shll %cl, %eax
subl $0x1, %eax
addl -0x10(%rbp), %eax
movl %eax, -0x10(%rbp)
movl -0x10(%rbp), %edi
callq 0x226a0
movq -0x28(%rbp), %rdi
subl $0x1, %eax
subl 0x68(%rdi), %eax
movl %eax, -0x18(%rbp)
movl -0x18(%rbp), %esi
addl $0x8, %esi
sarl $0x3, %esi
movl $0x2, %edx
callq 0x316a0
movq -0x28(%rbp), %rdi
movl -0x18(%rbp), %esi
andl $0x7, %esi
movl $0x3, %edx
callq 0x316a0
movl -0x14(%rbp), %eax
addl $-0x1, %eax
movl %eax, -0x14(%rbp)
cmpl $0x2, %eax
jl 0x23b50
movq -0x28(%rbp), %rdi
movl $0x1, %edx
movl %edx, %esi
callq 0x316a0
movq -0x28(%rbp), %rdi
movl -0xc(%rbp), %esi
movl -0x14(%rbp), %ecx
shrl %cl, %esi
andl $0x1, %esi
movl $0x1, %edx
callq 0x316a0
jmp 0x23b17
movq -0x28(%rbp), %rdi
xorl %esi, %esi
movl $0x1, %edx
callq 0x316a0
movq -0x28(%rbp), %rdi
movl -0xc(%rbp), %esi
andl $0x3, %esi
movl $0x2, %edx
callq 0x316a0
movq -0x28(%rbp), %rdi
movl -0x10(%rbp), %esi
movl 0x68(%rdi), %edx
callq 0x316a0
movq -0x28(%rbp), %rdi
movl -0x10(%rbp), %esi
movl 0x68(%rdi), %ecx
shrl %cl, %esi
movl -0x18(%rbp), %edx
callq 0x316a0
jmp 0x23cea
movl -0x10(%rbp), %eax
addl $-0x1, %eax
movl %eax, -0x10(%rbp)
cmpl $0x0, -0xc(%rbp)
jbe 0x23ce8
movq -0x28(%rbp), %rcx
movl -0xc(%rbp), %eax
movl 0x3c(%rcx), %ecx
shll %ecx
addl $0x3f, %ecx
cmpl %ecx, %eax
jbe 0x23bd1
movq -0x28(%rbp), %rax
movl 0x3c(%rax), %eax
addl $0x3f, %eax
movl %eax, -0x2c(%rbp)
jmp 0x23bfd
movq -0x28(%rbp), %rcx
movl -0xc(%rbp), %eax
movl 0x3c(%rcx), %ecx
addl $0x3f, %ecx
cmpl %ecx, %eax
jbe 0x23bf1
movq -0x28(%rbp), %rcx
movl -0xc(%rbp), %eax
subl 0x3c(%rcx), %eax
movl %eax, -0x30(%rbp)
jmp 0x23bf7
movl -0xc(%rbp), %eax
movl %eax, -0x30(%rbp)
movl -0x30(%rbp), %eax
movl %eax, -0x2c(%rbp)
movl -0x2c(%rbp), %eax
movl %eax, -0x1c(%rbp)
cmpl $0x10000, -0x10(%rbp)   # imm = 0x10000
jae 0x23c3e
movq -0x28(%rbp), %rdi
movl -0x1c(%rbp), %esi
addl $0x40, %esi
subl 0x3c(%rdi), %esi
callq 0x31620
movq -0x28(%rbp), %rdi
movl -0x10(%rbp), %esi
shrl $0x8, %esi
callq 0x31620
movq -0x28(%rbp), %rdi
movl -0x10(%rbp), %esi
callq 0x31620
jmp 0x23cd8
cmpl $0x1000000, -0x10(%rbp) # imm = 0x1000000
jae 0x23c88
movq -0x28(%rbp), %rdi
movl -0x1c(%rbp), %esi
addl $0x80, %esi
subl 0x3c(%rdi), %esi
callq 0x31620
movq -0x28(%rbp), %rdi
movl -0x10(%rbp), %esi
shrl $0x10, %esi
callq 0x31620
movq -0x28(%rbp), %rdi
movl -0x10(%rbp), %esi
shrl $0x8, %esi
callq 0x31620
movq -0x28(%rbp), %rdi
movl -0x10(%rbp), %esi
callq 0x31620
jmp 0x23cd6
movq -0x28(%rbp), %rdi
movl -0x1c(%rbp), %esi
addl $0xc0, %esi
subl 0x3c(%rdi), %esi
callq 0x31620
movq -0x28(%rbp), %rdi
movl -0x10(%rbp), %esi
shrl $0x18, %esi
callq 0x31620
movq -0x28(%rbp), %rdi
movl -0x10(%rbp), %esi
shrl $0x10, %esi
callq 0x31620
movq -0x28(%rbp), %rdi
movl -0x10(%rbp), %esi
shrl $0x8, %esi
callq 0x31620
movq -0x28(%rbp), %rdi
movl -0x10(%rbp), %esi
callq 0x31620
jmp 0x23cd8
movl -0x1c(%rbp), %ecx
movl -0xc(%rbp), %eax
subl %ecx, %eax
movl %eax, -0xc(%rbp)
jmp 0x23ba5
jmp 0x23cea
addq $0x30, %rsp
popq %rbp
retq