// File: rpavlik[P]edid-decode/calc-gtf-cvt.cpp
// Function: edid_state::calc_cvt_mode(unsigned int, unsigned int, double, unsigned int, bool, bool, bool)
timings edid_state::calc_cvt_mode(unsigned h_pixels, unsigned v_lines,
				  double ip_freq_rqd, unsigned rb, bool int_rqd,
				  bool margins_rqd, bool alt)
{
	timings t = {};

	t.hact = h_pixels;
	t.vact = v_lines;
	t.interlaced = int_rqd;

	double cell_gran = rb == RB_CVT_V2 ? 1 : CELL_GRAN;
	double h_pixels_rnd = floor(h_pixels / cell_gran) * cell_gran;
	double v_lines_rnd = int_rqd ? floor(v_lines / 2.0) : v_lines;
	unsigned hor_margin = margins_rqd ?
		floor((h_pixels_rnd * MARGIN_PERC / 100.0) / cell_gran) * cell_gran : 0;
	unsigned vert_margin = margins_rqd ? floor(MARGIN_PERC / 100.0 * v_lines_rnd) : 0;
	double interlace = int_rqd ? 0.5 : 0;
	double total_active_pixels = h_pixels_rnd + hor_margin * 2;
	double v_field_rate_rqd = int_rqd ? ip_freq_rqd * 2 : ip_freq_rqd;
	double clock_step = rb == RB_CVT_V2 ? 0.001 : 0.25;
	double h_blank = (rb == RB_CVT_V1 || (rb == RB_CVT_V3 && alt)) ? 160 : 80;
	double rb_v_fporch = rb == RB_CVT_V1 ? 3 : 1;
	double refresh_multiplier = (rb == RB_CVT_V2 && alt) ? 1000.0 / 1001.0 : 1;
	double h_sync = 32;

	double v_sync;
	double pixel_freq;
	double v_blank;
	double v_sync_bp;

	/* Determine VSync Width from aspect ratio */
	if ((t.vact * 4 / 3) == t.hact)
		v_sync = 4;
	else if ((t.vact * 16 / 9) == t.hact)
		v_sync = 5;
	else if ((t.vact * 16 / 10) == t.hact)
		v_sync = 6;
	else if (!(t.vact % 4) && ((t.vact * 5 / 4) == t.hact))
		v_sync = 7;
	else if ((t.vact * 15 / 9) == t.hact)
		v_sync = 7;
	else                        /* Custom */
		v_sync = 10;

	if (rb >= RB_CVT_V2)
		v_sync = 8;

	if (rb == RB_NONE) {
		double h_period_est = ((1.0 / v_field_rate_rqd) - CVT_MIN_VSYNC_BP / 1000000.0) /
			(v_lines_rnd + vert_margin * 2 + CVT_MIN_V_PORCH + interlace) * 1000000.0;
		v_sync_bp = floor(CVT_MIN_VSYNC_BP / h_period_est) + 1;
		if (v_sync_bp < v_sync + CVT_MIN_V_BPORCH)
			v_sync_bp = v_sync + CVT_MIN_V_BPORCH;
		v_blank = v_sync_bp + CVT_MIN_V_PORCH;
		double ideal_duty_cycle = CVT_C_PRIME - (CVT_M_PRIME * h_period_est / 1000.0);
		if (ideal_duty_cycle < 20)
			ideal_duty_cycle = 20;
		h_blank = floor(total_active_pixels * ideal_duty_cycle /
				(100.0 - ideal_duty_cycle) /
				(2 * CELL_GRAN)) * 2 * CELL_GRAN;
		double total_pixels = total_active_pixels + h_blank;
		h_sync = floor(total_pixels * 0.08 / CELL_GRAN) * CELL_GRAN;
		pixel_freq = floor((total_pixels / h_period_est) / clock_step) * clock_step;
	} else {
		double h_period_est = ((1000000.0 / v_field_rate_rqd) - CVT_RB_MIN_VBLANK) /
					(v_lines_rnd + vert_margin * 2);
		double vbi_lines = floor(CVT_RB_MIN_VBLANK / h_period_est) + 1;
		double rb_min_vbi = rb_v_fporch + v_sync + CVT_MIN_V_BPORCH;
		v_blank = vbi_lines < rb_min_vbi ? rb_min_vbi : vbi_lines;
		double total_v_lines = v_blank + v_lines_rnd + vert_margin * 2 + interlace;
		if (rb == RB_CVT_V1)
			v_sync_bp = v_blank - rb_v_fporch;
		else
			v_sync_bp = v_sync + CVT_MIN_V_BPORCH;
		double total_pixels = h_blank + total_active_pixels;
		pixel_freq = floor((v_field_rate_rqd * total_v_lines * total_pixels / 1000000.0 *
				    refresh_multiplier) / clock_step) * clock_step;
	}

	t.vbp = v_sync_bp - v_sync;
	t.vsync = v_sync;
	t.vfp = v_blank - t.vbp - t.vsync;
	t.pixclk_khz = round(1000.0 * pixel_freq);
	t.hsync = h_sync;
	t.hfp = (h_blank / 2.0) - t.hsync;
	t.hbp = t.hfp + t.hsync;
	t.hborder = hor_margin;
	t.vborder = vert_margin;
	t.rb = rb;
	if (alt && (rb == RB_CVT_V2 || rb == RB_CVT_V3))
		t.rb |= RB_ALT;
	t.pos_pol_hsync = t.rb;
	t.pos_pol_vsync = !t.rb;
	calc_ratio(&t);
	return t;
}

