// File: /workspace/github_c_makefile_star2_O0/jsummers[P]deark/modules/exepack.c
// Function: do_decompress_code
static void do_decompress_code(deark *c, lctx *d)
{
	i64 compressed_len;
	i64 uncompressed_len;
	u8 *buf = NULL;
	i64 buf_alloc;
	i64 src, dst;

	compressed_len = 16*(d->host_ei->regCS - d->ohdr.skip_len + 1);
	uncompressed_len = 16*(d->ohdr.dest_len - d->ohdr.skip_len + 1);
	de_dbg(c, "compressed data: pos=%"I64_FMT", len=%"I64_FMT", end=%"I64_FMT,
		d->host_ei->start_of_dos_code, compressed_len,
		d->host_ei->start_of_dos_code + compressed_len);
	de_dbg(c, "uncompressed len: %"I64_FMT, uncompressed_len);
	if(compressed_len<0 || uncompressed_len<0 ||
		(d->host_ei->start_of_dos_code+compressed_len > c->infile->len))
	{
		d->errflag = 1; goto done;
	};

	// TODO: It would be safer to do all the work inside a membuf, but the nature
	// of the EXEPACK algorithm could make that inefficient.
	buf_alloc = de_max_int(compressed_len, uncompressed_len);
	// Though the size is untrusted, it's impossible for it to be more than about 1MB.
	buf = de_malloc(c, buf_alloc);
	de_read(buf, d->host_ei->start_of_dos_code, compressed_len);

	src = compressed_len;
	dst = uncompressed_len;

	while(1) {
		u8 opcode;

		if(src<1) { d->errflag = 1; goto done; };
		opcode = buf[--src];

		if(opcode>=0xb0 && opcode<=0xb3) { // opcodes followed by a count
			UI i;
			UI count;

			if(src<2) { d->errflag = 1; goto done; };
			count = (UI)buf[--src];
			count = (count<<8) | buf[--src];
			if(dst<(i64)count) { d->errflag = 1; goto done; };

			if(opcode==0xb0 || opcode==0xb1) { // (run)
				u8 n;

				if(src<1) { d->errflag = 1; goto done; };
				n = buf[--src];
				for(i=0; i<count; i++) {
					buf[--dst] = n;
				}
			}
			else { // 0xb2 or 0xb3 (noncompressed bytes)
				if(src<(i64)count) { d->errflag = 1; goto done; };
				for(i=0; i<count; i++) {
					buf[--dst] = buf[--src];
				}
			}
		}
		else if(opcode==0xff && dst==uncompressed_len) {
			; // Filler byte(s) at the end of compressed data
		}
		else {
			d->errflag = 1;
			goto done;
		}

		if(opcode==0xb1 || opcode==0xb3) {
			break; // Normal completion
		}
	}

	dbuf_write(d->dcmpr_code, buf, uncompressed_len);
done:
	de_free(c, buf);
}

