// File: twekkel[P]mzpq/libzpaq.cpp
// Function: libzpaq::Compiler::compile_comp(libzpaq::ZPAQL&)
int Compiler::compile_comp(ZPAQL& z) {
  int op=0;
  const int comp_begin=z.hend;
  while (true) {
    op=rtoken(opcodelist);
    if (op==POST || op==PCOMP || op==END) break;
    int operand=-1; // 0...255 if 2 bytes
    int operand2=-1;  // 0...255 if 3 bytes
    if (op==IF) {
      op=JF;
      operand=0; // set later
      if_stack.push(z.hend+1); // save jump target location
    }
    else if (op==IFNOT) {
      op=JT;
      operand=0;
      if_stack.push(z.hend+1); // save jump target location
    }
    else if (op==IFL || op==IFNOTL) {  // long if
      if (op==IFL) z.header[z.hend++]=(JT);
      if (op==IFNOTL) z.header[z.hend++]=(JF);
      z.header[z.hend++]=(3);
      op=LJ;
      operand=operand2=0;
      if_stack.push(z.hend+1);
    }
    else if (op==ELSE || op==ELSEL) {
      if (op==ELSE) op=JMP, operand=0;
      if (op==ELSEL) op=LJ, operand=operand2=0;
      int a=if_stack.pop();  // conditional jump target location
      assert(a>comp_begin && a<int(z.hend));
      if (z.header[a-1]!=LJ) {  // IF, IFNOT
        assert(z.header[a-1]==JT || z.header[a-1]==JF || z.header[a-1]==JMP);
        int j=z.hend-a+1+(op==LJ); // offset at IF
        assert(j>=0);
        if (j>127) syntaxError("IF too big, try IFL, IFNOTL");
        z.header[a]=j;
      }
      else {  // IFL, IFNOTL
        int j=z.hend-comp_begin+2+(op==LJ);
        assert(j>=0);
        z.header[a]=j&255;
        z.header[a+1]=(j>>8)&255;
      }
      if_stack.push(z.hend+1);  // save JMP target location
    }
    else if (op==ENDIF) {
      int a=if_stack.pop();  // jump target address
      assert(a>comp_begin && a<int(z.hend));
      int j=z.hend-a-1;  // jump offset
      assert(j>=0);
      if (z.header[a-1]!=LJ) {
        assert(z.header[a-1]==JT || z.header[a-1]==JF || z.header[a-1]==JMP);
        if (j>127) syntaxError("IF too big, try IFL, IFNOTL, ELSEL\n");
        z.header[a]=j;
      }
      else {
        assert(a+1<int(z.hend));
        j=z.hend-comp_begin;
        z.header[a]=j&255;
        z.header[a+1]=(j>>8)&255;
      }
    }
    else if (op==DO) {
      do_stack.push(z.hend);
    }
    else if (op==WHILE || op==UNTIL || op==FOREVER) {
      int a=do_stack.pop();
      assert(a>=comp_begin && a<int(z.hend));
      int j=a-z.hend-2;
      assert(j<=-2);
      if (j>=-127) {  // backward short jump
        if (op==WHILE) op=JT;
        if (op==UNTIL) op=JF;
        if (op==FOREVER) op=JMP;
        operand=j&255;
      }
      else {  // backward long jump
        j=a-comp_begin;
        assert(j>=0 && j<int(z.hend)-comp_begin);
        if (op==WHILE) {
          z.header[z.hend++]=(JF);
          z.header[z.hend++]=(3);
        }
        if (op==UNTIL) {
          z.header[z.hend++]=(JT);
          z.header[z.hend++]=(3);
        }
        op=LJ;
        operand=j&255;
        operand2=j>>8;
      }
    }
    else if ((op&7)==7) { // 2 byte operand, read N
      if (op==LJ) {
        operand=rtoken(0, 65535);
        operand2=operand>>8;
        operand&=255;
      }
      else if (op==JT || op==JF || op==JMP) {
        operand=rtoken(-128, 127);
        operand&=255;
      }
      else
        operand=rtoken(0, 255);
    }
    if (op>=0 && op<=255)
      z.header[z.hend++]=(op);
    if (operand>=0)
      z.header[z.hend++]=(operand);
    if (operand2>=0)
      z.header[z.hend++]=(operand2);
    if (z.hend>=z.header.isize()-130 || z.hend-z.hbegin+z.cend-2>65535)
      syntaxError("program too big");
  }
  z.header[z.hend++]=(0); // END
  return op;
}

