// File: Alcaro[P]bridges/arlib/image-png-decode.cpp
// Function: void image::png_unpack_rgb<6>(unsigned char const*, unsigned long) const
void image::png_unpack_rgb(const uint8_t * source, size_t srcstride) const
{
	uint32_t * pixels = this->pixels32;
	uint32_t width = this->width;
	uint32_t height = this->height;
	
	size_t nsamp;
	if (color_type == 0) nsamp = 1; // gray
	if (color_type == 2) nsamp = 3; // rgb
	if (color_type == 4) nsamp = 2; // gray+alpha
	if (color_type == 6) nsamp = 4; // rgba
	
	for (uint32_t y=0;y<height;y++)
	{
		uint32_t x = 0;
		if (color_type == 2)
		{
			image::convert_scanline<ifmt_rgb888_by, ifmt_bargb8888>(pixels, source, width);
			x = width;
		}
		
#ifdef __SSE2__
		if (color_type == 6)
		{
			while (x+3 < width)
			{
				const uint8_t * sourceat = source + x*nsamp;
				__m128i rgba = _mm_loadu_si128((__m128i*)sourceat);
				__m128i _g_a = _mm_and_si128(rgba, _mm_set1_epi32(0xFF00FF00));
				__m128i bxgx = _mm_shufflehi_epi16(_mm_shufflelo_epi16(rgba, _MM_SHUFFLE(2,3,0,1)), _MM_SHUFFLE(2,3,0,1));
				__m128i bgra = _mm_or_si128(_g_a, _mm_and_si128(bxgx, _mm_set1_epi32(0x00FF00FF)));
				_mm_storeu_si128((__m128i*)(pixels+x), bgra);
				x += 4;
			}
		}
		SIMD_LOOP_TAIL
#endif
		
		while (x < width)
		{
			const uint8_t * sourceat = source + x*nsamp;
			
			if (color_type == 0)
				pixels[x] = 0xFF000000 | sourceat[0]*0x010101;
			// type 2 fully handled above
			if (color_type == 4)
				pixels[x] = (uint32_t)sourceat[1]<<24 | sourceat[0]*0x010101;
			if (color_type == 6)
				pixels[x] = (uint32_t)sourceat[3]<<24 | sourceat[0]<<16 | sourceat[1]<<8 | sourceat[2]<<0;
			x++;
		}
		
		pixels += width;
		source += srcstride;
	}
}

