// File: Alcaro[P]bridges/arlib/image.cpp
// Function: blend_8888_on_8888(unsigned int, unsigned int)
static inline uint32_t blend_8888_on_8888(uint32_t argb_lower, uint32_t argb_upper)
{
#ifdef __SSE2__
	//no need to extend this above 128bit, it's complex enough without having to consider multiple pixels at once
	
	uint32_t spx = argb_upper;
	uint32_t tpx = argb_lower;
	
	//contains u16: spx.a, spx.b, spx.g, spx.r, tpx.{a,b,g,r}
	__m128i vals = _mm_unpacklo_epi8(_mm_set_epi32(0, 0, spx, tpx), _mm_setzero_si128());
	
	//contains u16: {sa}*4, {255-sa}*4
	__m128i alphas = _mm_xor_si128(_mm_set1_epi16(spx>>24), _mm_set_epi16(0,0,0,0, 255,255,255,255));
	//contains u16: pixel contributions times 255, separate per source/target
	__m128i newcols255 = _mm_mullo_epi16(vals, alphas);
	
	//contains u16: pixel contributions times 255, with combined channels (high half is garbage)
	newcols255 = _mm_add_epi16(_mm_bsrli_si128(newcols255, 64/8), _mm_add_epi16(newcols255, _mm_set1_epi16(254)));
	
	//ugly magic constants: (u16)*0x8081>>16>>7 = (u16)/255
	__m128i newcols = _mm_srli_epi16(_mm_mulhi_epu16(newcols255, _mm_set1_epi16(0x8081)), 7);
	
	return _mm_cvtsi128_si32(_mm_packus_epi16(newcols, _mm_undefined_si128()));
#else
	uint8_t sr = argb_upper>>0;
	uint8_t sg = argb_upper>>8;
	uint8_t sb = argb_upper>>16;
	uint8_t sa = argb_upper>>24;
	
	uint8_t tr = argb_lower>>0;
	uint8_t tg = argb_lower>>8;
	uint8_t tb = argb_lower>>16;
	uint8_t ta = argb_lower>>24;
	
	tr = (sr*sa + tr*(255-sa) + 254)/255;
	tg = (sg*sa + tg*(255-sa) + 254)/255;
	tb = (sb*sa + tb*(255-sa) + 254)/255;
	ta = (sa*sa + ta*(255-sa) + 254)/255;
	
	return (uint32_t)ta<<24 | tb<<16 | tg<<8 | tr<<0; // extra cast because u8 << 24 is signed
#endif
}