// Assembly:
pushq %rbp
movq %rsp, %rbp
subq $0x50, %rsp
movq %rdi, -0x8(%rbp)
movq %rsi, -0x10(%rbp)
movq $0x0, -0x28(%rbp)
movq -0x10(%rbp), %rax
movq 0x10(%rax), %rax
movq 0x20(%rax), %rax
movq -0x10(%rbp), %rcx
subq 0x78(%rcx), %rax
addq $0x1, %rax
shlq $0x4, %rax
movq %rax, -0x18(%rbp)
movq -0x10(%rbp), %rax
movq 0x70(%rax), %rax
movq -0x10(%rbp), %rcx
subq 0x78(%rcx), %rax
addq $0x1, %rax
shlq $0x4, %rax
movq %rax, -0x20(%rbp)
movq -0x8(%rbp), %rdi
movq -0x10(%rbp), %rax
movq 0x10(%rax), %rax
movq 0x38(%rax), %rdx
movq -0x18(%rbp), %rcx
movq -0x10(%rbp), %rax
movq 0x10(%rax), %rax
movq 0x38(%rax), %r8
addq -0x18(%rbp), %r8
leaq 0x145638(%rip), %rsi    # 0x1a97f7
movb $0x0, %al
callq 0x15b0d0
movq -0x8(%rbp), %rdi
movq -0x20(%rbp), %rdx
leaq 0x14564d(%rip), %rsi    # 0x1a9822
movb $0x0, %al
callq 0x15b0d0
cmpq $0x0, -0x18(%rbp)
jl 0x64208
cmpq $0x0, -0x20(%rbp)
jl 0x64208
movq -0x10(%rbp), %rax
movq 0x10(%rax), %rax
movq 0x38(%rax), %rax
addq -0x18(%rbp), %rax
movq -0x8(%rbp), %rcx
movq 0x18(%rcx), %rcx
cmpq 0x18(%rcx), %rax
jle 0x64217
movq -0x10(%rbp), %rax
movl $0x1, (%rax)
jmp 0x64461
movq -0x18(%rbp), %rdi
movq -0x20(%rbp), %rsi
callq 0x15cd20
movq %rax, -0x30(%rbp)
movq -0x8(%rbp), %rdi
movq -0x30(%rbp), %rsi
callq 0x15b780
movq %rax, -0x28(%rbp)
movq -0x8(%rbp), %rax
movq 0x18(%rax), %rdi
movq -0x28(%rbp), %rsi
movq -0x10(%rbp), %rax
movq 0x10(%rax), %rax
movq 0x38(%rax), %rdx
movq -0x18(%rbp), %rcx
callq 0x164d10
movq -0x18(%rbp), %rax
movq %rax, -0x38(%rbp)
movq -0x20(%rbp), %rax
movq %rax, -0x40(%rbp)
cmpq $0x1, -0x38(%rbp)
jge 0x64280
movq -0x10(%rbp), %rax
movl $0x1, (%rax)
jmp 0x64461
movq -0x28(%rbp), %rax
movq -0x38(%rbp), %rcx
movq %rcx, %rdx
addq $-0x1, %rdx
movq %rdx, -0x38(%rbp)
movb -0x1(%rax,%rcx), %al
movb %al, -0x41(%rbp)
movzbl -0x41(%rbp), %eax
cmpl $0xb0, %eax
jl 0x6440a
movzbl -0x41(%rbp), %eax
cmpl $0xb3, %eax
jg 0x6440a
cmpq $0x2, -0x38(%rbp)
jge 0x642ce
movq -0x10(%rbp), %rax
movl $0x1, (%rax)
jmp 0x64461
movq -0x28(%rbp), %rax
movq -0x38(%rbp), %rcx
movq %rcx, %rdx
addq $-0x1, %rdx
movq %rdx, -0x38(%rbp)
movzbl -0x1(%rax,%rcx), %eax
movl %eax, -0x4c(%rbp)
movl -0x4c(%rbp), %eax
shll $0x8, %eax
movq -0x28(%rbp), %rcx
movq -0x38(%rbp), %rdx
movq %rdx, %rsi
addq $-0x1, %rsi
movq %rsi, -0x38(%rbp)
movzbl -0x1(%rcx,%rdx), %ecx
orl %ecx, %eax
movl %eax, -0x4c(%rbp)
movq -0x40(%rbp), %rax
movl -0x4c(%rbp), %ecx
cmpq %rcx, %rax
jge 0x64327
movq -0x10(%rbp), %rax
movl $0x1, (%rax)
jmp 0x64461
movzbl -0x41(%rbp), %eax
cmpl $0xb0, %eax
je 0x6433d
movzbl -0x41(%rbp), %eax
cmpl $0xb1, %eax
jne 0x643a3
cmpq $0x1, -0x38(%rbp)
jge 0x64353
movq -0x10(%rbp), %rax
movl $0x1, (%rax)
jmp 0x64461
movq -0x28(%rbp), %rax
movq -0x38(%rbp), %rcx
movq %rcx, %rdx
addq $-0x1, %rdx
movq %rdx, -0x38(%rbp)
movb -0x1(%rax,%rcx), %al
movb %al, -0x4d(%rbp)
movl $0x0, -0x48(%rbp)
movl -0x48(%rbp), %eax
cmpl -0x4c(%rbp), %eax
jae 0x643a1
movb -0x4d(%rbp), %dl
movq -0x28(%rbp), %rax
movq -0x40(%rbp), %rcx
movq %rcx, %rsi
addq $-0x1, %rsi
movq %rsi, -0x40(%rbp)
movb %dl, -0x1(%rax,%rcx)
movl -0x48(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x48(%rbp)
jmp 0x64374
jmp 0x64408
movq -0x38(%rbp), %rax
movl -0x4c(%rbp), %ecx
cmpq %rcx, %rax
jge 0x643be
movq -0x10(%rbp), %rax
movl $0x1, (%rax)
jmp 0x64461
movl $0x0, -0x48(%rbp)
movl -0x48(%rbp), %eax
cmpl -0x4c(%rbp), %eax
jae 0x64406
movq -0x28(%rbp), %rax
movq -0x38(%rbp), %rcx
movq %rcx, %rdx
addq $-0x1, %rdx
movq %rdx, -0x38(%rbp)
movb -0x1(%rax,%rcx), %dl
movq -0x28(%rbp), %rax
movq -0x40(%rbp), %rcx
movq %rcx, %rsi
addq $-0x1, %rsi
movq %rsi, -0x40(%rbp)
movb %dl, -0x1(%rax,%rcx)
movl -0x48(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x48(%rbp)
jmp 0x643c5
jmp 0x64408
jmp 0x6442f
movzbl -0x41(%rbp), %eax
cmpl $0xff, %eax
jne 0x64421
movq -0x40(%rbp), %rax
cmpq -0x20(%rbp), %rax
jne 0x64421
jmp 0x6442d
movq -0x10(%rbp), %rax
movl $0x1, (%rax)
jmp 0x64461
jmp 0x6442f
movzbl -0x41(%rbp), %eax
cmpl $0xb1, %eax
je 0x64445
movzbl -0x41(%rbp), %eax
cmpl $0xb3, %eax
jne 0x64447
jmp 0x6444c
jmp 0x6426a
movq -0x10(%rbp), %rax
movq 0x40(%rax), %rdi
movq -0x28(%rbp), %rsi
movq -0x20(%rbp), %rdx
callq 0x166170
movq -0x8(%rbp), %rdi
movq -0x28(%rbp), %rsi
callq 0x15b820
addq $0x50, %rsp
popq %rbp
retq
nopw %cs:(%rax,%rax)