// File: /workspace/github_c_makefile_star2_O2/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 0x48ff
leal -0x3(%rsi), %eax
xorl %r15d, %r15d
cmpl $0x4, %esi
cmovgel %eax, %r15d
movl 0x90(%r14,%r15,4), %ebp
movq 0xa0(%r14), %rdi
leaq 0x3f3d(%rip), %rax      # 0x87e0
movslq (%rax,%r15,4), %rsi
addq %rax, %rsi
callq 0x3df2
testw %ax, %ax
jle 0x48dd
movswl %ax, %ebx
movq 0xa0(%r14), %rdi
movl %ebx, %esi
callq 0x3c08
leal -0x1(%rbx), %ecx
movzbl %cl, %ecx
btl %ecx, %eax
jb 0x48db
pushq $-0x1
popq %rdx
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)
pushq $0x1
popq %rbx
movl $0x278, %r13d           # imm = 0x278
jmp 0x4907
xorl %ebx, %ebx
movl $0x2b8, %r13d           # imm = 0x2B8
addq %r14, %r13
leaq 0x178(%r14), %rax
movq %rax, 0x8(%rsp)
pushq $0x1
popq %rbp
movq 0xa0(%r14), %rdi
leaq 0x3ec9(%rip), %rsi      # 0x87f0
callq 0x3df2
movzwl %ax, %r12d
cmpw $0x1, %r12w
jne 0x4952
testl %ebx, %ebx
je 0x4952
movq 0xa0(%r14), %rdi
movl %ebp, %esi
callq 0x3c08
testl %eax, %eax
jne 0x495f
jmp 0x4a92
cmpl $0xffff, %r12d          # imm = 0xFFFF
je 0x4a23
movl %r12d, %r15d
shrl $0x8, %r15d
movzbl %r12b, %r12d
movq 0xa0(%r14), %rdi
movl %ebp, %esi
callq 0x3c08
movl %eax, %ecx
movl %r12d, %eax
negl %eax
testl %ecx, %ecx
cmovel %r12d, %eax
addl %ebx, %r15d
cmpl $0x3f, %r15d
ja 0x4cb6
movl %r15d, %ecx
leal (%rax,%rax), %esi
sarl $0x1f, %esi
orl $0x1, %esi
xorl %edx, %edx
cmpl %edx, 0x8c(%r14)
cmovnel %edx, %esi
leaq 0x395f(%rip), %rdi      # 0x8310
movzbl (%rcx,%rdi), %ecx
leal (%rsi,%rax,2), %eax
imull 0x74(%r14), %eax
movzbl (%r13,%rcx), %r8d
imull %eax, %r8d
movl %r8d, %eax
sarl $0x4, %eax
xorl %esi, %esi
testl %eax, %eax
setle %dil
testb $0x10, %r8b
jne 0x49e5
movb %dil, %sil
leal -0x1(,%rsi,2), %edx
addl %eax, %edx
cmpl $0xfffff801, %edx       # imm = 0xFFFFF801
jge 0x49f4
movl $0xfffff800, %edx       # imm = 0xFFFFF800
movl $0x7ff, %eax            # imm = 0x7FF
cmpl %eax, %edx
jl 0x4a02
movl $0x7ff, %edx            # imm = 0x7FF
incl %r15d
leaq 0x4164(%rip), %rax      # 0x8b70
movzbl (%rcx,%rax), %eax
imull %edx, %eax
movl %eax, 0x178(%r14,%rcx,4)
movl %r15d, %ebx
jmp 0x4919
movq 0xa0(%r14), %rdi
pushq $0x6
popq %rsi
callq 0x3c08
movl %eax, %r15d
movq 0xa0(%r14), %rdi
pushq $0x8
popq %rsi
callq 0x3c08
cmpl $0x80, %eax
je 0x4a65
movl %eax, %ecx
testl %eax, %eax
jne 0x4a7e
movq 0xa0(%r14), %rdi
pushq $0x8
popq %rsi
callq 0x3c08
jmp 0x4985
movq 0xa0(%r14), %rdi
pushq $0x8
popq %rsi
callq 0x3c08
addl $0xffffff00, %eax       # imm = 0xFFFFFF00
jmp 0x4985
leal -0x100(%rcx), %eax
cmpl $0x81, %ecx
cmovll %ecx, %eax
jmp 0x4985
movq 0x10(%rsp), %rdx
cmpl $0x3, %edx
jg 0x4ad0
movq 0xc8(%r14), %r13
movl 0x30(%r14), %r15d
movl 0x80(%r14), %eax
imull %r15d, %eax
addl 0x84(%r14), %eax
shll $0x4, %eax
movl %edx, %ecx
andl $0x1, %ecx
leal (%rax,%rcx,8), %r12d
testb $0x2, %dl
je 0x4b01
leal (%r12,%r15,8), %r12d
jmp 0x4b01
xorl %eax, %eax
cmpl $0x4, %edx
sete %al
shll $0x4, %eax
movq 0xd8(%rax,%r14), %r13
movl 0x80(%r14), %eax
imull 0x30(%r14), %eax
movl 0x38(%r14), %r15d
shll $0x2, %eax
movl 0x84(%r14), %ecx
leal (%rax,%rcx,8), %r12d
cmpl $0x0, 0x8c(%r14)
je 0x4b61
cmpl $0x1, %ebx
jne 0x4bc7
movq 0x8(%rsp), %rdi
movl (%rdi), %eax
subl $-0x80, %eax
sarl $0x8, %eax
xorl %ecx, %ecx
testl %eax, %eax
cmovlel %ecx, %eax
movl $0xff, %edx
cmpl %edx, %eax
cmovgel %edx, %eax
addl $-0x8, %r15d
cmpl $0x8, %ecx
je 0x4c27
movslq %r12d, %rsi
addq %r13, %rsi
xorl %edx, %edx
cmpl $0x8, %edx
je 0x4b54
movb %al, (%rsi,%rdx)
incq %rdx
jmp 0x4b47
addl %r15d, %r12d
addl %r12d, %edx
incl %ecx
movl %edx, %r12d
jmp 0x4b36
cmpl $0x1, %ebx
jne 0x4c2f
movq 0x8(%rsp), %r10
movl (%r10), %eax
subl $-0x80, %eax
sarl $0x8, %eax
addl $-0x8, %r15d
xorl %ecx, %ecx
movl $0xff, %edx
xorl %esi, %esi
cmpl $0x8, %esi
je 0x4cb2
movslq %r12d, %r8
addq %r13, %r8
xorl %edi, %edi
cmpl $0x8, %edi
je 0x4bba
movzbl (%r8,%rdi), %r9d
addl %eax, %r9d
testl %r9d, %r9d
cmovlel %ecx, %r9d
cmpl %edx, %r9d
cmovgel %edx, %r9d
movb %r9b, (%r8,%rdi)
incq %rdi
jmp 0x4b96
addl %r15d, %r12d
addl %r12d, %edi
incl %esi
movl %edi, %r12d
jmp 0x4b85
movq 0x8(%rsp), %rbx
movq %rbx, %rdi
callq 0x52c1
addl $-0x8, %r15d
xorl %eax, %eax
movl $0xff, %ecx
movq %rbx, %rdx
xorl %esi, %esi
cmpl $0x8, %esi
je 0x4c95
movslq %r12d, %r8
addq %r13, %r8
xorl %edi, %edi
cmpq $0x8, %rdi
je 0x4c16
movl (%rdx,%rdi,4), %r9d
testl %r9d, %r9d
cmovlel %eax, %r9d
cmpl %ecx, %r9d
cmovgel %ecx, %r9d
movb %r9b, (%r8,%rdi)
incq %rdi
jmp 0x4bf5
addl %r15d, %r12d
addl %r12d, %edi
incl %esi
addq $0x20, %rdx
movl %edi, %r12d
jmp 0x4be4
andl $0x0, (%rdi)
jmp 0x4cb6
movq 0x8(%rsp), %rbx
movq %rbx, %rdi
callq 0x52c1
addl $-0x8, %r15d
xorl %eax, %eax
movq %rbx, %rcx
xorl %edx, %edx
movl $0xff, %r9d
cmpl $0x8, %edx
je 0x4c95
movslq %r12d, %rdi
addq %r13, %rdi
xorl %esi, %esi
cmpq $0x8, %rsi
je 0x4c84
movzbl (%rdi,%rsi), %r8d
addl (%rcx,%rsi,4), %r8d
testl %r8d, %r8d
cmovlel %eax, %r8d
cmpl %r9d, %r8d
jl 0x4c7b
movl $0xff, %r8d
movb %r8b, (%rdi,%rsi)
incq %rsi
jmp 0x4c5a
addl %r15d, %r12d
addl %r12d, %esi
incl %edx
addq $0x20, %rcx
movl %esi, %r12d
jmp 0x4c4d
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
andl $0x0, (%r10)
addq $0x18, %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq