// File: khedoros[P]khednes/cpu2.cpp
// Function: cpu::print_details(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char>> const&)
void cpu::print_details(const std::string& filename) {
    int total=0;
    int count=0;

    for(int i=0;i<256;++i) {
        if(inst_counts[i]>0) {
            printf("Saw instruction #%02x  %d times.\n",i,inst_counts[i]);
            total+=inst_counts[i];
            count++;
        }
    }
    printf("Total of %d instructions invoked a total of %d times.\n",count,total);

    if(filename == "") return;
    ifstream rom(filename);
    bool print_insts = true;
    size_t filesize = 0;
    Vect<uint8_t> data;
    if(!rom.is_open()) {
        print_insts = false;
        cout<<"wtf couldn't open "<<filename<<" grrrr"<<endl;
    }
    else {
        cout<<"Opened "<<filename<<". ";
        rom.seekg(0,ios::end);
        filesize = rom.tellg() - streampos(16);
        cout<<"Going to read "<<dec<<filesize<<" bytes from it."<<endl;
        rom.seekg(16,ios::beg);
        if(filesize < 40 * 1024) {
            data.resize(filesize+PRG_PAGE_SIZE);
            rom.read(reinterpret_cast<char *>(&data[0]), filesize);
            rom.seekg(16,ios::beg);
            rom.read(reinterpret_cast<char *>(&data[PRG_PAGE_SIZE]), filesize);
        }
        else {
            data.resize(filesize);
            rom.read(reinterpret_cast<char *>(&data[0]), filesize);
        }
        rom.close();
        cout<<"Read the data. Closed the file."<<endl;
    }
    cout.flush();
    int addr_count = 0;
    for(int j=0;j<0x8000;++j) {
        if(addresses[16][j]) {
            if(print_insts) {
                printf("RAM:%04X (%04X)\t%s\n", j, addresses[16][j], util::inst_string(memory->read(j),memory->read(j+1),memory->read(j+2)).c_str());
            }
            else {
                printf("RAM:%04X (%04X)\n", j, addresses[16][j]);
            }
            addr_count++;
        }
    }
    for(int i=0;i<16;++i) {
        for(int j=0;j<PRG_PAGE_SIZE;++j) {
            if(addresses[i][j]) {
                if(print_insts) {
                    int base = i * PRG_PAGE_SIZE + j;
                    if(base < data.size()) {
                        printf("%02X:%04X (%04X)\t%s\n", i, j, addresses[i][j], (util::inst_string(data[base],data[base+1],data[base+2])).c_str());
                    }
                    else {
                        printf("%02X:%04X is outside the file.\n",i,j);
                    }
                }
                else {
                    printf("%02X:%04X (%04X)\n",i,j, addresses[i][j]);
                }
                addr_count++;
            }
        }
    }
    cout<<"The code visited "<<dec<<addr_count<<" addresses during execution."<<endl;
}

