// File: Ziang95[P]Tomasulo_simulator/FU.cpp
// Function: intAdder::FU_automat()
void intAdder::FU_automat()
{
    next_vdd = 0;
    while (true)
    {
A:      at_rising_edge(next_vdd);
        if (squash_p.flag)
        {
            squash_p.flag = false;
            at_falling_edge(next_vdd);
            continue;
        }
        auto newTask = queue.deQ();
        if (newTask)
        {
            task = *newTask;
            ROBEntry *R = CPU_ROB->get_entry(task.dest);
            R->output.exe = sys_clk.get_prog_cyc();
            for (int i = 0; ;i++)
            {
                if (squash_p.flag)
                {
                    squash_p.flag = false;
                    if (is_prev_index(squash_p.ROB_i, task.dest, squash_p.R_f, squash_p.R_r))
                        break;
                }
                msg_log("Calculating INT "+to_string(task.oprnd1->i)+" + "+to_string(task.oprnd2->i) + " dest ROB = " + to_string(task.dest), 3);
                if (i == CPU_cfg->int_add->exe_time - 1)
                {
                    if (task.code == BEQ || task.code == BNE)
                    {
                        *task.busy = false;
                        bool branch = false;
                        int result = task.oprnd1->i - task.oprnd2->i;
                        if (result)
                            branch = task.code == BNE? true:false;
                        else
                            branch = task.code == BEQ? true:false;
                        if (auto tmp = CPU_BTB.getEntry(R->instr_i))
                        {
                            if (branch == tmp->taken)
                            {
                                if (tmp->taken && tmp->target != R->instr_i + 1 + task.offset)
                                {
                                    tmp->target = R->instr_i + 1 +task.offset;
                                    brcUnit.to_target(R->instr_i + 1 + task.offset);
                                    msg_log("Begin Squash", 3);
                                    brcUnit.to_squash(task.dest);   
                                    at_falling_edge(next_vdd);
                                }
                                else
                                {
                                    at_falling_edge(next_vdd);
                                    R->finished = true;
                                }
                            }
                            else
                            {
                                tmp->taken = branch;
                                if (branch)
                                    brcUnit.to_target(tmp->target);
                                else
                                    brcUnit.to_target(R->instr_i + 1);
                                msg_log("Begin Squash", 3);
                                brcUnit.to_squash(task.dest);
                                at_falling_edge(next_vdd);
                            }
                        }
                        else
                        {
                            if (branch)
                            {
                                CPU_BTB.addEntry(R->instr_i, R->instr_i + 1 + task.offset);
                                brcUnit.to_target(R->instr_i + 1 + task.offset);
                                msg_log("Begin Squash", 3);
                                brcUnit.to_squash(task.dest);
                                at_falling_edge(next_vdd);
                            }
                            else
                            {
                                at_falling_edge(next_vdd);
                                R->finished = true;
                            }
                        }
                        goto A;
                    }
                    else
                    {
                        task.res->i = task.oprnd1->i + task.oprnd2->i;
                        msg_log("CDB enqueued, ROB = " + to_string(task.dest), 3);
                        fCDB.enQ(task.res, task.dest);
                    }
                    break;
                }
                at_falling_edge(next_vdd);
                at_rising_edge(next_vdd);
            }
        }
        at_falling_edge(next_vdd);
    }
}