// Assembly:
pushq %rbp
movq %rsp, %rbp
subq $0x160, %rsp            # imm = 0x160
movl %r9d, %eax
movl %ecx, -0xf4(%rbp)
movl %edx, %r9d
movq %rsi, %r10
movl -0xf4(%rbp), %esi
movq %rdi, -0xf0(%rbp)
movb %al, %dl
movq %rdi, %rax
movq %rax, -0xe8(%rbp)
movb 0x18(%rbp), %al
movb 0x10(%rbp), %cl
movq %r10, -0x8(%rbp)
movl %r9d, -0xc(%rbp)
movl %esi, -0x10(%rbp)
movsd %xmm0, -0x18(%rbp)
movl %r8d, -0x1c(%rbp)
andb $0x1, %dl
movb %dl, -0x1d(%rbp)
andb $0x1, %cl
movb %cl, -0x1e(%rbp)
andb $0x1, %al
movb %al, -0x1f(%rbp)
xorps %xmm0, %xmm0
movups %xmm0, 0x40(%rdi)
movups %xmm0, 0x30(%rdi)
movups %xmm0, 0x20(%rdi)
movups %xmm0, 0x10(%rdi)
movups %xmm0, (%rdi)
movl $0x0, 0x50(%rdi)
movl -0xc(%rbp), %eax
movl %eax, (%rdi)
movl -0x10(%rbp), %eax
movl %eax, 0x4(%rdi)
movb -0x1d(%rbp), %al
andb $0x1, %al
movb %al, 0x18(%rdi)
movl -0x1c(%rbp), %eax
subl $0x2, %eax
sete %al
movzbl %al, %eax
movl %eax, %ecx
leaq 0x152e5(%rip), %rax     # 0x42c18
movsd (%rax,%rcx,8), %xmm0
movsd %xmm0, -0x28(%rbp)
movl -0xc(%rbp), %eax
cvtsi2sd %rax, %xmm0
divsd -0x28(%rbp), %xmm0
callq 0x4520
mulsd -0x28(%rbp), %xmm0
movsd %xmm0, -0x30(%rbp)
testb $0x1, -0x1d(%rbp)
je 0x2d982
movl -0x10(%rbp), %eax
cvtsi2sd %rax, %xmm0
movsd 0x16a1(%rip), %xmm1     # 0x2f010
divsd %xmm1, %xmm0
callq 0x4520
movsd %xmm0, -0x100(%rbp)
jmp 0x2d992
movl -0x10(%rbp), %eax
cvtsi2sd %rax, %xmm0
movsd %xmm0, -0x100(%rbp)
movsd -0x100(%rbp), %xmm0
movsd %xmm0, -0x38(%rbp)
testb $0x1, -0x1e(%rbp)
je 0x2d9d7
movsd 0x151e3(%rip), %xmm0    # 0x42b90
mulsd -0x30(%rbp), %xmm0
movsd 0x167e(%rip), %xmm1     # 0x2f038
divsd %xmm1, %xmm0
divsd -0x28(%rbp), %xmm0
callq 0x4520
mulsd -0x28(%rbp), %xmm0
movsd %xmm0, -0x108(%rbp)
jmp 0x2d9e4
xorps %xmm0, %xmm0
movsd %xmm0, -0x108(%rbp)
jmp 0x2d9e4
movsd -0x108(%rbp), %xmm0
cvttsd2si %xmm0, %rax
movl %eax, -0x3c(%rbp)
testb $0x1, -0x1e(%rbp)
je 0x2da16
movsd 0x15196(%rip), %xmm0    # 0x42b98
mulsd -0x38(%rbp), %xmm0
callq 0x4520
movsd %xmm0, -0x110(%rbp)
jmp 0x2da23
xorps %xmm0, %xmm0
movsd %xmm0, -0x110(%rbp)
jmp 0x2da23
movsd -0x110(%rbp), %xmm0
cvttsd2si %xmm0, %rax
movl %eax, -0x40(%rbp)
movb -0x1d(%rbp), %al
testb $0x1, %al
movsd 0x15d8(%rip), %xmm0     # 0x2f018
xorps %xmm1, %xmm1
movsd %xmm1, -0x120(%rbp)
movsd %xmm0, -0x118(%rbp)
jne 0x2da65
movsd -0x120(%rbp), %xmm0
movsd %xmm0, -0x118(%rbp)
movsd -0x118(%rbp), %xmm0
movsd %xmm0, -0x48(%rbp)
movsd -0x30(%rbp), %xmm0
movl -0x3c(%rbp), %eax
addl %eax, %eax
cvtsi2sd %rax, %xmm1
addsd %xmm1, %xmm0
movsd %xmm0, -0x50(%rbp)
testb $0x1, -0x1d(%rbp)
je 0x2daa7
movsd 0x1578(%rip), %xmm0     # 0x2f010
mulsd -0x18(%rbp), %xmm0
movsd %xmm0, -0x128(%rbp)
jmp 0x2dab4
movsd -0x18(%rbp), %xmm0
movsd %xmm0, -0x128(%rbp)
movsd -0x128(%rbp), %xmm0
movsd %xmm0, -0x58(%rbp)
movl -0x1c(%rbp), %eax
movsd 0x15104(%rip), %xmm0    # 0x42bd0
movsd 0xb8b4(%rip), %xmm1     # 0x39388
movsd %xmm1, -0x138(%rbp)
cmpl $0x2, %eax
movsd %xmm0, -0x130(%rbp)
je 0x2daf9
movsd -0x138(%rbp), %xmm0
movsd %xmm0, -0x130(%rbp)
movsd -0x130(%rbp), %xmm0
movsd %xmm0, -0x60(%rbp)
movb $0x1, %al
cmpl $0x1, -0x1c(%rbp)
movb %al, -0x139(%rbp)
je 0x2db37
xorl %eax, %eax
cmpl $0x3, -0x1c(%rbp)
movb %al, -0x13a(%rbp)
jne 0x2db2b
movb -0x1f(%rbp), %al
movb %al, -0x13a(%rbp)
movb -0x13a(%rbp), %al
movb %al, -0x139(%rbp)
movb -0x139(%rbp), %dl
movl $0x50, %eax
movl $0xa0, %ecx
testb $0x1, %dl
cmovnel %ecx, %eax
cvtsi2sd %eax, %xmm0
movsd %xmm0, -0x68(%rbp)
movl -0x1c(%rbp), %edx
movl $0x1, %eax
movl $0x3, %ecx
cmpl $0x1, %edx
cmovel %ecx, %eax
cvtsi2sd %eax, %xmm0
movsd %xmm0, -0x70(%rbp)
xorl %eax, %eax
cmpl $0x2, -0x1c(%rbp)
movb %al, -0x13b(%rbp)
jne 0x2db89
movb -0x1f(%rbp), %al
movb %al, -0x13b(%rbp)
movb -0x13b(%rbp), %al
movsd 0x15041(%rip), %xmm0    # 0x42bd8
movsd 0x5ce9(%rip), %xmm1     # 0x33888
movsd %xmm1, -0x150(%rbp)
testb $0x1, %al
movsd %xmm0, -0x148(%rbp)
jne 0x2dbc3
movsd -0x150(%rbp), %xmm0
movsd %xmm0, -0x148(%rbp)
movq -0xf0(%rbp), %rcx
movsd -0x148(%rbp), %xmm0
movsd %xmm0, -0x78(%rbp)
movsd 0xb7d9(%rip), %xmm0     # 0x393b8
movsd %xmm0, -0x80(%rbp)
movl 0x4(%rcx), %eax
shll $0x2, %eax
movl $0x3, %esi
xorl %edx, %edx
divl %esi
cmpl (%rcx), %eax
jne 0x2dc0c
movsd 0x14ff1(%rip), %xmm0    # 0x42bf0
movsd %xmm0, -0x88(%rbp)
jmp 0x2dcdf
movq -0xf0(%rbp), %rcx
movl 0x4(%rcx), %eax
shll $0x4, %eax
movl $0x9, %esi
xorl %edx, %edx
divl %esi
cmpl (%rcx), %eax
jne 0x2dc3b
movsd 0x14fba(%rip), %xmm0    # 0x42be8
movsd %xmm0, -0x88(%rbp)
jmp 0x2dcdd
movq -0xf0(%rbp), %rcx
movl 0x4(%rcx), %eax
shll $0x4, %eax
movl $0xa, %esi
xorl %edx, %edx
divl %esi
cmpl (%rcx), %eax
jne 0x2dc67
movsd 0x14f83(%rip), %xmm0    # 0x42be0
movsd %xmm0, -0x88(%rbp)
jmp 0x2dcdb
movq -0xf0(%rbp), %rax
movl 0x4(%rax), %eax
andl $0x3, %eax
cmpl $0x0, %eax
jne 0x2dc9d
movq -0xf0(%rbp), %rcx
imull $0x5, 0x4(%rcx), %eax
shrl $0x2, %eax
cmpl (%rcx), %eax
jne 0x2dc9d
movsd 0xb6a5(%rip), %xmm0     # 0x39338
movsd %xmm0, -0x88(%rbp)
jmp 0x2dcd9
movq -0xf0(%rbp), %rcx
imull $0xf, 0x4(%rcx), %eax
movl $0x9, %esi
xorl %edx, %edx
divl %esi
cmpl (%rcx), %eax
jne 0x2dcc7
movsd 0xb67b(%rip), %xmm0     # 0x39338
movsd %xmm0, -0x88(%rbp)
jmp 0x2dcd7
movsd 0xfe89(%rip), %xmm0     # 0x3db58
movsd %xmm0, -0x88(%rbp)
jmp 0x2dcd9
jmp 0x2dcdb
jmp 0x2dcdd
jmp 0x2dcdf
cmpl $0x2, -0x1c(%rbp)
jb 0x2dcf5
movsd 0x14e9b(%rip), %xmm0    # 0x42b88
movsd %xmm0, -0x88(%rbp)
cmpl $0x0, -0x1c(%rbp)
jne 0x2dee0
movsd -0x58(%rbp), %xmm1
movsd 0x5b7c(%rip), %xmm0     # 0x33888
divsd %xmm1, %xmm0
movsd 0x14ea0(%rip), %xmm1    # 0x42bb8
addsd %xmm1, %xmm0
movsd -0x38(%rbp), %xmm1
movl -0x40(%rbp), %eax
addl %eax, %eax
cvtsi2sd %rax, %xmm2
addsd %xmm2, %xmm1
movsd 0xfe31(%rip), %xmm2     # 0x3db68
addsd %xmm2, %xmm1
addsd -0x48(%rbp), %xmm1
divsd %xmm1, %xmm0
movsd 0x14e64(%rip), %xmm1    # 0x42bb0
mulsd %xmm1, %xmm0
movsd %xmm0, -0xa8(%rbp)
movsd 0x14e40(%rip), %xmm0    # 0x42ba0
divsd -0xa8(%rbp), %xmm0
callq 0x4520
movsd 0x5b13(%rip), %xmm1     # 0x33888
addsd %xmm1, %xmm0
movsd %xmm0, -0xa0(%rbp)
movsd -0xa0(%rbp), %xmm1
movsd 0x14e4f(%rip), %xmm0    # 0x42be0
addsd -0x88(%rbp), %xmm0
ucomisd %xmm1, %xmm0
jbe 0x2ddb7
movsd 0x14e39(%rip), %xmm0    # 0x42be0
addsd -0x88(%rbp), %xmm0
movsd %xmm0, -0xa0(%rbp)
movsd 0xfda9(%rip), %xmm0     # 0x3db68
addsd -0xa0(%rbp), %xmm0
movsd %xmm0, -0x98(%rbp)
movsd 0x14e39(%rip), %xmm1    # 0x42c10
mulsd -0xa8(%rbp), %xmm1
movsd 0x1239(%rip), %xmm0     # 0x2f020
divsd %xmm0, %xmm1
movsd 0x14e15(%rip), %xmm0    # 0x42c08
subsd %xmm1, %xmm0
movsd %xmm0, -0xb0(%rbp)
movsd 0x1251(%rip), %xmm0     # 0x2f058
ucomisd -0xb0(%rbp), %xmm0
jbe 0x2de21
movsd 0x123f(%rip), %xmm0     # 0x2f058
movsd %xmm0, -0xb0(%rbp)
movsd -0x50(%rbp), %xmm0
mulsd -0xb0(%rbp), %xmm0
movsd 0x1202(%rip), %xmm1     # 0x2f038
subsd -0xb0(%rbp), %xmm1
divsd %xmm1, %xmm0
movsd 0xfd36(%rip), %xmm1     # 0x3db80
divsd %xmm1, %xmm0
callq 0x4520
movsd 0x11b5(%rip), %xmm1     # 0x2f010
mulsd %xmm1, %xmm0
movsd 0x14d21(%rip), %xmm1    # 0x42b88
mulsd %xmm1, %xmm0
movsd %xmm0, -0x68(%rbp)
movsd -0x50(%rbp), %xmm0
addsd -0x68(%rbp), %xmm0
movsd %xmm0, -0xb8(%rbp)
movsd 0x14d3e(%rip), %xmm0    # 0x42bc8
mulsd -0xb8(%rbp), %xmm0
movsd 0x14cee(%rip), %xmm1    # 0x42b88
divsd %xmm1, %xmm0
callq 0x4520
movsd 0x14cdd(%rip), %xmm1    # 0x42b88
mulsd %xmm1, %xmm0
movsd %xmm0, -0x80(%rbp)
movsd -0xb8(%rbp), %xmm0
divsd -0xa8(%rbp), %xmm0
divsd -0x60(%rbp), %xmm0
callq 0x4520
mulsd -0x60(%rbp), %xmm0
movsd %xmm0, -0x90(%rbp)
jmp 0x2e05e
movsd -0x58(%rbp), %xmm1
movsd 0x14cc3(%rip), %xmm0    # 0x42bb0
divsd %xmm1, %xmm0
movsd 0x14d07(%rip), %xmm1    # 0x42c00
addsd %xmm1, %xmm0
movsd -0x38(%rbp), %xmm1
movl -0x40(%rbp), %eax
addl %eax, %eax
cvtsi2sd %rax, %xmm2
addsd %xmm2, %xmm1
divsd %xmm1, %xmm0
movsd %xmm0, -0xc0(%rbp)
movsd 0x14cd4(%rip), %xmm0    # 0x42bf8
divsd -0xc0(%rbp), %xmm0
callq 0x4520
movsd 0x594f(%rip), %xmm1     # 0x33888
addsd %xmm1, %xmm0
movsd %xmm0, -0xc8(%rbp)
movsd -0x70(%rbp), %xmm0
addsd -0x88(%rbp), %xmm0
movsd 0x14c86(%rip), %xmm1    # 0x42be0
addsd %xmm1, %xmm0
movsd %xmm0, -0xd0(%rbp)
movsd -0xc8(%rbp), %xmm1
movsd -0xd0(%rbp), %xmm0
ucomisd %xmm1, %xmm0
jbe 0x2df8e
movsd -0xd0(%rbp), %xmm0
movsd %xmm0, -0x158(%rbp)
jmp 0x2df9e
movsd -0xc8(%rbp), %xmm0
movsd %xmm0, -0x158(%rbp)
movsd -0x158(%rbp), %xmm0
movsd %xmm0, -0x98(%rbp)
movsd -0x98(%rbp), %xmm0
movsd -0x38(%rbp), %xmm1
addsd %xmm1, %xmm0
movl -0x40(%rbp), %eax
addl %eax, %eax
cvtsi2sd %rax, %xmm1
addsd %xmm1, %xmm0
addsd -0x48(%rbp), %xmm0
movsd %xmm0, -0xd8(%rbp)
cmpl $0x1, -0x1c(%rbp)
jne 0x2dff7
movsd -0x98(%rbp), %xmm0
subsd -0x70(%rbp), %xmm0
movsd %xmm0, -0xa0(%rbp)
jmp 0x2e00f
movsd 0x14be1(%rip), %xmm0    # 0x42be0
addsd -0x88(%rbp), %xmm0
movsd %xmm0, -0xa0(%rbp)
movsd -0x68(%rbp), %xmm0
addsd -0x50(%rbp), %xmm0
movsd %xmm0, -0xe0(%rbp)
movsd -0x58(%rbp), %xmm0
mulsd -0xd8(%rbp), %xmm0
mulsd -0xe0(%rbp), %xmm0
movsd 0x14b72(%rip), %xmm1    # 0x42bb0
divsd %xmm1, %xmm0
mulsd -0x78(%rbp), %xmm0
divsd -0x60(%rbp), %xmm0
callq 0x4520
mulsd -0x60(%rbp), %xmm0
movsd %xmm0, -0x90(%rbp)
movq -0xf0(%rbp), %rax
movsd -0xa0(%rbp), %xmm0
movsd -0x88(%rbp), %xmm1
subsd %xmm1, %xmm0
cvttsd2si %xmm0, %ecx
movl %ecx, 0x34(%rax)
cvttsd2si -0x88(%rbp), %rcx
movl %ecx, 0x30(%rax)
movsd -0x98(%rbp), %xmm0
cvtsi2sdl 0x34(%rax), %xmm1
subsd %xmm1, %xmm0
movl 0x30(%rax), %ecx
cvtsi2sd %rcx, %xmm1
subsd %xmm1, %xmm0
cvttsd2si %xmm0, %rcx
movl %ecx, 0x2c(%rax)
movsd -0x90(%rbp), %xmm0
movsd 0xf5f(%rip), %xmm1      # 0x2f020
mulsd %xmm1, %xmm0
callq 0x4160
movq -0xf0(%rbp), %rax
cvttsd2si %xmm0, %rcx
movl %ecx, 0x10(%rax)
cvttsd2si -0x80(%rbp), %rcx
movl %ecx, 0x20(%rax)
movsd -0x68(%rbp), %xmm0
movsd 0xf29(%rip), %xmm1      # 0x2f018
mulsd %xmm1, %xmm0
movl 0x20(%rax), %ecx
cvtsi2sd %rcx, %xmm1
subsd %xmm1, %xmm0
cvttsd2si %xmm0, %ecx
movl %ecx, 0x1c(%rax)
movl 0x1c(%rax), %ecx
addl 0x20(%rax), %ecx
movl %ecx, 0x24(%rax)
movl -0x3c(%rbp), %ecx
movl %ecx, 0x3c(%rax)
movl -0x40(%rbp), %ecx
movl %ecx, 0x40(%rax)
movl -0x1c(%rbp), %ecx
movl %ecx, 0x14(%rax)
testb $0x1, -0x1f(%rbp)
je 0x2e146
cmpl $0x2, -0x1c(%rbp)
je 0x2e133
cmpl $0x3, -0x1c(%rbp)
jne 0x2e146
movq -0xf0(%rbp), %rax
movl 0x14(%rax), %ecx
orl $0x80, %ecx
movl %ecx, 0x14(%rax)
movq -0xf0(%rbp), %rdi
cmpl $0x0, 0x14(%rdi)
setne %al
andb $0x1, %al
movb %al, 0x28(%rdi)
cmpl $0x0, 0x14(%rdi)
setne %al
xorb $-0x1, %al
andb $0x1, %al
movb %al, 0x38(%rdi)
callq 0x4c30
movq -0xe8(%rbp), %rax
addq $0x160, %rsp            # imm = 0x160
popq %rbp
retq
nopl (%rax)