// Assembly:
subq $0x3c8, %rsp            # imm = 0x3C8
movq %rdi, 0x3c0(%rsp)
movq %rsi, 0x3b8(%rsp)
movq 0x3c0(%rsp), %rax
movq %rax, 0xe8(%rsp)
movl $0x0, 0x3b4(%rsp)
movl $0x0, 0x3b0(%rsp)
movl $0x0, 0x3ac(%rsp)
cmpl $0x100, 0x3ac(%rsp) # imm = 0x100
jge 0x16ac4
movq 0xe8(%rsp), %rax
movslq 0x3ac(%rsp), %rcx
cmpl $0x0, 0x20(%rax,%rcx,4)
jle 0x16aac
movq 0xe8(%rsp), %rax
movl 0x3ac(%rsp), %esi
movslq 0x3ac(%rsp), %rcx
movl 0x20(%rax,%rcx,4), %edx
leaq 0x158be(%rip), %rdi     # 0x2c330
movb $0x0, %al
callq 0x4050
movq 0xe8(%rsp), %rax
movslq 0x3ac(%rsp), %rcx
movl 0x20(%rax,%rcx,4), %eax
addl 0x3b4(%rsp), %eax
movl %eax, 0x3b4(%rsp)
movl 0x3b0(%rsp), %eax
addl $0x1, %eax
movl %eax, 0x3b0(%rsp)
jmp 0x16aae
movl 0x3ac(%rsp), %eax
addl $0x1, %eax
movl %eax, 0x3ac(%rsp)
jmp 0x16a28
movl 0x3b0(%rsp), %esi
movl 0x3b4(%rsp), %edx
leaq 0x15879(%rip), %rdi     # 0x2c352
movb $0x0, %al
callq 0x4050
movq 0x3b8(%rsp), %rdi
leaq 0x1467e(%rip), %rsi     # 0x2b16d
callq 0x19850
testb $0x1, %al
jne 0x16afa
jmp 0x16aff
jmp 0x17391
movq 0x3b8(%rsp), %rsi
leaq 0x1a0(%rsp), %rdi
movq %rdi, 0xd8(%rsp)
movl $0x8, %edx
callq 0x45f0
movb $0x1, 0x19f(%rsp)
movq $0x0, 0x190(%rsp)
leaq 0x178(%rsp), %rdi
callq 0x112d0
movq 0xd8(%rsp), %rdi
callq 0x45e0
movb %al, 0xe7(%rsp)
jmp 0x16b58
movb 0xe7(%rsp), %al
testb $0x1, %al
jne 0x16bff
jmp 0x16b69
movb $0x0, 0x19f(%rsp)
movq 0x20438(%rip), %rdi     # 0x36fb0
leaq 0x1580a(%rip), %rsi     # 0x2c389
callq 0x43c0
movq %rax, 0xd0(%rsp)
jmp 0x16b8e
movq 0xd0(%rsp), %rdi
movq 0x3b8(%rsp), %rsi
callq 0x4350
movq %rax, 0xc8(%rsp)
jmp 0x16bad
movq 0xc8(%rsp), %rdi
leaq 0x157e0(%rip), %rsi     # 0x2c39c
callq 0x43c0
movq %rax, 0xc0(%rsp)
jmp 0x16bcb
movq 0xc0(%rsp), %rdi
movq 0x203b6(%rip), %rsi     # 0x36f90
callq 0x4400
jmp 0x16be1
jmp 0x16eaa
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0x170(%rsp)
movl %eax, 0x16c(%rsp)
jmp 0x17399
movq 0x203aa(%rip), %rdi     # 0x36fb0
leaq 0x15796(%rip), %rsi     # 0x2c3a3
callq 0x43c0
movq %rax, 0xb8(%rsp)
jmp 0x16c1c
movq 0xb8(%rsp), %rdi
movq 0x3b8(%rsp), %rsi
callq 0x4350
movq %rax, 0xb0(%rsp)
jmp 0x16c3b
movq 0xb0(%rsp), %rdi
leaq 0x15761(%rip), %rsi     # 0x2c3ab
callq 0x43c0
jmp 0x16c51
xorl %eax, %eax
movl %eax, %esi
leaq 0x1a0(%rsp), %rdi
movl $0x2, %edx
callq 0x44d0
jmp 0x16c69
leaq 0x1a0(%rsp), %rdi
callq 0x4670
movq %rdx, 0xa0(%rsp)
movq %rax, 0xa8(%rsp)
jmp 0x16c88
movq 0xa0(%rsp), %rax
movq 0xa8(%rsp), %rcx
movq %rcx, 0x158(%rsp)
movq %rax, 0x160(%rsp)
leaq 0x148(%rsp), %rdi
movl $0x10, %esi
callq 0x198a0
jmp 0x16cbc
leaq 0x158(%rsp), %rdi
leaq 0x148(%rsp), %rsi
callq 0x19880
movq %rax, 0x98(%rsp)
jmp 0x16cdb
movq 0x98(%rsp), %rax
movq %rax, 0x190(%rsp)
movq 0x202be(%rip), %rdi     # 0x36fb0
leaq 0x156b5(%rip), %rsi     # 0x2c3ae
callq 0x43c0
movq %rax, 0x90(%rsp)
jmp 0x16d08
movq 0x90(%rsp), %rdi
leaq -0x8297(%rip), %rsi     # 0xea80
callq 0x4150
movq %rax, 0x88(%rsp)
jmp 0x16d26
movq 0x88(%rsp), %rdi
movq 0x190(%rsp), %rsi
callq 0x40f0
movq %rax, 0x80(%rsp)
jmp 0x16d45
movq 0x80(%rsp), %rdi
leaq 0x15669(%rip), %rsi     # 0x2c3bd
callq 0x43c0
movq %rax, 0x78(%rsp)
jmp 0x16d60
movq 0x78(%rsp), %rdi
movq 0x20224(%rip), %rsi     # 0x36f90
callq 0x4400
jmp 0x16d73
leaq 0x1a0(%rsp), %rdi
movl $0x10, %esi
xorl %edx, %edx
callq 0x44d0
jmp 0x16d89
cmpq $0xa000, 0x190(%rsp) # imm = 0xA000
jae 0x16e28
movq 0x190(%rsp), %rsi
addq $0x4000, %rsi           # imm = 0x4000
leaq 0x178(%rsp), %rdi
callq 0x114c0
jmp 0x16db9
xorl %eax, %eax
movl %eax, %esi
leaq 0x178(%rsp), %rdi
callq 0x114a0
movq %rax, %rsi
movq 0x190(%rsp), %rdx
leaq 0x1a0(%rsp), %rdi
callq 0x4490
jmp 0x16de4
leaq 0x1a0(%rsp), %rdi
movl $0x10, %esi
xorl %edx, %edx
callq 0x44d0
jmp 0x16dfa
leaq 0x178(%rsp), %rdi
movl $0x4000, %esi           # imm = 0x4000
callq 0x114a0
movq %rax, %rsi
movq 0x190(%rsp), %rdx
leaq 0x1a0(%rsp), %rdi
callq 0x4490
jmp 0x16e26
jmp 0x16e6c
movq 0x190(%rsp), %rsi
leaq 0x178(%rsp), %rdi
callq 0x114c0
jmp 0x16e3f
xorl %eax, %eax
movl %eax, %esi
leaq 0x178(%rsp), %rdi
callq 0x114a0
movq %rax, %rsi
movq 0x190(%rsp), %rdx
leaq 0x1a0(%rsp), %rdi
callq 0x4490
jmp 0x16e6a
jmp 0x16e6c
leaq 0x1a0(%rsp), %rdi
callq 0x40d0
jmp 0x16e7b
movq 0x2012e(%rip), %rdi     # 0x36fb0
leaq 0x15544(%rip), %rsi     # 0x2c3cd
callq 0x43c0
movq %rax, 0x70(%rsp)
jmp 0x16e95
movq 0x70(%rsp), %rdi
movq 0x200ef(%rip), %rsi     # 0x36f90
callq 0x4400
jmp 0x16ea8
jmp 0x16eaa
movq 0x200ff(%rip), %rdi     # 0x36fb0
callq 0x42a0
jmp 0x16eb8
movl $0x0, 0x144(%rsp)
movl $0x0, 0x140(%rsp)
cmpl $0x8000, 0x140(%rsp) # imm = 0x8000
jge 0x17090
leaq 0x204ca(%rip), %rdi     # 0x373b0
movl $0x10, %esi
callq 0x19790
movq %rax, %rdi
movslq 0x140(%rsp), %rsi
callq 0x15080
cmpl $0x0, (%rax)
je 0x17078
testb $0x1, 0x19f(%rsp)
je 0x17023
movl 0x140(%rsp), %eax
movl %eax, 0x64(%rsp)
leaq 0x20487(%rip), %rdi     # 0x373b0
movl $0x10, %esi
callq 0x19790
movq %rax, %rdi
movslq 0x140(%rsp), %rsi
callq 0x15080
movq %rax, %rcx
movq 0xe8(%rsp), %rax
movl (%rcx), %ecx
movl %ecx, 0x68(%rsp)
movq 0x10(%rax), %rdi
movl 0x140(%rsp), %esi
callq 0x14460
movl %eax, 0x6c(%rsp)
jmp 0x16f6a
movq 0xe8(%rsp), %rax
movq 0x10(%rax), %rdi
movl 0x140(%rsp), %esi
incl %esi
callq 0x14460
movl %eax, 0x60(%rsp)
jmp 0x16f8a
movq 0xe8(%rsp), %rax
movq 0x10(%rax), %rdi
movl 0x140(%rsp), %esi
addl $0x2, %esi
callq 0x14460
movl %eax, 0x5c(%rsp)
jmp 0x16fab
movl 0x5c(%rsp), %ecx
movl 0x60(%rsp), %edx
movl 0x6c(%rsp), %esi
leaq 0x120(%rsp), %rdi
callq 0x21190
jmp 0x16fc6
leaq 0x120(%rsp), %rdi
callq 0x41a0
movl 0x64(%rsp), %esi
movl 0x68(%rsp), %edx
movq %rax, %rcx
leaq 0x15408(%rip), %rdi     # 0x2c3ed
xorl %eax, %eax
callq 0x4050
jmp 0x16fee
leaq 0x120(%rsp), %rdi
callq 0x4240
jmp 0x17067
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0x170(%rsp)
movl %eax, 0x16c(%rsp)
leaq 0x120(%rsp), %rdi
callq 0x4240
jmp 0x17399
movl 0x140(%rsp), %eax
movl %eax, 0x58(%rsp)
leaq 0x2037b(%rip), %rdi     # 0x373b0
movl $0x10, %esi
callq 0x19790
movq %rax, %rdi
movslq 0x140(%rsp), %rsi
callq 0x15080
movl 0x58(%rsp), %esi
movl (%rax), %edx
leaq 0x153a5(%rip), %rdi     # 0x2c401
xorl %eax, %eax
callq 0x4050
jmp 0x17065
jmp 0x17067
movl 0x144(%rsp), %eax
addl $0x1, %eax
movl %eax, 0x144(%rsp)
jmp 0x1707a
movl 0x140(%rsp), %eax
addl $0x1, %eax
movl %eax, 0x140(%rsp)
jmp 0x16ece
movl $0x0, 0x11c(%rsp)
cmpl $0x10, 0x11c(%rsp)
jge 0x17302
movl $0x0, 0x118(%rsp)
cmpl $0x4000, 0x118(%rsp) # imm = 0x4000
jge 0x172ea
movslq 0x11c(%rsp), %rsi
leaq 0x202dc(%rip), %rdi     # 0x373b0
callq 0x19790
movq %rax, %rdi
movslq 0x118(%rsp), %rsi
callq 0x15080
cmpl $0x0, (%rax)
je 0x172d2
testb $0x1, 0x19f(%rsp)
je 0x17270
movl 0x11c(%rsp), %eax
shll $0xe, %eax
addl 0x118(%rsp), %eax
movl %eax, 0x114(%rsp)
movslq 0x114(%rsp), %rax
movq %rax, 0x50(%rsp)
leaq 0x178(%rsp), %rdi
callq 0x11640
movq %rax, %rcx
movq 0x50(%rsp), %rax
cmpq %rcx, %rax
jae 0x1724e
movl 0x11c(%rsp), %eax
movl %eax, 0x34(%rsp)
movl 0x118(%rsp), %ecx
movl %ecx, 0x38(%rsp)
movslq %eax, %rsi
leaq 0x2024d(%rip), %rdi     # 0x373b0
callq 0x19790
movq %rax, %rdi
movslq 0x118(%rsp), %rsi
callq 0x15080
movl (%rax), %eax
movl %eax, 0x3c(%rsp)
movslq 0x114(%rsp), %rsi
leaq 0x178(%rsp), %rdi
movq %rdi, 0x40(%rsp)
callq 0x114a0
movq 0x40(%rsp), %rdi
movzbl (%rax), %eax
movl %eax, 0x48(%rsp)
movl 0x114(%rsp), %eax
incl %eax
movslq %eax, %rsi
callq 0x114a0
movq 0x40(%rsp), %rdi
movzbl (%rax), %eax
movl %eax, 0x4c(%rsp)
movl 0x114(%rsp), %eax
addl $0x2, %eax
movslq %eax, %rsi
callq 0x114a0
movl 0x48(%rsp), %esi
movl 0x4c(%rsp), %edx
movzbl (%rax), %ecx
leaq 0xf0(%rsp), %rdi
callq 0x21190
jmp 0x171ed
leaq 0xf0(%rsp), %rdi
callq 0x41a0
movl 0x34(%rsp), %esi
movl 0x38(%rsp), %edx
movl 0x3c(%rsp), %ecx
movq %rax, %r8
leaq 0x15202(%rip), %rdi     # 0x2c412
xorl %eax, %eax
callq 0x4050
jmp 0x17219
leaq 0xf0(%rsp), %rdi
callq 0x4240
jmp 0x1726e
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0x170(%rsp)
movl %eax, 0x16c(%rsp)
leaq 0xf0(%rsp), %rdi
callq 0x4240
jmp 0x17399
movl 0x11c(%rsp), %esi
movl 0x118(%rsp), %edx
leaq 0x151c4(%rip), %rdi     # 0x2c427
xorl %eax, %eax
callq 0x4050
jmp 0x1726c
jmp 0x1726e
jmp 0x172c1
movl 0x11c(%rsp), %eax
movl %eax, 0x2c(%rsp)
movl 0x118(%rsp), %ecx
movl %ecx, 0x30(%rsp)
movslq %eax, %rsi
leaq 0x20120(%rip), %rdi     # 0x373b0
callq 0x19790
movq %rax, %rdi
movslq 0x118(%rsp), %rsi
callq 0x15080
movl 0x2c(%rsp), %esi
movl 0x30(%rsp), %edx
movl (%rax), %ecx
leaq 0x15191(%rip), %rdi     # 0x2c447
xorl %eax, %eax
callq 0x4050
jmp 0x172bf
jmp 0x172c1
movl 0x144(%rsp), %eax
addl $0x1, %eax
movl %eax, 0x144(%rsp)
jmp 0x172d4
movl 0x118(%rsp), %eax
addl $0x1, %eax
movl %eax, 0x118(%rsp)
jmp 0x170b4
jmp 0x172ec
movl 0x11c(%rsp), %eax
addl $0x1, %eax
movl %eax, 0x11c(%rsp)
jmp 0x1709b
movq 0x1fca7(%rip), %rdi     # 0x36fb0
leaq 0x15149(%rip), %rsi     # 0x2c459
callq 0x43c0
movq %rax, 0x20(%rsp)
jmp 0x1731c
movq 0x20(%rsp), %rdi
leaq -0x88a8(%rip), %rsi     # 0xea80
callq 0x4150
movq %rax, 0x18(%rsp)
jmp 0x17334
movq 0x18(%rsp), %rdi
movl 0x144(%rsp), %esi
callq 0x4660
movq %rax, 0x10(%rsp)
jmp 0x1734c
movq 0x10(%rsp), %rdi
leaq 0x15113(%rip), %rsi     # 0x2c46b
callq 0x43c0
movq %rax, 0x8(%rsp)
jmp 0x17364
movq 0x8(%rsp), %rdi
movq 0x1fc20(%rip), %rsi     # 0x36f90
callq 0x4400
jmp 0x17377
leaq 0x178(%rsp), %rdi
callq 0x112f0
leaq 0x1a0(%rsp), %rdi
callq 0x4100
addq $0x3c8, %rsp            # imm = 0x3C8
retq
leaq 0x178(%rsp), %rdi
callq 0x112f0
leaq 0x1a0(%rsp), %rdi
callq 0x4100
movq 0x170(%rsp), %rdi
callq 0x4680