// File: taurheim[P]AgNES/codeGenerator.cpp
// Function: CodeGenerator::generateCodeFromTAC(TAC)
void CodeGenerator::generateCodeFromTAC(TAC tac) {
    switch (tac.op) {
        case IR_DECLARATION: {
            allocateGlobal(tac.first, "type");
            break;
        }
        case IR_NEWLABEL: {
            if (!jumpedToMain) {
                code << "JMP main" << nl;
                jumpedToMain = true;
            }
            code.seekp(-1, code.cur);
            code << tac.first << ":" << nl;
            break;
        } 
        case IR_BEGINFUNC: {
            generateBeginFunc(tac);
            break;
        }
        case IR_ASSIGN: {
            generateAssign(tac);
            break;
        }
        case IR_ADD: {
            generateAddition(tac);
            break;
        }
        case IR_SUBTRACT: {
            generateSubtraction(tac);
            break;
        }
        case IR_IFTRUEGOTO: {
            generateBranchOnCondition(tac, true);
            break;
        }
        case IR_IFFALSEGOTO: {
            generateBranchOnCondition(tac, false);
            break;
        }
        case IR_GOTO: {
            generateJump(tac);
            break;
        }
        case IR_PUSHPARAM: {
            generatePushParam(tac);
            break;
        }
        case IR_POPPARAMS: {
            generatePopParams(tac);
            break;
        }
        case IR_CALL: {
            generateSubroutineCall(tac);
            break;
        }
        case IR_RETURN: {
            code << "RTS" << nl;
            break;
        }
        case IR_ENDFUNC: {
            generateEndFunc(tac);
            break;
        }
        case IR_NES_WAITFORFRAME: {
            code << ";;;;;; NESWAITFORFRAME ;;;;;;" << nl;
            code << "INC 99" << nl;
            code << "wait_for_frame:" << nl;
            code << "LDA 99" << nl;
            code << "BNE wait_for_frame" << nl;
            break;
        }
        case IR_NES_SETSPRITEX: {
            code << ";;;;;; NESSETSPRITEX ;;;;;;" << nl;
            int offset = globalToAddressMap[tac.first];
            loadGlobalIntoA(offset);
            code << "STA $0203" << nl;
            break;
        }
        case IR_NES_SETSPRITEY: {
            code << ";;;;;; NESSETSPRITEY ;;;;;;" << nl;
            int offset = globalToAddressMap[tac.first];
            loadGlobalIntoA(offset);
            code << "STA $0200" << nl;
            break;
        }
    }
}

