// File: /workspace/github_c_makefile_star2_O0/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:
pushq %rbp
movq %rsp, %rbp
subq $0x70, %rsp
movq %rdi, -0x8(%rbp)
movq -0x8(%rbp), %rax
movq (%rax), %rax
movq 0x10(%rax), %rax
movq %rax, -0x10(%rbp)
movq -0x10(%rbp), %rax
leaq 0x873a(%rip), %rcx      # 0xe0d0
subq %rcx, %rax
sarq $0x3, %rax
movq %rax, -0x68(%rbp)
subq $0x38, %rax
ja 0x5b8c
movq -0x68(%rbp), %rax
leaq 0x487a(%rip), %rcx      # 0xa230
movslq (%rcx,%rax,4), %rax
addq %rcx, %rax
jmpq *%rax
movq -0x8(%rbp), %rax
movq 0x8(%rax), %rax
movq %rax, -0x18(%rbp)
movq -0x8(%rbp), %rax
movq 0x8(%rax), %rax
movq 0x10(%rax), %rax
movq %rax, -0x20(%rbp)
movq -0x8(%rbp), %rax
movq 0x8(%rax), %rax
movq 0x10(%rax), %rax
movq 0x10(%rax), %rax
movq %rax, -0x28(%rbp)
movq -0x20(%rbp), %rax
movzbl 0xd(%rax), %edi
andl $0x1f, %edi
shll $0x15, %edi
orl $0x0, %edi
movq -0x28(%rbp), %rax
movzbl 0xd(%rax), %eax
andl $0x1f, %eax
shll $0x10, %eax
orl %eax, %edi
movq -0x18(%rbp), %rax
movzbl 0xd(%rax), %eax
andl $0x1f, %eax
shll $0xb, %eax
orl %eax, %edi
orl $0x0, %edi
movq -0x10(%rbp), %rax
movzbl 0x1(%rax), %eax
andl $0x3f, %eax
orl %eax, %edi
callq 0x37c0
jmp 0x5b8c
movq -0x8(%rbp), %rax
movq 0x8(%rax), %rax
movq %rax, -0x30(%rbp)
movq -0x30(%rbp), %rax
movzbl 0xd(%rax), %edi
andl $0x1f, %edi
shll $0x15, %edi
orl $0x0, %edi
orl $0x0, %edi
orl $0x0, %edi
orl $0x0, %edi
movq -0x10(%rbp), %rax
movzbl 0x1(%rax), %eax
andl $0x3f, %eax
orl %eax, %edi
callq 0x37c0
jmp 0x5b8c
movq -0x8(%rbp), %rax
movq 0x8(%rax), %rax
movq %rax, -0x38(%rbp)
movq -0x38(%rbp), %rax
movzbl 0xd(%rax), %edi
andl $0x1f, %edi
shll $0xb, %edi
orl $0x0, %edi
orl $0x0, %edi
movq -0x10(%rbp), %rax
movzbl 0x1(%rax), %eax
andl $0x3f, %eax
orl %eax, %edi
callq 0x37c0
jmp 0x5b8c
movq -0x8(%rbp), %rax
movq 0x8(%rax), %rax
movq %rax, -0x40(%rbp)
movq -0x8(%rbp), %rax
movq 0x8(%rax), %rax
movq 0x10(%rax), %rax
movq %rax, -0x48(%rbp)
movq -0x8(%rbp), %rax
movq 0x8(%rax), %rax
movq 0x10(%rax), %rax
movq 0x10(%rax), %rax
movq %rax, -0x50(%rbp)
movq -0x48(%rbp), %rax
movzbl 0xd(%rax), %edi
andl $0x1f, %edi
shll $0x10, %edi
orl $0x0, %edi
movq -0x40(%rbp), %rax
movzbl 0xd(%rax), %eax
andl $0x1f, %eax
shll $0xb, %eax
orl %eax, %edi
movq -0x50(%rbp), %rax
movl 0x8(%rax), %eax
andl $0x1f, %eax
shll $0x6, %eax
orl %eax, %edi
movq -0x10(%rbp), %rax
movzbl 0x1(%rax), %eax
andl $0x3f, %eax
orl %eax, %edi
callq 0x37c0
jmp 0x5b8c
movq -0x10(%rbp), %rax
movzbl 0x1(%rax), %edi
andl $0x3f, %edi
orl $0x0, %edi
callq 0x37c0
jmp 0x5b8c
movq -0x8(%rbp), %rax
movq 0x8(%rax), %rax
movq %rax, -0x58(%rbp)
movq -0x8(%rbp), %rax
movq 0x8(%rax), %rax
movq 0x10(%rax), %rax
movq %rax, -0x60(%rbp)
movq -0x58(%rbp), %rax
movzbl 0xd(%rax), %edi
andl $0x1f, %edi
shll $0x15, %edi
orl $0x0, %edi
movq -0x60(%rbp), %rax
movzbl 0xd(%rax), %eax
andl $0x1f, %eax
shll $0x10, %eax
orl %eax, %edi
orl $0x0, %edi
orl $0x0, %edi
movq -0x10(%rbp), %rax
movzbl 0x1(%rax), %eax
andl $0x3f, %eax
orl %eax, %edi
callq 0x37c0
movl $0x1, %eax
addq $0x70, %rsp
popq %rbp
retq
nopw (%rax,%rax)