// Assembly:
pushq %rbp
movq %rsp, %rbp
subq $0x70, %rsp
movq %rdi, -0x8(%rbp)
movq %rsi, -0x10(%rbp)
movq -0x8(%rbp), %rax
movq %rax, -0x58(%rbp)
movl $0x0, -0x14(%rbp)
movq -0x10(%rbp), %rax
movl 0x30(%rax), %eax
movl %eax, -0x18(%rbp)
movq -0x58(%rbp), %rdi
leaq 0x2cd0c(%rip), %rsi     # 0x41ad0
callq 0x14b70
movl %eax, -0x14(%rbp)
cmpl $0x100, -0x14(%rbp)     # imm = 0x100
je 0x14de7
cmpl $0x101, -0x14(%rbp)     # imm = 0x101
je 0x14de7
cmpl $0x102, -0x14(%rbp)     # imm = 0x102
jne 0x14dec
jmp 0x15486
movl $0xffffffff, -0x1c(%rbp) # imm = 0xFFFFFFFF
movl $0xffffffff, -0x20(%rbp) # imm = 0xFFFFFFFF
cmpl $0x103, -0x14(%rbp)     # imm = 0x103
jne 0x14e35
movq -0x58(%rbp), %rdi
movl $0x2f, -0x14(%rbp)
movl $0x0, -0x1c(%rbp)
addq $0x30, %rdi
movq -0x10(%rbp), %rax
movl 0x30(%rax), %eax
addl $0x1, %eax
movw %ax, -0x22(%rbp)
leaq -0x22(%rbp), %rsi
callq 0x310f0
jmp 0x1538f
cmpl $0x104, -0x14(%rbp)     # imm = 0x104
jne 0x14e70
movq -0x58(%rbp), %rdi
movl $0x27, -0x14(%rbp)
movl $0x0, -0x1c(%rbp)
addq $0x30, %rdi
movq -0x10(%rbp), %rax
movl 0x30(%rax), %eax
addl $0x1, %eax
movw %ax, -0x24(%rbp)
leaq -0x24(%rbp), %rsi
callq 0x310f0
jmp 0x1538d
cmpl $0x10b, -0x14(%rbp)     # imm = 0x10B
je 0x14e86
cmpl $0x10c, -0x14(%rbp)     # imm = 0x10C
jne 0x14f37
cmpl $0x10b, -0x14(%rbp)     # imm = 0x10B
jne 0x14eb1
movq -0x10(%rbp), %rdi
addq $0x10, %rdi
movq -0x10(%rbp), %rcx
movl 0x30(%rcx), %eax
movl %eax, %edx
addl $0x1, %edx
movl %edx, 0x30(%rcx)
movslq %eax, %rsi
callq 0x30630
movb $0x27, (%rax)
cmpl $0x10c, -0x14(%rbp)     # imm = 0x10C
jne 0x14edc
movq -0x10(%rbp), %rdi
addq $0x10, %rdi
movq -0x10(%rbp), %rcx
movl 0x30(%rcx), %eax
movl %eax, %edx
addl $0x1, %edx
movl %edx, 0x30(%rcx)
movslq %eax, %rsi
callq 0x30630
movb $0x2f, (%rax)
movq -0x10(%rbp), %rdi
addq $0x10, %rdi
movq -0x10(%rbp), %rcx
movl 0x30(%rcx), %eax
movl %eax, %edx
addl $0x1, %edx
movl %edx, 0x30(%rcx)
movslq %eax, %rsi
callq 0x30630
movq -0x58(%rbp), %rdi
movb $0x3, (%rax)
movl $0xff, -0x14(%rbp)
movl $0x0, -0x20(%rbp)
movl $0x0, -0x1c(%rbp)
addq $0x30, %rdi
movq -0x10(%rbp), %rax
movl 0x30(%rax), %eax
addl $0x1, %eax
movw %ax, -0x26(%rbp)
leaq -0x26(%rbp), %rsi
callq 0x310f0
jmp 0x1538b
cmpl $0x105, -0x14(%rbp)     # imm = 0x105
je 0x14f4d
cmpl $0x10d, -0x14(%rbp)     # imm = 0x10D
jne 0x1509f
cmpl $0x105, -0x14(%rbp)     # imm = 0x105
jne 0x14f64
movl $0x3f, -0x14(%rbp)
movl $0x0, -0x1c(%rbp)
cmpl $0x10d, -0x14(%rbp)     # imm = 0x10D
jne 0x14f82
movl $0xff, -0x14(%rbp)
movl $0x0, -0x20(%rbp)
movl $0x0, -0x1c(%rbp)
movq -0x58(%rbp), %rdi
addq $0x30, %rdi
callq 0x31160
movzwl %ax, %eax
movl %eax, -0x2c(%rbp)
movq -0x10(%rbp), %rdi
addq $0x10, %rdi
movl -0x2c(%rbp), %eax
subl $0x1, %eax
movslq %eax, %rsi
callq 0x30630
movzbl (%rax), %eax
cmpl $0xff, %eax
je 0x1500f
movq -0x10(%rbp), %rax
movl 0x30(%rax), %eax
subl -0x2c(%rbp), %eax
addl $0x1, %eax
cmpl $0xff, -0x14(%rbp)
sete %cl
andb $0x1, %cl
movzbl %cl, %ecx
addl %ecx, %eax
movl %eax, -0x30(%rbp)
cmpl $0x7f, -0x30(%rbp)
jle 0x14ff1
movq -0x58(%rbp), %rdi
leaq 0x2369d(%rip), %rsi     # 0x38685
xorl %eax, %eax
movl %eax, %edx
callq 0x149a0
movl -0x30(%rbp), %eax
movb %al, -0x59(%rbp)
movq -0x10(%rbp), %rdi
addq $0x10, %rdi
movslq -0x2c(%rbp), %rsi
callq 0x30630
movb -0x59(%rbp), %cl
movb %cl, (%rax)
jmp 0x1507b
movq -0x10(%rbp), %rax
movl 0x30(%rax), %eax
subl -0x18(%rbp), %eax
addl $0x2, %eax
cmpl $0xff, -0x14(%rbp)
sete %cl
andb $0x1, %cl
movzbl %cl, %ecx
addl %ecx, %eax
movl %eax, -0x34(%rbp)
movl -0x34(%rbp), %eax
andl $0xff, %eax
movb %al, -0x5b(%rbp)
movq -0x10(%rbp), %rdi
addq $0x10, %rdi
movslq -0x2c(%rbp), %rsi
callq 0x30630
movb -0x5b(%rbp), %cl
movb %cl, (%rax)
movl -0x34(%rbp), %eax
sarl $0x8, %eax
andl $0xff, %eax
movb %al, -0x5a(%rbp)
movq -0x10(%rbp), %rdi
addq $0x10, %rdi
movl -0x2c(%rbp), %eax
addl $0x1, %eax
movslq %eax, %rsi
callq 0x30630
movb -0x5a(%rbp), %cl
movb %cl, (%rax)
movq -0x58(%rbp), %rdi
addq $0x30, %rdi
movq -0x10(%rbp), %rax
movl 0x30(%rax), %eax
addl $0x1, %eax
movw %ax, -0x36(%rbp)
leaq -0x36(%rbp), %rsi
callq 0x310f0
jmp 0x15389
cmpl $0x106, -0x14(%rbp)     # imm = 0x106
jne 0x15183
movq -0x58(%rbp), %rdi
addq $0x30, %rdi
callq 0x31160
movzwl %ax, %eax
movl %eax, -0x3c(%rbp)
movq -0x10(%rbp), %rax
movl 0x30(%rax), %eax
subl -0x3c(%rbp), %eax
subl $0x1, %eax
movl %eax, -0x40(%rbp)
movq -0x10(%rbp), %rdi
addq $0x10, %rdi
movl -0x3c(%rbp), %eax
subl $0x1, %eax
movslq %eax, %rsi
callq 0x30630
movzbl (%rax), %eax
cmpl $0xff, %eax
je 0x15127
cmpl $0x7f, -0x40(%rbp)
jle 0x15109
movq -0x58(%rbp), %rdi
leaq 0x235a1(%rip), %rsi     # 0x386a1
xorl %eax, %eax
movl %eax, %edx
callq 0x149a0
movl -0x40(%rbp), %eax
movb %al, -0x5c(%rbp)
movq -0x10(%rbp), %rdi
addq $0x10, %rdi
movslq -0x3c(%rbp), %rsi
callq 0x30630
movb -0x5c(%rbp), %cl
movb %cl, (%rax)
jmp 0x1517e
movq -0x10(%rbp), %rax
movl 0x30(%rax), %eax
subl -0x18(%rbp), %eax
movl %eax, -0x40(%rbp)
movl -0x40(%rbp), %eax
andl $0xff, %eax
movb %al, -0x5e(%rbp)
movq -0x10(%rbp), %rdi
addq $0x10, %rdi
movslq -0x3c(%rbp), %rsi
callq 0x30630
movb -0x5e(%rbp), %cl
movb %cl, (%rax)
movl -0x40(%rbp), %eax
sarl $0x8, %eax
andl $0xff, %eax
movb %al, -0x5d(%rbp)
movq -0x10(%rbp), %rdi
addq $0x10, %rdi
movl -0x3c(%rbp), %eax
addl $0x1, %eax
movslq %eax, %rsi
callq 0x30630
movb -0x5d(%rbp), %cl
movb %cl, (%rax)
jmp 0x15387
cmpl $0x107, -0x14(%rbp)     # imm = 0x107
jne 0x151ad
movq -0x58(%rbp), %rdi
addq $0x50, %rdi
movq -0x10(%rbp), %rax
movl 0x30(%rax), %eax
movw %ax, -0x42(%rbp)
leaq -0x42(%rbp), %rsi
callq 0x310f0
jmp 0x15385
cmpl $0x108, -0x14(%rbp)     # imm = 0x108
je 0x151cc
cmpl $0x109, -0x14(%rbp)     # imm = 0x109
je 0x151cc
cmpl $0x10a, -0x14(%rbp)     # imm = 0x10A
jne 0x152f8
movq -0x58(%rbp), %rdi
addq $0x50, %rdi
callq 0x31160
movzwl %ax, %eax
movl %eax, -0x48(%rbp)
movl -0x48(%rbp), %eax
movq -0x10(%rbp), %rcx
subl 0x30(%rcx), %eax
subl $0x2, %eax
movl %eax, -0x4c(%rbp)
cmpl $-0x7f, -0x4c(%rbp)
jl 0x15235
cmpl $0x108, -0x14(%rbp)     # imm = 0x108
jne 0x15205
movl $0x27, -0x14(%rbp)
cmpl $0x109, -0x14(%rbp)     # imm = 0x109
jne 0x15215
movl $0x2f, -0x14(%rbp)
cmpl $0x10a, -0x14(%rbp)     # imm = 0x10A
jne 0x15225
movl $0x3f, -0x14(%rbp)
movl -0x4c(%rbp), %eax
andl $0xff, %eax
movl %eax, -0x1c(%rbp)
jmp 0x152f3
movl -0x48(%rbp), %eax
subl -0x18(%rbp), %eax
movl %eax, -0x4c(%rbp)
cmpl $0x108, -0x14(%rbp)     # imm = 0x108
jne 0x1528b
movq -0x10(%rbp), %rdi
addq $0x10, %rdi
movq -0x10(%rbp), %rcx
movl 0x30(%rcx), %eax
movl %eax, %edx
addl $0x1, %edx
movl %edx, 0x30(%rcx)
movslq %eax, %rsi
callq 0x30630
movb $0x2f, (%rax)
movq -0x10(%rbp), %rdi
addq $0x10, %rdi
movq -0x10(%rbp), %rcx
movl 0x30(%rcx), %eax
movl %eax, %edx
addl $0x1, %edx
movl %edx, 0x30(%rcx)
movslq %eax, %rsi
callq 0x30630
movb $0x3, (%rax)
cmpl $0x109, -0x14(%rbp)     # imm = 0x109
jne 0x152d8
movq -0x10(%rbp), %rdi
addq $0x10, %rdi
movq -0x10(%rbp), %rcx
movl 0x30(%rcx), %eax
movl %eax, %edx
addl $0x1, %edx
movl %edx, 0x30(%rcx)
movslq %eax, %rsi
callq 0x30630
movb $0x27, (%rax)
movq -0x10(%rbp), %rdi
addq $0x10, %rdi
movq -0x10(%rbp), %rcx
movl 0x30(%rcx), %eax
movl %eax, %edx
addl $0x1, %edx
movl %edx, 0x30(%rcx)
movslq %eax, %rsi
callq 0x30630
movb $0x3, (%rax)
movl $0xff, -0x14(%rbp)
movl -0x4c(%rbp), %eax
andl $0xff, %eax
movl %eax, -0x1c(%rbp)
movl -0x4c(%rbp), %eax
sarl $0x8, %eax
movl %eax, -0x20(%rbp)
jmp 0x15383
movl -0x14(%rbp), %eax
andl $0x7, %eax
cmpl $0x7, %eax
jne 0x15381
cmpl $0xff, -0x14(%rbp)
jne 0x15335
movq -0x58(%rbp), %rdi
xorl %esi, %esi
movl $0xffff, %edx           # imm = 0xFFFF
callq 0x14c50
movl %eax, -0x1c(%rbp)
movl -0x1c(%rbp), %eax
sarl $0x8, %eax
movl %eax, -0x20(%rbp)
movl -0x1c(%rbp), %eax
andl $0xff, %eax
movl %eax, -0x1c(%rbp)
jmp 0x1537f
cmpl $0x27, -0x14(%rbp)
je 0x15347
cmpl $0x2f, -0x14(%rbp)
je 0x15347
cmpl $0x3f, -0x14(%rbp)
jne 0x1536a
movq -0x58(%rbp), %rdi
movl $0xffffff80, %esi       # imm = 0xFFFFFF80
movl $0x7f, %edx
callq 0x14c50
movl %eax, -0x1c(%rbp)
movl -0x1c(%rbp), %eax
andl $0xff, %eax
movl %eax, -0x1c(%rbp)
jmp 0x1537d
movq -0x58(%rbp), %rdi
xorl %esi, %esi
movl $0xff, %edx
callq 0x14c50
movl %eax, -0x1c(%rbp)
jmp 0x1537f
jmp 0x15381
jmp 0x15383
jmp 0x15385
jmp 0x15387
jmp 0x15389
jmp 0x1538b
jmp 0x1538d
jmp 0x1538f
cmpl $0x0, -0x14(%rbp)
jl 0x153c8
cmpl $0xff, -0x14(%rbp)
jg 0x153c8
movl -0x14(%rbp), %eax
movb %al, -0x5f(%rbp)
movq -0x10(%rbp), %rdi
addq $0x10, %rdi
movq -0x10(%rbp), %rcx
movl 0x30(%rcx), %eax
movl %eax, %edx
addl $0x1, %edx
movl %edx, 0x30(%rcx)
movslq %eax, %rsi
callq 0x30630
movb -0x5f(%rbp), %cl
movb %cl, (%rax)
cmpl $0x0, -0x1c(%rbp)
jl 0x153f8
movl -0x1c(%rbp), %eax
movb %al, -0x60(%rbp)
movq -0x10(%rbp), %rdi
addq $0x10, %rdi
movq -0x10(%rbp), %rcx
movl 0x30(%rcx), %eax
movl %eax, %edx
addl $0x1, %edx
movl %edx, 0x30(%rcx)
movslq %eax, %rsi
callq 0x30630
movb -0x60(%rbp), %cl
movb %cl, (%rax)
cmpl $0x0, -0x20(%rbp)
jl 0x15428
movl -0x20(%rbp), %eax
movb %al, -0x61(%rbp)
movq -0x10(%rbp), %rdi
addq $0x10, %rdi
movq -0x10(%rbp), %rcx
movl 0x30(%rcx), %eax
movl %eax, %edx
addl $0x1, %edx
movl %edx, 0x30(%rcx)
movslq %eax, %rsi
callq 0x30630
movb -0x61(%rbp), %cl
movb %cl, (%rax)
movq -0x10(%rbp), %rax
movl 0x30(%rax), %eax
movl %eax, -0x68(%rbp)
movq -0x10(%rbp), %rdi
addq $0x10, %rdi
callq 0x30f70
movl %eax, %ecx
movl -0x68(%rbp), %eax
subl $0x82, %ecx
cmpl %ecx, %eax
jge 0x1546d
movq -0x10(%rbp), %rax
movl 0x30(%rax), %eax
movq -0x10(%rbp), %rcx
subl 0x2c(%rcx), %eax
movq -0x10(%rbp), %rcx
addl 0x28(%rcx), %eax
subl $0x2, %eax
cmpl $0xffff, %eax           # imm = 0xFFFF
jle 0x15481
movq -0x58(%rbp), %rdi
leaq 0x2324d(%rip), %rsi     # 0x386c5
xorl %eax, %eax
movl %eax, %edx
callq 0x149a0
jmp 0x14db9
movq -0x10(%rbp), %rdi
addq $0x10, %rdi
movq -0x10(%rbp), %rcx
movl 0x30(%rcx), %eax
movl %eax, %edx
addl $0x1, %edx
movl %edx, 0x30(%rcx)
movslq %eax, %rsi
callq 0x30630
movb $0x0, (%rax)
movl -0x14(%rbp), %eax
addq $0x70, %rsp
popq %rbp
retq
nopw %cs:(%rax,%rax)