// File: /workspace/github_cpp_makefile_star2_O1/saeefahmad[P]MIPS-pipeline-simulator/pipeline.cpp
// Function: main
int main(int argc, char* args[]) {
  int choice;
  if (argc !=2) {
    cout << "ERROR: Wrong number of argument!!!" << endl;
    cout << "USAGE: " << string(args[0]) << " program_num" << endl; 
    exit(-1);
  } else
    choice = atoi(args[1]);
  initialize(choice);
  
  int i = 0;
  AbstractStage* stages[TOTAL_STAGE_TYPE];
  AbstractStage* prevStage = NULL;
  
  for (i = 0; i < TOTAL_STAGE_TYPE; i++) {
	  stages[i] = AbstractStage::createStage((StageType)i, prevStage);
	  prevStage = stages[i];
  }

  // Simulates one cycle at a time until end
  while (continueSimulation && (clockCycle <= TOTALCYCLE)) {
    // - Call the process function of each stage.
    // - You need to determine whether you should call the process
    //   function starting from the WB stage or FETCH stage.

	  stages[4]->process();
	  stages[3]->process();
	  stages[2]->process();
	  stages[1]->process();
	  stages[0]->process();

	  clockCycle++;
  }
  cout << "Name: Saeef Ahmad, ID: gij817" << endl;
  cout << "Fetched ins " << fetchedIns << endl;
  cout << "Finished ins " << finishedIns << endl;
  cout << "Total cycles " << (clockCycle - 1) << endl;
  cout << "Stall cycles " << stallCycle << endl;
  for (i = 1; i < TOTAL_REGISTER_TYPE; i++)
	cout << registerNames[i] << " " << getReg((RegisterType)i) << endl;

  for (i = 0; i < TOTAL_STAGE_TYPE; i++)
    delete stages[i];
  finalize();
  return 0;
}

