// File: Alcaro[P]bridges/arlib/image.cpp
// Function: void convert_scanline_rgb888_nrgb8888<4278190080u>(unsigned int*, unsigned char const*, unsigned long)
void convert_scanline_rgb888_nrgb8888(uint32_t* out, const uint8_t* in, size_t npx)
{
	uint32_t* out32 = (uint32_t*)out;
	size_t x = 0;
#if defined(__SSE2__)
	// we wish to read 12 bytes at the time, but loadu_si28 does 16, so -2 to ensure we don't read out of bounds
	// except put the -2 at the x side, (size_t)1-2 isn't less than anything
	while (x+4+2 <= npx)
	{
		uint8_t* src = (uint8_t*)in + x*3;
		
		__m128i pix = _mm_loadu_si128((__m128i*)src);
		//pix = u8*16 { rgbrgbrgbrgbXXXX }
		pix = _mm_bslli_si128(pix, 2);
		//pix = u8*16 { 00rgbrgbrgbrgbXX }
		pix = _mm_shufflehi_epi16(pix, _MM_SHUFFLE(2,1,0,3));
		//pix = u8*16 { 00rgbrgbXXrgbrgb }
		if (newalpha == 0x00000000)
		{
			pix = _mm_srli_epi64(pix, 2*8);
			//pix = u8*16 { rgbrgb00rgbrgb00 }
			pix = _mm_slli_epi64(pix, 1*8);
			//pix = u8*16 { 0rgbrgb00rgbrgb0 }
		}
		else
		{
			pix = _mm_srli_epi64(pix, 1*8);
			//pix = u8*16 { 0rgbrgb0Xrgbrgb0 }
		}
		
		__m128i pix1 = _mm_unpacklo_epi8(pix, _mm_setzero_si128());
		__m128i pix2 = _mm_unpackhi_epi8(pix, _mm_setzero_si128());
		pix1 = _mm_shufflelo_epi16(pix1, _MM_SHUFFLE(0,1,2,3)); // 0rgb -> 0bgr
		pix1 = _mm_shufflehi_epi16(pix1, _MM_SHUFFLE(3,0,1,2)); // rgb0 -> 0bgr
		pix2 = _mm_shufflelo_epi16(pix2, _MM_SHUFFLE(0,1,2,3)); // Xrgb -> Xbgr
		pix2 = _mm_shufflehi_epi16(pix2, _MM_SHUFFLE(3,0,1,2)); // rgb0 -> 0bgr
		pix = _mm_packus_epi16(pix1, pix2);
		//pix = u8*16 { 0bgr0bgrXbgr0bgr }
		
		if (newalpha == 0xFF000000)
			pix = _mm_or_si128(pix, _mm_set1_epi32(0xFF000000));
		
		_mm_storeu_si128((__m128i*)(out32 + x), pix);
		
		x += 4;
	}
	SIMD_LOOP_TAIL
#endif
	// Clang can vectorize this, but it emits some quite messy code, so keep the SSE2 anyways
	// (in fact, Clang flattens the above all the way to a single pshufb, if -mssse3)
	// gcc doesn't vectorize the below, nor do anything interesting to the above
	while (x < npx)
	{
		uint8_t* src = (uint8_t*)in + x*3;
		out32[x] = src[0]<<16 | src[1]<<8 | src[2];
		if (newalpha == 0xFF000000)
			out32[x] |= 0xFF000000;
		x++;
	}
}

