// File: rpavlik[P]edid-decode/parse-base-block.cpp
// Function: edid_state::detailed_cvt_descriptor(char const*, unsigned char const*, bool)
void edid_state::detailed_cvt_descriptor(const char *prefix, const unsigned char *x, bool first)
{
	static const unsigned char empty[3] = { 0, 0, 0 };
	struct timings cvt_t = {};
	unsigned char preferred;

	if (!first && !memcmp(x, empty, 3))
		return;

	cvt_t.vact = x[0];
	if (!cvt_t.vact)
		fail("CVT byte 0 is 0, which is a reserved value.\n");
	cvt_t.vact |= (x[1] & 0xf0) << 4;
	cvt_t.vact++;
	cvt_t.vact *= 2;

	switch (x[1] & 0x0c) {
	case 0x00:
	default: /* avoids 'width/ratio may be used uninitialized' warnings */
		cvt_t.hratio = 4;
		cvt_t.vratio = 3;
		break;
	case 0x04:
		cvt_t.hratio = 16;
		cvt_t.vratio = 9;
		break;
	case 0x08:
		cvt_t.hratio = 16;
		cvt_t.vratio = 10;
		break;
	case 0x0c:
		cvt_t.hratio = 15;
		cvt_t.vratio = 9;
		break;
	}
	cvt_t.hact = 8 * (((cvt_t.vact * cvt_t.hratio) / cvt_t.vratio) / 8);

	if (x[1] & 0x03)
		fail("Reserved bits of CVT byte 1 are non-zero.\n");
	if (x[2] & 0x80)
		fail("Reserved bit of CVT byte 2 is non-zero.\n");
	if (!(x[2] & 0x1f))
		fail("CVT byte 2 does not support any vertical rates.\n");
	preferred = (x[2] & 0x60) >> 5;
	if (preferred == 1 && (x[2] & 0x01))
		preferred = 4;
	if (!(x[2] & (1 << (4 - preferred))))
		fail("The preferred CVT Vertical Rate is not supported.\n");

	static const char *s_pref = "preferred vertical rate";

	if (x[2] & 0x10) {
		edid_cvt_mode(50, cvt_t);
		print_timings(prefix, &cvt_t, "CVT", preferred == 0 ? s_pref : "");
	}
	if (x[2] & 0x08) {
		edid_cvt_mode(60, cvt_t);
		print_timings(prefix, &cvt_t, "CVT", preferred == 1 ? s_pref : "");
	}
	if (x[2] & 0x04) {
		edid_cvt_mode(75, cvt_t);
		print_timings(prefix, &cvt_t, "CVT", preferred == 2 ? s_pref : "");
	}
	if (x[2] & 0x02) {
		edid_cvt_mode(85, cvt_t);
		print_timings(prefix, &cvt_t, "CVT", preferred == 3 ? s_pref : "");
	}
	if (x[2] & 0x01) {
		cvt_t.rb = RB_CVT_V1;
		edid_cvt_mode(60, cvt_t);
		print_timings(prefix, &cvt_t, "CVT", preferred == 4 ? s_pref : "");
	}
}

