// File: /workspace/github_c_makefile_star2_O3/phoboslab[P]pl_mpeg/./pl_mpeg.h
// Function: plm_video_decode_block
void plm_video_decode_block(plm_video_t *self, int block) {

	int n = 0;
	uint8_t *quant_matrix;

	// Decode DC coefficient of intra-coded blocks
	if (self->macroblock_intra) {
		int predictor;
		int dct_size;

		// DC prediction
		int plane_index = block > 3 ? block - 3 : 0;
		predictor = self->dc_predictor[plane_index];
		dct_size = plm_buffer_read_vlc(self->buffer, PLM_VIDEO_DCT_SIZE[plane_index]);

		// Read DC coeff
		if (dct_size > 0) {
			int differential = plm_buffer_read(self->buffer, dct_size);
			if ((differential & (1 << (dct_size - 1))) != 0) {
				self->block_data[0] = predictor + differential;
			}
			else {
				self->block_data[0] = predictor + (-(1 << dct_size) | (differential + 1));
			}
		}
		else {
			self->block_data[0] = predictor;
		}

		// Save predictor value
		self->dc_predictor[plane_index] = self->block_data[0];

		// Dequantize + premultiply
		self->block_data[0] <<= (3 + 5);

		quant_matrix = self->intra_quant_matrix;
		n = 1;
	}
	else {
		quant_matrix = self->non_intra_quant_matrix;
	}

	// Decode AC coefficients (+DC for non-intra)
	int level = 0;
	while (TRUE) {
		int run = 0;
		uint16_t coeff = plm_buffer_read_vlc_uint(self->buffer, PLM_VIDEO_DCT_COEFF);

		if ((coeff == 0x0001) && (n > 0) && (plm_buffer_read(self->buffer, 1) == 0)) {
			// end_of_block
			break;
		}
		if (coeff == 0xffff) {
			// escape
			run = plm_buffer_read(self->buffer, 6);
			level = plm_buffer_read(self->buffer, 8);
			if (level == 0) {
				level = plm_buffer_read(self->buffer, 8);
			}
			else if (level == 128) {
				level = plm_buffer_read(self->buffer, 8) - 256;
			}
			else if (level > 128) {
				level = level - 256;
			}
		}
		else {
			run = coeff >> 8;
			level = coeff & 0xff;
			if (plm_buffer_read(self->buffer, 1)) {
				level = -level;
			}
		}

		n += run;
		if (n < 0 || n >= 64) {
			return; // invalid
		}

		int de_zig_zagged = PLM_VIDEO_ZIG_ZAG[n];
		n++;

		// Dequantize, oddify, clip
		level = (unsigned)level << 1;
		if (!self->macroblock_intra) {
			level += (level < 0 ? -1 : 1);
		}
		level = (level * self->quantizer_scale * quant_matrix[de_zig_zagged]) >> 4;
		if ((level & 1) == 0) {
			level -= level > 0 ? 1 : -1;
		}
		if (level > 2047) {
			level = 2047;
		}
		else if (level < -2048) {
			level = -2048;
		}

		// Save premultiplied coefficient
		self->block_data[de_zig_zagged] = level * PLM_VIDEO_PREMULTIPLIER_MATRIX[de_zig_zagged];
	}

	// Move block to its place
	uint8_t *d;
	int dw;
	int di;

	if (block < 4) {
		d = self->frame_current.y.data;
		dw = self->luma_width;
		di = (self->mb_row * self->luma_width + self->mb_col) << 4;
		if ((block & 1) != 0) {
			di += 8;
		}
		if ((block & 2) != 0) {
			di += self->luma_width << 3;
		}
	}
	else {
		d = (block == 4) ? self->frame_current.cb.data : self->frame_current.cr.data;
		dw = self->chroma_width;
		di = ((self->mb_row * self->luma_width) << 2) + (self->mb_col << 3);
	}

	int *s = self->block_data;
	int si = 0;
	if (self->macroblock_intra) {
		// Overwrite (no prediction)
		if (n == 1) {
			int clamped = plm_clamp((s[0] + 128) >> 8);
			PLM_BLOCK_SET(d, di, dw, si, 8, 8, clamped);
			s[0] = 0;
		}
		else {
			plm_video_idct(s);
			PLM_BLOCK_SET(d, di, dw, si, 8, 8, plm_clamp(s[si]));
			memset(self->block_data, 0, sizeof(self->block_data));
		}
	}
	else {
		// Add data to the predicted macroblock
		if (n == 1) {
			int value = (s[0] + 128) >> 8;
			PLM_BLOCK_SET(d, di, dw, si, 8, 8, plm_clamp(d[di] + value));
			s[0] = 0;
		}
		else {
			plm_video_idct(s);
			PLM_BLOCK_SET(d, di, dw, si, 8, 8, plm_clamp(d[di] + s[si]));
			memset(self->block_data, 0, sizeof(self->block_data));
		}
	}
}

// Assembly:
pushq %rbp
pushq %r15
pushq %r14
pushq %r13
pushq %r12
pushq %rbx
subq $0x18, %rsp
movq %rdi, %r14
cmpl $0x0, 0x8c(%rdi)
movq %rsi, 0x10(%rsp)
je 0x521a
leal -0x3(%rsi), %r15d
xorl %eax, %eax
cmpl $0x4, %esi
cmovll %eax, %r15d
movl 0x90(%r14,%r15,4), %ebp
movq 0xa0(%r14), %rbx
leaq 0x8c31(%rip), %rcx      # 0xddd0
movq (%rcx,%r15,8), %r12
movzwl %ax, %r13d
movq %rbx, %rdi
movl $0x1, %esi
callq 0x4215
addl %r13d, %eax
movslq %eax, %rcx
movzwl (%r12,%rcx,4), %eax
testw %ax, %ax
jg 0x51a3
movswl 0x2(%r12,%rcx,4), %ebx
testl %ebx, %ebx
jle 0x51f6
movq 0xa0(%r14), %rdi
movl %ebx, %esi
callq 0x4215
leal -0x1(%rbx), %ecx
movzbl %cl, %ecx
btl %ecx, %eax
jb 0x51f4
movl $0xffffffff, %edx       # imm = 0xFFFFFFFF
movl %ebx, %ecx
shll %cl, %edx
incl %eax
orl %edx, %eax
addl %eax, %ebp
movl %ebp, 0x178(%r14)
movl %ebp, 0x90(%r14,%r15,4)
shll $0x8, 0x178(%r14)
movl $0x1, %ebx
movl $0x278, %r15d           # imm = 0x278
jmp 0x5222
movl $0x2b8, %r15d           # imm = 0x2B8
xorl %ebx, %ebx
addq %r14, %r15
leaq 0x178(%r14), %rax
movq %rax, 0x8(%rsp)
leaq 0x45f8(%rip), %r13      # 0x9830
movq 0xa0(%r14), %r12
xorl %eax, %eax
movzwl %ax, %ebp
movq %r12, %rdi
movl $0x1, %esi
callq 0x4215
addl %ebp, %eax
movslq %eax, %rcx
movzwl (%r13,%rcx,4), %eax
testw %ax, %ax
jg 0x5241
movzwl 0x2(%r13,%rcx,4), %r12d
cmpl $0x1, %r12d
jne 0x528b
testl %ebx, %ebx
jle 0x528b
movq 0xa0(%r14), %rdi
movl $0x1, %esi
callq 0x4215
testl %eax, %eax
jne 0x5298
jmp 0x53c3
cmpl $0xffff, %r12d          # imm = 0xFFFF
je 0x534d
movl %r12d, %ebp
shrl $0x8, %ebp
movzbl %r12b, %r12d
movq 0xa0(%r14), %rdi
movl $0x1, %esi
callq 0x4215
movl %eax, %ecx
movl %r12d, %eax
negl %eax
testl %ecx, %ecx
cmovel %r12d, %eax
addl %ebx, %ebp
cmpl $0x3f, %ebp
ja 0x54f4
movl %ebp, %ecx
incl %ebp
leal (%rax,%rax), %edx
sarl $0x1f, %edx
orl $0x1, %edx
xorl %edi, %edi
cmpl %edi, 0x8c(%r14)
cmovnel %edi, %edx
leal (%rdx,%rax,2), %eax
imull 0x74(%r14), %eax
leaq 0x406d(%rip), %rdx      # 0x9360
movzbl (%rcx,%rdx), %ecx
movzbl (%r15,%rcx), %edx
imull %eax, %edx
movl %edx, %eax
sarl $0x4, %eax
xorl %esi, %esi
testl %eax, %eax
setle %sil
testb $0x10, %dl
leal -0x1(%rsi,%rsi), %edx
cmovnel %edi, %edx
addl %eax, %edx
cmpl $0xfffff801, %edx       # imm = 0xFFFFF801
movl $0xfffff800, %eax       # imm = 0xFFFFF800
cmovll %eax, %edx
movl $0x7ff, %eax            # imm = 0x7FF
cmpl %eax, %edx
cmovgel %eax, %edx
leaq 0x4879(%rip), %rax      # 0x9bb0
movzbl (%rcx,%rax), %eax
imull %edx, %eax
movl %eax, 0x178(%r14,%rcx,4)
movl %ebp, %ebx
jmp 0x5238
movq 0xa0(%r14), %rdi
movl $0x6, %esi
callq 0x4215
movl %eax, %ebp
movq 0xa0(%r14), %rdi
movl $0x8, %esi
callq 0x4215
cmpl $0x80, %eax
je 0x5394
movl %eax, %ecx
testl %eax, %eax
jne 0x53af
movq 0xa0(%r14), %rdi
movl $0x8, %esi
callq 0x4215
jmp 0x52c0
movq 0xa0(%r14), %rdi
movl $0x8, %esi
callq 0x4215
addl $0xffffff00, %eax       # imm = 0xFFFFFF00
jmp 0x52c0
leal -0x100(%rcx), %eax
cmpl $0x81, %ecx
cmovll %ecx, %eax
jmp 0x52c0
movq 0x10(%rsp), %rdx
cmpl $0x3, %edx
jg 0x5401
movq 0xc8(%r14), %r12
movl 0x30(%r14), %r13d
movl 0x80(%r14), %eax
imull %r13d, %eax
addl 0x84(%r14), %eax
shll $0x4, %eax
movl %edx, %ecx
andl $0x1, %ecx
leal (%rax,%rcx,8), %ebp
testb $0x2, %dl
je 0x5431
leal (%rbp,%r13,8), %ebp
jmp 0x5431
xorl %eax, %eax
cmpl $0x4, %edx
sete %al
shll $0x4, %eax
movq 0xd8(%rax,%r14), %r12
movl 0x80(%r14), %eax
imull 0x30(%r14), %eax
movl 0x38(%r14), %r13d
shll $0x2, %eax
movl 0x84(%r14), %ecx
leal (%rax,%rcx,8), %ebp
cmpl $0x0, 0x8c(%r14)
je 0x548e
cmpl $0x1, %ebx
jne 0x5503
movq 0x8(%rsp), %rsi
movl (%rsi), %eax
subl $-0x80, %eax
sarl $0x8, %eax
xorl %ecx, %ecx
testl %eax, %eax
cmovgl %eax, %ecx
movl $0xff, %eax
cmpl %eax, %ecx
cmovgel %eax, %ecx
movl $0x8, %eax
movzbl %cl, %edx
movabsq $0x101010101010101, %rcx # imm = 0x101010101010101
imulq %rdx, %rcx
movslq %ebp, %rbp
movq %rcx, (%r12,%rbp)
addl %r13d, %ebp
decl %eax
jne 0x5478
movl $0x0, (%rsi)
jmp 0x54f4
cmpl $0x1, %ebx
jne 0x555a
movq 0x8(%rsp), %rcx
movl (%rcx), %eax
subl $-0x80, %eax
movd %eax, %xmm0
pshufd $0x0, %xmm0, %xmm0      # xmm0 = xmm0[0,0,0,0]
psrad $0x8, %xmm0
movl $0x8, %eax
pxor %xmm1, %xmm1
movslq %ebp, %rbp
movq (%r12,%rbp), %xmm2
punpcklbw %xmm1, %xmm2    # xmm2 = xmm2[0],xmm1[0],xmm2[1],xmm1[1],xmm2[2],xmm1[2],xmm2[3],xmm1[3],xmm2[4],xmm1[4],xmm2[5],xmm1[5],xmm2[6],xmm1[6],xmm2[7],xmm1[7]
movdqa %xmm2, %xmm3
punpcklwd %xmm1, %xmm3    # xmm3 = xmm3[0],xmm1[0],xmm3[1],xmm1[1],xmm3[2],xmm1[2],xmm3[3],xmm1[3]
punpckhwd %xmm1, %xmm2    # xmm2 = xmm2[4],xmm1[4],xmm2[5],xmm1[5],xmm2[6],xmm1[6],xmm2[7],xmm1[7]
paddd %xmm0, %xmm2
paddd %xmm0, %xmm3
packssdw %xmm2, %xmm3
packuswb %xmm3, %xmm3
movq %xmm3, (%r12,%rbp)
addl %r13d, %ebp
decl %eax
jne 0x54b8
movl $0x0, (%rcx)
addq $0x18, %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq
movq 0x8(%rsp), %rbx
movq %rbx, %rdi
callq 0x5b53
addl $-0x8, %r13d
xorl %eax, %eax
movl $0xff, %ecx
movq %rbx, %rdx
xorl %esi, %esi
movslq %ebp, %r8
addq %r12, %r8
xorl %edi, %edi
movl (%rdx,%rdi,4), %r9d
testl %r9d, %r9d
cmovlel %eax, %r9d
cmpl %ecx, %r9d
cmovgel %ecx, %r9d
movb %r9b, (%r8,%rdi)
incq %rdi
cmpl $0x8, %edi
jne 0x5528
addl %r13d, %ebp
addl %ebp, %edi
incl %esi
addq $0x20, %rdx
movl %edi, %ebp
cmpl $0x8, %esi
jne 0x5520
jmp 0x55b9
movq 0x8(%rsp), %rbx
movq %rbx, %rdi
callq 0x5b53
addl $-0x8, %r13d
xorl %eax, %eax
movq %rbx, %rcx
xorl %edx, %edx
movl $0xff, %r9d
movslq %ebp, %rdi
addq %r12, %rdi
xorl %esi, %esi
movzbl (%rdi,%rsi), %r8d
addl (%rcx,%rsi,4), %r8d
testl %r8d, %r8d
cmovlel %eax, %r8d
cmpl %r9d, %r8d
jl 0x559b
movl $0xff, %r8d
movb %r8b, (%rdi,%rsi)
incq %rsi
cmpl $0x8, %esi
jne 0x5580
addl %r13d, %ebp
addl %ebp, %esi
incl %edx
addq $0x20, %rcx
movl %esi, %ebp
cmpl $0x8, %edx
jne 0x5578
movl $0x100, %edx            # imm = 0x100
movq %rbx, %rdi
xorl %esi, %esi
addq $0x18, %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
jmp 0x20e0