// Assembly:
pushq %rbp
movq %rsp, %rbp
subq $0x230, %rsp            # imm = 0x230
movq %rdi, -0x8(%rbp)
movq -0x8(%rbp), %rax
movq %rax, -0x200(%rbp)
movl $0x0, 0x3888(%rax)
jmp 0x5aa6
movq -0x200(%rbp), %rdi
addq $0x3888, %rdi           # imm = 0x3888
callq 0x12130
movq -0x200(%rbp), %rax
testb $0x1, 0x38a4(%rax)
je 0x5ae5
movq -0x200(%rbp), %rdi
movb $0x0, 0x38a4(%rdi)
addq $0x3888, %rdi           # imm = 0x3888
callq 0x121a0
jmp 0x5aa4
movq -0x200(%rbp), %rdi
addq $0x8, %rdi
callq 0x5790
movq %rax, -0x10(%rbp)
cmpq $0x0, -0x10(%rbp)
je 0x63da
movq -0x200(%rbp), %rdi
movq -0x10(%rbp), %rsi
addq $0x3838, %rdi           # imm = 0x3838
movl $0x38, %edx
callq 0x42f0
movq -0x200(%rbp), %rax
leaq 0x29932(%rip), %rcx     # 0x2f460
movq (%rcx), %rdi
movl 0x383c(%rax), %esi
callq 0xe4d0
movq %rax, -0x18(%rbp)
leaq 0x2a251(%rip), %rdi     # 0x2fd98
callq 0x116c0
movl %eax, %ecx
movq -0x18(%rbp), %rax
movl %ecx, 0x54(%rax)
movl $0x0, -0x1c(%rbp)
movq -0x200(%rbp), %rax
testb $0x1, 0x38a4(%rax)
je 0x5ba4
movq -0x200(%rbp), %rax
movb $0x0, 0x38a4(%rax)
movl 0x38a0(%rax), %edi
movl 0x383c(%rax), %esi
movl 0x3898(%rax), %edx
movl 0x389c(%rax), %ecx
callq 0x1aec0
testb $0x1, %al
jne 0x5b9d
jmp 0x5ba2
jmp 0x63d8
jmp 0x5ba4
movq -0x200(%rbp), %rax
movq 0x3848(%rax), %rax
movl (%rax), %esi
leaq -0xe0(%rbp), %rdi
movq %rdi, -0x208(%rbp)
callq 0x8410
movq -0x208(%rbp), %rdx
leaq 0x1c46e(%rip), %rsi     # 0x22043
leaq -0xc0(%rbp), %rdi
callq 0x83c0
jmp 0x5be3
leaq 0x1c46a(%rip), %rdx     # 0x22054
leaq -0xa0(%rbp), %rdi
leaq -0xc0(%rbp), %rsi
callq 0x8810
jmp 0x5bff
movq -0x200(%rbp), %rax
movq 0x3850(%rax), %rax
movl (%rax), %esi
leaq -0x110(%rbp), %rdi
callq 0x8410
jmp 0x5c1d
leaq -0x80(%rbp), %rdi
leaq -0xa0(%rbp), %rsi
leaq -0x110(%rbp), %rdx
callq 0x8740
jmp 0x5c36
leaq 0x1ce0b(%rip), %rdx     # 0x22a48
leaq -0x60(%rbp), %rdi
leaq -0x80(%rbp), %rsi
callq 0x8810
jmp 0x5c4c
movq -0x200(%rbp), %rax
movl 0x383c(%rax), %esi
leaq -0x130(%rbp), %rdi
callq 0x8410
jmp 0x5c67
leaq -0x40(%rbp), %rdi
leaq -0x60(%rbp), %rsi
leaq -0x130(%rbp), %rdx
callq 0x8740
jmp 0x5c7d
leaq -0x40(%rbp), %rdi
movl $0x3, %esi
callq 0x12060
jmp 0x5c8d
leaq -0x40(%rbp), %rdi
callq 0x4240
leaq -0x130(%rbp), %rdi
callq 0x4240
leaq -0x60(%rbp), %rdi
callq 0x4240
leaq -0x80(%rbp), %rdi
callq 0x4240
leaq -0x110(%rbp), %rdi
callq 0x4240
leaq -0xa0(%rbp), %rdi
callq 0x4240
leaq -0xc0(%rbp), %rdi
callq 0x4240
leaq -0xe0(%rbp), %rdi
callq 0x4240
movl -0x1c(%rbp), %eax
leaq 0x29762(%rip), %rcx     # 0x2f450
movq (%rcx), %rcx
movq 0x8(%rcx), %rcx
movl 0x4(%rcx), %ecx
subl $0x1, %ecx
cmpl %ecx, %eax
jne 0x63a4
movq -0x200(%rbp), %rax
cmpl $0x9, 0x3838(%rax)
je 0x5d27
movq -0x200(%rbp), %rax
cmpl $0x8, 0x3838(%rax)
jne 0x62bc
movq -0x200(%rbp), %rcx
movq 0x3868(%rcx), %rax
movb $0x0, (%rax)
movb $0x0, -0x131(%rbp)
movq 0x3848(%rcx), %rax
movl (%rax), %eax
movq 0x3850(%rcx), %rcx
subl (%rcx), %eax
movl %eax, -0x138(%rbp)
cmpl $0x0, -0x138(%rbp)
je 0x5e89
movq -0x200(%rbp), %rax
movl 0x3838(%rax), %eax
subl $0x8, %eax
sete %al
negb %al
andb $0x1, %al
movb %al, -0x131(%rbp)
jmp 0x5ea6
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0xe8(%rbp)
movl %eax, -0xec(%rbp)
jmp 0x5e78
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0xe8(%rbp)
movl %eax, -0xec(%rbp)
jmp 0x5e6c
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0xe8(%rbp)
movl %eax, -0xec(%rbp)
jmp 0x5e60
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0xe8(%rbp)
movl %eax, -0xec(%rbp)
jmp 0x5e54
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0xe8(%rbp)
movl %eax, -0xec(%rbp)
jmp 0x5e4b
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0xe8(%rbp)
movl %eax, -0xec(%rbp)
jmp 0x5e42
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0xe8(%rbp)
movl %eax, -0xec(%rbp)
jmp 0x5e36
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0xe8(%rbp)
movl %eax, -0xec(%rbp)
leaq -0x40(%rbp), %rdi
callq 0x4240
leaq -0x130(%rbp), %rdi
callq 0x4240
leaq -0x60(%rbp), %rdi
callq 0x4240
leaq -0x80(%rbp), %rdi
callq 0x4240
leaq -0x110(%rbp), %rdi
callq 0x4240
leaq -0xa0(%rbp), %rdi
callq 0x4240
leaq -0xc0(%rbp), %rdi
callq 0x4240
leaq -0xe0(%rbp), %rdi
callq 0x4240
jmp 0x63f2
movq -0x200(%rbp), %rax
movl 0x3838(%rax), %eax
subl $0x9, %eax
sete %al
negb %al
andb $0x1, %al
movb %al, -0x131(%rbp)
movq -0x18(%rbp), %rax
movl 0x64(%rax), %esi
leaq 0x295b4(%rip), %rdi     # 0x2f468
callq 0x10530
movq %rax, -0x140(%rbp)
cmpq $0x0, -0x140(%rbp)
je 0x6173
movb -0x131(%rbp), %al
andb $0x1, %al
movzbl %al, %eax
movq -0x140(%rbp), %rcx
movb 0x5(%rcx), %cl
andb $0x1, %cl
movzbl %cl, %ecx
cmpl %ecx, %eax
jne 0x605a
movq -0x140(%rbp), %rax
testb $0x1, 0x5(%rax)
je 0x603b
movq -0x200(%rbp), %rdx
movq -0x140(%rbp), %rax
movl (%rax), %eax
movq -0x18(%rbp), %rcx
movl 0x64(%rcx), %ecx
addl $0x1, %ecx
addl 0x3860(%rdx), %ecx
cmpl %ecx, %eax
je 0x603b
movq -0x200(%rbp), %rax
movq -0x18(%rbp), %rcx
movl 0x64(%rcx), %esi
movl 0x3860(%rax), %ecx
movl %ecx, %edx
movl %esi, %ecx
leal 0x1(%rcx,%rdx), %edx
movq -0x140(%rbp), %rcx
movl %edx, (%rcx)
movq -0x18(%rbp), %rcx
movl 0x64(%rcx), %edx
movl 0x3860(%rax), %eax
movl %eax, %ecx
movl %edx, %eax
leal 0x1(%rax,%rcx), %esi
leaq 0x2951d(%rip), %rdi     # 0x2f488
callq 0x105d0
leaq -0x161(%rbp), %rdi
movq %rdi, -0x210(%rbp)
callq 0x4600
movq -0x210(%rbp), %rdx
leaq 0x1c0c7(%rip), %rsi     # 0x22058
leaq -0x160(%rbp), %rdi
callq 0x44c0
jmp 0x5f9f
leaq -0x160(%rbp), %rdi
movl $0x3, %esi
callq 0x12060
jmp 0x5fb2
leaq -0x160(%rbp), %rdi
callq 0x4240
leaq -0x161(%rbp), %rdi
callq 0x43d0
movq -0x200(%rbp), %rax
movl 0x383c(%rax), %esi
leaq 0x294aa(%rip), %rdi     # 0x2f488
callq 0x105b0
movq -0x200(%rbp), %rdi
addq $0x3888, %rdi           # imm = 0x3888
callq 0x121a0
jmp 0x6055
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0xe8(%rbp)
movl %eax, -0xec(%rbp)
jmp 0x602a
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0xe8(%rbp)
movl %eax, -0xec(%rbp)
leaq -0x160(%rbp), %rdi
callq 0x4240
leaq -0x161(%rbp), %rdi
callq 0x43d0
jmp 0x63f2
movq -0x200(%rbp), %rdi
addq $0x3888, %rdi           # imm = 0x3888
callq 0x121a0
movq -0x18(%rbp), %rax
movb $0x1, (%rax)
jmp 0x616e
movb -0x131(%rbp), %cl
movq -0x140(%rbp), %rax
andb $0x1, %cl
movb %cl, 0x5(%rax)
testb $0x1, -0x131(%rbp)
je 0x608d
movq -0x140(%rbp), %rax
movl (%rax), %esi
leaq 0x29402(%rip), %rdi     # 0x2f488
callq 0x105d0
jmp 0x60a3
movq -0x18(%rbp), %rax
movl 0x64(%rax), %esi
addl $0x1, %esi
leaq 0x293ea(%rip), %rdi     # 0x2f488
callq 0x105d0
leaq -0x189(%rbp), %rdi
movq %rdi, -0x218(%rbp)
callq 0x4600
movq -0x218(%rbp), %rdx
leaq 0x1bf94(%rip), %rsi     # 0x22058
leaq -0x188(%rbp), %rdi
callq 0x44c0
jmp 0x60d2
leaq -0x188(%rbp), %rdi
movl $0x3, %esi
callq 0x12060
jmp 0x60e5
leaq -0x188(%rbp), %rdi
callq 0x4240
leaq -0x189(%rbp), %rdi
callq 0x43d0
movq -0x200(%rbp), %rax
movl 0x383c(%rax), %esi
leaq 0x29377(%rip), %rdi     # 0x2f488
callq 0x105b0
movq -0x200(%rbp), %rdi
addq $0x3888, %rdi           # imm = 0x3888
callq 0x121a0
jmp 0x616e
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0xe8(%rbp)
movl %eax, -0xec(%rbp)
jmp 0x615d
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0xe8(%rbp)
movl %eax, -0xec(%rbp)
leaq -0x188(%rbp), %rdi
callq 0x4240
leaq -0x189(%rbp), %rdi
callq 0x43d0
jmp 0x63f2
jmp 0x62b7
testb $0x1, -0x131(%rbp)
je 0x629b
movq -0x200(%rbp), %rax
movq -0x18(%rbp), %rcx
movl 0x64(%rcx), %esi
movl 0x3860(%rax), %eax
movl %eax, %ecx
movl %esi, %eax
leal 0x1(%rax,%rcx), %edx
leaq 0x292c5(%rip), %rdi     # 0x2f468
callq 0x104e0
movq -0x200(%rbp), %rax
movq -0x18(%rbp), %rcx
movl 0x64(%rcx), %edx
movl 0x3860(%rax), %eax
movl %eax, %ecx
movl %edx, %eax
leal 0x1(%rax,%rcx), %esi
leaq 0x292bd(%rip), %rdi     # 0x2f488
callq 0x105d0
leaq -0x1b1(%rbp), %rdi
movq %rdi, -0x220(%rbp)
callq 0x4600
movq -0x220(%rbp), %rdx
leaq 0x1be67(%rip), %rsi     # 0x22058
leaq -0x1b0(%rbp), %rdi
callq 0x44c0
jmp 0x61ff
leaq -0x1b0(%rbp), %rdi
movl $0x3, %esi
callq 0x12060
jmp 0x6212
leaq -0x1b0(%rbp), %rdi
callq 0x4240
leaq -0x1b1(%rbp), %rdi
callq 0x43d0
movq -0x200(%rbp), %rax
movl 0x383c(%rax), %esi
leaq 0x2924a(%rip), %rdi     # 0x2f488
callq 0x105b0
movq -0x200(%rbp), %rdi
addq $0x3888, %rdi           # imm = 0x3888
callq 0x121a0
jmp 0x62b5
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0xe8(%rbp)
movl %eax, -0xec(%rbp)
jmp 0x628a
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0xe8(%rbp)
movl %eax, -0xec(%rbp)
leaq -0x1b0(%rbp), %rdi
callq 0x4240
leaq -0x1b1(%rbp), %rdi
callq 0x43d0
jmp 0x63f2
movq -0x200(%rbp), %rdi
addq $0x3888, %rdi           # imm = 0x3888
callq 0x121a0
movq -0x18(%rbp), %rax
movb $0x1, (%rax)
jmp 0x62b7
jmp 0x5aa6
movq -0x200(%rbp), %rax
movq 0x3840(%rax), %rcx
movq 0x3848(%rax), %rdx
movl (%rdx), %edx
movq 0x3850(%rax), %rsi
movl (%rsi), %esi
addl %esi, %edx
movl %edx, (%rcx)
movl 0x383c(%rax), %esi
leaq -0x1f8(%rbp), %rdi
movq %rdi, -0x228(%rbp)
callq 0x8410
movq -0x228(%rbp), %rdx
leaq 0x1bd5e(%rip), %rsi     # 0x22065
leaq -0x1d8(%rbp), %rdi
callq 0x83c0
jmp 0x6315
leaq -0x1d8(%rbp), %rdi
movl $0x3, %esi
callq 0x12060
jmp 0x6328
leaq -0x1d8(%rbp), %rdi
callq 0x4240
leaq -0x1f8(%rbp), %rdi
callq 0x4240
movq -0x200(%rbp), %rax
movq 0x3840(%rax), %rsi
movl 0x383c(%rax), %edx
leaq 0x291b5(%rip), %rdi     # 0x2f510
callq 0x4de0
jmp 0x63a2
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0xe8(%rbp)
movl %eax, -0xec(%rbp)
jmp 0x6394
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0xe8(%rbp)
movl %eax, -0xec(%rbp)
leaq -0x1d8(%rbp), %rdi
callq 0x4240
leaq -0x1f8(%rbp), %rdi
callq 0x4240
jmp 0x63f2
jmp 0x63d8
movq -0x200(%rbp), %rdi
addq $0x3888, %rdi           # imm = 0x3888
callq 0x121a0
movq -0x200(%rbp), %rdi
addq $0x3888, %rdi           # imm = 0x3888
callq 0x12130
movl -0x1c(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x1c(%rbp)
jmp 0x5b5c
jmp 0x63da
movq -0x200(%rbp), %rdi
addq $0x3888, %rdi           # imm = 0x3888
callq 0x121a0
jmp 0x5aa4
movq -0xe8(%rbp), %rdi
callq 0x45f0
nop