// File: 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
movq %rsp, %rbp
subq $0xd0, %rsp
movl $0x0, -0x4(%rbp)
movl %edi, -0x8(%rbp)
movq %rsi, -0x10(%rbp)
cmpl $0x2, -0x8(%rbp)
je 0x2a14
movq 0xa6ce(%rip), %rdi      # 0xcfd8
movq %rdi, -0xa8(%rbp)
leaq 0x671c(%rip), %rsi      # 0x9034
callq 0x2100
movq %rax, %rdi
movq 0xa6a1(%rip), %rsi      # 0xcfc8
callq 0x2130
movq -0xa8(%rbp), %rdi
leaq 0x671d(%rip), %rsi      # 0x9057
callq 0x2100
movq %rax, -0xa0(%rbp)
movq -0x10(%rbp), %rax
movq (%rax), %rax
movq %rax, -0x98(%rbp)
leaq -0x39(%rbp), %rdi
movq %rdi, -0x90(%rbp)
callq 0x2210
movq -0x98(%rbp), %rsi
movq -0x90(%rbp), %rdx
leaq -0x38(%rbp), %rdi
callq 0x6370
jmp 0x297d
movq -0xa0(%rbp), %rdi
leaq -0x38(%rbp), %rsi
callq 0x20f0
movq %rax, -0xb0(%rbp)
jmp 0x2996
movq -0xb0(%rbp), %rdi
leaq 0x66bb(%rip), %rsi      # 0x905f
callq 0x2100
movq %rax, -0xb8(%rbp)
jmp 0x29b2
movq -0xb8(%rbp), %rdi
movq 0xa608(%rip), %rsi      # 0xcfc8
callq 0x2130
jmp 0x29c7
leaq -0x38(%rbp), %rdi
callq 0x2080
leaq -0x39(%rbp), %rdi
callq 0x2150
movl $0xffffffff, %edi       # imm = 0xFFFFFFFF
callq 0x2180
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x48(%rbp)
movl %eax, -0x4c(%rbp)
jmp 0x2a06
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x48(%rbp)
movl %eax, -0x4c(%rbp)
leaq -0x38(%rbp), %rdi
callq 0x2080
leaq -0x39(%rbp), %rdi
callq 0x2150
jmp 0x2c91
movq -0x10(%rbp), %rax
movq 0x8(%rax), %rdi
callq 0x21d0
movl %eax, -0x14(%rbp)
movl -0x14(%rbp), %edi
callq 0x2ca0
movl $0x0, -0x50(%rbp)
movq $0x0, -0x88(%rbp)
movl $0x0, -0x50(%rbp)
cmpl $0x5, -0x50(%rbp)
jge 0x2a81
movl -0x50(%rbp), %edi
movq -0x88(%rbp), %rsi
callq 0x6ae0
movq %rax, %rcx
movslq -0x50(%rbp), %rax
movq %rcx, -0x80(%rbp,%rax,8)
movslq -0x50(%rbp), %rax
movq -0x80(%rbp,%rax,8), %rax
movq %rax, -0x88(%rbp)
movl -0x50(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x50(%rbp)
jmp 0x2a45
jmp 0x2a83
xorl %eax, %eax
testb $0x1, 0xab04(%rip)      # 0xd590
movb %al, -0xb9(%rbp)
je 0x2aa4
cmpl $0x64, 0xaaf9(%rip)     # 0xd594
setle %al
movb %al, -0xb9(%rbp)
movb -0xb9(%rbp), %al
testb $0x1, %al
jne 0x2ab0
jmp 0x2aee
movq -0x60(%rbp), %rdi
movq (%rdi), %rax
callq *(%rax)
movq -0x68(%rbp), %rdi
movq (%rdi), %rax
callq *(%rax)
movq -0x70(%rbp), %rdi
movq (%rdi), %rax
callq *(%rax)
movq -0x78(%rbp), %rdi
movq (%rdi), %rax
callq *(%rax)
movq -0x80(%rbp), %rdi
movq (%rdi), %rax
callq *(%rax)
movl 0xaab1(%rip), %eax      # 0xd594
addl $0x1, %eax
movl %eax, 0xaaa8(%rip)      # 0xd594
jmp 0x2a83
movq 0xa4e3(%rip), %rdi      # 0xcfd8
leaq 0x6570(%rip), %rsi      # 0x906c
callq 0x2100
movq %rax, %rdi
movq 0xa4bd(%rip), %rsi      # 0xcfc8
callq 0x2130
movq 0xa4c1(%rip), %rdi      # 0xcfd8
leaq 0x656c(%rip), %rsi      # 0x908a
callq 0x2100
movq %rax, %rdi
movl 0xaa70(%rip), %esi      # 0xd59c
callq 0x21f0
movq %rax, %rdi
movq 0xa48d(%rip), %rsi      # 0xcfc8
callq 0x2130
movq 0xa491(%rip), %rdi      # 0xcfd8
leaq 0x6549(%rip), %rsi      # 0x9097
callq 0x2100
movq %rax, %rdi
movl 0xaa44(%rip), %esi      # 0xd5a0
callq 0x21f0
movq %rax, %rdi
movq 0xa45d(%rip), %rsi      # 0xcfc8
callq 0x2130
movq 0xa461(%rip), %rdi      # 0xcfd8
leaq 0x6527(%rip), %rsi      # 0x90a5
callq 0x2100
movq %rax, %rdi
movl 0xaa08(%rip), %esi      # 0xd594
subl $0x1, %esi
callq 0x21f0
movq %rax, %rdi
movq 0xa42a(%rip), %rsi      # 0xcfc8
callq 0x2130
movq 0xa42e(%rip), %rdi      # 0xcfd8
leaq 0x6502(%rip), %rsi      # 0x90b3
callq 0x2100
movq %rax, %rdi
movl 0xa9d9(%rip), %esi      # 0xd598
callq 0x21f0
movq %rax, %rdi
movq 0xa3fa(%rip), %rsi      # 0xcfc8
callq 0x2130
movl $0x1, -0x50(%rbp)
cmpl $0x8, -0x50(%rbp)
jge 0x2c44
movslq -0x50(%rbp), %rax
leaq 0xa9c5(%rip), %rsi      # 0xd5b0
shlq $0x5, %rax
addq %rax, %rsi
movq 0xa3df(%rip), %rdi      # 0xcfd8
callq 0x20f0
movq %rax, %rdi
leaq 0x6455(%rip), %rsi      # 0x905d
callq 0x2100
movq %rax, -0xc8(%rbp)
movl -0x50(%rbp), %edi
callq 0x5d00
movq -0xc8(%rbp), %rdi
movl %eax, %esi
callq 0x21f0
movq %rax, %rdi
movq 0xa394(%rip), %rsi      # 0xcfc8
callq 0x2130
movl -0x50(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x50(%rbp)
jmp 0x2bda
movl $0x0, -0x50(%rbp)
cmpl $0x5, -0x50(%rbp)
jge 0x2c81
movslq -0x50(%rbp), %rax
movq -0x80(%rbp,%rax,8), %rax
movq %rax, -0xd0(%rbp)
cmpq $0x0, %rax
je 0x2c74
movq -0xd0(%rbp), %rdi
movq (%rdi), %rax
callq *0x10(%rax)
jmp 0x2c76
movl -0x50(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x50(%rbp)
jmp 0x2c4b
callq 0x5d20
xorl %eax, %eax
addq $0xd0, %rsp
popq %rbp
retq
movq -0x48(%rbp), %rdi
callq 0x2200
nopw (%rax,%rax)