// File: /workspace/github_c_makefile_star2_O3/lmcilroy[P]lzm/lzmdecode.c
// Function: lzm_decode
unsigned int
lzm_decode(
    const struct lzm_state * const state,
    const unsigned char * const buffer_in,
    const unsigned int size_in,
    unsigned char * const buffer_out,
    unsigned int * const size_out)
{
	const unsigned char * const end = buffer_in + size_in;
	const unsigned char * const match_end = end - 5;
	const unsigned char *curr_in = (const unsigned char *) buffer_in;
	unsigned char *curr_out = (unsigned char *) buffer_out;
	const unsigned char * const out_limit = buffer_out + *size_out;
	const unsigned char *out_limit_fast_path;
	unsigned char *match;
	unsigned char *mend;
	unsigned long int c;
	unsigned int llen;
	unsigned int mlen;
	unsigned int off = 1;
	unsigned char op;

	(void)state;

	if (buffer_in == NULL || buffer_out == NULL)
		return EINVAL;

	out_limit_fast_path = (*size_out < (14 + 14 + MIN_MATCH)) ? NULL :
		out_limit - (14 + 14 + MIN_MATCH);

	while (likely(curr_in <= match_end)) {
		op = *curr_in++;
		llen = op >> 4;
		mlen = (op & 15) + MIN_MATCH;

		curr_in = decode_offset(curr_in, &off);

		if (likely(llen < 15 && (curr_in + 16) <= end &&
		    curr_out <= out_limit_fast_path)) {
			LOG("L %d\n", llen);
			memcpy(curr_out, curr_in, 16);
			curr_out += llen;
			curr_in += llen;
			if (unlikely(off > (curr_out - buffer_out)))
				return EIO;
			if (likely(mlen < (15 + MIN_MATCH) &&
			    likely(((off >= mlen) | (off >= 8))))) {
				LOG("M %d %d\n", mlen, off);
				match = curr_out - off;
				memcpy(curr_out, match, 8);
				memcpy(curr_out+8, match+8, 8);
				memcpy(curr_out+16, match+16, 2);
				curr_out += mlen;
				continue;
			}
			goto match;
		}

		if (likely(llen > 0)) {
			if (unlikely(llen == 15)) {
				if (unlikely(curr_in >= end - 15))
					return EIO;

				curr_in = decode_length(curr_in, &llen);
				llen += 15;
			}
			LOG("L %d\n", llen);
			if (unlikely((curr_in + llen) > end))
				return EIO;
			if (unlikely((curr_out + llen) > out_limit))
				return EOVERFLOW;
			memcpy(curr_out, curr_in, llen);
			curr_in += llen;
			curr_out += llen;
		}

		if (unlikely(off > (curr_out - buffer_out)))
			return EIO;

 match:
		if (unlikely(off == 0))
			break;

		if (likely(mlen < (15 + MIN_MATCH) && off >= mlen &&
		    (curr_out + (14 + MIN_MATCH)) <= out_limit)) {
			LOG("M %d %d\n", mlen, off);
			match = curr_out - off;
			memcpy(curr_out, match, 8);
			memcpy(curr_out+8, match+8, 8);
			memcpy(curr_out+16, match+16, 2);
			curr_out += mlen;
			continue;
		}

		if (likely(mlen == (15 + MIN_MATCH))) {
			if (unlikely(curr_in >= match_end))
				return EIO;

			curr_in = decode_length(curr_in, &mlen);
			mlen += 15 + MIN_MATCH;
		}

		LOG("M %d %d\n", mlen, off);
		if (unlikely((curr_out + mlen) > out_limit))
			return EOVERFLOW;

		match = curr_out - off;
		mend = curr_out + mlen;

		if (likely(mlen <= off)) {
			memcpy(curr_out, match, mlen);
			curr_out += mlen;
			continue;
		}

		if (off == 1) {
			c = *match;
			*curr_out++ = c;
			*curr_out++ = c;
			*curr_out++ = c;
			*curr_out++ = c;
			while (curr_out < mend)
				*curr_out++ = c;
			continue;
		}

		if (off == 2) {
			c = readmem16(match);
			writemem16(curr_out, c);
			curr_out += 2;
			writemem16(curr_out, c);
			curr_out += 2;
			while (curr_out < mend) {
				writemem16(curr_out, c);
				curr_out += 2;
				writemem16(curr_out, c);
				curr_out += 2;
			}
			curr_out = mend;
			continue;
		}

		if (off == 3) {
			unsigned char c1, c2, c3;
			c1 = *match;
			c2 = *(match+1);
			c3 = *(match+2);
			*curr_out++ = c1;
			*curr_out++ = c2;
			*curr_out++ = c3;
			*curr_out++ = c1;
			*curr_out++ = c2;
			*curr_out++ = c3;
			while (curr_out < mend) {
				*curr_out++ = c1;
				*curr_out++ = c2;
				*curr_out++ = c3;
			}
			curr_out = mend;
		}

		if (off == 4) {
			c = readmem32(match);
			writemem32(curr_out, c);
			curr_out += off;
			writemem32(curr_out, c);
			curr_out += off;
			while (curr_out < mend) {
				writemem32(curr_out, c);
				curr_out += off;
				writemem32(curr_out, c);
				curr_out += off;
			}
			curr_out = mend;
			continue;
		}

		if (off <= 8) {
			c = readmem64(match);
			writemem64(curr_out, c);
			curr_out += off;
			while (curr_out < mend) {
				writemem64(curr_out, c);
				curr_out += off;
			}
			curr_out = mend;
			continue;
		}

		memcpy(curr_out, match, 4);
		match += 4;
		curr_out += 4;
		while (curr_out < mend) {
			memcpy(curr_out, match, 8);
			match += 8;
			curr_out += 8;
		}
		curr_out = mend;
	}

	*size_out = curr_out - buffer_out;

	/* Finished without seeing end of stream? */
	if (off != 0)
		return EIO;

	return 0;
}

