// File: /workspace/github_c_makefile_star2_O2/hobo0xcc[P]rve/src/cpu.c
// Function: ExecCompressedInstr
void ExecCompressedInstr(State *state, uint16_t instr) {
    if (instr == 0) {
        state->excepted = true;
        printf("Compressed Instr Illegal\n");
        state->exception_code = IllegalInstruction;
        return;
    }
    uint8_t opcode = instr & SetNBits(2);

    switch (opcode) {
    case 0x0: {
        uint8_t rd = (instr >> 2) & SetNBits(2);
        int8_t funct3 = (instr >> 13) & SetNBits(3);
        uint8_t f_5_12 = (instr >> 5) & SetNBits(8);

        if (funct3 == 0x0 && f_5_12 != 0) {
            ExecCAddi4spn(state, instr);
            if (state->excepted) return;
            state->pc += 2;
        } else if (funct3 == 0x1) {
            // TODO: Implement c.fld.
            state->pc += 2;
        } else if (funct3 == 0x2) {
            ExecCLw(state, instr);
            if (state->excepted) return;
            state->pc += 2;
        } else if (funct3 == 0x3) {
            ExecCLd(state, instr);
            if (state->excepted) return;
            state->pc += 2;
        } else if (funct3 == 0x5) {
            // TODO: Implement c.fsd.
            state->pc += 2;
        } else if (funct3 == 0x6) {
            ExecCSw(state, instr);
            if (state->excepted) return;
            state->pc += 2;
        } else if (funct3 == 0x7) {
            ExecCSd(state, instr);
            if (state->excepted) return;
            state->pc += 2;
        } else {
            Error("Invalid instruction: funct3=%d", funct3);
        }
    } break;
    case 0x1: {
        uint8_t r1 = (instr >> 7) & SetNBits(3);
        int32_t immediate = Sext(((instr >> 2) & SetNBits(5)) |
                                     ((instr >> 12 & SetNBits(1)) << 5),
                                 5);
        uint8_t funct3 = (instr >> 13) & SetNBits(3);
        uint8_t funct2_1 = (instr >> 10) & SetNBits(2);
        uint8_t funct2_2 = (instr >> 5) & SetNBits(2);
        uint8_t funct6 = (instr >> 10) & SetNBits(6);
        uint8_t rd = instr >> 7 & SetNBits(5);

        if (funct6 == 0x23 && funct2_2 == 0x0) {
            ExecCSub(state, instr);
            if (state->excepted) return;
            state->pc += 2;
        } else if (funct6 == 0x23 && funct2_2 == 0x1) {
            ExecCXor(state, instr);
            if (state->excepted) return;
            state->pc += 2;
        } else if (funct6 == 0x23 && funct2_2 == 0x2) {
            ExecCOr(state, instr);
            if (state->excepted) return;
            state->pc += 2;
        } else if (funct6 == 0x23 && funct2_2 == 0x3) {
            ExecCAnd(state, instr);
            if (state->excepted) return;
            state->pc += 2;
        } else if (funct6 == 0x27 && funct2_2 == 0x0) {
            ExecCSubw(state, instr);
            if (state->excepted) return;
            state->pc += 2;
        } else if (funct6 == 0x27 && funct2_2 == 0x1) {
            ExecCAddw(state, instr);
            if (state->excepted) return;
            state->pc += 2;
        } else if (funct3 == 0x0 && rd == 0) {
            // C.NOP
            state->pc += 2;
        } else if (funct3 == 0x0 && rd != 0x0) {
            ExecCAddi(state, instr);
            if (state->excepted) return;
            state->pc += 2;
        } else if (funct3 == 0x1 && rd != 0x0) {
            ExecCAddiw(state, instr);
            if (state->excepted) return;
            state->pc += 2;
        } else if (funct3 == 0x2) {
            ExecCLi(state, instr);
            if (state->excepted) return;
            state->pc += 2;
        } else if (funct3 == 0x3 && rd == 2) {
            ExecCAddi16sp(state, instr);
            if (state->excepted) return;
            state->pc += 2;
        } else if (funct3 == 0x3) {
            ExecCLui(state, instr);
            if (state->excepted) return;
            state->pc += 2;
        } else if (funct3 == 0x4 && funct2_1 == 0x0) {
            ExecCSrli(state, instr);
            if (state->excepted) return;
            state->pc += 2;
        } else if (funct3 == 0x4 && funct2_1 == 0x1) {
            ExecCSrai(state, instr);
            if (state->excepted) return;
            state->pc += 2;
        } else if (funct3 == 0x4 && funct2_1 == 0x2) {
            ExecCAndi(state, instr);
            if (state->excepted) return;
            state->pc += 2;
        } else if (funct3 == 0x5) {
            ExecCJ(state, instr);
            if (state->excepted) return;
        } else if (funct3 == 0x6) {
            ExecCBeqz(state, instr);
            if (state->excepted) return;
        } else if (funct3 == 0x7) {
            ExecCBnez(state, instr);
            if (state->excepted) return;
        } else {
            Error("Invalid instruction");
        }
    } break;
    case 0x2: {
        uint8_t funct3 = (instr >> 13) & SetNBits(3);
        uint8_t f_7_11 = (instr >> 7) & SetNBits(5);
        uint8_t f_2_6 = (instr >> 2) & SetNBits(5);
        uint8_t f_12 = (instr >> 12) & SetNBits(1);

        if (funct3 == 0x0 && f_12 == 0 && f_2_6 == 0 && f_7_11 != 0) {
            printf("c.slli64\n");
            state->pc += 2;
            // TODO: Understand c.slli64.
        } else if (funct3 == 0x0 && f_7_11 != 0) {
            ExecCSlli(state, instr);
            if (state->excepted) return;
            state->pc += 2;
        } else if (funct3 == 0x1) {
            // TODO: Implement c.fldsp.
        } else if (funct3 == 0x2 && f_7_11 != 0) {
            ExecCLwsp(state, instr);
            if (state->excepted) return;
            state->pc += 2;
        } else if (funct3 == 0x3) {
            ExecCLdsp(state, instr);
            if (state->excepted) return;
            state->pc += 2;
        } else if (funct3 == 0x4 && f_12 == 0 && f_7_11 != 0 && f_2_6 == 0) {
            ExecCJr(state, instr);
            if (state->excepted) return;
        } else if (funct3 == 0x4 && f_12 == 0 && f_7_11 != 0 && f_2_6 != 0) {
            ExecCMv(state, instr);
            if (state->excepted) return;
            state->pc += 2;
        } else if (funct3 == 0x4 && f_12 == 1 && f_7_11 == 0 && f_2_6 == 0) {
            // ExecCEbreak(state, instr);
            state->pc += 2;
        } else if (funct3 == 0x4 && f_12 == 1 && f_7_11 != 0 && f_2_6 == 0) {
            ExecCJalr(state, instr);
            if (state->excepted) return;
        } else if (funct3 == 0x4 && f_12 == 1 && f_7_11 != 0 && f_2_6 != 0) {
            ExecCAdd(state, instr);
            if (state->excepted) return;
            state->pc += 2;
        } else if (funct3 == 0x5) {
            // TODO: Implement c.fsdsp.
            state->pc += 2;
        } else if (funct3 == 0x6) {
            ExecCSwsp(state, instr);
            if (state->excepted) return;
            state->pc += 2;
        } else if (funct3 == 0x7) {
            ExecCSdsp(state, instr);
            if (state->excepted) return;
            state->pc += 2;
        } else {
            Error("Invalid instruction");
        }
    } break;
    }
}

