// File: /workspace/github_cpp_makefile_star2_O1/rpavlik[P]edid-decode/calc-gtf-cvt.cpp
// Function: edid_state::calc_gtf_mode(unsigned int, unsigned int, double, bool, gtf_ip_parm, bool, bool, double, double, double, double)
timings edid_state::calc_gtf_mode(unsigned h_pixels, unsigned v_lines,
				  double ip_freq_rqd, bool int_rqd,
				  enum gtf_ip_parm ip_parm, bool margins_rqd,
				  bool secondary, double C, double M, double K, double J)
{
	timings t = {};
	/* C' and M' are part of the Blanking Duty Cycle computation */
	double C_PRIME = ((C - J) * K / 256.0) + J;
	double M_PRIME = K / 256.0 * M;

	double h_pixels_rnd = round(h_pixels / CELL_GRAN) * CELL_GRAN;
	double v_lines_rnd = int_rqd ? round(v_lines / 2.0) : v_lines;
	unsigned hor_margin = margins_rqd ?
		round(h_pixels_rnd * MARGIN_PERC / 100.0 / CELL_GRAN)  * CELL_GRAN : 0;
	unsigned vert_margin = margins_rqd ? round(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;

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

	double pixel_freq;
	double h_blank_pixels;
	double total_pixels;
	double v_sync_bp;

	if (ip_parm == gtf_ip_vert_freq) {
		// vertical frame frequency (Hz)
		double v_field_rate_rqd = int_rqd ? ip_freq_rqd * 2 : ip_freq_rqd;
		double h_period_est = ((1.0 / v_field_rate_rqd) - GTF_MIN_VSYNC_BP / 1000000.0) /
			(v_lines_rnd + vert_margin * 2 + GTF_MIN_PORCH + interlace) * 1000000.0;
		v_sync_bp = round(GTF_MIN_VSYNC_BP / h_period_est);
		double total_v_lines = v_lines_rnd + vert_margin * 2 +
			v_sync_bp + interlace + GTF_MIN_PORCH;
		double v_field_rate_est = 1.0 / h_period_est / total_v_lines * 1000000.0;
		double h_period = h_period_est / (v_field_rate_rqd / v_field_rate_est);
		double ideal_duty_cycle = C_PRIME - (M_PRIME * h_period / 1000.0);
		h_blank_pixels = round(total_active_pixels * ideal_duty_cycle /
				       (100.0 - ideal_duty_cycle) /
				       (2 * CELL_GRAN)) * 2 * CELL_GRAN;
		total_pixels = total_active_pixels + h_blank_pixels;
		pixel_freq = total_pixels / h_period;
	} else if (ip_parm == gtf_ip_hor_freq) {
		// horizontal frequency (kHz)
		double h_freq = ip_freq_rqd;
		v_sync_bp = round(GTF_MIN_VSYNC_BP * h_freq / 1000.0);
		double ideal_duty_cycle = C_PRIME - (M_PRIME / h_freq);
		h_blank_pixels = round(total_active_pixels * ideal_duty_cycle /
				       (100.0 - ideal_duty_cycle) /
				       (2 * CELL_GRAN)) * 2 * CELL_GRAN;
		total_pixels = total_active_pixels + h_blank_pixels;
		pixel_freq = total_pixels * h_freq / 1000.0;
	} else {
		// pixel clock rate (MHz)
		pixel_freq = ip_freq_rqd;
		double ideal_h_period =
			((C_PRIME - 100.0) +
			 sqrt(((100.0 - C_PRIME) * (100.0 - C_PRIME) +
			       (0.4 * M_PRIME * (total_active_pixels + hor_margin * 2) /
				pixel_freq)))) / 2.0 / M_PRIME * 1000.0;
		double ideal_duty_cycle = C_PRIME - (M_PRIME * ideal_h_period) / 1000.0;
		h_blank_pixels = round(total_active_pixels * ideal_duty_cycle /
				       (100.0 - ideal_duty_cycle) /
				       (2 * CELL_GRAN)) * 2 * CELL_GRAN;
		total_pixels = total_active_pixels + h_blank_pixels;
		double h_freq = pixel_freq / total_pixels * 1000.0;
		v_sync_bp = round(GTF_MIN_VSYNC_BP * h_freq / 1000.0);
	}

	double v_back_porch = v_sync_bp - GTF_V_SYNC_RQD;

	t.vbp = v_back_porch;
	t.vsync = GTF_V_SYNC_RQD;
	t.vfp = GTF_MIN_PORCH;
	t.pixclk_khz = round(1000.0 * pixel_freq);
	t.hsync = round(GTF_H_SYNC_PERC / 100.0 * total_pixels / CELL_GRAN) * CELL_GRAN;
	t.hfp = (h_blank_pixels / 2.0) - t.hsync;
	t.hbp = t.hfp + t.hsync;
	t.hborder = hor_margin;
	t.vborder = vert_margin;
	t.pos_pol_hsync = secondary;
	t.pos_pol_vsync = !secondary;
	t.rb = secondary ? RB_GTF : RB_NONE;
	return t;
}

// Assembly:
pushq %rbp
pushq %r15
pushq %r14
pushq %r13
pushq %r12
pushq %rbx
subq $0x48, %rsp
movsd %xmm3, 0x20(%rsp)
movsd %xmm2, 0x38(%rsp)
movl %r9d, %r14d
movl %r8d, %ebp
movsd %xmm0, 0x18(%rsp)
movl %ecx, %r15d
movq %rdi, %rbx
movb 0x80(%rsp), %r12b
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)
movsd %xmm4, 0x30(%rsp)
subsd %xmm4, %xmm1
movsd %xmm1, 0x8(%rsp)
movl %edx, %eax
xorps %xmm0, %xmm0
cvtsi2sd %rax, %xmm0
mulsd 0xade5(%rip), %xmm0     # 0x29f50
callq 0x3100
movapd %xmm0, %xmm3
movl %r15d, %eax
xorps %xmm0, %xmm0
cvtsi2sd %rax, %xmm0
testl %ebp, %ebp
je 0x1f19c
mulsd 0xe7d(%rip), %xmm0      # 0x20008
movsd %xmm3, 0x10(%rsp)
callq 0x3100
movsd 0x10(%rsp), %xmm3
movsd %xmm0, 0x28(%rsp)
movsd 0x8(%rsp), %xmm4
movsd 0x20(%rsp), %xmm5
mulsd %xmm5, %xmm4
mulsd 0x141d6(%rip), %xmm3    # 0x33390
movsd 0xad76(%rip), %xmm0     # 0x29f38
xorl %r13d, %r13d
movl $0x0, %ecx
testb %r12b, %r12b
movsd %xmm3, 0x10(%rsp)
je 0x1f223
movsd 0x141bb(%rip), %xmm0    # 0x33398
mulsd %xmm3, %xmm0
divsd 0xe2f(%rip), %xmm0      # 0x20018
mulsd 0xad5f(%rip), %xmm0     # 0x29f50
movsd %xmm4, 0x8(%rsp)
callq 0x3100
movsd 0x20(%rsp), %xmm5
movsd 0x8(%rsp), %xmm4
movsd 0x10(%rsp), %xmm3
mulsd 0x1417a(%rip), %xmm0    # 0x33390
cvttsd2si %xmm0, %rcx
movsd 0xad15(%rip), %xmm0     # 0x29f38
mulsd %xmm0, %xmm4
mulsd %xmm0, %xmm5
testb %r12b, %r12b
je 0x1f26c
movsd 0x14168(%rip), %xmm0    # 0x333a0
mulsd 0x28(%rsp), %xmm0
movq %rcx, %r12
movsd %xmm4, 0x8(%rsp)
movsd %xmm5, 0x20(%rsp)
callq 0x3100
movsd 0x20(%rsp), %xmm5
movsd 0x8(%rsp), %xmm4
movq %r12, %rcx
movsd 0x10(%rsp), %xmm3
cvttsd2si %xmm0, %r13
movb 0x88(%rsp), %r12b
addsd 0x30(%rsp), %xmm4
leal (%rcx,%rcx), %eax
xorps %xmm1, %xmm1
cvtsi2sd %rax, %xmm1
mulsd 0x38(%rsp), %xmm5
cvttsd2si %xmm3, %rax
addsd %xmm1, %xmm3
movl %eax, (%rbx)
movl %r15d, 0x4(%rbx)
movb %bpl, 0x18(%rbx)
cmpl $0x2, %r14d
movsd %xmm3, 0x10(%rsp)
je 0x1f2c6
cmpl $0x1, %r14d
jne 0x1f376
testb %bpl, %bpl
jne 0x1f3ce
xorpd %xmm2, %xmm2
jmp 0x1f3d6
movq %rcx, %r15
movsd 0x140d7(%rip), %xmm0    # 0x333a8
mulsd 0x18(%rsp), %xmm0
divsd 0xd31(%rip), %xmm0      # 0x20010
movsd %xmm4, 0x8(%rsp)
movsd %xmm5, 0x20(%rsp)
callq 0x3100
movsd %xmm0, 0x38(%rsp)
movsd 0x20(%rsp), %xmm0
divsd 0x18(%rsp), %xmm0
movsd 0x8(%rsp), %xmm1
subsd %xmm0, %xmm1
movsd 0xd04(%rip), %xmm0      # 0x20018
subsd %xmm1, %xmm0
mulsd 0x10(%rsp), %xmm1
divsd %xmm0, %xmm1
mulsd 0xf2fe(%rip), %xmm1     # 0x2e628
movapd %xmm1, %xmm0
callq 0x3100
movsd 0x38(%rsp), %xmm1
movapd %xmm0, %xmm2
movsd 0x18(%rsp), %xmm0
addsd %xmm2, %xmm2
mulsd 0x14041(%rip), %xmm2    # 0x33390
movsd %xmm2, 0x8(%rsp)
movsd 0x10(%rsp), %xmm3
addsd %xmm2, %xmm3
movsd %xmm3, 0x10(%rsp)
mulsd %xmm3, %xmm0
divsd 0xc9f(%rip), %xmm0      # 0x20010
jmp 0x1f5fa
movsd 0x1404a(%rip), %xmm7    # 0x333c8
addsd %xmm4, %xmm7
movsd 0xc8e(%rip), %xmm6      # 0x20018
movapd %xmm6, %xmm0
subsd %xmm4, %xmm0
movsd 0x14036(%rip), %xmm2    # 0x333d0
mulsd %xmm5, %xmm2
addsd %xmm3, %xmm1
mulsd %xmm2, %xmm1
divsd 0x18(%rsp), %xmm1
mulsd %xmm0, %xmm0
addsd %xmm1, %xmm0
xorpd %xmm1, %xmm1
movq %rcx, %r15
ucomisd %xmm1, %xmm0
jb 0x1f52b
sqrtsd %xmm0, %xmm0
jmp 0x1f562
movsd 0xc32(%rip), %xmm2      # 0x20008
movsd 0x18(%rsp), %xmm0
movsd %xmm4, 0x8(%rsp)
movsd %xmm5, 0x20(%rsp)
movq %rcx, %r15
je 0x1f3f1
addsd %xmm0, %xmm0
movsd %xmm0, 0x18(%rsp)
movsd 0x52c9(%rip), %xmm3     # 0x246c8
movapd %xmm3, %xmm1
divsd %xmm0, %xmm1
addsd 0x13fa1(%rip), %xmm1    # 0x333b0
leal (%r13,%r13), %eax
xorps %xmm0, %xmm0
cvtsi2sd %rax, %xmm0
movsd 0x28(%rsp), %xmm4
addsd %xmm0, %xmm4
movsd %xmm4, 0x28(%rsp)
movapd %xmm4, %xmm0
addsd %xmm3, %xmm0
addsd %xmm2, %xmm0
divsd %xmm0, %xmm1
mulsd 0x13f74(%rip), %xmm1    # 0x333b8
movsd %xmm1, 0x30(%rsp)
movsd 0x13f56(%rip), %xmm0    # 0x333a8
divsd %xmm1, %xmm0
movsd %xmm2, 0x40(%rsp)
callq 0x3100
movsd %xmm0, 0x38(%rsp)
movsd 0x28(%rsp), %xmm1
addsd %xmm0, %xmm1
addsd 0x40(%rsp), %xmm1
movsd 0x5249(%rip), %xmm0     # 0x246c8
addsd %xmm0, %xmm1
movapd %xmm1, %xmm2
movsd 0x30(%rsp), %xmm1
divsd %xmm1, %xmm0
divsd %xmm2, %xmm0
mulsd 0x13f1b(%rip), %xmm0    # 0x333b8
movsd 0x18(%rsp), %xmm2
divsd %xmm0, %xmm2
divsd %xmm2, %xmm1
movsd %xmm1, 0x30(%rsp)
movsd 0x20(%rsp), %xmm0
mulsd %xmm1, %xmm0
divsd 0x13efd(%rip), %xmm0    # 0x333c0
movsd 0x8(%rsp), %xmm2
addsd %xmm0, %xmm2
movsd 0x10(%rsp), %xmm0
mulsd %xmm2, %xmm0
movsd 0xb39(%rip), %xmm1      # 0x20018
subsd %xmm2, %xmm1
divsd %xmm1, %xmm0
mulsd 0xf139(%rip), %xmm0     # 0x2e628
callq 0x3100
movsd 0x38(%rsp), %xmm1
addsd %xmm0, %xmm0
mulsd 0x13e8a(%rip), %xmm0    # 0x33390
movsd %xmm0, 0x8(%rsp)
movsd 0x10(%rsp), %xmm2
addsd %xmm0, %xmm2
movsd %xmm2, 0x10(%rsp)
movapd %xmm2, %xmm0
divsd 0x30(%rsp), %xmm0
jmp 0x1f5fa
movsd %xmm4, 0x8(%rsp)
movsd %xmm5, 0x20(%rsp)
movsd %xmm7, 0x28(%rsp)
callq 0x31c0
movsd 0x28(%rsp), %xmm7
movsd 0xac8(%rip), %xmm6      # 0x20018
movsd 0x20(%rsp), %xmm5
movsd 0x8(%rsp), %xmm4
movsd 0x10(%rsp), %xmm3
addsd %xmm0, %xmm7
mulsd 0x13e6a(%rip), %xmm7    # 0x333d8
divsd %xmm5, %xmm7
movsd 0xa96(%rip), %xmm0      # 0x20010
mulsd %xmm0, %xmm7
mulsd %xmm5, %xmm7
divsd %xmm0, %xmm7
addsd %xmm7, %xmm4
mulsd %xmm4, %xmm3
subsd %xmm4, %xmm6
divsd %xmm6, %xmm3
mulsd 0xf08a(%rip), %xmm3     # 0x2e628
movapd %xmm3, %xmm0
callq 0x3100
addsd %xmm0, %xmm0
mulsd 0x13ddd(%rip), %xmm0    # 0x33390
movsd %xmm0, 0x8(%rsp)
movsd 0x10(%rsp), %xmm1
addsd %xmm0, %xmm1
movsd 0x18(%rsp), %xmm0
movsd %xmm1, 0x10(%rsp)
divsd %xmm1, %xmm0
movsd 0xa35(%rip), %xmm1      # 0x20010
mulsd %xmm1, %xmm0
mulsd 0x13dc1(%rip), %xmm0    # 0x333a8
divsd %xmm1, %xmm0
callq 0x3100
movapd %xmm0, %xmm1
movsd 0x18(%rsp), %xmm0
addsd 0x13dde(%rip), %xmm1    # 0x333e0
cvttsd2si %xmm1, %eax
movl %eax, 0x34(%rbx)
movabsq $0x300000001, %rax      # imm = 0x300000001
movq %rax, 0x2c(%rbx)
mulsd 0x9f1(%rip), %xmm0      # 0x20010
callq 0x3100
cvttsd2si %xmm0, %rax
movl %eax, 0x10(%rbx)
movsd 0x10(%rsp), %xmm0
mulsd 0x13dae(%rip), %xmm0    # 0x333e8
mulsd 0xa90e(%rip), %xmm0     # 0x29f50
callq 0x3100
mulsd 0x13d41(%rip), %xmm0    # 0x33390
cvttsd2si %xmm0, %rax
movsd 0x8(%rsp), %xmm1
mulsd 0x9a6(%rip), %xmm1      # 0x20008
movl %eax, %ecx
xorps %xmm0, %xmm0
cvtsi2sd %rcx, %xmm0
movl %eax, 0x20(%rbx)
subsd %xmm0, %xmm1
cvttsd2si %xmm1, %ecx
movl %ecx, 0x1c(%rbx)
addl %eax, %ecx
movl %ecx, 0x24(%rbx)
movl %r15d, 0x3c(%rbx)
movl %r13d, 0x40(%rbx)
movb %r12b, 0x28(%rbx)
movzbl %r12b, %eax
xorb $0x1, %r12b
movb %r12b, 0x38(%rbx)
shll $0x2, %eax
movl %eax, 0x14(%rbx)
movq %rbx, %rax
addq $0x48, %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq
nop