// File: /workspace/github_c_makefile_star2_O0/theandrew168[P]skylark/src/inst_test.c
// Function: test_instruction_decode
bool
test_instruction_decode(void)
{
    const struct {
        uint16_t code;
        struct instruction want;
    } tests[] = {
        { .code = 0x00E0, .want = { .opcode = OPCODE_CLS_00E0 }},
        { .code = 0x00EE, .want = { .opcode = OPCODE_RET_00EE }},
        { .code = 0x0234, .want = { .opcode = OPCODE_SYS_0nnn, .nnn = 0x234 }},
        { .code = 0x1234, .want = { .opcode = OPCODE_JP_1nnn, .nnn = 0x234 }},
        { .code = 0x2234, .want = { .opcode = OPCODE_CALL_2nnn, .nnn = 0x234 }},
        { .code = 0x3234, .want = { .opcode = OPCODE_SE_3xkk, .x = 0x2, .kk = 0x34 }},
        { .code = 0x4234, .want = { .opcode = OPCODE_SNE_4xkk, .x = 0x2, .kk = 0x34 }},
        { .code = 0x5230, .want = { .opcode = OPCODE_SE_5xy0, .x = 0x2, .y = 0x3 }},
        { .code = 0x6234, .want = { .opcode = OPCODE_LD_6xkk, .x = 0x2, .kk = 0x34 }},
        { .code = 0x7234, .want = { .opcode = OPCODE_ADD_7xkk, .x = 0x2, .kk = 0x34 }},
        { .code = 0x8230, .want = { .opcode = OPCODE_LD_8xy0, .x = 0x2, .y = 0x3 }},
        { .code = 0x8231, .want = { .opcode = OPCODE_OR_8xy1, .x = 0x2, .y = 0x3 }},
        { .code = 0x8232, .want = { .opcode = OPCODE_AND_8xy2, .x = 0x2, .y = 0x3 }},
        { .code = 0x8233, .want = { .opcode = OPCODE_XOR_8xy3, .x = 0x2, .y = 0x3 }},
        { .code = 0x8234, .want = { .opcode = OPCODE_ADD_8xy4, .x = 0x2, .y = 0x3 }},
        { .code = 0x8235, .want = { .opcode = OPCODE_SUB_8xy5, .x = 0x2, .y = 0x3 }},
        { .code = 0x8236, .want = { .opcode = OPCODE_SHR_8xy6, .x = 0x2, .y = 0x3 }},
        { .code = 0x8237, .want = { .opcode = OPCODE_SUBN_8xy7, .x = 0x2, .y = 0x3 }},
        { .code = 0x823E, .want = { .opcode = OPCODE_SHL_8xyE, .x = 0x2, .y = 0x3 }},
        { .code = 0x9230, .want = { .opcode = OPCODE_SNE_9xy0, .x = 0x2, .y = 0x3 }},
        { .code = 0xA234, .want = { .opcode = OPCODE_LD_Annn, .nnn = 0x234 }},
        { .code = 0xB234, .want = { .opcode = OPCODE_JP_Bnnn, .nnn = 0x234 }},
        { .code = 0xC234, .want = { .opcode = OPCODE_RND_Cxkk, .x = 0x2, .kk = 0x34 }},
        { .code = 0xD234, .want = { .opcode = OPCODE_DRW_Dxyn, .x = 0x2, .y = 0x3, .n = 0x4 }},
        { .code = 0xE29E, .want = { .opcode = OPCODE_SKP_Ex9E, .x = 0x2 }},
        { .code = 0xE2A1, .want = { .opcode = OPCODE_SKNP_ExA1, .x = 0x2 }},
        { .code = 0xF207, .want = { .opcode = OPCODE_LD_Fx07, .x = 0x2 }},
        { .code = 0xF20A, .want = { .opcode = OPCODE_LD_Fx0A, .x = 0x2 }},
        { .code = 0xF215, .want = { .opcode = OPCODE_LD_Fx15, .x = 0x2 }},
        { .code = 0xF218, .want = { .opcode = OPCODE_LD_Fx18, .x = 0x2 }},
        { .code = 0xF21E, .want = { .opcode = OPCODE_ADD_Fx1E, .x = 0x2 }},
        { .code = 0xF229, .want = { .opcode = OPCODE_LD_Fx29, .x = 0x2 }},
        { .code = 0xF233, .want = { .opcode = OPCODE_LD_Fx33, .x = 0x2 }},
        { .code = 0xF255, .want = { .opcode = OPCODE_LD_Fx55, .x = 0x2 }},
        { .code = 0xF265, .want = { .opcode = OPCODE_LD_Fx65, .x = 0x2 }},
    };
    long num_tests = sizeof(tests) / sizeof(tests[0]);

    struct instruction inst = { 0 };
    for (long i = 0; i < num_tests; i++) {
        int rc = instruction_decode(&inst, tests[i].code);
        if (rc != INSTRUCTION_OK) {
            fprintf(stderr, "failed to decode instruction: %04x\n", tests[i].code);
            return false;
        }

        if (inst.opcode != tests[i].want.opcode) {
            fprintf(stderr, "want %d; got %d\n", tests[i].want.opcode, inst.opcode);
            return false;
        }
    }

    return true;
}