// Assembly:
pushq %rbp
pushq %r15
pushq %r14
pushq %r13
pushq %r12
pushq %rbx
subq $0x38, %rsp
movq %rsi, %r14
cmpl $0x2, %edi
jne 0x2837
movq 0x8(%r14), %rdi
callq 0x2160
movl %eax, %edi
callq 0x28eb
xorl %ebx, %ebx
xorl %eax, %eax
movl %ebx, %edi
movq %rax, %rsi
callq 0x42bc
movq %rax, 0x10(%rsp,%rbx,8)
incq %rbx
cmpq $0x5, %rbx
jne 0x258a
cmpb $0x1, 0x5f97(%rip)      # 0x8540
jne 0x2614
cmpl $0x64, 0x5f92(%rip)     # 0x8544
jg 0x2614
movq 0x30(%rsp), %rbx
movq 0x28(%rsp), %r14
movq 0x20(%rsp), %r15
movq 0x10(%rsp), %r12
movq 0x18(%rsp), %r13
movq (%rbx), %rax
movq %rbx, %rdi
callq *(%rax)
movq (%r14), %rax
movq %r14, %rdi
callq *(%rax)
movq (%r15), %rax
movq %r15, %rdi
callq *(%rax)
movq (%r13), %rax
movq %r13, %rdi
callq *(%rax)
movq (%r12), %rax
movq %r12, %rdi
callq *(%rax)
movl 0x5f47(%rip), %eax      # 0x8544
leal 0x1(%rax), %ecx
movl %ecx, 0x5f3e(%rip)      # 0x8544
cmpb $0x1, 0x5f33(%rip)      # 0x8540
jne 0x2614
cmpl $0x64, %eax
jl 0x25cd
movq 0x59bd(%rip), %rbx      # 0x7fd8
leaq 0x2a32(%rip), %rsi      # 0x5054
movl $0x1d, %edx
movq %rbx, %rdi
callq 0x2120
movq (%rbx), %rax
movq -0x18(%rax), %rdi
addq %rbx, %rdi
movl $0xa, %esi
callq 0x20e0
movsbl %al, %esi
movq %rbx, %rdi
callq 0x2040
movq %rax, %rdi
callq 0x20a0
leaq 0x2a15(%rip), %rsi      # 0x5072
movl $0xc, %edx
movq %rbx, %rdi
callq 0x2120
movl 0x5edc(%rip), %esi      # 0x854c
movq %rbx, %rdi
callq 0x2170
movq %rax, %r14
movq (%rax), %rax
movq -0x18(%rax), %rdi
addq %r14, %rdi
movl $0xa, %esi
callq 0x20e0
movsbl %al, %esi
movq %r14, %rdi
callq 0x2040
movq %rax, %rdi
callq 0x20a0
leaq 0x29d6(%rip), %rsi      # 0x507f
movl $0xd, %edx
movq %rbx, %rdi
callq 0x2120
movl 0x5e94(%rip), %esi      # 0x8550
movq %rbx, %rdi
callq 0x2170
movq %rax, %r14
movq (%rax), %rax
movq -0x18(%rax), %rdi
addq %r14, %rdi
movl $0xa, %esi
callq 0x20e0
movsbl %al, %esi
movq %r14, %rdi
callq 0x2040
movq %rax, %rdi
callq 0x20a0
leaq 0x2998(%rip), %rsi      # 0x508d
movl $0xd, %edx
movq %rbx, %rdi
callq 0x2120
movl 0x5e3c(%rip), %esi      # 0x8544
decl %esi
movq %rbx, %rdi
callq 0x2170
movq %rax, %r14
movq (%rax), %rax
movq -0x18(%rax), %rdi
addq %r14, %rdi
movl $0xa, %esi
callq 0x20e0
movsbl %al, %esi
movq %r14, %rdi
callq 0x2040
movq %rax, %rdi
callq 0x20a0
leaq 0x2958(%rip), %rsi      # 0x509b
movl $0xd, %edx
movq %rbx, %rdi
callq 0x2120
movl 0x5df2(%rip), %esi      # 0x8548
movq %rbx, %rdi
callq 0x2170
movq %rax, %r14
movq (%rax), %rax
movq -0x18(%rax), %rdi
addq %r14, %rdi
movl $0xa, %esi
callq 0x20e0
movsbl %al, %esi
movq %r14, %rdi
callq 0x2040
movq %rax, %rdi
callq 0x20a0
xorl %r12d, %r12d
leaq 0x5dce(%rip), %r13      # 0x8560
leaq 0x28ac(%rip), %r14      # 0x5045
leaq 0x5970(%rip), %rbp      # 0x8110
movq 0x20(%r13,%r12,8), %rsi
movq 0x28(%r13,%r12,8), %rdx
movq %rbx, %rdi
callq 0x2120
movq %rax, %r15
movl $0x1, %edx
movq %rax, %rdi
movq %r14, %rsi
callq 0x2120
movl 0x4(%r12,%rbp), %esi
movq %r15, %rdi
callq 0x2170
movq %rax, %r15
movq (%rax), %rax
movq -0x18(%rax), %rdi
addq %r15, %rdi
movl $0xa, %esi
callq 0x20e0
movsbl %al, %esi
movq %r15, %rdi
callq 0x2040
movq %rax, %rdi
callq 0x20a0
addq $0x4, %r12
cmpq $0x1c, %r12
jne 0x27a0
xorl %ebx, %ebx
movq 0x10(%rsp,%rbx,8), %rdi
testq %rdi, %rdi
je 0x2818
movq (%rdi), %rax
callq *0x10(%rax)
incq %rbx
cmpq $0x5, %rbx
jne 0x2808
callq 0x3f96
xorl %eax, %eax
addq $0x38, %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq
movq 0x579a(%rip), %rbx      # 0x7fd8
leaq 0x27d7(%rip), %rsi      # 0x501c
movl $0x22, %edx
movq %rbx, %rdi
callq 0x2120
movq %rbx, %rdi
callq 0x2070
leaq 0x27de(%rip), %rsi      # 0x503f
movl $0x7, %edx
movq %rbx, %rdi
callq 0x2120
movq (%r14), %rsi
leaq 0x10(%rsp), %r14
leaq 0xf(%rsp), %rdx
movq %r14, %rdi
callq 0x41ae
movq (%r14), %rsi
movq 0x8(%r14), %rdx
movq %rbx, %rdi
callq 0x2120
movq %rax, %rbx
leaq 0x27ab(%rip), %rsi      # 0x5047
movl $0xc, %edx
movq %rax, %rdi
callq 0x2120
movq %rbx, %rdi
callq 0x2070
leaq 0x10(%rsp), %rdi
callq 0x2060
movl $0xffffffff, %edi       # imm = 0xFFFFFFFF
callq 0x2130
movq %rax, %rbx
leaq 0x20(%rsp), %rax
movq -0x10(%rax), %rdi
cmpq %rax, %rdi
je 0x28e3
movq 0x20(%rsp), %rsi
incq %rsi
callq 0x2110
movq %rbx, %rdi
callq 0x2180