// Assembly:
pushq %rbp
movq %rsp, %rbp
subq $0xe0, %rsp
movq %rdi, -0xd8(%rbp)
movq %rsi, -0xe0(%rbp)
movq %rdx, -0xe8(%rbp)
movq -0xd8(%rbp), %rax
movq 0x10(%rax), %rcx
movq %rcx, -0xf0(%rbp)
movl (%rax), %ecx
movl %ecx, -0xf4(%rbp)
movl 0x4(%rax), %eax
movl %eax, -0xf8(%rbp)
movq $0x4, -0x100(%rbp)
movl $0x0, -0x104(%rbp)
movl -0x104(%rbp), %eax
cmpl -0xf8(%rbp), %eax
jae 0x181d8
movl $0x0, -0x108(%rbp)
movl -0x108(%rbp), %eax
addl $0x3, %eax
cmpl -0xf4(%rbp), %eax
jae 0x180fe
movq -0xe0(%rbp), %rax
movl -0x108(%rbp), %ecx
movq -0x100(%rbp), %rdx
imulq %rdx, %rcx
addq %rcx, %rax
movq %rax, -0x110(%rbp)
movq -0x110(%rbp), %rax
movq %rax, -0x48(%rbp)
movq -0x48(%rbp), %rax
movups (%rax), %xmm0
movaps %xmm0, -0x120(%rbp)
movaps -0x120(%rbp), %xmm1
movl $0xff00ff00, -0x64(%rbp) # imm = 0xFF00FF00
movl -0x64(%rbp), %eax
movl %eax, -0x24(%rbp)
movl %eax, -0x28(%rbp)
movl %eax, -0x2c(%rbp)
movl %eax, -0x30(%rbp)
movd -0x24(%rbp), %xmm0
movd -0x28(%rbp), %xmm2
punpckldq %xmm0, %xmm2    # xmm2 = xmm2[0],xmm0[0],xmm2[1],xmm0[1]
movd -0x2c(%rbp), %xmm3
movd -0x30(%rbp), %xmm0
punpckldq %xmm3, %xmm0    # xmm0 = xmm0[0],xmm3[0],xmm0[1],xmm3[1]
punpcklqdq %xmm2, %xmm0    # xmm0 = xmm0[0],xmm2[0]
movaps %xmm0, -0x40(%rbp)
movaps -0x40(%rbp), %xmm0
movaps %xmm1, -0xa0(%rbp)
movaps %xmm0, -0xb0(%rbp)
movaps -0xa0(%rbp), %xmm0
movaps -0xb0(%rbp), %xmm1
pand %xmm1, %xmm0
movaps %xmm0, -0x130(%rbp)
movaps -0x120(%rbp), %xmm0
pshuflw $0xb1, %xmm0, %xmm0     # xmm0 = xmm0[1,0,3,2,4,5,6,7]
pshufhw $0xb1, %xmm0, %xmm0     # xmm0 = xmm0[0,1,2,3,5,4,7,6]
movaps %xmm0, -0x140(%rbp)
movaps -0x130(%rbp), %xmm1
movaps -0x140(%rbp), %xmm2
movl $0xff00ff, -0x68(%rbp)  # imm = 0xFF00FF
movl -0x68(%rbp), %eax
movl %eax, -0x4(%rbp)
movl %eax, -0x8(%rbp)
movl %eax, -0xc(%rbp)
movl %eax, -0x10(%rbp)
movd -0x4(%rbp), %xmm0
movd -0x8(%rbp), %xmm3
punpckldq %xmm0, %xmm3    # xmm3 = xmm3[0],xmm0[0],xmm3[1],xmm0[1]
movd -0xc(%rbp), %xmm4
movd -0x10(%rbp), %xmm0
punpckldq %xmm4, %xmm0    # xmm0 = xmm0[0],xmm4[0],xmm0[1],xmm4[1]
punpcklqdq %xmm3, %xmm0    # xmm0 = xmm0[0],xmm3[0]
movdqa %xmm0, -0x20(%rbp)
movdqa -0x20(%rbp), %xmm0
movdqa %xmm2, -0xc0(%rbp)
movdqa %xmm0, -0xd0(%rbp)
movdqa -0xc0(%rbp), %xmm0
pand -0xd0(%rbp), %xmm0
movdqa %xmm1, -0x80(%rbp)
movdqa %xmm0, -0x90(%rbp)
movdqa -0x80(%rbp), %xmm0
por -0x90(%rbp), %xmm0
movdqa %xmm0, -0x150(%rbp)
movq -0xf0(%rbp), %rax
movl -0x108(%rbp), %ecx
shlq $0x2, %rcx
addq %rcx, %rax
movdqa -0x150(%rbp), %xmm0
movq %rax, -0x50(%rbp)
movdqa %xmm0, -0x60(%rbp)
movdqa -0x60(%rbp), %xmm0
movq -0x50(%rbp), %rax
movdqu %xmm0, (%rax)
movl -0x108(%rbp), %eax
addl $0x4, %eax
movl %eax, -0x108(%rbp)
jmp 0x17f54
jmp 0x18100
movl -0x108(%rbp), %eax
cmpl -0xf4(%rbp), %eax
jae 0x18192
movq -0xe0(%rbp), %rax
movl -0x108(%rbp), %ecx
imulq -0x100(%rbp), %rcx
addq %rcx, %rax
movq %rax, -0x158(%rbp)
movq -0x158(%rbp), %rax
movzbl 0x3(%rax), %edx
shll $0x18, %edx
movq -0x158(%rbp), %rax
movzbl (%rax), %eax
shll $0x10, %eax
orl %eax, %edx
movq -0x158(%rbp), %rax
movzbl 0x1(%rax), %eax
shll $0x8, %eax
orl %eax, %edx
movq -0x158(%rbp), %rax
movzbl 0x2(%rax), %eax
shll $0x0, %eax
orl %eax, %edx
movq -0xf0(%rbp), %rax
movl -0x108(%rbp), %ecx
movl %edx, (%rax,%rcx,4)
movl -0x108(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x108(%rbp)
jmp 0x18100
movl -0xf4(%rbp), %ecx
movq -0xf0(%rbp), %rax
movl %ecx, %ecx
shlq $0x2, %rcx
addq %rcx, %rax
movq %rax, -0xf0(%rbp)
movq -0xe8(%rbp), %rax
addq -0xe0(%rbp), %rax
movq %rax, -0xe0(%rbp)
movl -0x104(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x104(%rbp)
jmp 0x17f38
addq $0xe0, %rsp
popq %rbp
retq
nopw %cs:(%rax,%rax)
nopl (%rax,%rax)