// Assembly:
pushq %rbp
movq %rsp, %rbp
subq $0xe0, %rsp
movb %cl, %al
movq %rdi, -0x8(%rbp)
movq %rsi, -0x10(%rbp)
movq %rdx, -0x18(%rbp)
andb $0x1, %al
movb %al, -0x19(%rbp)
movq -0x8(%rbp), %rax
movq %rax, -0x80(%rbp)
leaq -0x70(%rbp), %rdi
xorl %esi, %esi
movl $0x54, %edx
callq 0x41c0
testb $0x1, -0x19(%rbp)
jne 0xf10b
movq -0x18(%rbp), %rdi
leaq 0x24765(%rip), %rsi     # 0x3385c
movl $0x3, %edx
callq 0x4190
cmpl $0x0, %eax
jne 0xf10b
jmp 0xf52a
movq -0x18(%rbp), %rax
movzbl (%rax), %eax
movl %eax, -0x6c(%rbp)
cmpl $0x0, -0x6c(%rbp)
jne 0xf12b
xorl %edi, %edi
leaq 0x24820(%rip), %rsi     # 0x33944
movb $0x0, %al
callq 0x47d0
movq -0x18(%rbp), %rax
movzbl 0x1(%rax), %ecx
andl $-0x10, %ecx
shll $0x4, %ecx
movl -0x6c(%rbp), %eax
orl %ecx, %eax
movl %eax, -0x6c(%rbp)
movl -0x6c(%rbp), %eax
incl %eax
movl %eax, -0x6c(%rbp)
movl -0x6c(%rbp), %eax
addl %eax, %eax
movl %eax, -0x6c(%rbp)
movq -0x18(%rbp), %rax
movzbl 0x1(%rax), %eax
andl $0xc, %eax
movl %eax, %ecx
movq %rcx, -0x88(%rbp)
subl $0xc, %eax
ja 0xf183
movq -0x88(%rbp), %rax
leaq 0x22498(%rip), %rcx     # 0x31610
movslq (%rcx,%rax,4), %rax
addq %rcx, %rax
jmpq *%rax
jmp 0xf183
movl $0x4, -0x68(%rbp)
movl $0x3, -0x64(%rbp)
jmp 0xf1c1
movl $0x10, -0x68(%rbp)
movl $0x9, -0x64(%rbp)
jmp 0xf1c1
movl $0x10, -0x68(%rbp)
movl $0xa, -0x64(%rbp)
jmp 0xf1c1
movl $0xf, -0x68(%rbp)
movl $0x9, -0x64(%rbp)
movl -0x6c(%rbp), %eax
imull -0x68(%rbp), %eax
xorl %edx, %edx
divl -0x64(%rbp)
shrl $0x3, %eax
shll $0x3, %eax
movl %eax, -0x70(%rbp)
movq -0x18(%rbp), %rax
movzbl 0x1(%rax), %eax
andl $0x3, %eax
cmpl $0x0, %eax
je 0xf1f6
xorl %edi, %edi
leaq 0x24782(%rip), %rsi     # 0x33971
movb $0x0, %al
callq 0x47d0
movq -0x18(%rbp), %rax
movzbl 0x2(%rax), %eax
andl $0x80, %eax
cmpl $0x0, %eax
je 0xf218
xorl %edi, %edi
leaq 0x2478b(%rip), %rsi     # 0x3399c
movb $0x0, %al
callq 0x47d0
movq -0x18(%rbp), %rax
movzbl 0x2(%rax), %eax
andl $0x1f, %eax
cmpl $0x0, %eax
jne 0xf238
xorl %edi, %edi
leaq 0x24794(%rip), %rsi     # 0x339c5
movb $0x0, %al
callq 0x47d0
movq -0x18(%rbp), %rax
movzbl 0x2(%rax), %eax
andl $0x60, %eax
sarl $0x5, %eax
movb %al, -0x71(%rbp)
movzbl -0x71(%rbp), %eax
cmpl $0x1, %eax
jne 0xf266
movq -0x18(%rbp), %rax
movzbl 0x2(%rax), %eax
andl $0x1, %eax
cmpl $0x0, %eax
je 0xf266
movb $0x4, -0x71(%rbp)
movq -0x18(%rbp), %rax
movzbl 0x2(%rax), %eax
movzbl -0x71(%rbp), %edx
movl $0x4, %ecx
subl %edx, %ecx
movl $0x1, %edx
shll %cl, %edx
movl %edx, %ecx
andl %ecx, %eax
cmpl $0x0, %eax
jne 0xf299
xorl %edi, %edi
leaq 0x24764(%rip), %rsi     # 0x339f6
movb $0x0, %al
callq 0x47d0
movq -0x18(%rbp), %rax
movzbl 0x2(%rax), %eax
andl $0x10, %eax
cmpl $0x0, %eax
je 0xf31b
movq -0x80(%rbp), %rdi
movl $0x32, %esi
leaq -0x70(%rbp), %rdx
callq 0x2e180
movq -0x10(%rbp), %rax
movq %rax, -0x90(%rbp)
movzbl -0x71(%rbp), %eax
cmpl $0x0, %eax
jne 0xf2df
movq 0x3c3ba(%rip), %rax     # 0x4b690
movq %rax, -0x98(%rbp)
jmp 0xf2ef
leaq 0x20bd3(%rip), %rax     # 0x2feb9
movq %rax, -0x98(%rbp)
jmp 0xf2ef
movq -0x90(%rbp), %rsi
movq -0x80(%rbp), %rdi
movq -0x98(%rbp), %r8
leaq -0x70(%rbp), %rdx
leaq 0x20b67(%rip), %rcx     # 0x2fe73
xorl %r9d, %r9d
movl $0x1, (%rsp)
callq 0x50c0
movq -0x18(%rbp), %rax
movzbl 0x2(%rax), %eax
andl $0x8, %eax
cmpl $0x0, %eax
je 0xf39d
movq -0x80(%rbp), %rdi
movl $0x3c, %esi
leaq -0x70(%rbp), %rdx
callq 0x2e180
movq -0x10(%rbp), %rax
movq %rax, -0xa0(%rbp)
movzbl -0x71(%rbp), %eax
cmpl $0x1, %eax
jne 0xf361
movq 0x3c338(%rip), %rax     # 0x4b690
movq %rax, -0xa8(%rbp)
jmp 0xf371
leaq 0x20b51(%rip), %rax     # 0x2feb9
movq %rax, -0xa8(%rbp)
jmp 0xf371
movq -0xa0(%rbp), %rsi
movq -0x80(%rbp), %rdi
movq -0xa8(%rbp), %r8
leaq -0x70(%rbp), %rdx
leaq 0x20ae5(%rip), %rcx     # 0x2fe73
xorl %r9d, %r9d
movl $0x1, (%rsp)
callq 0x50c0
movq -0x18(%rbp), %rax
movzbl 0x2(%rax), %eax
andl $0x4, %eax
cmpl $0x0, %eax
je 0xf41f
movq -0x80(%rbp), %rdi
movl $0x4b, %esi
leaq -0x70(%rbp), %rdx
callq 0x2e180
movq -0x10(%rbp), %rax
movq %rax, -0xb0(%rbp)
movzbl -0x71(%rbp), %eax
cmpl $0x2, %eax
jne 0xf3e3
movq 0x3c2b6(%rip), %rax     # 0x4b690
movq %rax, -0xb8(%rbp)
jmp 0xf3f3
leaq 0x20acf(%rip), %rax     # 0x2feb9
movq %rax, -0xb8(%rbp)
jmp 0xf3f3
movq -0xb0(%rbp), %rsi
movq -0x80(%rbp), %rdi
movq -0xb8(%rbp), %r8
leaq -0x70(%rbp), %rdx
leaq 0x20a63(%rip), %rcx     # 0x2fe73
xorl %r9d, %r9d
movl $0x1, (%rsp)
callq 0x50c0
movq -0x18(%rbp), %rax
movzbl 0x2(%rax), %eax
andl $0x2, %eax
cmpl $0x0, %eax
je 0xf4a1
movq -0x80(%rbp), %rdi
movl $0x55, %esi
leaq -0x70(%rbp), %rdx
callq 0x2e180
movq -0x10(%rbp), %rax
movq %rax, -0xc0(%rbp)
movzbl -0x71(%rbp), %eax
cmpl $0x3, %eax
jne 0xf465
movq 0x3c234(%rip), %rax     # 0x4b690
movq %rax, -0xc8(%rbp)
jmp 0xf475
leaq 0x20a4d(%rip), %rax     # 0x2feb9
movq %rax, -0xc8(%rbp)
jmp 0xf475
movq -0xc0(%rbp), %rsi
movq -0x80(%rbp), %rdi
movq -0xc8(%rbp), %r8
leaq -0x70(%rbp), %rdx
leaq 0x209e1(%rip), %rcx     # 0x2fe73
xorl %r9d, %r9d
movl $0x1, (%rsp)
callq 0x50c0
movq -0x18(%rbp), %rax
movzbl 0x2(%rax), %eax
andl $0x1, %eax
cmpl $0x0, %eax
je 0xf52a
movq -0x80(%rbp), %rdi
movl $0x1, -0x5c(%rbp)
movl $0x3c, %esi
leaq -0x70(%rbp), %rdx
callq 0x2e180
movq -0x10(%rbp), %rax
movq %rax, -0xd0(%rbp)
movzbl -0x71(%rbp), %eax
cmpl $0x4, %eax
jne 0xf4ee
movq 0x3c1ab(%rip), %rax     # 0x4b690
movq %rax, -0xd8(%rbp)
jmp 0xf4fe
leaq 0x209c4(%rip), %rax     # 0x2feb9
movq %rax, -0xd8(%rbp)
jmp 0xf4fe
movq -0xd0(%rbp), %rsi
movq -0x80(%rbp), %rdi
movq -0xd8(%rbp), %r8
leaq -0x70(%rbp), %rdx
leaq 0x20958(%rip), %rcx     # 0x2fe73
xorl %r9d, %r9d
movl $0x1, (%rsp)
callq 0x50c0
addq $0xe0, %rsp
popq %rbp
retq
nopw %cs:(%rax,%rax)