// File: blackle[P]LZMA-Vizualizer/LzmaSpec.cpp
// Function: CLzmaDecoder::Decode(bool, unsigned long)
int CLzmaDecoder::Decode(bool unpackSizeDefined, UInt64 unpackSize)
{
  if (!RangeDec.Init())
    return LZMA_RES_ERROR;

  Init();

  UInt32 rep0 = 0, rep1 = 0, rep2 = 0, rep3 = 0;
  unsigned state = 0;

  for (;;)
  {
    if (unpackSizeDefined && unpackSize == 0 && !markerIsMandatory)
      if (RangeDec.IsFinishedOK())
        return LZMA_RES_FINISHED_WITHOUT_MARKER;

    unsigned posState = OutWindow.TotalPos & ((1 << pb) - 1);

    if (RangeDec.DecodeBit(&IsMatch[(state << kNumPosBitsMax) + posState]) == 0)
    {
      if (unpackSizeDefined && unpackSize == 0)
        return LZMA_RES_ERROR;
      DecodeLiteral(state, rep0);
      PushPerplexities(1);
      Literals.push_back(true);
      state = UpdateState_Literal(state);
      unpackSize--;
      continue;
    }

    unsigned len;

    if (RangeDec.DecodeBit(&IsRep[state]) != 0)
    {
      if (unpackSizeDefined && unpackSize == 0)
        return LZMA_RES_ERROR;
      if (OutWindow.IsEmpty())
        return LZMA_RES_ERROR;
      if (RangeDec.DecodeBit(&IsRepG0[state]) == 0)
      {
        if (RangeDec.DecodeBit(&IsRep0Long[(state << kNumPosBitsMax) + posState]) == 0)
        {
          state = UpdateState_ShortRep(state);
          OutWindow.PutByte(OutWindow.GetByte(rep0 + 1));
          PushPerplexities(1);
          Literals.push_back(false);
          unpackSize--;
          continue;
        }
      }
      else
      {
        UInt32 dist;
        if (RangeDec.DecodeBit(&IsRepG1[state]) == 0)
          dist = rep1;
        else
        {
          if (RangeDec.DecodeBit(&IsRepG2[state]) == 0)
            dist = rep2;
          else
          {
            dist = rep3;
            rep3 = rep2;
          }
          rep2 = rep1;
        }
        rep1 = rep0;
        rep0 = dist;
      }
      len = RepLenDecoder.Decode(&RangeDec, posState);
      state = UpdateState_Rep(state);
    }
    else
    {
      rep3 = rep2;
      rep2 = rep1;
      rep1 = rep0;
      len = LenDecoder.Decode(&RangeDec, posState);
      state = UpdateState_Match(state);
      rep0 = DecodeDistance(len);
      if (rep0 == 0xFFFFFFFF)
        return RangeDec.IsFinishedOK() ?
            LZMA_RES_FINISHED_WITH_MARKER :
            LZMA_RES_ERROR;

      if (unpackSizeDefined && unpackSize == 0)
        return LZMA_RES_ERROR;
      if (rep0 >= dictSize || !OutWindow.CheckDistance(rep0))
        return LZMA_RES_ERROR;
    }
    len += kMatchMinLen;
    bool isError = false;
    if (unpackSizeDefined && unpackSize < len)
    {
      len = (unsigned)unpackSize;
      isError = true;
    }
    OutWindow.CopyMatch(rep0 + 1, len);
    Literals.insert(Literals.end(), len, false);
    PushPerplexities(len);
    unpackSize -= len;
    if (isError)
      return LZMA_RES_ERROR;
  }
}

