// File: Alcaro[P]bridges/arlib/image-png-decode.cpp
// Function: image::png_defilter(unsigned char*, unsigned long, unsigned char const*, int, unsigned long, unsigned long)
bool image::png_defilter(uint8_t * out, size_t out_stride, const uint8_t * in, int bytes_per_pixel, size_t width_bytes, size_t height)
{
	for (size_t y=0;y<height;y++)
	{
		const uint8_t * defilter_in = in + y*(width_bytes+1) + 1;
		uint8_t filter_type = defilter_in[-1]; // cache this, in case input and output ends at same place
		
		uint8_t * defilter_out = out + y*out_stride;
		*(defilter_out++) = 0; // x=-1 is all zeroes (always use 4, not width_bytes, makes the math easier)
		*(defilter_out++) = 0;
		*(defilter_out++) = 0;
		*(defilter_out++) = 0;
		
		memmove(defilter_out, defilter_in, width_bytes);
		switch (filter_type)
		{
		case 0: // None
			break;
		
		case 1: // Sub
			for (size_t x=0;x<width_bytes;x++)
				defilter_out[x] += defilter_out[x-bytes_per_pixel];
			break;
		
		case 2: // Up
			for (size_t x=0;x<width_bytes;x++)
				defilter_out[x] += defilter_out[x-out_stride];
			break;
		
		case 3: // Average
			for (size_t x=0;x<width_bytes;x++)
			{
				int a = defilter_out[x-bytes_per_pixel];
				int b = defilter_out[x-out_stride];
				defilter_out[x] += (a+b)/2;
			}
			break;
		
		case 4: // Paeth
		{
#ifdef __SSE2__
#ifndef __SSSE3__
			auto _mm_abs_epi16 = [](__m128i a) -> __m128i {
				// abs(x) = (x^(x<0)) - (x<0)
				// however, that's four insns (three obvious, plus have to copy the argument)
				// instead, this one is three (or two, if first call reuses a zeroed reg from the a/b/c calculation)
				// abs(x) = max_i16(x, -x) (or min_u16(x, -x))
				return _mm_max_epi16(a, _mm_sub_epi16(_mm_setzero_si128(), a)); 
			};
#endif
			// ignore simding the other filters; Paeth is the most common, and also the most expensive per pixel
			// it can only be SIMDed to a degree of bytes_per_pixel, so ignore bytes_per_pixel=1 (and =2, gray+alpha, too rare)
			// (it's possible to interlace processing of two consecutive Paeth scanlines by having the upper one 1px ahead of the
			//    one below, but the required data structures would be quite annoying, and combining the bytes would be annoying too)
			// (it'd also be possible to assume the previous pixel was predicted Up aka B and discard the calculation if wrong,
			//    but it's 84.6% Left/A, 13% Up/B, 2.4% Diag/C, so such a thing would be wrong most of the time and not accomplish much)
			// macro instead of function is 7% faster
#define SIMD_PAETH(bytes_per_pixel) do { \
					uint32_t a32 = *(uint32_t*)(defilter_out+x           -bytes_per_pixel);          \
					uint32_t b32 = *(uint32_t*)(defilter_out+x-out_stride                );          \
					uint32_t c32 = *(uint32_t*)(defilter_out+x-out_stride-bytes_per_pixel);          \
					__m128i a = _mm_unpacklo_epi8(_mm_cvtsi32_si128(a32), _mm_setzero_si128());      \
					__m128i b = _mm_unpacklo_epi8(_mm_cvtsi32_si128(b32), _mm_setzero_si128());      \
					__m128i c = _mm_unpacklo_epi8(_mm_cvtsi32_si128(c32), _mm_setzero_si128());      \
					                                                                                 \
					__m128i p = _mm_sub_epi16(_mm_add_epi16(a, b), c);                               \
					__m128i pa = _mm_abs_epi16(_mm_sub_epi16(p, a));                                 \
					__m128i pb = _mm_abs_epi16(_mm_sub_epi16(p, b));                                 \
					__m128i pc = _mm_abs_epi16(_mm_sub_epi16(p, c));                                 \
					                                                                                 \
					/* 0 to use pa, -1 for something else */                                         \
					__m128i pa_skip = _mm_cmplt_epi16(_mm_min_epi16(pb, pc), pa);                    \
					/* -1 to use pc, 0 for something else */                                         \
					__m128i pc_use = _mm_and_si128(pa_skip, _mm_cmplt_epi16(pc, pb));                \
					__m128i pb_use = _mm_andnot_si128(pc_use, pa_skip);                              \
					                                                                                 \
					__m128i prediction = _mm_or_si128(_mm_andnot_si128(pa_skip, a),                  \
					                     _mm_or_si128(_mm_and_si128(   pb_use, b),                   \
					                                  _mm_and_si128(   pc_use, c)));                 \
					                                                                                 \
					uint32_t* outp = (uint32_t*)(defilter_out+x);                                    \
					__m128i out = _mm_add_epi8(_mm_cvtsi32_si128(*outp),                             \
					                           _mm_packus_epi16(prediction, _mm_undefined_si128())); \
					uint32_t out32 = _mm_cvtsi128_si32(out);                                         \
					if (bytes_per_pixel == 3)                                                        \
						out32 = (out32&0xFFFFFF00) | (*outp&0x000000FF);                             \
					*outp = out32;                                                                   \
				} while(0)
			if (bytes_per_pixel == 3)
			{
				//one pixel at the time, no need for a scalar tail loop
				//shift one byte to the left, so we don't overflow the malloc at the last scanline (x=-1 is safe, it's all zero)
				//we don't actually change that byte, but it's UB anyways
				defilter_out--;
				for (size_t x=0;x<width_bytes;x+=3)
				{
					SIMD_PAETH(3);
				}
				break;
			}
			if (bytes_per_pixel == 4)
			{
				for (size_t x=0;x<width_bytes;x+=4)
				{
					SIMD_PAETH(4);
				}
				break;
			}
			
			// not SIMD_LOOP_TAIL, the below runs for bytes_per_pixel=1 aka palette
#endif
			for (size_t x=0;x<width_bytes;x++)
			{
				int a = defilter_out[x-bytes_per_pixel];
				int b = defilter_out[x-out_stride];
				int c = defilter_out[x-out_stride-bytes_per_pixel];
				
				int p = a+b-c;
				int pa = abs(p-a);
				int pb = abs(p-b);
				int pc = abs(p-c);
				
				int prediction;
				if (pa <= pb && pa <= pc) prediction = a;
				else if (pb <= pc) prediction = b;
				else prediction = c;
				
				defilter_out[x] += prediction;
			}
		}
		break;
		
		default:
			return false;
		}
	}
	return true;
}