// Assembly:
pushq %rbp
movq %rsp, %rbp
subq $0x100, %rsp            # imm = 0x100
movq %rdi, -0x118(%rbp)
movq %rsi, -0x120(%rbp)
movq %rdx, -0x128(%rbp)
movq -0x118(%rbp), %rax
movq %rax, -0x130(%rbp)
movq $0x0, -0x138(%rbp)
movq -0x138(%rbp), %rax
addq $0x4, %rax
addq $0x2, %rax
cmpq -0x128(%rbp), %rax
ja 0x1b5cd
movq -0x120(%rbp), %rax
movq -0x138(%rbp), %rcx
leaq (%rcx,%rcx,2), %rcx
addq %rcx, %rax
movq %rax, -0x140(%rbp)
movq -0x140(%rbp), %rax
movq %rax, -0x108(%rbp)
movq -0x108(%rbp), %rax
movups (%rax), %xmm0
movaps %xmm0, -0x150(%rbp)
movaps -0x150(%rbp), %xmm0
pslldq $0x2, %xmm0             # xmm0 = zero,zero,xmm0[0,1,2,3,4,5,6,7,8,9,10,11,12,13]
movaps %xmm0, -0x150(%rbp)
movaps -0x150(%rbp), %xmm0
pshufhw $0x93, %xmm0, %xmm0     # xmm0 = xmm0[0,1,2,3,7,4,5,6]
movaps %xmm0, -0x150(%rbp)
movaps -0x150(%rbp), %xmm0
movaps %xmm0, -0x30(%rbp)
movl $0x8, -0x34(%rbp)
movaps -0x30(%rbp), %xmm0
movd -0x34(%rbp), %xmm1
psrlq %xmm1, %xmm0
movaps %xmm0, -0x150(%rbp)
movaps -0x150(%rbp), %xmm2
xorps %xmm0, %xmm0
movaps %xmm0, -0x70(%rbp)
movaps -0x70(%rbp), %xmm1
movaps %xmm2, -0x90(%rbp)
movaps %xmm1, -0xa0(%rbp)
movaps -0x90(%rbp), %xmm1
movaps -0xa0(%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, -0x160(%rbp)
movaps -0x150(%rbp), %xmm1
movaps %xmm0, -0x80(%rbp)
movaps -0x80(%rbp), %xmm0
movaps %xmm1, -0x10(%rbp)
movaps %xmm0, -0x20(%rbp)
movaps -0x10(%rbp), %xmm0
movaps -0x20(%rbp), %xmm1
punpckhbw %xmm1, %xmm0    # xmm0 = xmm0[8],xmm1[8],xmm0[9],xmm1[9],xmm0[10],xmm1[10],xmm0[11],xmm1[11],xmm0[12],xmm1[12],xmm0[13],xmm1[13],xmm0[14],xmm1[14],xmm0[15],xmm1[15]
movaps %xmm0, -0x170(%rbp)
movaps -0x160(%rbp), %xmm0
pshuflw $0x1b, %xmm0, %xmm0     # xmm0 = xmm0[3,2,1,0,4,5,6,7]
movaps %xmm0, -0x160(%rbp)
movaps -0x160(%rbp), %xmm0
pshufhw $0xc6, %xmm0, %xmm0     # xmm0 = xmm0[0,1,2,3,6,5,4,7]
movaps %xmm0, -0x160(%rbp)
movaps -0x170(%rbp), %xmm0
pshuflw $0x1b, %xmm0, %xmm0     # xmm0 = xmm0[3,2,1,0,4,5,6,7]
movaps %xmm0, -0x170(%rbp)
movaps -0x170(%rbp), %xmm0
pshufhw $0xc6, %xmm0, %xmm0     # xmm0 = xmm0[0,1,2,3,6,5,4,7]
movaps %xmm0, -0x170(%rbp)
movaps -0x160(%rbp), %xmm1
movaps -0x170(%rbp), %xmm0
movaps %xmm1, -0x50(%rbp)
movaps %xmm0, -0x60(%rbp)
movaps -0x50(%rbp), %xmm0
movaps -0x60(%rbp), %xmm1
packuswb %xmm1, %xmm0
movaps %xmm0, -0x150(%rbp)
movaps -0x150(%rbp), %xmm1
movl $0xff000000, -0x10c(%rbp) # imm = 0xFF000000
movl -0x10c(%rbp), %eax
movl %eax, -0xa4(%rbp)
movl %eax, -0xa8(%rbp)
movl %eax, -0xac(%rbp)
movl %eax, -0xb0(%rbp)
movd -0xa4(%rbp), %xmm0
movd -0xa8(%rbp), %xmm2
punpckldq %xmm0, %xmm2    # xmm2 = xmm2[0],xmm0[0],xmm2[1],xmm0[1]
movd -0xac(%rbp), %xmm3
movd -0xb0(%rbp), %xmm0
punpckldq %xmm3, %xmm0    # xmm0 = xmm0[0],xmm3[0],xmm0[1],xmm3[1]
punpcklqdq %xmm2, %xmm0    # xmm0 = xmm0[0],xmm2[0]
movdqa %xmm0, -0xc0(%rbp)
movdqa -0xc0(%rbp), %xmm0
movdqa %xmm1, -0xf0(%rbp)
movdqa %xmm0, -0x100(%rbp)
movdqa -0xf0(%rbp), %xmm0
por -0x100(%rbp), %xmm0
movdqa %xmm0, -0x150(%rbp)
movq -0x130(%rbp), %rax
movq -0x138(%rbp), %rcx
shlq $0x2, %rcx
addq %rcx, %rax
movdqa -0x150(%rbp), %xmm0
movq %rax, -0xc8(%rbp)
movdqa %xmm0, -0xe0(%rbp)
movdqa -0xe0(%rbp), %xmm0
movq -0xc8(%rbp), %rax
movdqu %xmm0, (%rax)
movq -0x138(%rbp), %rax
addq $0x4, %rax
movq %rax, -0x138(%rbp)
jmp 0x1b369
jmp 0x1b5cf
movq -0x138(%rbp), %rax
cmpq -0x128(%rbp), %rax
jae 0x1b668
movq -0x120(%rbp), %rax
imulq $0x3, -0x138(%rbp), %rcx
addq %rcx, %rax
movq %rax, -0x178(%rbp)
movq -0x178(%rbp), %rax
movzbl (%rax), %edx
shll $0x10, %edx
movq -0x178(%rbp), %rax
movzbl 0x1(%rax), %eax
shll $0x8, %eax
orl %eax, %edx
movq -0x178(%rbp), %rax
movzbl 0x2(%rax), %eax
orl %eax, %edx
movq -0x130(%rbp), %rax
movq -0x138(%rbp), %rcx
movl %edx, (%rax,%rcx,4)
movq -0x130(%rbp), %rax
movq -0x138(%rbp), %rcx
movl (%rax,%rcx,4), %edx
orl $0xff000000, %edx       # imm = 0xFF000000
movl %edx, (%rax,%rcx,4)
movq -0x138(%rbp), %rax
addq $0x1, %rax
movq %rax, -0x138(%rbp)
jmp 0x1b5cf
addq $0x100, %rsp            # imm = 0x100
popq %rbp
retq
nopw %cs:(%rax,%rax)
nopl (%rax,%rax)