// Assembly:
pushq %rbp
movq %rsp, %rbp
subq $0xb0, %rsp
movb %sil, %al
movq %rdi, -0x10(%rbp)
andb $0x1, %al
movb %al, -0x11(%rbp)
movq %rdx, -0x20(%rbp)
movq -0x10(%rbp), %rdi
movq %rdi, -0x98(%rbp)
callq 0x2420
testb $0x1, %al
jne 0x283b
movl $0x0, -0x4(%rbp)
jmp 0x2cc6
movq -0x98(%rbp), %rdi
callq 0x3d40
movl $0x0, -0x24(%rbp)
movl $0x0, -0x28(%rbp)
movl $0x0, -0x2c(%rbp)
movl $0x0, -0x30(%rbp)
movl $0x0, -0x34(%rbp)
testb $0x1, -0x11(%rbp)
je 0x28a7
cmpq $0x0, -0x20(%rbp)
jne 0x28a7
movq -0x98(%rbp), %rax
testb $0x1, 0x88(%rax)
jne 0x28a7
movq -0x98(%rbp), %rdi
callq 0x3ea0
testb $0x1, %al
jne 0x2899
jmp 0x28a5
movl $0x2, -0x4(%rbp)
jmp 0x2cc6
jmp 0x28a7
movq -0x98(%rbp), %rdi
movl 0x2c(%rdi), %eax
movl 0x90(%rdi), %ecx
movl $0x1, %edx
shll %cl, %edx
movl %edx, %ecx
subl $0x1, %ecx
andl %ecx, %eax
movl %eax, -0x38(%rbp)
movq %rdi, %rsi
addq $0x3ae, %rsi            # imm = 0x3AE
movl -0x34(%rbp), %eax
shll $0x4, %eax
addl -0x38(%rbp), %eax
movl %eax, %eax
shlq %rax
addq %rax, %rsi
callq 0x25c0
cmpl $0x0, %eax
jne 0x295a
testb $0x1, -0x11(%rbp)
je 0x2906
cmpq $0x0, -0x20(%rbp)
jne 0x2906
movl $0x0, -0x4(%rbp)
jmp 0x2cc6
movq -0x98(%rbp), %rdi
movl -0x34(%rbp), %esi
movl -0x24(%rbp), %edx
callq 0x3ec0
movq -0x98(%rbp), %rdi
movl $0x1, %esi
callq 0x4040
movq -0x98(%rbp), %rdi
addq $0x60, %rdi
movl $0x1, %esi
callq 0x40b0
movl -0x34(%rbp), %edi
callq 0x2760
movl %eax, -0x34(%rbp)
movq -0x20(%rbp), %rax
addq $-0x1, %rax
movq %rax, -0x20(%rbp)
jmp 0x286a
movq -0x98(%rbp), %rdi
movq %rdi, %rsi
addq $0x52e, %rsi            # imm = 0x52E
movl -0x34(%rbp), %eax
shlq %rax
addq %rax, %rsi
callq 0x25c0
cmpl $0x0, %eax
je 0x2b27
testb $0x1, -0x11(%rbp)
je 0x299b
cmpq $0x0, -0x20(%rbp)
jne 0x299b
movl $0x0, -0x4(%rbp)
jmp 0x2cc6
movq -0x98(%rbp), %rdi
addq $0x18, %rdi
callq 0x4180
testb $0x1, %al
jne 0x29b1
jmp 0x29bd
movl $0x0, -0x4(%rbp)
jmp 0x2cc6
movq -0x98(%rbp), %rdi
movq %rdi, %rsi
addq $0x546, %rsi            # imm = 0x546
movl -0x34(%rbp), %eax
shlq %rax
addq %rax, %rsi
callq 0x25c0
cmpl $0x0, %eax
jne 0x2a85
movq -0x98(%rbp), %rdi
movq %rdi, %rsi
addq $0x58e, %rsi            # imm = 0x58E
movl -0x34(%rbp), %eax
shll $0x4, %eax
addl -0x38(%rbp), %eax
movl %eax, %eax
shlq %rax
addq %rax, %rsi
callq 0x25c0
cmpl $0x0, %eax
jne 0x2a83
movl -0x34(%rbp), %edi
callq 0x27e0
movq -0x98(%rbp), %rdi
movl %eax, -0x34(%rbp)
movq %rdi, %rax
addq $0x18, %rax
movq %rax, -0xa0(%rbp)
addq $0x18, %rdi
movl -0x24(%rbp), %esi
addl $0x1, %esi
callq 0x4220
movq -0xa0(%rbp), %rdi
movzbl %al, %esi
callq 0x41b0
movq -0x98(%rbp), %rdi
movl $0x1, %esi
callq 0x4040
movq -0x98(%rbp), %rdi
addq $0x60, %rdi
xorl %esi, %esi
callq 0x40b0
movq -0x20(%rbp), %rax
addq $-0x1, %rax
movq %rax, -0x20(%rbp)
jmp 0x286a
jmp 0x2afb
movq -0x98(%rbp), %rdi
movq %rdi, %rsi
addq $0x55e, %rsi            # imm = 0x55E
movl -0x34(%rbp), %eax
shlq %rax
addq %rax, %rsi
callq 0x25c0
cmpl $0x0, %eax
jne 0x2ab1
movl -0x28(%rbp), %eax
movl %eax, -0x40(%rbp)
jmp 0x2aef
movq -0x98(%rbp), %rdi
movq %rdi, %rsi
addq $0x576, %rsi            # imm = 0x576
movl -0x34(%rbp), %eax
shlq %rax
addq %rax, %rsi
callq 0x25c0
cmpl $0x0, %eax
jne 0x2add
movl -0x2c(%rbp), %eax
movl %eax, -0x40(%rbp)
jmp 0x2ae9
movl -0x30(%rbp), %eax
movl %eax, -0x40(%rbp)
movl -0x2c(%rbp), %eax
movl %eax, -0x30(%rbp)
movl -0x28(%rbp), %eax
movl %eax, -0x2c(%rbp)
movl -0x24(%rbp), %eax
movl %eax, -0x28(%rbp)
movl -0x40(%rbp), %eax
movl %eax, -0x24(%rbp)
movq -0x98(%rbp), %rsi
movq %rsi, %rdi
addq $0xb12, %rdi            # imm = 0xB12
movl -0x38(%rbp), %edx
callq 0x4270
movl %eax, -0x3c(%rbp)
movl -0x34(%rbp), %edi
callq 0x27c0
movl %eax, -0x34(%rbp)
jmp 0x2beb
movq -0x98(%rbp), %rsi
movl -0x2c(%rbp), %eax
movl %eax, -0x30(%rbp)
movl -0x28(%rbp), %eax
movl %eax, -0x2c(%rbp)
movl -0x24(%rbp), %eax
movl %eax, -0x28(%rbp)
movq %rsi, %rdi
addq $0x70e, %rdi            # imm = 0x70E
movl -0x38(%rbp), %edx
callq 0x4270
movl %eax, -0x3c(%rbp)
movl -0x34(%rbp), %edi
callq 0x27a0
movq -0x98(%rbp), %rdi
movl %eax, -0x34(%rbp)
movl -0x3c(%rbp), %esi
callq 0x4320
movl %eax, -0x24(%rbp)
cmpl $-0x1, -0x24(%rbp)
jne 0x2b9b
movq -0x98(%rbp), %rdi
callq 0x3ea0
movb %al, %dl
xorl %eax, %eax
movl $0x1, %ecx
testb $0x1, %dl
cmovnel %ecx, %eax
movl %eax, -0x4(%rbp)
jmp 0x2cc6
testb $0x1, -0x11(%rbp)
je 0x2bb4
cmpq $0x0, -0x20(%rbp)
jne 0x2bb4
movl $0x0, -0x4(%rbp)
jmp 0x2cc6
movq -0x98(%rbp), %rcx
movl -0x24(%rbp), %eax
cmpl 0x98(%rcx), %eax
jae 0x2bdd
movq -0x98(%rbp), %rdi
addq $0x18, %rdi
movl -0x24(%rbp), %esi
callq 0x4420
testb $0x1, %al
jne 0x2be9
movl $0x0, -0x4(%rbp)
jmp 0x2cc6
jmp 0x2beb
movl -0x3c(%rbp), %eax
addl $0x2, %eax
movl %eax, -0x3c(%rbp)
movb $0x0, -0x41(%rbp)
testb $0x1, -0x11(%rbp)
je 0x2c15
movq -0x20(%rbp), %rax
movl -0x3c(%rbp), %ecx
cmpq %rcx, %rax
jae 0x2c15
movq -0x20(%rbp), %rax
movl %eax, -0x3c(%rbp)
movb $0x1, -0x41(%rbp)
movq -0x98(%rbp), %rdi
addq $0x18, %rdi
movl -0x24(%rbp), %esi
incl %esi
movl -0x3c(%rbp), %edx
callq 0x4460
movq -0x98(%rbp), %rdi
addq $0x60, %rdi
movq %rdi, -0xa8(%rbp)
callq 0x45d0
movl %edx, -0x70(%rbp)
movq %rax, -0x78(%rbp)
movq -0x78(%rbp), %rax
movq %rax, -0x68(%rbp)
movl -0x70(%rbp), %eax
movl %eax, -0x60(%rbp)
leaq -0x58(%rbp), %rdi
leaq -0x68(%rbp), %rsi
callq 0x45f0
movq -0xa8(%rbp), %rdi
movl -0x3c(%rbp), %eax
movl %eax, %ecx
movb $0x0, -0x79(%rbp)
movq -0x58(%rbp), %rsi
movl -0x50(%rbp), %edx
leaq -0x79(%rbp), %r8
callq 0x44b0
movq -0x98(%rbp), %rdi
movq %rax, -0x90(%rbp)
movl %edx, -0x88(%rbp)
movl -0x3c(%rbp), %esi
callq 0x4040
movl -0x3c(%rbp), %eax
movl %eax, %ecx
movq -0x20(%rbp), %rax
subq %rcx, %rax
movq %rax, -0x20(%rbp)
testb $0x1, -0x41(%rbp)
je 0x2cc1
movl $0x0, -0x4(%rbp)
jmp 0x2cc6
jmp 0x286a
movl -0x4(%rbp), %eax
addq $0xb0, %rsp
popq %rbp
retq
nopw %cs:(%rax,%rax)