// File: /workspace/github_c_makefile_star2_O3/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 0x535d
movzwl %si, %eax
movl %eax, %ecx
andl $0x3, %ecx
leaq 0x2e45(%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 0x5432
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 0x55b1
movb $0x1, 0x8138(%rbx)
leaq 0x31c0(%rip), %rdi      # 0x852b
callq 0x1060
movq $0x2, 0x8140(%rbx)
jmp 0x55be
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 0x5408
andl $0x7, %ecx
andl $0xf, %edx
movq 0x8048(%rbx,%rcx,8), %rax
subq %rax, 0x8008(%rbx,%rdx,8)
jmp 0x55b1
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 0x5462
cmpl $0x1fff, %eax           # imm = 0x1FFF
ja 0x5462
movl %r8d, %r9d
orl %edx, %r9d
jne 0x5462
leaq 0x3124(%rip), %rdi      # 0x8522
callq 0x1060
jmp 0x55ba
movl %r8d, %r9d
xorl $0x1, %r9d
movl %r10d, %r11d
orl %r9d, %r11d
jne 0x548a
andl $0x7, %ecx
andl $0xf, %edx
movq 0x8048(%rbx,%rcx,8), %rax
xorq %rax, 0x8008(%rbx,%rdx,8)
jmp 0x55b1
movl %esi, %ecx
shrl $0xd, %ecx
leal -0x1(%rcx), %edx
cmpl $0x6, %edx
ja 0x551c
leaq 0x2d06(%rip), %rdi      # 0x8150
movslq (%rdi,%rdx,4), %rdx
addq %rdi, %rdx
jmpq *%rdx
movq %rbx, %rdi
movl %eax, %esi
callq 0x4be4
jmp 0x55b1
testl %edi, %edi
sete %r9b
cmpl $0x2000, %eax           # imm = 0x2000
setae %r11b
orb %r9b, %r11b
jne 0x54b1
andl $0x20, %ecx
orl %edx, %ecx
movl %edi, %eax
shlq %cl, 0x8008(%rbx,%rax,8)
jmp 0x55b1
movl %r8d, %r11d
xorl $0x2, %r11d
orl %r10d, %r11d
jne 0x54e8
andl $0x7, %ecx
andl $0xf, %edx
movq 0x8048(%rbx,%rcx,8), %rax
orq %rax, 0x8008(%rbx,%rdx,8)
jmp 0x55b1
movl %esi, %r9d
shrl $0xd, %r9d
cmpl $0x1, %r9d
je 0x55be
testl %edi, %edi
sete %r11b
cmpl $0x2, %r9d
setne %r14b
orb %r11b, %r14b
jne 0x556a
movq %rbx, %rdi
movl %eax, %esi
callq 0x5156
jmp 0x55b1
movl %r8d, %r11d
xorl $0x3, %r11d
orl %r11d, %r10d
jne 0x5546
andl $0x7, %ecx
andl $0xf, %edx
movq 0x8048(%rbx,%rcx,8), %rax
andq %rax, 0x8008(%rbx,%rdx,8)
jmp 0x55b1
movq %rbx, %rdi
callq 0x4ccb
jmp 0x55b1
leaq 0x2eef(%rip), %rdi      # 0x8412
movl %ecx, %esi
xorl %eax, %eax
popq %rbx
popq %r14
popq %rbp
jmp 0x6c10
movq %rbx, %rdi
callq 0x4c45
jmp 0x55b1
movq %rbx, %rdi
movl %eax, %esi
callq 0x4c8d
jmp 0x55b1
movl %edi, %r10d
xorl $0x27, %r10d
orl %r10d, %r8d
jne 0x557a
andl $0x7, %ecx
andl $0xf, %edx
movq 0x8008(%rbx,%rdx,8), %rax
subq 0x8048(%rbx,%rcx,8), %rax
jmp 0x5595
cmpl $0x3, %r9d
jne 0x55c3
movq %rbx, %rdi
callq 0x51b1
jmp 0x55b1
orl %r9d, %r10d
jne 0x55f6
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 0x55be
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 0x563a
testb %r11b, %r11b
je 0x563a
shrl $0x7, %esi
andl $0x1f, %esi
movq 0x8008(%rbx,%rsi,8), %rax
movq %rax, (%rbx)
jmp 0x55be
movl %edx, %r8d
andl $0x1f, %r8d
cmpl $0x2000, %eax           # imm = 0x2000
setae %r9b
testl %r8d, %r8d
setne %r10b
orb %r9b, %r10b
je 0x55ba
cmpl $0x2000, %eax           # imm = 0x2000
setae %r9b
testl %r8d, %r8d
sete %r10b
orb %r9b, %r10b
jne 0x56b3
movq %rbx, %rdi
movl %eax, %esi
callq 0x4d05
jmp 0x55b1
testl %edx, %edx
sete %r14b
xorb $0x1, %r11b
orb %r14b, %r11b
jne 0x5662
movl %edx, %eax
movq 0x8008(%rbx,%rax,8), %rax
movl %edi, %ecx
movq %rax, 0x8008(%rbx,%rcx,8)
jmp 0x55b1
cmpl $0x4, %r9d
sete %r11b
andb %r11b, %r8b
cmpb $0x1, %r8b
jne 0x567f
orl %r10d, %ecx
andl $0x1f, %ecx
je 0x55ba
testl %edi, %edi
setne %cl
andb %r8b, %cl
testl %edx, %edx
jne 0x56f7
testb %cl, %cl
je 0x56f7
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 0x55be
shrl $0xd, %esi
testl %r8d, %r8d
sete %r9b
cmpl $0x1, %esi
setne %r10b
orb %r9b, %r10b
jne 0x56d8
movq %rbx, %rdi
movl %eax, %esi
callq 0x4d5b
jmp 0x55b1
cmpl $0x2, %esi
jne 0x571e
andl $0x20, %edx
andl $0x1f, %ecx
orl %edx, %ecx
leaq -0x40(%rcx), %rax
testl %edx, %edx
cmoveq %rcx, %rax
movl %r8d, %ecx
jmp 0x5655
testl %edx, %edx
sete %r8b
xorb $0x1, %cl
orb %r8b, %cl
jne 0x573d
movl %edi, %eax
movl %edx, %ecx
movq 0x8008(%rbx,%rcx,8), %rcx
addq %rcx, 0x8008(%rbx,%rax,8)
jmp 0x55b1
movl %esi, %r9d
xorl $0x3, %r9d
xorl $0x2, %r8d
orl %r9d, %r8d
jne 0x5765
movq %rbx, %rdi
movl %eax, %esi
callq 0x4dd6
jmp 0x55b1
cmpl $0x7, %r9d
je 0x57b4
cmpl $0x6, %r9d
je 0x5779
cmpl $0x5, %r9d
je 0x55ba
leaq 0x2cd7(%rip), %rdi      # 0x8431
xorl %eax, %eax
popq %rbx
popq %r14
popq %rbp
jmp 0x6c10
cmpl $0x3, %esi
jne 0x5788
movq %rbx, %rdi
movl %eax, %esi
callq 0x4e1f
jmp 0x55b1
movq %rbx, %rdi
movl %eax, %esi
callq 0x527a
jmp 0x55b1
andl $0x3, %edi
movl %esi, %r8d
xorl $0x4, %r8d
movl %r8d, %r9d
orl %edi, %r9d
jne 0x57c1
movl %edx, %eax
andl $0x20, %eax
andl $0x1f, %ecx
orl %eax, %ecx
andl $0x7, %edx
shrq %cl, 0x8048(%rbx,%rdx,8)
jmp 0x55b1
movq %rbx, %rdi
callq 0x52ab
jmp 0x55b1
movl %edi, %r9d
xorl $0x1, %r9d
orl %r8d, %r9d
jne 0x57f2
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 0x55b1
xorl $0x2, %edi
orl %edi, %r8d
jne 0x581e
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 0x55b1
cmpl $0x7, %esi
je 0x584d
cmpl $0x6, %esi
je 0x583f
cmpl $0x5, %esi
jne 0x5753
movq %rbx, %rdi
movl %eax, %esi
popq %rbx
popq %r14
popq %rbp
jmp 0x4f05
movq %rbx, %rdi
movl %eax, %esi
popq %rbx
popq %r14
popq %rbp
jmp 0x4f77
movq %rbx, %rdi
movl %eax, %esi
popq %rbx
popq %r14
popq %rbp
jmp 0x4fce