// Assembly:
movq %rcx, %rdi
testq %rsi, %rsi
sete %al
testq %rcx, %rcx
sete %cl
orb %al, %cl
je 0x27c6
pushq $0x16
popq %rax
retq
pushq %rbp
pushq %r15
pushq %r14
pushq %r13
pushq %r12
pushq %rbx
subq $0x38, %rsp
movl %edx, %r9d
leaq (%rsi,%r9), %r10
addq $-0x5, %r10
movl (%r8), %eax
movq %rax, %r11
addq %rdi, %r11
leaq -0x20(%r11), %rcx
xorl %edx, %edx
cmpl $0x20, %eax
cmovaeq %rcx, %rdx
movq %rdx, (%rsp)
cmpq %rsi, %r10
jb 0x2cbc
movq %r8, 0x18(%rsp)
addq %rsi, %r9
leaq -0xf(%r9), %rax
movq %rax, 0x20(%rsp)
movq %rdi, %r15
movq %r10, 0x10(%rsp)
movq (%rsp), %r8
movq %rdi, 0x28(%rsp)
movq %r11, 0x8(%rsp)
movzbl (%rsi), %r13d
movl %r13d, %eax
shrl $0x4, %eax
andl $0xf, %r13d
movl 0x1(%rsi), %r14d
bsfl %r14d, %edx
leal 0x1(%rdx), %ecx
leaq 0x4037(%rip), %rbx      # 0x6880
andl (%rbx,%rcx,4), %r14d
shrq %cl, %r14
leaq 0x4(%r13), %rbx
leaq (%rdx,%rsi), %r12
addq $0x2, %r12
movl %r14d, %ebp
cmpl $0xf, %eax
je 0x28ef
leaq (%rdx,%rsi), %rcx
addq $0x12, %rcx
cmpq %r9, %rcx
ja 0x28ef
cmpq %r8, %r15
ja 0x28ef
movdqu (%r12), %xmm0
movdqu %xmm0, (%r15)
addq %rax, %r15
movq %r15, %rcx
subq %rdi, %rcx
cmpq %rbp, %rcx
jl 0x2c90
addq %rax, %r12
cmpl $0xf, %r13d
je 0x295f
cmpl %ebx, %r14d
setb %al
cmpl $0x8, %r14d
setb %cl
testb %cl, %al
jne 0x295f
movq %r15, %rax
subq %rbp, %rax
movq (%rax), %rcx
movq %rcx, (%r15)
movq 0x8(%rax), %rax
movq %rax, 0x8(%r15)
negq %rbp
movzwl 0x10(%r15,%rbp), %eax
movw %ax, 0x10(%r15)
addq %rbx, %r15
movq %r12, %rsi
cmpq %r10, %r12
jbe 0x2829
jmp 0x2c95
testl %eax, %eax
je 0x2a0c
cmpl $0xf, %eax
je 0x2a14
movl %eax, %edx
leaq (%r12,%rdx), %rcx
cmpq %r9, %rcx
ja 0x2c90
leaq (%r15,%rdx), %rax
cmpq %r11, %rax
ja 0x2cc8
movq %r15, %rdi
movq %r12, %rsi
movq %r9, %r15
movq %rax, %r12
movq %rcx, 0x30(%rsp)
callq 0x11c0
movq %r12, %rcx
movq 0x8(%rsp), %r11
movq 0x10(%rsp), %r10
movq %r15, %r9
movq 0x28(%rsp), %rdi
movq %r12, %r15
movq 0x30(%rsp), %r12
movq %rcx, %rax
subq %rdi, %rax
cmpq %rbp, %rax
jge 0x2962
jmp 0x2c90
movq %r15, %rcx
testl %r14d, %r14d
je 0x2cc4
cmpl $0xf, %r13d
je 0x29aa
cmpl %ebx, %r14d
jb 0x29aa
leaq 0x12(%r15), %rax
cmpq %r11, %rax
ja 0x29aa
movq %r15, %rax
subq %rbp, %rax
movq (%rax), %rcx
movq %rcx, (%r15)
movq 0x8(%rax), %rcx
movq %rcx, 0x8(%r15)
movzwl 0x10(%rax), %eax
movw %ax, 0x10(%r15)
movl %ebx, %eax
addq %rax, %r15
movq (%rsp), %r8
jmp 0x28de
cmpl $0x13, %ebx
jne 0x29cf
cmpq %r10, %r12
jae 0x2c90
movzbl (%r12), %ebx
cmpl $0xfc, %ebx
jae 0x2aa5
incq %r12
addl $0x13, %ebx
movl %ebx, %edx
leaq (%r15,%rdx), %rbx
cmpq %r11, %rbx
ja 0x2cc8
movq %r9, %rbp
movq %rdi, %r13
movq %r15, %rsi
subq %r14, %rsi
cmpl %r14d, %edx
ja 0x2a3a
movq %r15, %rdi
callq 0x11c0
movq %rbx, %r15
movq %r13, %rdi
movq %rbp, %r9
movq 0x10(%rsp), %r10
movq 0x8(%rsp), %r11
jmp 0x29a1
movq %r15, %rcx
jmp 0x294f
cmpq 0x20(%rsp), %r12
jae 0x2c90
movzbl (%r12), %eax
cmpl $0xfc, %eax
jae 0x2b7e
incq %r12
addl $0xf, %eax
jmp 0x2900
movq %rdx, %r8
cmpl $0x3, %r14d
je 0x2ac0
cmpl $0x2, %r14d
je 0x2b4d
cmpl $0x1, %r14d
jne 0x2b07
movzbl (%rsi), %eax
leaq 0x4(%r15), %rdi
movd %eax, %xmm0
punpcklbw %xmm0, %xmm0    # xmm0 = xmm0[0,0,1,1,2,2,3,3,4,4,5,5,6,6,7,7]
pshuflw $0x0, %xmm0, %xmm0      # xmm0 = xmm0[0,0,0,0,4,5,6,7]
movd %xmm0, (%r15)
cmpl $0x5, %r8d
jb 0x2bb4
movq %rcx, %rdx
movq %r8, %rbx
addq %rcx, %rbx
addq $0x5, %rcx
cmpq %rcx, %rbx
cmovbeq %rcx, %rbx
subq %rdx, %rbx
leaq -0x4(%rbx), %rdx
movzbl %al, %esi
callq 0x1120
addq %rbx, %r15
jmp 0x29fa
jne 0x2bea
movzbl 0x1(%r12), %ebx
addl $0xfc, %ebx
addq $0x2, %r12
jmp 0x29cc
movb (%rsi), %al
movb 0x1(%rsi), %cl
movb 0x2(%rsi), %dl
movb %al, (%r15)
movb %cl, 0x1(%r15)
movb %dl, 0x2(%r15)
movb %al, 0x3(%r15)
movb %cl, 0x4(%r15)
movb %dl, 0x5(%r15)
movq %rbx, %rdi
cmpl $0x7, %r8d
jb 0x2ba1
addq $0x6, %r15
movb %al, (%r15)
movb %cl, 0x1(%r15)
movb %dl, 0x2(%r15)
addq $0x3, %r15
cmpq %rbx, %r15
jb 0x2af0
movq %rbx, %r15
cmpl $0x4, %r14d
jne 0x2b98
movl (%rsi), %eax
movl %eax, (%r15)
leaq (%r15,%r14), %rcx
movl %eax, (%r15,%r14)
addq %r14, %rcx
cmpq %rbx, %rcx
jae 0x29f7
leaq (%r14,%r14,2), %rcx
movq %r14, %rdx
addq %r14, %rdx
movl %eax, (%r15,%rdx)
movl %eax, (%r15,%rcx)
addq %rdx, %r15
leaq (%r15,%rdx), %rsi
cmpq %rbx, %rsi
jb 0x2b34
jmp 0x29f7
movzwl (%rsi), %eax
movw %ax, (%r15)
movw %ax, 0x2(%r15)
cmpl $0x5, %r8d
jb 0x29f7
addq $0x4, %r15
movw %ax, (%r15)
movw %ax, 0x2(%r15)
addq $0x4, %r15
cmpq %rbx, %r15
jb 0x2b67
jmp 0x29f7
jne 0x2c07
movzbl 0x1(%r12), %eax
addl $0xfc, %eax
addq $0x2, %r12
jmp 0x2a32
cmpl $0x8, %r14d
ja 0x2bbc
movq %r15, %rdi
movq (%rsi), %rax
movq %rax, (%rdi)
addq %r14, %rdi
cmpq %rbx, %rdi
jb 0x2ba4
jmp 0x29f7
movq %rdi, %r15
jmp 0x29fa
movl (%rsi), %eax
movl %eax, (%r15)
addq $0x4, %r15
cmpq %rbx, %r15
jae 0x29f7
addq $0x4, %rsi
movq (%rsi), %rax
movq %rax, (%r15)
addq $0x8, %rsi
addq $0x8, %r15
cmpq %rbx, %r15
jb 0x2bd2
jmp 0x29f7
cmpl $0xfd, %ebx
jne 0x2c22
movzwl 0x1(%r12), %ebx
addl $0xfd, %ebx
addq $0x3, %r12
jmp 0x29cc
cmpl $0xfd, %eax
jne 0x2c45
movzwl 0x1(%r12), %eax
addl $0xfd, %eax
addq $0x3, %r12
jmp 0x2a32
cmpl $0xfe, %ebx
jne 0x2c66
movl 0x1(%r12), %ebx
movl $0xffffff, %eax         # imm = 0xFFFFFF
andl %eax, %ebx
addl $0xfe, %ebx
addq $0x4, %r12
jmp 0x29cc
cmpl $0xfe, %eax
jne 0x2c7b
movl 0x1(%r12), %eax
movl $0xffffff, %ecx         # imm = 0xFFFFFF
andl %ecx, %eax
addl $0xfe, %eax
addq $0x4, %r12
jmp 0x2a32
movl 0x1(%r12), %ebx
movl $0xff, %eax
addl %eax, %ebx
addq $0x5, %r12
jmp 0x29cc
movl 0x1(%r12), %eax
movl $0xff, %ecx
addl %ecx, %eax
addq $0x5, %r12
jmp 0x2a32
pushq $0x5
popq %rax
jmp 0x2cad
xorl %eax, %eax
testl %r14d, %r14d
setne %al
leal (%rax,%rax,4), %eax
movq %r15, %rcx
movq 0x18(%rsp), %r8
subl %edi, %ecx
movl %ecx, (%r8)
addq $0x38, %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq
pushq $0x5
popq %rax
movq %rdi, %rcx
jmp 0x2ca8
xorl %eax, %eax
jmp 0x2ca3
pushq $0x4b
jmp 0x2c92
nopl (%rax)