// Assembly:
pushq %rbp
movq %rsp, %rbp
subq $0x270, %rsp            # imm = 0x270
leaq -0x240(%rbp), %rdi
leaq 0x1db7(%rip), %rsi      # 0x30c0
movl $0x230, %edx            # imm = 0x230
callq 0x1080
movq $0x23, -0x248(%rbp)
leaq -0x254(%rbp), %rdi
xorl %esi, %esi
movl $0xc, %edx
callq 0x1050
movq $0x0, -0x260(%rbp)
movq -0x260(%rbp), %rax
cmpq -0x248(%rbp), %rax
jge 0x142e
movq -0x260(%rbp), %rcx
leaq -0x240(%rbp), %rax
shlq $0x4, %rcx
addq %rcx, %rax
leaq -0x254(%rbp), %rdi
movzwl (%rax), %esi
callq 0x11c0
movl %eax, -0x264(%rbp)
cmpl $0x0, -0x264(%rbp)
je 0x13b9
movq 0x4c6e(%rip), %rax      # 0x5ff8
movq (%rax), %rdi
movq -0x260(%rbp), %rcx
leaq -0x240(%rbp), %rax
shlq $0x4, %rcx
addq %rcx, %rax
movzwl (%rax), %edx
leaq 0x1f80(%rip), %rsi      # 0x332c
movb $0x0, %al
callq 0x1070
movb $0x0, -0x1(%rbp)
jmp 0x1432
movl -0x254(%rbp), %eax
movq -0x260(%rbp), %rdx
leaq -0x240(%rbp), %rcx
shlq $0x4, %rdx
addq %rdx, %rcx
cmpl 0x4(%rcx), %eax
je 0x1415
movq 0x4c18(%rip), %rax      # 0x5ff8
movq (%rax), %rdi
movq -0x260(%rbp), %rcx
leaq -0x240(%rbp), %rax
shlq $0x4, %rcx
addq %rcx, %rax
movl 0x4(%rax), %edx
movl -0x254(%rbp), %ecx
leaq 0x1f48(%rip), %rsi      # 0x3350
movb $0x0, %al
callq 0x1070
movb $0x0, -0x1(%rbp)
jmp 0x1432
jmp 0x1417
movq -0x260(%rbp), %rax
addq $0x1, %rax
movq %rax, -0x260(%rbp)
jmp 0x133c
movb $0x1, -0x1(%rbp)
movb -0x1(%rbp), %al
andb $0x1, %al
addq $0x270, %rsp            # imm = 0x270
popq %rbp
retq