// File: /workspace/github_c_makefile_star2_O3/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 0xcc6(%rip), %r9        # 0x31a0
movslq (%r9,%rdi,4), %rdi
addq %r9, %rdi
jmpq *%rdi
shrl $0x4, %edx
andl $0xf, %edx
cmpw $0x7, %dx
ja 0x2667
leaq 0xce6(%rip), %rax       # 0x31e0
movslq (%rax,%rdx,4), %rdx
addq %rax, %rdx
jmpq *%rdx
movb $0x0, 0x4(%rsi)
movl $0x544c4148, (%rsi)     # imm = 0x544C4148
jmp 0x2667
shrl $0x4, %edx
andl $0xf, %edx
leaq 0xeb3(%rip), %rax       # 0x33d2
jmp 0x2609
shrl $0x4, %edx
andl $0xf, %edx
leaq 0xe59(%rip), %rax       # 0x338a
jmp 0x2609
shrl $0x4, %edx
andl $0xf, %edx
movzwl %ax, %eax
movzbl %al, %ecx
leaq 0xd9b(%rip), %rax       # 0x32e4
jmp 0x25c4
shrl $0x4, %edx
andl $0xf, %edx
movzwl %ax, %eax
movzbl %al, %ecx
leaq 0xe42(%rip), %rax       # 0x33a0
jmp 0x25c4
shrl $0x4, %edx
andl $0xf, %edx
leaq 0xdf1(%rip), %rax       # 0x335e
jmp 0x2609
shrl $0x4, %edx
andl $0xf, %edx
leaq 0xd39(%rip), %rax       # 0x32b8
jmp 0x2609
shrl $0x4, %edx
andl $0xf, %edx
leaq 0xe40(%rip), %rax       # 0x33d1
jmp 0x2609
shrl $0x4, %edx
andl $0xf, %edx
leaq 0xd2e(%rip), %rax       # 0x32ce
jmp 0x2609
shrl $0x4, %edx
andl $0xf, %edx
leaq 0xd83(%rip), %rax       # 0x3332
jmp 0x2609
shrl $0x4, %edx
andl $0xf, %edx
movzwl %ax, %eax
movzbl %al, %ecx
leaq 0xd3c(%rip), %rax       # 0x3300
movq %rsi, %rdi
movq %rax, %rsi
movl %ecx, %r8d
jmp 0x260f
shrl $0x4, %edx
andl $0xf, %edx
leaq 0xddf(%rip), %rax       # 0x33bb
jmp 0x2609
shrl $0x4, %edx
andl $0xf, %edx
leaq 0xd31(%rip), %rax       # 0x331c
jmp 0x2609
shrl $0x4, %edx
andl $0xf, %edx
leaq 0xd7a(%rip), %rax       # 0x3374
jmp 0x2609
shrl $0x4, %edx
andl $0xf, %edx
leaq 0xd3f(%rip), %rax       # 0x3348
movq %rsi, %rdi
movq %rax, %rsi
xorl %eax, %eax
popq %rbp
jmp 0x1080
leaq 0xc75(%rip), %rax       # 0x3293
jmp 0x264e
leaq 0xc4e(%rip), %rax       # 0x3275
jmp 0x264e
leaq 0xc53(%rip), %rax       # 0x3283
jmp 0x264e
movb $0x0, 0x4(%rsi)
movl $0x504b5242, (%rsi)     # imm = 0x504B5242
jmp 0x2667
leaq 0xc20(%rip), %rax       # 0x3265
jmp 0x264e
leaq 0xc55(%rip), %rax       # 0x32a3
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