// File: /workspace/github_c_makefile_star2_O3/tstword[P]MIPSAssemblerC/src/assembler.c
// Function: assemble_funct_instruction
int assemble_funct_instruction(struct instruction_node *instr) {
    struct opcode_entry *entry = (struct opcode_entry *)instr->mnemonic->attrptr;

    switch(entry - opcode_table) {
        case MNEMONIC_ADD:
        case MNEMONIC_ADDU:
        case MNEMONIC_AND:
        case MNEMONIC_NOR:
        case MNEMONIC_OR:
        case MNEMONIC_SLT:
        case MNEMONIC_SLTU:
        case MNEMONIC_SUB:
        case MNEMONIC_SUBU:
        case MNEMONIC_XOR: {
            struct operand_node *rd = instr->operand_list;
            struct operand_node *rs = instr->operand_list->next;
            struct operand_node *rt = instr->operand_list->next->next;
            write_instruction(CREATE_INSTRUCTION_R(0, rs->value.reg, rt->value.reg, rd->value.reg, 0, entry->funct));
            break; 
        }

        case MNEMONIC_JR: {
            struct operand_node *rs = instr->operand_list;
            write_instruction(CREATE_INSTRUCTION_R(0, rs->value.reg, 0, 0, 0, entry->funct));
            break;
        }

        case MNEMONIC_MFHI:
        case MNEMONIC_MFLO: {
            struct operand_node *rd = instr->operand_list;
            write_instruction(CREATE_INSTRUCTION_R(0, 0, 0, rd->value.reg, 0, entry->funct));
            break;
        }

        case MNEMONIC_SLL:
        case MNEMONIC_SRA:
        case MNEMONIC_SRL: {
            struct operand_node *rd = instr->operand_list;
            struct operand_node *rt = instr->operand_list->next;
            struct operand_node *shamt = instr->operand_list->next->next;
            write_instruction(CREATE_INSTRUCTION_R(0, 0, rt->value.reg, rd->value.reg, shamt->value.integer, entry->funct));
            break;
        }

        case MNEMONIC_SYSCALL:
            write_instruction(CREATE_INSTRUCTION_R(0, 0, 0, 0, 0, entry->funct));
            break;

        case MNEMONIC_DIV:
        case MNEMONIC_DIVU:
        case MNEMONIC_MULT:
        case MNEMONIC_MULTU: {
            struct operand_node *rs = instr->operand_list;
            struct operand_node *rt = instr->operand_list->next;
            write_instruction(CREATE_INSTRUCTION_R(0, rs->value.reg, rt->value.reg, 0, 0, entry->funct));
            break;
        }
    }

    /* No branch instructions here, instructions will always be assembled */

    return 1;
}

// Assembly:
movq (%rdi), %rax
movq 0x10(%rax), %rax
movq %rax, %rcx
subq 0x64a1(%rip), %rcx      # 0xafb8
sarq $0x3, %rcx
cmpq $0x18, %rcx
ja 0x4b6a
leaq 0x25d8(%rip), %rdx      # 0x7100
movslq (%rdx,%rcx,4), %rcx
addq %rdx, %rcx
jmpq *%rcx
movq 0x8(%rdi), %rcx
movq 0x10(%rcx), %rdx
movq 0x10(%rdx), %rsi
movzbl 0xd(%rdx), %edx
andl $0x1f, %edx
shll $0x15, %edx
movzbl 0xd(%rsi), %esi
andl $0x1f, %esi
shll $0x10, %esi
orl %edx, %esi
movzbl 0xd(%rcx), %ecx
andl $0x1f, %ecx
shll $0xb, %ecx
orl %esi, %ecx
movzbl 0x1(%rax), %edi
andl $0x3f, %edi
orl %ecx, %edi
jmp 0x4bd4
cmpq $0x38, %rcx
ja 0x4bde
movabsq $0x198000000000000, %rdx # imm = 0x198000000000000
btq %rcx, %rdx
jae 0x4be4
movq 0x8(%rdi), %rcx
movq 0x10(%rcx), %rdx
movzbl 0xd(%rcx), %ecx
andl $0x1f, %ecx
shll $0x15, %ecx
movzbl 0xd(%rdx), %edx
andl $0x1f, %edx
shll $0x10, %edx
jmp 0x4bc9
movq 0x8(%rdi), %rcx
movq 0x10(%rcx), %rdx
movq 0x10(%rdx), %rsi
movzbl 0xd(%rdx), %edx
andl $0x1f, %edx
shll $0x10, %edx
movzbl 0xd(%rcx), %ecx
andl $0x1f, %ecx
shll $0xb, %ecx
orl %edx, %ecx
movl 0x8(%rsi), %edx
andl $0x1f, %edx
shll $0x6, %edx
orl %ecx, %edx
movzbl 0x1(%rax), %edi
andl $0x3f, %edi
orl %edx, %edi
pushq %rax
callq 0x399b
addq $0x8, %rsp
movl $0x1, %eax
retq
movabsq $0x60000000000000, %rdx # imm = 0x60000000000000
btq %rcx, %rdx
jae 0x4bde
movq 0x8(%rdi), %rcx
movzbl 0xd(%rcx), %ecx
andl $0x1f, %ecx
shll $0xb, %ecx
jmp 0x4b5f
movzbl 0x1(%rax), %edi
andl $0x3f, %edi
jmp 0x4bd4
movq 0x8(%rdi), %rcx
movzbl 0xd(%rcx), %ecx
andl $0x1f, %ecx
shll $0x15, %ecx
jmp 0x4b5f