// File: /workspace/github_c_makefile_star2_O1/minkcv[P]vm/machine/cpu.c
// Function: disassemble
void disassemble(Instruction* instr, char* assembly)
{
    // If the instructions reads the last 2 arguments as a constant
    uint8_t constant = ((instr->arg1 << 4) & 0x00F0) + instr->arg2;
    switch(instr->opcode)
    {
        case EXT:
            switch(instr->arg0)
            {
                case EXT_HALT:
                    sprintf(assembly, "HALT");
                    break;
                case EXT_CPY:
                    sprintf(assembly, "CPY r%02d r%02d", instr->arg1, instr->arg2);
                    break;
                case EXT_NOT:
                    sprintf(assembly, "NOT %02d %02d", instr->arg1, instr->arg2);
                    break;
                case EXT_LSL:
                    sprintf(assembly, "LSL r%02d r%02d", instr->arg1, instr->arg2);
                    break;
                case EXT_LSR:
                    sprintf(assembly, "LSR r%02d r%02d", instr->arg1, instr->arg2);
                    break;
                case EXT_JMP:
                    sprintf(assembly, "JMP r%02d r%02d", instr->arg1, instr->arg2);
                    break;
                case EXT_NOP:
                    sprintf(assembly, "NOP");
                    break;
                case EXT_BRKP:
                    sprintf(assembly, "BRKP");
                    break;
            }
            break;
        case ADD:
            sprintf(assembly, "ADD r%02d r%02d r%02d", instr->arg0, instr->arg1, instr->arg2);
            break;
        case SUB:
            sprintf(assembly, "SUB r%02d r%02d r%02d", instr->arg0, instr->arg1, instr->arg2);
            break;
        case ADDC:
            sprintf(assembly, "ADDC r%02d #%03d ; (0x%04X)", instr->arg0, constant, constant);
            break;
        case SUBC:
            sprintf(assembly, "SUBC r%02d #%03d ; (0x%04X)", instr->arg0, constant, constant);
            break;
        case CMP:
            sprintf(assembly, "CMP r%02d r%02d r%02d", instr->arg0, instr->arg1, instr->arg2);
            break;
        case JLT:
            sprintf(assembly, "JLT r%02d r%02d r%02d", instr->arg0, instr->arg1, instr->arg2);
            break;
        case JGT:
            sprintf(assembly, "JGT r%02d r%02d r%02d", instr->arg0, instr->arg1, instr->arg2);
            break;
        case JEQ:
            sprintf(assembly, "JEQ r%02d r%02d r%02d", instr->arg0, instr->arg1, instr->arg2);
            break;
        case LDR:
            sprintf(assembly, "LDR r%02d r%02d r%02d", instr->arg0, instr->arg1, instr->arg2);
            break;
        case STR:
            sprintf(assembly, "STR r%02d r%02d r%02d", instr->arg0, instr->arg1, instr->arg2);
            break;
        case LRC:
            sprintf(assembly, "LRC r%02d #%03d ; (0x%04X)", instr->arg0, constant, constant);
            break;
        case AND:
            sprintf(assembly, "AND r%02d r%02d r%02d", instr->arg0, instr->arg1, instr->arg2);
            break;
        case OR:
            sprintf(assembly, "OR r%02d r%02d r%02d", instr->arg0, instr->arg1, instr->arg2);
            break;
        case XOR:
            sprintf(assembly, "XOR r%02d r%02d r%02d", instr->arg0, instr->arg1, instr->arg2);
            break;
    }
}

// Assembly:
pushq %rbp
movq %rsp, %rbp
movzwl (%rdi), %edx
movl %edx, %eax
shrl $0x8, %eax
movl %eax, %ecx
andl $0xf, %ecx
shll $0x4, %eax
movl %edx, %r8d
shrl $0xc, %r8d
orl %r8d, %eax
movl %edx, %edi
andl $0xf, %edi
leaq 0xc46(%rip), %r9        # 0x31b0
movslq (%r9,%rdi,4), %rdi
addq %r9, %rdi
jmpq *%rdi
shrl $0x4, %edx
andl $0xf, %edx
cmpw $0x7, %dx
ja 0x26f7
leaq 0xc66(%rip), %rax       # 0x31f0
movslq (%rax,%rdx,4), %rdx
addq %rax, %rdx
jmpq *%rdx
movb $0x0, 0x4(%rsi)
movl $0x544c4148, (%rsi)     # imm = 0x544C4148
jmp 0x26f7
shrl $0x4, %edx
andl $0xf, %edx
leaq 0xe33(%rip), %rax       # 0x33e2
jmp 0x2699
shrl $0x4, %edx
andl $0xf, %edx
leaq 0xdd9(%rip), %rax       # 0x339a
jmp 0x2699
shrl $0x4, %edx
andl $0xf, %edx
movzwl %ax, %eax
movzbl %al, %ecx
leaq 0xd1b(%rip), %rax       # 0x32f4
jmp 0x2654
shrl $0x4, %edx
andl $0xf, %edx
movzwl %ax, %eax
movzbl %al, %ecx
leaq 0xdc2(%rip), %rax       # 0x33b0
jmp 0x2654
shrl $0x4, %edx
andl $0xf, %edx
leaq 0xd71(%rip), %rax       # 0x336e
jmp 0x2699
shrl $0x4, %edx
andl $0xf, %edx
leaq 0xcb9(%rip), %rax       # 0x32c8
jmp 0x2699
shrl $0x4, %edx
andl $0xf, %edx
leaq 0xdc0(%rip), %rax       # 0x33e1
jmp 0x2699
shrl $0x4, %edx
andl $0xf, %edx
leaq 0xcae(%rip), %rax       # 0x32de
jmp 0x2699
shrl $0x4, %edx
andl $0xf, %edx
leaq 0xd03(%rip), %rax       # 0x3342
jmp 0x2699
shrl $0x4, %edx
andl $0xf, %edx
movzwl %ax, %eax
movzbl %al, %ecx
leaq 0xcbc(%rip), %rax       # 0x3310
movq %rsi, %rdi
movq %rax, %rsi
movl %ecx, %r8d
jmp 0x269f
shrl $0x4, %edx
andl $0xf, %edx
leaq 0xd5f(%rip), %rax       # 0x33cb
jmp 0x2699
shrl $0x4, %edx
andl $0xf, %edx
leaq 0xcb1(%rip), %rax       # 0x332c
jmp 0x2699
shrl $0x4, %edx
andl $0xf, %edx
leaq 0xcfa(%rip), %rax       # 0x3384
jmp 0x2699
shrl $0x4, %edx
andl $0xf, %edx
leaq 0xcbf(%rip), %rax       # 0x3358
movq %rsi, %rdi
movq %rax, %rsi
xorl %eax, %eax
popq %rbp
jmp 0x1080
leaq 0xbf5(%rip), %rax       # 0x32a3
jmp 0x26de
leaq 0xbce(%rip), %rax       # 0x3285
jmp 0x26de
leaq 0xbd3(%rip), %rax       # 0x3293
jmp 0x26de
movb $0x0, 0x4(%rsi)
movl $0x504b5242, (%rsi)     # imm = 0x504B5242
jmp 0x26f7
leaq 0xba0(%rip), %rax       # 0x3275
jmp 0x26de
leaq 0xbd5(%rip), %rax       # 0x32b3
movq %rsi, %rdi
movq %rax, %rsi
movl %ecx, %edx
movl %r8d, %ecx
xorl %eax, %eax
popq %rbp
jmp 0x1080
movl $0x504f4e, (%rsi)       # imm = 0x504F4E
popq %rbp
retq