// Assembly:
pushq %rbp
movq %rsp, %rbp
pushq %r14
pushq %rbx
movq %rdi, %rbx
testl %esi, %esi
je 0x4792
movl %esi, %eax
movzwl %ax, %esi
movl %esi, %ecx
andl $0x3, %ecx
leaq 0x29da(%rip), %rdx      # 0x7140
movslq (%rdx,%rcx,4), %rcx
addq %rdx, %rcx
jmpq *%rcx
cmpw $0x2000, %ax            # imm = 0x2000
setae %cl
testw $0x1fe0, %ax            # imm = 0x1FE0
sete %dl
orb %cl, %dl
jne 0x4839
movq %rbx, %rdi
callq 0x4000
jmp 0x49ff
movb $0x1, 0x8138(%rbx)
leaq 0x2d8b(%rip), %rdi      # 0x752b
callq 0x1060
movq $0x2, 0x8140(%rbx)
jmp 0x4a0c
movl %eax, %ecx
shrl $0xa, %ecx
movl %eax, %edx
shrl $0x5, %edx
andl $0x3, %edx
movl %ecx, %r8d
xorl $0x23, %r8d
movl %r8d, %edi
orl %edx, %edi
jne 0x481f
movq %rbx, %rdi
callq 0x4490
jmp 0x49ff
movl %eax, %edi
shrl $0x7, %edi
movl %eax, %r10d
shrl $0x2, %r10d
movl %r10d, %ecx
andl $0x1f, %ecx
movl %eax, %edx
shrl $0xc, %edx
andl $0x1, %edx
movl %edi, %r9d
andl $0x1f, %r9d
je 0x4867
cmpw $0x1fff, %ax            # imm = 0x1FFF
ja 0x4867
movl %edx, %r8d
orl %ecx, %r8d
jne 0x4867
leaq 0x2d0d(%rip), %rdi      # 0x7522
callq 0x1060
jmp 0x4a08
movl %edx, %edi
xorl $0x1, %edi
movl %r8d, %r9d
orl %edi, %r9d
jne 0x4888
movq %rbx, %rdi
callq 0x44b3
jmp 0x49ff
movl %eax, %ecx
shrl $0xd, %ecx
leal -0x1(%rcx), %edx
cmpl $0x6, %edx
ja 0x48fb
leaq 0x28ff(%rip), %rdi      # 0x7150
movslq (%rdi,%rdx,4), %rdx
addq %rdi, %rdx
jmpq *%rdx
movq %rbx, %rdi
callq 0x4041
jmp 0x49ff
testl %r9d, %r9d
sete %r8b
cmpw $0x2000, %ax            # imm = 0x2000
setae %r11b
orb %r8b, %r11b
jne 0x48a1
movq %rbx, %rdi
callq 0x459c
jmp 0x49ff
movl %edx, %r9d
xorl $0x2, %r9d
orl %r8d, %r9d
jne 0x48d3
movq %rbx, %rdi
callq 0x44d6
jmp 0x49ff
movl %eax, %r8d
shrl $0xd, %r8d
cmpl $0x1, %r8d
je 0x4a0c
testl %r9d, %r9d
sete %r11b
cmpl $0x2, %r8d
setne %r14b
orb %r11b, %r14b
jne 0x4944
movq %rbx, %rdi
callq 0x45bf
jmp 0x49ff
movl %edx, %r9d
xorl $0x3, %r9d
orl %r9d, %r8d
jne 0x492b
movq %rbx, %rdi
callq 0x44f9
jmp 0x49ff
movq %rbx, %rdi
movl %eax, %esi
callq 0x4128
jmp 0x49ff
leaq 0x2b10(%rip), %rdi      # 0x7412
movl %ecx, %esi
xorl %eax, %eax
popq %rbx
popq %r14
popq %rbp
jmp 0x5ca8
movq %rbx, %rdi
movl %eax, %esi
callq 0x40a2
jmp 0x49ff
movq %rbx, %rdi
callq 0x40ea
jmp 0x49ff
movl %ecx, %r8d
xorl $0x27, %r8d
orl %r8d, %edx
jne 0x4959
movq %rbx, %rdi
callq 0x451c
jmp 0x49ff
cmpl $0x3, %r8d
jne 0x496b
movq %rbx, %rdi
movl %eax, %esi
callq 0x461a
jmp 0x49ff
orl %edi, %r8d
jne 0x499f
movq %rbx, %rdi
callq 0x455c
jmp 0x49ff
testl %r9d, %r9d
setne %r14b
movl %r8d, %r11d
xorl $0x4, %r11d
orl %edx, %r11d
sete %r11b
andb %r14b, %r11b
testl %ecx, %ecx
jne 0x49db
testb %r11b, %r11b
je 0x49db
shrl $0x7, %eax
andl $0x1f, %eax
movq 0x8008(%rbx,%rax,8), %rax
movq %rax, (%rbx)
jmp 0x4a0c
movl %eax, %edx
shrl $0x7, %edx
andl $0x1f, %edx
cmpw $0x2000, %ax            # imm = 0x2000
setae %dil
testl %edx, %edx
setne %r8b
orb %dil, %r8b
je 0x4a08
cmpw $0x2000, %ax            # imm = 0x2000
setae %dil
testl %edx, %edx
sete %r8b
orb %dil, %r8b
jne 0x4a5d
movq %rbx, %rdi
callq 0x4162
jmp 0x49ff
testl %ecx, %ecx
sete %r14b
xorb $0x1, %r11b
orb %r14b, %r11b
jne 0x4a11
movl %ecx, %eax
movq 0x8008(%rbx,%rax,8), %rax
movl %r9d, %ecx
movq %rax, 0x8008(%rbx,%rcx,8)
cmpb $0x0, 0x8138(%rbx)
jne 0x4a0c
addq $0x2, (%rbx)
popq %rbx
popq %r14
popq %rbp
retq
cmpl $0x4, %r8d
sete %r11b
andb %r11b, %dl
cmpb $0x1, %dl
jne 0x4a29
orl %r10d, %edi
andl $0x1f, %edi
je 0x4a08
testl %r9d, %r9d
setne %dil
andb %dl, %dil
testl %ecx, %ecx
jne 0x4a8e
testb %dil, %dil
je 0x4a8e
shrl $0x7, %eax
andl $0x1f, %eax
movq (%rbx), %rcx
addq $0x2, %rcx
movq 0x8008(%rbx,%rax,8), %rax
movq %rax, (%rbx)
movq %rcx, 0x8010(%rbx)
jmp 0x4a0c
shrl $0xd, %eax
testl %edx, %edx
sete %dil
cmpl $0x1, %eax
setne %r8b
orb %dil, %r8b
jne 0x4a7c
movq %rbx, %rdi
callq 0x41b8
jmp 0x49ff
cmpl $0x2, %eax
jne 0x4aa9
movq %rbx, %rdi
callq 0x4206
jmp 0x49ff
testl %ecx, %ecx
sete %cl
xorb $0x1, %dil
orb %cl, %dil
jne 0x4ac2
movq %rbx, %rdi
callq 0x46c0
jmp 0x49ff
movl %eax, %edi
xorl $0x3, %edi
xorl $0x2, %edx
orl %edi, %edx
jne 0x4aea
movq %rbx, %rdi
callq 0x4233
jmp 0x49ff
cmpl $0x7, %r8d
je 0x4b24
cmpl $0x6, %r8d
je 0x4afc
cmpl $0x5, %r8d
je 0x4a08
leaq 0x2952(%rip), %rdi      # 0x7431
xorl %eax, %eax
popq %rbx
popq %r14
popq %rbp
jmp 0x5ca8
cmpl $0x3, %eax
jne 0x4b09
movq %rbx, %rdi
callq 0x427c
jmp 0x49ff
movq %rbx, %rdi
callq 0x46e3
jmp 0x49ff
andl $0x3, %ecx
movl %eax, %edx
xorl $0x4, %edx
movl %edx, %edi
orl %ecx, %edi
jne 0x4b33
movq %rbx, %rdi
callq 0x42db
jmp 0x49ff
movq %rbx, %rdi
movl %eax, %esi
callq 0x4714
jmp 0x49ff
movl %ecx, %edi
xorl $0x1, %edi
orl %edx, %edi
jne 0x4b49
movq %rbx, %rdi
callq 0x4301
jmp 0x49ff
xorl $0x2, %ecx
orl %ecx, %edx
jne 0x4b5d
movq %rbx, %rdi
callq 0x4332
jmp 0x49ff
cmpl $0x7, %eax
je 0x4b88
cmpl $0x6, %eax
je 0x4b7c
cmpl $0x5, %eax
jne 0x4ad8
movq %rbx, %rdi
popq %rbx
popq %r14
popq %rbp
jmp 0x4362
movq %rbx, %rdi
popq %rbx
popq %r14
popq %rbp
jmp 0x43d4
movq %rbx, %rdi
popq %rbx
popq %r14
popq %rbp
jmp 0x4432