// Assembly:
pushq %rbp
movq %rsp, %rbp
subq $0x560, %rsp            # imm = 0x560
movq %rsi, -0x500(%rbp)
movq %rdi, -0x8(%rbp)
movq %rsi, -0x10(%rbp)
movq -0x8(%rbp), %rax
movq %rax, -0x4f8(%rbp)
movl (%rsi), %eax
movq %rax, -0x4f0(%rbp)
subq $0x10, %rax
ja 0x1fd32
movq -0x4f0(%rbp), %rax
leaq 0x532a(%rip), %rcx      # 0x248e0
movslq (%rcx,%rax,4), %rax
addq %rcx, %rax
jmpq *%rax
movq -0x500(%rbp), %rsi
addq $0x8, %rsi
leaq -0x30(%rbp), %rdi
callq 0x3140
leaq -0x51(%rbp), %rdi
movq %rdi, -0x508(%rbp)
callq 0x3530
movq -0x508(%rbp), %rdx
leaq 0x5359(%rip), %rsi      # 0x2494a
leaq -0x50(%rbp), %rdi
callq 0x33f0
jmp 0x1f5fc
movq -0x4f8(%rbp), %rdi
leaq -0x30(%rbp), %rsi
leaq -0x50(%rbp), %rdx
callq 0x1fd50
jmp 0x1f612
leaq -0x50(%rbp), %rdi
callq 0x31d0
leaq -0x51(%rbp), %rdi
callq 0x3350
leaq -0x30(%rbp), %rdi
callq 0x31d0
jmp 0x1fd32
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x60(%rbp)
movl %eax, -0x64(%rbp)
jmp 0x1f655
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x60(%rbp)
movl %eax, -0x64(%rbp)
leaq -0x50(%rbp), %rdi
callq 0x31d0
leaq -0x51(%rbp), %rdi
callq 0x3350
leaq -0x30(%rbp), %rdi
callq 0x31d0
jmp 0x1fd3b
movq -0x4f8(%rbp), %rax
testb $0x1, 0x290(%rax)
jne 0x1f6b3
movq -0x4f8(%rbp), %rdi
addq $0x80, %rdi
leaq 0x52be(%rip), %rsi      # 0x2494f
callq 0x32e0
movq -0x4f8(%rbp), %rsi
movq %rax, %rdi
callq 0x32a0
movq -0x4f8(%rbp), %rax
movb $0x1, 0x290(%rax)
movq -0x4f8(%rbp), %rdi
addq $0x80, %rdi
movq $-0x1, %rsi
movl $0x1, %edx
callq 0x32f0
movq -0x500(%rbp), %rsi
movq -0x4f8(%rbp), %rdi
addq $0x80, %rdi
addq $0x8, %rsi
callq 0x32a0
movq %rax, %rdi
leaq 0x5295(%rip), %rsi      # 0x2498f
callq 0x32e0
movq -0x4f8(%rbp), %rsi
movq %rax, %rdi
callq 0x32a0
jmp 0x1fd32
movq -0x500(%rbp), %rsi
leaq -0xd0(%rbp), %rdi
movq %rdi, -0x510(%rbp)
callq 0xccd0
movq -0x4f8(%rbp), %rdi
movq -0x510(%rbp), %rsi
callq 0x1fe00
jmp 0x1f742
leaq -0xd0(%rbp), %rdi
callq 0x94e0
jmp 0x1fd32
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x60(%rbp)
movl %eax, -0x64(%rbp)
leaq -0xd0(%rbp), %rdi
callq 0x94e0
jmp 0x1fd3b
movq -0x500(%rbp), %rsi
leaq -0x138(%rbp), %rdi
movq %rdi, -0x518(%rbp)
callq 0xccd0
movq -0x4f8(%rbp), %rdi
movq -0x518(%rbp), %rsi
callq 0x20200
jmp 0x1f79f
leaq -0x138(%rbp), %rdi
callq 0x94e0
jmp 0x1fd32
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x60(%rbp)
movl %eax, -0x64(%rbp)
leaq -0x138(%rbp), %rdi
callq 0x94e0
jmp 0x1fd3b
movq -0x500(%rbp), %rsi
leaq -0x1a0(%rbp), %rdi
movq %rdi, -0x520(%rbp)
callq 0xccd0
movq -0x4f8(%rbp), %rdi
movq -0x520(%rbp), %rsi
callq 0x20540
jmp 0x1f7fc
leaq -0x1a0(%rbp), %rdi
callq 0x94e0
jmp 0x1fd32
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x60(%rbp)
movl %eax, -0x64(%rbp)
leaq -0x1a0(%rbp), %rdi
callq 0x94e0
jmp 0x1fd3b
movq -0x500(%rbp), %rsi
leaq -0x208(%rbp), %rdi
movq %rdi, -0x528(%rbp)
callq 0xccd0
movq -0x4f8(%rbp), %rdi
movq -0x528(%rbp), %rsi
callq 0x20850
jmp 0x1f859
leaq -0x208(%rbp), %rdi
callq 0x94e0
jmp 0x1fd32
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x60(%rbp)
movl %eax, -0x64(%rbp)
leaq -0x208(%rbp), %rdi
callq 0x94e0
jmp 0x1fd3b
movq -0x500(%rbp), %rsi
leaq -0x270(%rbp), %rdi
movq %rdi, -0x530(%rbp)
callq 0xccd0
movq -0x4f8(%rbp), %rdi
movq -0x530(%rbp), %rsi
movl $0x1, %edx
callq 0x20b60
jmp 0x1f8bb
leaq -0x270(%rbp), %rdi
callq 0x94e0
jmp 0x1fd32
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x60(%rbp)
movl %eax, -0x64(%rbp)
leaq -0x270(%rbp), %rdi
callq 0x94e0
jmp 0x1fd3b
movq -0x500(%rbp), %rsi
leaq -0x2d8(%rbp), %rdi
movq %rdi, -0x538(%rbp)
callq 0xccd0
movq -0x4f8(%rbp), %rdi
movq -0x538(%rbp), %rsi
xorl %edx, %edx
callq 0x20b60
jmp 0x1f91a
leaq -0x2d8(%rbp), %rdi
callq 0x94e0
jmp 0x1fd32
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x60(%rbp)
movl %eax, -0x64(%rbp)
leaq -0x2d8(%rbp), %rdi
callq 0x94e0
jmp 0x1fd3b
movq -0x500(%rbp), %rsi
leaq -0x340(%rbp), %rdi
movq %rdi, -0x540(%rbp)
callq 0xccd0
movq -0x4f8(%rbp), %rdi
movq -0x540(%rbp), %rsi
callq 0x20cb0
jmp 0x1f977
leaq -0x340(%rbp), %rdi
callq 0x94e0
jmp 0x1fd32
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x60(%rbp)
movl %eax, -0x64(%rbp)
leaq -0x340(%rbp), %rdi
callq 0x94e0
jmp 0x1fd3b
movq -0x500(%rbp), %rsi
leaq -0x3a8(%rbp), %rdi
movq %rdi, -0x548(%rbp)
callq 0xccd0
movq -0x4f8(%rbp), %rdi
movq -0x548(%rbp), %rsi
callq 0x20d40
jmp 0x1f9d4
leaq -0x3a8(%rbp), %rdi
callq 0x94e0
jmp 0x1fd32
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x60(%rbp)
movl %eax, -0x64(%rbp)
leaq -0x3a8(%rbp), %rdi
callq 0x94e0
jmp 0x1fd3b
movq -0x500(%rbp), %rsi
leaq -0x410(%rbp), %rdi
movq %rdi, -0x550(%rbp)
callq 0xccd0
movq -0x4f8(%rbp), %rdi
movq -0x550(%rbp), %rsi
callq 0x20e00
jmp 0x1fa31
leaq -0x410(%rbp), %rdi
callq 0x94e0
jmp 0x1fd32
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x60(%rbp)
movl %eax, -0x64(%rbp)
leaq -0x410(%rbp), %rdi
callq 0x94e0
jmp 0x1fd3b
movq -0x500(%rbp), %rsi
leaq -0x478(%rbp), %rdi
movq %rdi, -0x558(%rbp)
callq 0xccd0
movq -0x4f8(%rbp), %rdi
movq -0x558(%rbp), %rsi
callq 0x20e90
jmp 0x1fa8e
leaq -0x478(%rbp), %rdi
callq 0x94e0
jmp 0x1fd32
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x60(%rbp)
movl %eax, -0x64(%rbp)
leaq -0x478(%rbp), %rdi
callq 0x94e0
jmp 0x1fd3b
movq -0x4f8(%rbp), %rdi
addq $0x80, %rdi
leaq 0x4e87(%rip), %rsi      # 0x24958
callq 0x32e0
movq -0x4f8(%rbp), %rsi
movq %rax, %rdi
callq 0x32a0
jmp 0x1fd32
movq -0x500(%rbp), %rsi
leaq -0x4e0(%rbp), %rdi
movq %rdi, -0x560(%rbp)
callq 0xccd0
movq -0x4f8(%rbp), %rdi
movq -0x560(%rbp), %rsi
callq 0x20ff0
jmp 0x1fb19
leaq -0x4e0(%rbp), %rdi
callq 0x94e0
jmp 0x1fd32
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x60(%rbp)
movl %eax, -0x64(%rbp)
leaq -0x4e0(%rbp), %rdi
callq 0x94e0
jmp 0x1fd3b
movq -0x4f8(%rbp), %rdi
addq $0x80, %rdi
leaq 0x4e00(%rip), %rsi      # 0x2495c
callq 0x32e0
movq -0x4f8(%rbp), %rsi
movq %rax, %rdi
callq 0x32a0
movq -0x4f8(%rbp), %rdi
addq $0x80, %rdi
leaq 0x4df5(%rip), %rsi      # 0x2497a
callq 0x32e0
movq -0x4f8(%rbp), %rsi
movq %rax, %rdi
callq 0x32a0
movq -0x4f8(%rbp), %rdi
addq $0x80, %rdi
leaq 0x4dd3(%rip), %rsi      # 0x24981
callq 0x32e0
movq -0x4f8(%rbp), %rsi
movq %rax, %rdi
callq 0x32a0
movq -0x4f8(%rbp), %rdi
addq $0x80, %rdi
leaq 0x4dba(%rip), %rsi      # 0x24991
callq 0x32e0
movq -0x4f8(%rbp), %rsi
movq %rax, %rdi
callq 0x32a0
movq -0x4f8(%rbp), %rdi
addq $0x80, %rdi
leaq 0x4d98(%rip), %rsi      # 0x24998
callq 0x32e0
movq -0x4f8(%rbp), %rsi
movq %rax, %rdi
callq 0x32a0
jmp 0x1fd32
movq -0x4f8(%rbp), %rdi
addq $0x80, %rdi
leaq 0x4d7d(%rip), %rsi      # 0x249ab
callq 0x32e0
movq -0x4f8(%rbp), %rsi
movq %rax, %rdi
callq 0x32a0
movq -0x500(%rbp), %rsi
movq -0x4f8(%rbp), %rdi
addq $0x1f8, %rdi            # imm = 0x1F8
addq $0x8, %rsi
callq 0x21b90
movq -0x4f8(%rbp), %rdi
movl (%rax), %eax
movl %eax, -0x4e4(%rbp)
movl -0x4e4(%rbp), %esi
callq 0x21080
movq -0x4f8(%rbp), %rdi
addq $0x80, %rdi
leaq 0x4d38(%rip), %rsi      # 0x249c7
callq 0x32e0
movq -0x4f8(%rbp), %rsi
movq %rax, %rdi
callq 0x32a0
jmp 0x1fd32
movq -0x4f8(%rbp), %rdi
addq $0x80, %rdi
leaq 0x4d14(%rip), %rsi      # 0x249d1
callq 0x32e0
movq -0x4f8(%rbp), %rsi
movq %rax, %rdi
callq 0x32a0
movq -0x500(%rbp), %rsi
movq -0x4f8(%rbp), %rdi
addq $0x1f8, %rdi            # imm = 0x1F8
addq $0x8, %rsi
callq 0x21b90
movq -0x4f8(%rbp), %rdi
movl (%rax), %eax
movl %eax, -0x4e8(%rbp)
movl -0x4e8(%rbp), %esi
callq 0x21080
movq -0x4f8(%rbp), %rdi
addq $0x80, %rdi
leaq 0x4ccf(%rip), %rsi      # 0x249ed
callq 0x32e0
movq -0x4f8(%rbp), %rsi
movq %rax, %rdi
callq 0x32a0
addq $0x560, %rsp            # imm = 0x560
popq %rbp
retq
movq -0x60(%rbp), %rdi
callq 0x3520
nopw %cs:(%rax,%rax)