// Assembly:
pushq %rbp
movq %rsp, %rbp
subq $0xa00, %rsp            # imm = 0xA00
movq %rdi, -0x730(%rbp)
movq %rsi, -0x738(%rbp)
movq %rdx, -0x740(%rbp)
movl %ecx, -0x744(%rbp)
movq %r8, -0x750(%rbp)
movq %r9, -0x758(%rbp)
movq $0x0, -0x760(%rbp)
movq -0x760(%rbp), %rax
cmpq -0x758(%rbp), %rax
jae 0x16f58
movq -0x740(%rbp), %rax
movq -0x760(%rbp), %rcx
movq -0x750(%rbp), %rdx
incq %rdx
imulq %rdx, %rcx
leaq 0x1(%rax,%rcx), %rax
movq %rax, -0x768(%rbp)
movq -0x768(%rbp), %rax
movb -0x1(%rax), %al
movb %al, -0x769(%rbp)
movq -0x730(%rbp), %rax
movq -0x760(%rbp), %rcx
movq -0x738(%rbp), %rdx
imulq %rdx, %rcx
addq %rcx, %rax
movq %rax, -0x778(%rbp)
movq -0x778(%rbp), %rax
movq %rax, %rcx
incq %rcx
movq %rcx, -0x778(%rbp)
movb $0x0, (%rax)
movq -0x778(%rbp), %rax
movq %rax, %rcx
incq %rcx
movq %rcx, -0x778(%rbp)
movb $0x0, (%rax)
movq -0x778(%rbp), %rax
movq %rax, %rcx
incq %rcx
movq %rcx, -0x778(%rbp)
movb $0x0, (%rax)
movq -0x778(%rbp), %rax
movq %rax, %rcx
incq %rcx
movq %rcx, -0x778(%rbp)
movb $0x0, (%rax)
movq -0x778(%rbp), %rdi
movq -0x768(%rbp), %rsi
movq -0x750(%rbp), %rdx
callq 0x45f0
movzbl -0x769(%rbp), %eax
movq %rax, -0x9b8(%rbp)
subq $0x4, %rax
ja 0x16f36
movq -0x9b8(%rbp), %rax
leaq 0x4d756(%rip), %rcx     # 0x63840
movslq (%rcx,%rax,4), %rax
addq %rcx, %rax
jmpq *%rax
jmp 0x16f3f
movq $0x0, -0x780(%rbp)
movq -0x780(%rbp), %rax
cmpq -0x750(%rbp), %rax
jae 0x1615a
movq -0x778(%rbp), %rax
movq -0x780(%rbp), %rcx
movslq -0x744(%rbp), %rdx
subq %rdx, %rcx
movzbl (%rax,%rcx), %esi
movq -0x778(%rbp), %rax
movq -0x780(%rbp), %rcx
movzbl (%rax,%rcx), %edx
addl %esi, %edx
movb %dl, (%rax,%rcx)
movq -0x780(%rbp), %rax
addq $0x1, %rax
movq %rax, -0x780(%rbp)
jmp 0x16103
jmp 0x16f3f
movq $0x0, -0x788(%rbp)
movq -0x788(%rbp), %rax
cmpq -0x750(%rbp), %rax
jae 0x161be
movq -0x778(%rbp), %rax
movq -0x788(%rbp), %rcx
subq -0x738(%rbp), %rcx
movzbl (%rax,%rcx), %esi
movq -0x778(%rbp), %rax
movq -0x788(%rbp), %rcx
movzbl (%rax,%rcx), %edx
addl %esi, %edx
movb %dl, (%rax,%rcx)
movq -0x788(%rbp), %rax
addq $0x1, %rax
movq %rax, -0x788(%rbp)
jmp 0x1616a
jmp 0x16f3f
movq $0x0, -0x790(%rbp)
movq -0x790(%rbp), %rax
cmpq -0x750(%rbp), %rax
jae 0x16267
movq -0x778(%rbp), %rax
movq -0x790(%rbp), %rcx
movslq -0x744(%rbp), %rdx
subq %rdx, %rcx
movzbl (%rax,%rcx), %eax
movl %eax, -0x794(%rbp)
movq -0x778(%rbp), %rax
movq -0x790(%rbp), %rcx
subq -0x738(%rbp), %rcx
movzbl (%rax,%rcx), %eax
movl %eax, -0x798(%rbp)
movl -0x794(%rbp), %eax
addl -0x798(%rbp), %eax
movl $0x2, %ecx
cltd
idivl %ecx
movl %eax, %esi
movq -0x778(%rbp), %rax
movq -0x790(%rbp), %rcx
movzbl (%rax,%rcx), %edx
addl %esi, %edx
movb %dl, (%rax,%rcx)
movq -0x790(%rbp), %rax
addq $0x1, %rax
movq %rax, -0x790(%rbp)
jmp 0x161ce
jmp 0x16f3f
movb 0x4d66e(%rip), %al      # 0x638e0
movb %al, -0x799(%rbp)
cmpl $0x3, -0x744(%rbp)
jne 0x16836
movq -0x778(%rbp), %rax
addq $-0x1, %rax
movq %rax, -0x778(%rbp)
movq $0x0, -0x7a8(%rbp)
movq -0x7a8(%rbp), %rax
cmpq -0x750(%rbp), %rax
jae 0x16831
jmp 0x162b8
movq -0x778(%rbp), %rax
movq -0x7a8(%rbp), %rcx
movl -0x3(%rax,%rcx), %eax
movl %eax, -0x7ac(%rbp)
movq -0x778(%rbp), %rax
movq -0x7a8(%rbp), %rcx
addq %rcx, %rax
movq -0x738(%rbp), %rcx
subq %rcx, %rax
movl (%rax), %eax
movl %eax, -0x7b0(%rbp)
movq -0x778(%rbp), %rax
movq -0x7a8(%rbp), %rcx
addq %rcx, %rax
movq -0x738(%rbp), %rcx
subq %rcx, %rax
movl -0x3(%rax), %eax
movl %eax, -0x7b4(%rbp)
movl -0x7ac(%rbp), %eax
movl %eax, -0x564(%rbp)
movd -0x564(%rbp), %xmm0
movaps %xmm0, -0x580(%rbp)
movaps -0x580(%rbp), %xmm2
xorps %xmm0, %xmm0
movaps %xmm0, -0x9d0(%rbp)
movaps %xmm0, -0x510(%rbp)
movaps -0x510(%rbp), %xmm1
movaps %xmm2, -0x670(%rbp)
movaps %xmm1, -0x680(%rbp)
movaps -0x670(%rbp), %xmm1
movaps -0x680(%rbp), %xmm2
punpcklbw %xmm2, %xmm1    # xmm1 = xmm1[0],xmm2[0],xmm1[1],xmm2[1],xmm1[2],xmm2[2],xmm1[3],xmm2[3],xmm1[4],xmm2[4],xmm1[5],xmm2[5],xmm1[6],xmm2[6],xmm1[7],xmm2[7]
movaps %xmm1, -0x7d0(%rbp)
movl -0x7b0(%rbp), %eax
movl %eax, -0x584(%rbp)
movd -0x584(%rbp), %xmm1
movaps %xmm1, -0x5a0(%rbp)
movaps -0x5a0(%rbp), %xmm2
movaps %xmm0, -0x520(%rbp)
movaps -0x520(%rbp), %xmm1
movaps %xmm2, -0x690(%rbp)
movaps %xmm1, -0x6a0(%rbp)
movaps -0x690(%rbp), %xmm1
movaps -0x6a0(%rbp), %xmm2
punpcklbw %xmm2, %xmm1    # xmm1 = xmm1[0],xmm2[0],xmm1[1],xmm2[1],xmm1[2],xmm2[2],xmm1[3],xmm2[3],xmm1[4],xmm2[4],xmm1[5],xmm2[5],xmm1[6],xmm2[6],xmm1[7],xmm2[7]
movaps %xmm1, -0x7e0(%rbp)
movl -0x7b4(%rbp), %eax
movl %eax, -0x5a4(%rbp)
movd -0x5a4(%rbp), %xmm1
movaps %xmm1, -0x5c0(%rbp)
movaps -0x5c0(%rbp), %xmm1
movaps %xmm0, -0x530(%rbp)
movaps -0x530(%rbp), %xmm0
movaps %xmm1, -0x6b0(%rbp)
movaps %xmm0, -0x6c0(%rbp)
movaps -0x6b0(%rbp), %xmm0
movaps -0x6c0(%rbp), %xmm1
punpcklbw %xmm1, %xmm0    # xmm0 = xmm0[0],xmm1[0],xmm0[1],xmm1[1],xmm0[2],xmm1[2],xmm0[3],xmm1[3],xmm0[4],xmm1[4],xmm0[5],xmm1[5],xmm0[6],xmm1[6],xmm0[7],xmm1[7]
movaps %xmm0, -0x7f0(%rbp)
movaps -0x7d0(%rbp), %xmm1
movaps -0x7e0(%rbp), %xmm0
movaps %xmm1, -0x3d0(%rbp)
movaps %xmm0, -0x3e0(%rbp)
movaps -0x3d0(%rbp), %xmm1
movaps -0x3e0(%rbp), %xmm0
paddw %xmm0, %xmm1
movaps -0x7f0(%rbp), %xmm0
movaps %xmm1, -0x410(%rbp)
movaps %xmm0, -0x420(%rbp)
movaps -0x410(%rbp), %xmm0
movaps -0x420(%rbp), %xmm1
psubw %xmm1, %xmm0
movaps %xmm0, -0x800(%rbp)
movaps -0x800(%rbp), %xmm1
movaps -0x7d0(%rbp), %xmm0
movaps %xmm1, -0x430(%rbp)
movaps %xmm0, -0x440(%rbp)
movaps -0x430(%rbp), %xmm0
movaps -0x440(%rbp), %xmm1
psubw %xmm1, %xmm0
leaq -0x799(%rbp), %rdi
movq %rdi, -0x9d8(%rbp)
callq 0x16f70
movq -0x9d8(%rbp), %rdi
movaps %xmm0, -0x810(%rbp)
movaps -0x800(%rbp), %xmm1
movaps -0x7e0(%rbp), %xmm0
movaps %xmm1, -0x450(%rbp)
movaps %xmm0, -0x460(%rbp)
movaps -0x450(%rbp), %xmm0
movaps -0x460(%rbp), %xmm1
psubw %xmm1, %xmm0
callq 0x16f70
movq -0x9d8(%rbp), %rdi
movaps %xmm0, -0x820(%rbp)
movaps -0x800(%rbp), %xmm1
movaps -0x7f0(%rbp), %xmm0
movaps %xmm1, -0x470(%rbp)
movaps %xmm0, -0x480(%rbp)
movaps -0x470(%rbp), %xmm0
movaps -0x480(%rbp), %xmm1
psubw %xmm1, %xmm0
callq 0x16f70
movaps %xmm0, %xmm1
movaps -0x9d0(%rbp), %xmm0
movaps %xmm1, -0x830(%rbp)
movaps -0x820(%rbp), %xmm2
movaps -0x830(%rbp), %xmm1
movaps %xmm2, -0x310(%rbp)
movaps %xmm1, -0x320(%rbp)
movaps -0x310(%rbp), %xmm2
movaps -0x320(%rbp), %xmm1
pminsw %xmm1, %xmm2
movaps -0x810(%rbp), %xmm1
movaps %xmm2, -0x350(%rbp)
movaps %xmm1, -0x360(%rbp)
movaps -0x360(%rbp), %xmm2
movaps -0x350(%rbp), %xmm1
movaps %xmm2, -0x70(%rbp)
movaps %xmm1, -0x80(%rbp)
movaps -0x70(%rbp), %xmm1
movaps -0x80(%rbp), %xmm2
pcmpgtw %xmm2, %xmm1
movaps %xmm1, -0x840(%rbp)
movaps -0x840(%rbp), %xmm2
movaps -0x830(%rbp), %xmm3
movaps -0x820(%rbp), %xmm1
movaps %xmm3, -0x370(%rbp)
movaps %xmm1, -0x380(%rbp)
movaps -0x380(%rbp), %xmm3
movaps -0x370(%rbp), %xmm1
movaps %xmm3, -0x50(%rbp)
movaps %xmm1, -0x60(%rbp)
movaps -0x50(%rbp), %xmm1
movaps -0x60(%rbp), %xmm3
pcmpgtw %xmm3, %xmm1
movaps %xmm2, -0x250(%rbp)
movaps %xmm1, -0x260(%rbp)
movaps -0x250(%rbp), %xmm1
movaps -0x260(%rbp), %xmm2
pand %xmm2, %xmm1
movaps %xmm1, -0x850(%rbp)
movaps -0x850(%rbp), %xmm2
movaps -0x840(%rbp), %xmm1
movaps %xmm2, -0x1d0(%rbp)
movaps %xmm1, -0x1e0(%rbp)
movaps -0x1d0(%rbp), %xmm1
movaps -0x1e0(%rbp), %xmm2
pandn %xmm2, %xmm1
movaps %xmm1, -0x860(%rbp)
movaps -0x840(%rbp), %xmm2
movaps -0x7d0(%rbp), %xmm1
movaps %xmm2, -0x1f0(%rbp)
movaps %xmm1, -0x200(%rbp)
movaps -0x1f0(%rbp), %xmm2
movaps -0x200(%rbp), %xmm1
pandn %xmm1, %xmm2
movaps -0x860(%rbp), %xmm3
movaps -0x7e0(%rbp), %xmm1
movaps %xmm3, -0x270(%rbp)
movaps %xmm1, -0x280(%rbp)
movaps -0x270(%rbp), %xmm3
movaps -0x280(%rbp), %xmm1
pand %xmm1, %xmm3
movaps -0x850(%rbp), %xmm4
movaps -0x7f0(%rbp), %xmm1
movaps %xmm4, -0x290(%rbp)
movaps %xmm1, -0x2a0(%rbp)
movaps -0x290(%rbp), %xmm1
movaps -0x2a0(%rbp), %xmm4
pand %xmm4, %xmm1
movaps %xmm3, -0x150(%rbp)
movaps %xmm1, -0x160(%rbp)
movaps -0x150(%rbp), %xmm1
movaps -0x160(%rbp), %xmm3
por %xmm3, %xmm1
movaps %xmm2, -0x170(%rbp)
movaps %xmm1, -0x180(%rbp)
movaps -0x170(%rbp), %xmm1
movaps -0x180(%rbp), %xmm2
por %xmm2, %xmm1
movaps %xmm1, -0x870(%rbp)
movq -0x778(%rbp), %rax
movq -0x7a8(%rbp), %rcx
addq %rcx, %rax
movq %rax, -0x878(%rbp)
movq -0x878(%rbp), %rax
movl (%rax), %eax
movl %eax, -0x5c4(%rbp)
movd -0x5c4(%rbp), %xmm1
movaps %xmm1, -0x5e0(%rbp)
movaps -0x5e0(%rbp), %xmm1
movaps -0x870(%rbp), %xmm2
movaps %xmm2, -0xd0(%rbp)
movaps %xmm0, -0xe0(%rbp)
movaps -0xd0(%rbp), %xmm0
movaps -0xe0(%rbp), %xmm2
packuswb %xmm2, %xmm0
movaps %xmm1, -0x110(%rbp)
movaps %xmm0, -0x120(%rbp)
movaps -0x110(%rbp), %xmm0
movaps -0x120(%rbp), %xmm1
paddb %xmm1, %xmm0
movaps %xmm0, -0x890(%rbp)
movaps -0x890(%rbp), %xmm0
movaps %xmm0, -0x90(%rbp)
movaps -0x90(%rbp), %xmm0
movaps %xmm0, -0xa0(%rbp)
movl -0xa0(%rbp), %eax
movl %eax, -0x894(%rbp)
movl -0x894(%rbp), %eax
andl $0xffffff00, %eax       # imm = 0xFFFFFF00
movq -0x878(%rbp), %rcx
movl (%rcx), %ecx
andl $0xff, %ecx
orl %ecx, %eax
movl %eax, -0x894(%rbp)
movl -0x894(%rbp), %ecx
movq -0x878(%rbp), %rax
movl %ecx, (%rax)
jmp 0x1681a
movq -0x7a8(%rbp), %rax
addq $0x3, %rax
movq %rax, -0x7a8(%rbp)
jmp 0x162a2
jmp 0x16f3f
cmpl $0x4, -0x744(%rbp)
jne 0x16dc0
movq $0x0, -0x8a0(%rbp)
movq -0x8a0(%rbp), %rax
cmpq -0x750(%rbp), %rax
jae 0x16dbb
jmp 0x16864
movq -0x778(%rbp), %rax
movq -0x8a0(%rbp), %rcx
movl -0x4(%rax,%rcx), %eax
movl %eax, -0x8a4(%rbp)
movq -0x778(%rbp), %rax
movq -0x8a0(%rbp), %rcx
addq %rcx, %rax
movq -0x738(%rbp), %rcx
subq %rcx, %rax
movl (%rax), %eax
movl %eax, -0x8a8(%rbp)
movq -0x778(%rbp), %rax
movq -0x8a0(%rbp), %rcx
addq %rcx, %rax
movq -0x738(%rbp), %rcx
subq %rcx, %rax
movl -0x4(%rax), %eax
movl %eax, -0x8ac(%rbp)
movl -0x8a4(%rbp), %eax
movl %eax, -0x5e4(%rbp)
movd -0x5e4(%rbp), %xmm0
movaps %xmm0, -0x600(%rbp)
movaps -0x600(%rbp), %xmm2
xorps %xmm0, %xmm0
movaps %xmm0, -0x9f0(%rbp)
movaps %xmm0, -0x540(%rbp)
movaps -0x540(%rbp), %xmm1
movaps %xmm2, -0x6d0(%rbp)
movaps %xmm1, -0x6e0(%rbp)
movaps -0x6d0(%rbp), %xmm1
movaps -0x6e0(%rbp), %xmm2
punpcklbw %xmm2, %xmm1    # xmm1 = xmm1[0],xmm2[0],xmm1[1],xmm2[1],xmm1[2],xmm2[2],xmm1[3],xmm2[3],xmm1[4],xmm2[4],xmm1[5],xmm2[5],xmm1[6],xmm2[6],xmm1[7],xmm2[7]
movaps %xmm1, -0x8c0(%rbp)
movl -0x8a8(%rbp), %eax
movl %eax, -0x604(%rbp)
movd -0x604(%rbp), %xmm1
movaps %xmm1, -0x620(%rbp)
movaps -0x620(%rbp), %xmm2
movaps %xmm0, -0x550(%rbp)
movaps -0x550(%rbp), %xmm1
movaps %xmm2, -0x6f0(%rbp)
movaps %xmm1, -0x700(%rbp)
movaps -0x6f0(%rbp), %xmm1
movaps -0x700(%rbp), %xmm2
punpcklbw %xmm2, %xmm1    # xmm1 = xmm1[0],xmm2[0],xmm1[1],xmm2[1],xmm1[2],xmm2[2],xmm1[3],xmm2[3],xmm1[4],xmm2[4],xmm1[5],xmm2[5],xmm1[6],xmm2[6],xmm1[7],xmm2[7]
movaps %xmm1, -0x8d0(%rbp)
movl -0x8ac(%rbp), %eax
movl %eax, -0x624(%rbp)
movd -0x624(%rbp), %xmm1
movaps %xmm1, -0x640(%rbp)
movaps -0x640(%rbp), %xmm1
movaps %xmm0, -0x560(%rbp)
movaps -0x560(%rbp), %xmm0
movaps %xmm1, -0x710(%rbp)
movaps %xmm0, -0x720(%rbp)
movaps -0x710(%rbp), %xmm0
movaps -0x720(%rbp), %xmm1
punpcklbw %xmm1, %xmm0    # xmm0 = xmm0[0],xmm1[0],xmm0[1],xmm1[1],xmm0[2],xmm1[2],xmm0[3],xmm1[3],xmm0[4],xmm1[4],xmm0[5],xmm1[5],xmm0[6],xmm1[6],xmm0[7],xmm1[7]
movaps %xmm0, -0x8e0(%rbp)
movaps -0x8c0(%rbp), %xmm1
movaps -0x8d0(%rbp), %xmm0
movaps %xmm1, -0x3f0(%rbp)
movaps %xmm0, -0x400(%rbp)
movaps -0x3f0(%rbp), %xmm1
movaps -0x400(%rbp), %xmm0
paddw %xmm0, %xmm1
movaps -0x8e0(%rbp), %xmm0
movaps %xmm1, -0x490(%rbp)
movaps %xmm0, -0x4a0(%rbp)
movaps -0x490(%rbp), %xmm0
movaps -0x4a0(%rbp), %xmm1
psubw %xmm1, %xmm0
movaps %xmm0, -0x8f0(%rbp)
movaps -0x8f0(%rbp), %xmm1
movaps -0x8c0(%rbp), %xmm0
movaps %xmm1, -0x4b0(%rbp)
movaps %xmm0, -0x4c0(%rbp)
movaps -0x4b0(%rbp), %xmm0
movaps -0x4c0(%rbp), %xmm1
psubw %xmm1, %xmm0
leaq -0x799(%rbp), %rdi
movq %rdi, -0x9f8(%rbp)
callq 0x16f70
movq -0x9f8(%rbp), %rdi
movaps %xmm0, -0x900(%rbp)
movaps -0x8f0(%rbp), %xmm1
movaps -0x8d0(%rbp), %xmm0
movaps %xmm1, -0x4d0(%rbp)
movaps %xmm0, -0x4e0(%rbp)
movaps -0x4d0(%rbp), %xmm0
movaps -0x4e0(%rbp), %xmm1
psubw %xmm1, %xmm0
callq 0x16f70
movq -0x9f8(%rbp), %rdi
movaps %xmm0, -0x910(%rbp)
movaps -0x8f0(%rbp), %xmm1
movaps -0x8e0(%rbp), %xmm0
movaps %xmm1, -0x4f0(%rbp)
movaps %xmm0, -0x500(%rbp)
movaps -0x4f0(%rbp), %xmm0
movaps -0x500(%rbp), %xmm1
psubw %xmm1, %xmm0
callq 0x16f70
movaps %xmm0, %xmm1
movaps -0x9f0(%rbp), %xmm0
movaps %xmm1, -0x920(%rbp)
movaps -0x910(%rbp), %xmm2
movaps -0x920(%rbp), %xmm1
movaps %xmm2, -0x330(%rbp)
movaps %xmm1, -0x340(%rbp)
movaps -0x330(%rbp), %xmm2
movaps -0x340(%rbp), %xmm1
pminsw %xmm1, %xmm2
movaps -0x900(%rbp), %xmm1
movaps %xmm2, -0x390(%rbp)
movaps %xmm1, -0x3a0(%rbp)
movaps -0x3a0(%rbp), %xmm2
movaps -0x390(%rbp), %xmm1
movaps %xmm2, -0x30(%rbp)
movaps %xmm1, -0x40(%rbp)
movaps -0x30(%rbp), %xmm1
movaps -0x40(%rbp), %xmm2
pcmpgtw %xmm2, %xmm1
movaps %xmm1, -0x930(%rbp)
movaps -0x930(%rbp), %xmm2
movaps -0x920(%rbp), %xmm3
movaps -0x910(%rbp), %xmm1
movaps %xmm3, -0x3b0(%rbp)
movaps %xmm1, -0x3c0(%rbp)
movaps -0x3c0(%rbp), %xmm3
movaps -0x3b0(%rbp), %xmm1
movaps %xmm3, -0x10(%rbp)
movaps %xmm1, -0x20(%rbp)
movaps -0x10(%rbp), %xmm1
movaps -0x20(%rbp), %xmm3
pcmpgtw %xmm3, %xmm1
movaps %xmm2, -0x2b0(%rbp)
movaps %xmm1, -0x2c0(%rbp)
movaps -0x2b0(%rbp), %xmm1
movaps -0x2c0(%rbp), %xmm2
pand %xmm2, %xmm1
movaps %xmm1, -0x940(%rbp)
movaps -0x940(%rbp), %xmm2
movaps -0x930(%rbp), %xmm1
movaps %xmm2, -0x210(%rbp)
movaps %xmm1, -0x220(%rbp)
movaps -0x210(%rbp), %xmm1
movaps -0x220(%rbp), %xmm2
pandn %xmm2, %xmm1
movaps %xmm1, -0x950(%rbp)
movaps -0x930(%rbp), %xmm2
movaps -0x8c0(%rbp), %xmm1
movaps %xmm2, -0x230(%rbp)
movaps %xmm1, -0x240(%rbp)
movaps -0x230(%rbp), %xmm2
movaps -0x240(%rbp), %xmm1
pandn %xmm1, %xmm2
movaps -0x950(%rbp), %xmm3
movaps -0x8d0(%rbp), %xmm1
movaps %xmm3, -0x2d0(%rbp)
movaps %xmm1, -0x2e0(%rbp)
movaps -0x2d0(%rbp), %xmm3
movaps -0x2e0(%rbp), %xmm1
pand %xmm1, %xmm3
movaps -0x940(%rbp), %xmm4
movaps -0x8e0(%rbp), %xmm1
movaps %xmm4, -0x2f0(%rbp)
movaps %xmm1, -0x300(%rbp)
movaps -0x2f0(%rbp), %xmm1
movaps -0x300(%rbp), %xmm4
pand %xmm4, %xmm1
movaps %xmm3, -0x190(%rbp)
movaps %xmm1, -0x1a0(%rbp)
movaps -0x190(%rbp), %xmm1
movaps -0x1a0(%rbp), %xmm3
por %xmm3, %xmm1
movaps %xmm2, -0x1b0(%rbp)
movaps %xmm1, -0x1c0(%rbp)
movaps -0x1b0(%rbp), %xmm1
movaps -0x1c0(%rbp), %xmm2
por %xmm2, %xmm1
movaps %xmm1, -0x960(%rbp)
movq -0x778(%rbp), %rax
movq -0x8a0(%rbp), %rcx
addq %rcx, %rax
movq %rax, -0x968(%rbp)
movq -0x968(%rbp), %rax
movl (%rax), %eax
movl %eax, -0x644(%rbp)
movd -0x644(%rbp), %xmm1
movaps %xmm1, -0x660(%rbp)
movaps -0x660(%rbp), %xmm1
movaps -0x960(%rbp), %xmm2
movaps %xmm2, -0xf0(%rbp)
movaps %xmm0, -0x100(%rbp)
movaps -0xf0(%rbp), %xmm0
movaps -0x100(%rbp), %xmm2
packuswb %xmm2, %xmm0
movaps %xmm1, -0x130(%rbp)
movaps %xmm0, -0x140(%rbp)
movaps -0x130(%rbp), %xmm0
movaps -0x140(%rbp), %xmm1
paddb %xmm1, %xmm0
movaps %xmm0, -0x980(%rbp)
movaps -0x980(%rbp), %xmm0
movaps %xmm0, -0xb0(%rbp)
movaps -0xb0(%rbp), %xmm0
movaps %xmm0, -0xc0(%rbp)
movl -0xc0(%rbp), %eax
movl %eax, -0x984(%rbp)
movl -0x984(%rbp), %ecx
movq -0x968(%rbp), %rax
movl %ecx, (%rax)
jmp 0x16da4
movq -0x8a0(%rbp), %rax
addq $0x4, %rax
movq %rax, -0x8a0(%rbp)
jmp 0x1684e
jmp 0x16f3f
movq $0x0, -0x990(%rbp)
movq -0x990(%rbp), %rax
cmpq -0x750(%rbp), %rax
jae 0x16f34
movq -0x778(%rbp), %rax
movq -0x990(%rbp), %rcx
movslq -0x744(%rbp), %rdx
subq %rdx, %rcx
movzbl (%rax,%rcx), %eax
movl %eax, -0x994(%rbp)
movq -0x778(%rbp), %rax
movq -0x990(%rbp), %rcx
subq -0x738(%rbp), %rcx
movzbl (%rax,%rcx), %eax
movl %eax, -0x998(%rbp)
movq -0x778(%rbp), %rax
movq -0x990(%rbp), %rcx
subq -0x738(%rbp), %rcx
movslq -0x744(%rbp), %rdx
subq %rdx, %rcx
movzbl (%rax,%rcx), %eax
movl %eax, -0x99c(%rbp)
movl -0x994(%rbp), %eax
addl -0x998(%rbp), %eax
subl -0x99c(%rbp), %eax
movl %eax, -0x9a0(%rbp)
movl -0x9a0(%rbp), %eax
subl -0x994(%rbp), %eax
movl %eax, %ecx
negl %ecx
cmovnsl %ecx, %eax
movl %eax, -0x9a4(%rbp)
movl -0x9a0(%rbp), %eax
subl -0x998(%rbp), %eax
movl %eax, %ecx
negl %ecx
cmovnsl %ecx, %eax
movl %eax, -0x9a8(%rbp)
movl -0x9a0(%rbp), %eax
subl -0x99c(%rbp), %eax
movl %eax, %ecx
negl %ecx
cmovnsl %ecx, %eax
movl %eax, -0x9ac(%rbp)
movl -0x9a4(%rbp), %eax
cmpl -0x9a8(%rbp), %eax
jg 0x16ed6
movl -0x9a4(%rbp), %eax
cmpl -0x9ac(%rbp), %eax
jg 0x16ed6
movl -0x994(%rbp), %eax
movl %eax, -0x9b0(%rbp)
jmp 0x16f00
movl -0x9a8(%rbp), %eax
cmpl -0x9ac(%rbp), %eax
jg 0x16ef2
movl -0x998(%rbp), %eax
movl %eax, -0x9b0(%rbp)
jmp 0x16efe
movl -0x99c(%rbp), %eax
movl %eax, -0x9b0(%rbp)
jmp 0x16f00
movl -0x9b0(%rbp), %esi
movq -0x778(%rbp), %rax
movq -0x990(%rbp), %rcx
movzbl (%rax,%rcx), %edx
addl %esi, %edx
movb %dl, (%rax,%rcx)
movq -0x990(%rbp), %rax
addq $0x1, %rax
movq %rax, -0x990(%rbp)
jmp 0x16dcb
jmp 0x16f3f
movb $0x0, -0x721(%rbp)
jmp 0x16f5f
jmp 0x16f41
movq -0x760(%rbp), %rax
addq $0x1, %rax
movq %rax, -0x760(%rbp)
jmp 0x15fdf
movb $0x1, -0x721(%rbp)
movb -0x721(%rbp), %al
andb $0x1, %al
addq $0xa00, %rsp            # imm = 0xA00
popq %rbp
retq