// File: /workspace/github_c_makefile_star2_O1/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 0x52be
movzwl %si, %eax
movl %eax, %ecx
andl $0x3, %ecx
leaq 0x2ee4(%rip), %rdx      # 0x8140
movslq (%rdx,%rcx,4), %rcx
addq %rdx, %rcx
jmpq *%rcx
cmpl $0x2000, %eax           # imm = 0x2000
setae %cl
testl $0x1fe0, %esi           # imm = 0x1FE0
sete %dl
orb %cl, %dl
jne 0x5393
movl %esi, %eax
shrl %eax
andl $0x3c0, %eax            # imm = 0x3C0
movl %esi, %ecx
shrl $0x7, %ecx
andl $0x30, %ecx
orl %eax, %ecx
movl %esi, %eax
shrl $0x2, %eax
andl $0x8, %eax
orl %ecx, %eax
movl %esi, %ecx
shrl $0x4, %ecx
andl $0x4, %ecx
orl %eax, %ecx
addq 0x8018(%rbx), %rcx
addl %esi, %esi
andl $0x38, %esi
movq %rcx, 0x8048(%rbx,%rsi)
jmp 0x5512
movb $0x1, 0x8138(%rbx)
leaq 0x325f(%rip), %rdi      # 0x852b
callq 0x1060
movq $0x2, 0x8140(%rbx)
jmp 0x551f
movl %esi, %edx
shrl $0x7, %edx
movl %esi, %ecx
shrl $0x2, %ecx
movl %esi, %edi
shrl $0xa, %edi
movl %esi, %r8d
shrl $0x5, %r8d
andl $0x3, %r8d
movl %edi, %r10d
xorl $0x23, %r10d
movl %r10d, %r9d
orl %r8d, %r9d
jne 0x5369
andl $0x7, %ecx
andl $0xf, %edx
movq 0x8048(%rbx,%rcx,8), %rax
subq %rax, 0x8008(%rbx,%rdx,8)
jmp 0x5512
movl %esi, %ecx
shrl $0x7, %ecx
movl %esi, %r10d
shrl $0x2, %r10d
movl %r10d, %edx
andl $0x1f, %edx
movl %esi, %r8d
shrl $0xc, %r8d
andl $0x1, %r8d
movl %ecx, %edi
andl $0x1f, %edi
je 0x53c3
cmpl $0x1fff, %eax           # imm = 0x1FFF
ja 0x53c3
movl %r8d, %r9d
orl %edx, %r9d
jne 0x53c3
leaq 0x31c3(%rip), %rdi      # 0x8522
callq 0x1060
jmp 0x551b
movl %r8d, %r9d
xorl $0x1, %r9d
movl %r10d, %r11d
orl %r9d, %r11d
jne 0x53eb
andl $0x7, %ecx
andl $0xf, %edx
movq 0x8048(%rbx,%rcx,8), %rax
xorq %rax, 0x8008(%rbx,%rdx,8)
jmp 0x5512
movl %esi, %ecx
shrl $0xd, %ecx
leal -0x1(%rcx), %edx
cmpl $0x6, %edx
ja 0x547d
leaq 0x2da5(%rip), %rdi      # 0x8150
movslq (%rdi,%rdx,4), %rdx
addq %rdi, %rdx
jmpq *%rdx
movq %rbx, %rdi
movl %eax, %esi
callq 0x4b41
jmp 0x5512
testl %edi, %edi
sete %r9b
cmpl $0x2000, %eax           # imm = 0x2000
setae %r11b
orb %r9b, %r11b
jne 0x5412
andl $0x20, %ecx
orl %edx, %ecx
movl %edi, %eax
shlq %cl, 0x8008(%rbx,%rax,8)
jmp 0x5512
movl %r8d, %r11d
xorl $0x2, %r11d
orl %r10d, %r11d
jne 0x5449
andl $0x7, %ecx
andl $0xf, %edx
movq 0x8048(%rbx,%rcx,8), %rax
orq %rax, 0x8008(%rbx,%rdx,8)
jmp 0x5512
movl %esi, %r9d
shrl $0xd, %r9d
cmpl $0x1, %r9d
je 0x551f
testl %edi, %edi
sete %r11b
cmpl $0x2, %r9d
setne %r14b
orb %r11b, %r14b
jne 0x54cb
movq %rbx, %rdi
movl %eax, %esi
callq 0x50b7
jmp 0x5512
movl %r8d, %r11d
xorl $0x3, %r11d
orl %r11d, %r10d
jne 0x54a7
andl $0x7, %ecx
andl $0xf, %edx
movq 0x8048(%rbx,%rcx,8), %rax
andq %rax, 0x8008(%rbx,%rdx,8)
jmp 0x5512
movq %rbx, %rdi
callq 0x4c28
jmp 0x5512
leaq 0x2f8e(%rip), %rdi      # 0x8412
movl %ecx, %esi
xorl %eax, %eax
popq %rbx
popq %r14
popq %rbp
jmp 0x6b70
movq %rbx, %rdi
callq 0x4ba2
jmp 0x5512
movq %rbx, %rdi
movl %eax, %esi
callq 0x4bea
jmp 0x5512
movl %edi, %r10d
xorl $0x27, %r10d
orl %r10d, %r8d
jne 0x54db
andl $0x7, %ecx
andl $0xf, %edx
movq 0x8008(%rbx,%rdx,8), %rax
subq 0x8048(%rbx,%rcx,8), %rax
jmp 0x54f6
cmpl $0x3, %r9d
jne 0x5524
movq %rbx, %rdi
callq 0x5112
jmp 0x5512
orl %r9d, %r10d
jne 0x5557
andl $0x7, %ecx
andl $0xf, %edx
movq 0x8048(%rbx,%rcx,8), %rax
addq 0x8008(%rbx,%rdx,8), %rax
movl %eax, %ecx
cltq
movabsq $-0x100000000, %rsi     # imm = 0xFFFFFFFF00000000
andq %rax, %rsi
orq %rcx, %rsi
movq %rsi, 0x8008(%rbx,%rdx,8)
cmpb $0x0, 0x8138(%rbx)
jne 0x551f
addq $0x2, (%rbx)
popq %rbx
popq %r14
popq %rbp
retq
testl %edi, %edi
setne %r14b
movl %r9d, %r11d
xorl $0x4, %r11d
orl %r8d, %r11d
sete %r11b
andb %r14b, %r11b
testl %edx, %edx
jne 0x559b
testb %r11b, %r11b
je 0x559b
shrl $0x7, %esi
andl $0x1f, %esi
movq 0x8008(%rbx,%rsi,8), %rax
movq %rax, (%rbx)
jmp 0x551f
movl %edx, %r8d
andl $0x1f, %r8d
cmpl $0x2000, %eax           # imm = 0x2000
setae %r9b
testl %r8d, %r8d
setne %r10b
orb %r9b, %r10b
je 0x551b
cmpl $0x2000, %eax           # imm = 0x2000
setae %r9b
testl %r8d, %r8d
sete %r10b
orb %r9b, %r10b
jne 0x5614
movq %rbx, %rdi
movl %eax, %esi
callq 0x4c62
jmp 0x5512
testl %edx, %edx
sete %r14b
xorb $0x1, %r11b
orb %r14b, %r11b
jne 0x55c3
movl %edx, %eax
movq 0x8008(%rbx,%rax,8), %rax
movl %edi, %ecx
movq %rax, 0x8008(%rbx,%rcx,8)
jmp 0x5512
cmpl $0x4, %r9d
sete %r11b
andb %r11b, %r8b
cmpb $0x1, %r8b
jne 0x55e0
orl %r10d, %ecx
andl $0x1f, %ecx
je 0x551b
testl %edi, %edi
setne %cl
andb %r8b, %cl
testl %edx, %edx
jne 0x5658
testb %cl, %cl
je 0x5658
shrl $0x7, %esi
andl $0x1f, %esi
movq (%rbx), %rax
addq $0x2, %rax
movq 0x8008(%rbx,%rsi,8), %rcx
movq %rcx, (%rbx)
movq %rax, 0x8010(%rbx)
jmp 0x551f
shrl $0xd, %esi
testl %r8d, %r8d
sete %r9b
cmpl $0x1, %esi
setne %r10b
orb %r9b, %r10b
jne 0x5639
movq %rbx, %rdi
movl %eax, %esi
callq 0x4cbc
jmp 0x5512
cmpl $0x2, %esi
jne 0x567f
andl $0x20, %edx
andl $0x1f, %ecx
orl %edx, %ecx
leaq -0x40(%rcx), %rax
testl %edx, %edx
cmoveq %rcx, %rax
movl %r8d, %ecx
jmp 0x55b6
testl %edx, %edx
sete %r8b
xorb $0x1, %cl
orb %r8b, %cl
jne 0x569e
movl %edi, %eax
movl %edx, %ecx
movq 0x8008(%rbx,%rcx,8), %rcx
addq %rcx, 0x8008(%rbx,%rax,8)
jmp 0x5512
movl %esi, %r9d
xorl $0x3, %r9d
xorl $0x2, %r8d
orl %r9d, %r8d
jne 0x56c6
movq %rbx, %rdi
movl %eax, %esi
callq 0x4d37
jmp 0x5512
cmpl $0x7, %r9d
je 0x5715
cmpl $0x6, %r9d
je 0x56da
cmpl $0x5, %r9d
je 0x551b
leaq 0x2d76(%rip), %rdi      # 0x8431
xorl %eax, %eax
popq %rbx
popq %r14
popq %rbp
jmp 0x6b70
cmpl $0x3, %esi
jne 0x56e9
movq %rbx, %rdi
movl %eax, %esi
callq 0x4d80
jmp 0x5512
movq %rbx, %rdi
movl %eax, %esi
callq 0x51db
jmp 0x5512
andl $0x3, %edi
movl %esi, %r8d
xorl $0x4, %r8d
movl %r8d, %r9d
orl %edi, %r9d
jne 0x5722
movl %edx, %eax
andl $0x20, %eax
andl $0x1f, %ecx
orl %eax, %ecx
andl $0x7, %edx
shrq %cl, 0x8048(%rbx,%rdx,8)
jmp 0x5512
movq %rbx, %rdi
callq 0x520c
jmp 0x5512
movl %edi, %r9d
xorl $0x1, %r9d
orl %r8d, %r9d
jne 0x5753
movl %edx, %eax
andl $0x20, %eax
andl $0x1f, %ecx
orl %eax, %ecx
andl $0x7, %edx
movl 0x8048(%rbx,%rdx,8), %eax
sarl %cl, %eax
cltq
movq %rax, 0x8048(%rbx,%rdx,8)
jmp 0x5512
xorl $0x2, %edi
orl %edi, %r8d
jne 0x577f
movl %edx, %eax
andl $0x20, %eax
andl $0x1f, %ecx
orl %eax, %ecx
andl $0x7, %edx
leaq -0x40(%rcx), %rsi
testl %eax, %eax
cmoveq %rcx, %rsi
andq %rsi, 0x8048(%rbx,%rdx,8)
jmp 0x5512
cmpl $0x7, %esi
je 0x57ae
cmpl $0x6, %esi
je 0x57a0
cmpl $0x5, %esi
jne 0x56b4
movq %rbx, %rdi
movl %eax, %esi
popq %rbx
popq %r14
popq %rbp
jmp 0x4e66
movq %rbx, %rdi
movl %eax, %esi
popq %rbx
popq %r14
popq %rbp
jmp 0x4ed8
movq %rbx, %rdi
movl %eax, %esi
popq %rbx
popq %r14
popq %rbp
jmp 0x4f2f