// Assembly:
pushq %rbp
movq %rsp, %rbp
subq $0x1b0, %rsp            # imm = 0x1B0
movl %edi, -0x1e4(%rbp)
movl %esi, -0x1e8(%rbp)
movl -0x1e8(%rbp), %eax
movl %eax, -0x1ec(%rbp)
movl -0x1e4(%rbp), %eax
movl %eax, -0x1f0(%rbp)
movl -0x1ec(%rbp), %ecx
movl -0x1f0(%rbp), %eax
movl $0x0, -0x1c4(%rbp)
movl $0x0, -0x1c8(%rbp)
movl %ecx, -0x1cc(%rbp)
movl %eax, -0x1d0(%rbp)
movd -0x1c4(%rbp), %xmm0
movd -0x1c8(%rbp), %xmm1
punpckldq %xmm0, %xmm1    # xmm1 = xmm1[0],xmm0[0],xmm1[1],xmm0[1]
movd -0x1cc(%rbp), %xmm2
movd -0x1d0(%rbp), %xmm0
punpckldq %xmm2, %xmm0    # xmm0 = xmm0[0],xmm2[0],xmm0[1],xmm2[1]
punpcklqdq %xmm1, %xmm0    # xmm0 = xmm0[0],xmm1[0]
movaps %xmm0, -0x1e0(%rbp)
movaps -0x1e0(%rbp), %xmm2
xorps %xmm0, %xmm0
movaps %xmm0, -0x1a0(%rbp)
movaps -0x1a0(%rbp), %xmm1
movaps %xmm2, -0x1b0(%rbp)
movaps %xmm1, -0x1c0(%rbp)
movaps -0x1b0(%rbp), %xmm1
movaps -0x1c0(%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, -0x200(%rbp)
movzbl -0x1e9(%rbp), %eax
movw %ax, -0x162(%rbp)
movw -0x162(%rbp), %ax
movw %ax, -0x142(%rbp)
movw %ax, -0x144(%rbp)
movw %ax, -0x146(%rbp)
movw %ax, -0x148(%rbp)
movw %ax, -0x14a(%rbp)
movw %ax, -0x14c(%rbp)
movw %ax, -0x14e(%rbp)
movw %ax, -0x150(%rbp)
movzwl -0x142(%rbp), %eax
movd %eax, %xmm2
movzwl -0x144(%rbp), %eax
movd %eax, %xmm1
punpcklwd %xmm2, %xmm1    # xmm1 = xmm1[0],xmm2[0],xmm1[1],xmm2[1],xmm1[2],xmm2[2],xmm1[3],xmm2[3]
movzwl -0x146(%rbp), %eax
movd %eax, %xmm3
movzwl -0x148(%rbp), %eax
movd %eax, %xmm2
punpcklwd %xmm3, %xmm2    # xmm2 = xmm2[0],xmm3[0],xmm2[1],xmm3[1],xmm2[2],xmm3[2],xmm2[3],xmm3[3]
punpckldq %xmm1, %xmm2    # xmm2 = xmm2[0],xmm1[0],xmm2[1],xmm1[1]
movzwl -0x14a(%rbp), %eax
movd %eax, %xmm1
movzwl -0x14c(%rbp), %eax
movd %eax, %xmm3
punpcklwd %xmm1, %xmm3    # xmm3 = xmm3[0],xmm1[0],xmm3[1],xmm1[1],xmm3[2],xmm1[2],xmm3[3],xmm1[3]
movzwl -0x14e(%rbp), %eax
movd %eax, %xmm4
movzwl -0x150(%rbp), %eax
movd %eax, %xmm1
punpcklwd %xmm4, %xmm1    # xmm1 = xmm1[0],xmm4[0],xmm1[1],xmm4[1],xmm1[2],xmm4[2],xmm1[3],xmm4[3]
punpckldq %xmm3, %xmm1    # xmm1 = xmm1[0],xmm3[0],xmm1[1],xmm3[1]
punpcklqdq %xmm2, %xmm1    # xmm1 = xmm1[0],xmm2[0]
movaps %xmm1, -0x160(%rbp)
movaps -0x160(%rbp), %xmm2
movw $0x0, -0xe2(%rbp)
movw $0x0, -0xe4(%rbp)
movw $0x0, -0xe6(%rbp)
movw $0x0, -0xe8(%rbp)
movw $0xff, -0xea(%rbp)
movw $0xff, -0xec(%rbp)
movw $0xff, -0xee(%rbp)
movw $0xff, -0xf0(%rbp)
movzwl -0xe2(%rbp), %eax
movd %eax, %xmm3
movzwl -0xe4(%rbp), %eax
movd %eax, %xmm1
punpcklwd %xmm3, %xmm1    # xmm1 = xmm1[0],xmm3[0],xmm1[1],xmm3[1],xmm1[2],xmm3[2],xmm1[3],xmm3[3]
movzwl -0xe6(%rbp), %eax
movd %eax, %xmm4
movzwl -0xe8(%rbp), %eax
movd %eax, %xmm3
punpcklwd %xmm4, %xmm3    # xmm3 = xmm3[0],xmm4[0],xmm3[1],xmm4[1],xmm3[2],xmm4[2],xmm3[3],xmm4[3]
punpckldq %xmm1, %xmm3    # xmm3 = xmm3[0],xmm1[0],xmm3[1],xmm1[1]
movzwl -0xea(%rbp), %eax
movd %eax, %xmm1
movzwl -0xec(%rbp), %eax
movd %eax, %xmm4
punpcklwd %xmm1, %xmm4    # xmm4 = xmm4[0],xmm1[0],xmm4[1],xmm1[1],xmm4[2],xmm1[2],xmm4[3],xmm1[3]
movzwl -0xee(%rbp), %eax
movd %eax, %xmm5
movzwl -0xf0(%rbp), %eax
movd %eax, %xmm1
punpcklwd %xmm5, %xmm1    # xmm1 = xmm1[0],xmm5[0],xmm1[1],xmm5[1],xmm1[2],xmm5[2],xmm1[3],xmm5[3]
punpckldq %xmm4, %xmm1    # xmm1 = xmm1[0],xmm4[0],xmm1[1],xmm4[1]
punpcklqdq %xmm3, %xmm1    # xmm1 = xmm1[0],xmm3[0]
movaps %xmm1, -0x100(%rbp)
movaps -0x100(%rbp), %xmm1
movaps %xmm2, -0x180(%rbp)
movaps %xmm1, -0x190(%rbp)
movaps -0x180(%rbp), %xmm1
movaps -0x190(%rbp), %xmm2
pxor %xmm2, %xmm1
movaps %xmm1, -0x210(%rbp)
movaps -0x200(%rbp), %xmm2
movaps -0x210(%rbp), %xmm1
movaps %xmm2, -0xd0(%rbp)
movaps %xmm1, -0xe0(%rbp)
movaps -0xd0(%rbp), %xmm1
movaps -0xe0(%rbp), %xmm2
pmullw %xmm2, %xmm1
movaps %xmm1, -0x220(%rbp)
movaps -0x220(%rbp), %xmm3
movaps %xmm3, %xmm2
psrldq $0x8, %xmm2             # xmm2 = xmm2[8,9,10,11,12,13,14,15],zero,zero,zero,zero,zero,zero,zero,zero
movw $0xfe, -0x164(%rbp)
movw -0x164(%rbp), %ax
movw %ax, -0x122(%rbp)
movw %ax, -0x124(%rbp)
movw %ax, -0x126(%rbp)
movw %ax, -0x128(%rbp)
movw %ax, -0x12a(%rbp)
movw %ax, -0x12c(%rbp)
movw %ax, -0x12e(%rbp)
movw %ax, -0x130(%rbp)
movzwl -0x122(%rbp), %eax
movd %eax, %xmm4
movzwl -0x124(%rbp), %eax
movd %eax, %xmm1
punpcklwd %xmm4, %xmm1    # xmm1 = xmm1[0],xmm4[0],xmm1[1],xmm4[1],xmm1[2],xmm4[2],xmm1[3],xmm4[3]
movzwl -0x126(%rbp), %eax
movd %eax, %xmm5
movzwl -0x128(%rbp), %eax
movd %eax, %xmm4
punpcklwd %xmm5, %xmm4    # xmm4 = xmm4[0],xmm5[0],xmm4[1],xmm5[1],xmm4[2],xmm5[2],xmm4[3],xmm5[3]
punpckldq %xmm1, %xmm4    # xmm4 = xmm4[0],xmm1[0],xmm4[1],xmm1[1]
movzwl -0x12a(%rbp), %eax
movd %eax, %xmm1
movzwl -0x12c(%rbp), %eax
movd %eax, %xmm5
punpcklwd %xmm1, %xmm5    # xmm5 = xmm5[0],xmm1[0],xmm5[1],xmm1[1],xmm5[2],xmm1[2],xmm5[3],xmm1[3]
movzwl -0x12e(%rbp), %eax
movd %eax, %xmm6
movzwl -0x130(%rbp), %eax
movd %eax, %xmm1
punpcklwd %xmm6, %xmm1    # xmm1 = xmm1[0],xmm6[0],xmm1[1],xmm6[1],xmm1[2],xmm6[2],xmm1[3],xmm6[3]
punpckldq %xmm5, %xmm1    # xmm1 = xmm1[0],xmm5[0],xmm1[1],xmm5[1]
punpcklqdq %xmm4, %xmm1    # xmm1 = xmm1[0],xmm4[0]
movaps %xmm1, -0x140(%rbp)
movaps -0x140(%rbp), %xmm1
movaps %xmm3, -0x90(%rbp)
movaps %xmm1, -0xa0(%rbp)
movaps -0x90(%rbp), %xmm1
movaps -0xa0(%rbp), %xmm3
paddw %xmm3, %xmm1
movaps %xmm2, -0xb0(%rbp)
movaps %xmm1, -0xc0(%rbp)
movaps -0xb0(%rbp), %xmm1
movaps -0xc0(%rbp), %xmm2
paddw %xmm2, %xmm1
movaps %xmm1, -0x220(%rbp)
movaps -0x220(%rbp), %xmm2
movw $0x8081, -0x166(%rbp)   # imm = 0x8081
movw -0x166(%rbp), %ax
movw %ax, -0x102(%rbp)
movw %ax, -0x104(%rbp)
movw %ax, -0x106(%rbp)
movw %ax, -0x108(%rbp)
movw %ax, -0x10a(%rbp)
movw %ax, -0x10c(%rbp)
movw %ax, -0x10e(%rbp)
movw %ax, -0x110(%rbp)
movzwl -0x102(%rbp), %eax
movd %eax, %xmm3
movzwl -0x104(%rbp), %eax
movd %eax, %xmm1
punpcklwd %xmm3, %xmm1    # xmm1 = xmm1[0],xmm3[0],xmm1[1],xmm3[1],xmm1[2],xmm3[2],xmm1[3],xmm3[3]
movzwl -0x106(%rbp), %eax
movd %eax, %xmm4
movzwl -0x108(%rbp), %eax
movd %eax, %xmm3
punpcklwd %xmm4, %xmm3    # xmm3 = xmm3[0],xmm4[0],xmm3[1],xmm4[1],xmm3[2],xmm4[2],xmm3[3],xmm4[3]
punpckldq %xmm1, %xmm3    # xmm3 = xmm3[0],xmm1[0],xmm3[1],xmm1[1]
movzwl -0x10a(%rbp), %eax
movd %eax, %xmm1
movzwl -0x10c(%rbp), %eax
movd %eax, %xmm4
punpcklwd %xmm1, %xmm4    # xmm4 = xmm4[0],xmm1[0],xmm4[1],xmm1[1],xmm4[2],xmm1[2],xmm4[3],xmm1[3]
movzwl -0x10e(%rbp), %eax
movd %eax, %xmm5
movzwl -0x110(%rbp), %eax
movd %eax, %xmm1
punpcklwd %xmm5, %xmm1    # xmm1 = xmm1[0],xmm5[0],xmm1[1],xmm5[1],xmm1[2],xmm5[2],xmm1[3],xmm5[3]
punpckldq %xmm4, %xmm1    # xmm1 = xmm1[0],xmm4[0],xmm1[1],xmm4[1]
punpcklqdq %xmm3, %xmm1    # xmm1 = xmm1[0],xmm3[0]
movaps %xmm1, -0x120(%rbp)
movaps -0x120(%rbp), %xmm1
movaps %xmm2, -0x50(%rbp)
movaps %xmm1, -0x60(%rbp)
movaps -0x50(%rbp), %xmm1
movaps -0x60(%rbp), %xmm2
pmulhuw %xmm2, %xmm1
movaps %xmm1, -0x70(%rbp)
movl $0x7, -0x74(%rbp)
movaps -0x70(%rbp), %xmm1
movd -0x74(%rbp), %xmm2
psrlw %xmm2, %xmm1
movaps %xmm1, -0x230(%rbp)
movaps -0x230(%rbp), %xmm1
movaps %xmm1, -0x10(%rbp)
movaps %xmm0, -0x20(%rbp)
movaps -0x10(%rbp), %xmm0
movaps -0x20(%rbp), %xmm1
packuswb %xmm1, %xmm0
movaps %xmm0, -0x30(%rbp)
movaps -0x30(%rbp), %xmm0
movaps %xmm0, -0x40(%rbp)
movl -0x40(%rbp), %eax
addq $0x1b0, %rsp            # imm = 0x1B0
popq %rbp
retq
nopl (%rax)