// File: /workspace/github_c_makefile_star2_O2/tstword[P]MIPSAssemblerC/src/assembler.c
// Function: operand_cfg
struct operand_node *operand_cfg() {
    struct operand_node *node = NULL;

    switch(cfg_assembler->lookahead) {
        case TOK_REGISTER: {
            int value = cfg_assembler->tokenizer->attrval;
            match_cfg(TOK_REGISTER);
            
            node = (struct operand_node *)malloc(sizeof(struct operand_node));
            
            if(node == NULL) {
                perror("CRITICAL ERROR: Failed to allocate memory for operand node: ");
                exit(EXIT_FAILURE);
            }
            
            node->operand = OPERAND_REGISTER;
            node->identifier = NULL;
            node->value.reg = value;
            node->next = NULL;
            
            break;
        }
        case TOK_IDENTIFIER: {
            char *id = strdup_wrap(cfg_assembler->tokenizer->lexbuf);
            match_cfg(TOK_IDENTIFIER);
            
            node = (struct operand_node *)malloc(sizeof(struct operand_node));

            if(node == NULL) {
                perror("CRITICAL ERROR: Failed to allocate memory for operand node: ");
                exit(EXIT_FAILURE);
            }

            node->operand = OPERAND_LABEL;
            node->identifier = id;
            node->next = NULL;
            
            break;
        }
        case TOK_STRING: {
            char *id = strdup_wrap(cfg_assembler->tokenizer->lexbuf);
            match_cfg(TOK_STRING);
            
            node = (struct operand_node *)malloc(sizeof(struct operand_node));

            if(node == NULL) {
                perror("CRITICAL ERROR: Failed to allocate memory for operand node: ");
                exit(EXIT_FAILURE);
            }

            node->operand = OPERAND_STRING;
            node->identifier = id;
            node->next = NULL;
            
            break;
        }
        case TOK_INTEGER: {
            int value = cfg_assembler->tokenizer->attrval;
            match_cfg(TOK_INTEGER);
            
            node = (struct operand_node *)malloc(sizeof(struct operand_node));

            if(node == NULL) {
                perror("CRITICAL ERROR: Failed to allocate memory for operand node: ");
                exit(EXIT_FAILURE);
            }

            node->operand = OPERAND_IMMEDIATE;
            node->identifier = NULL;
            node->value.integer = value;
            node->next = NULL;
            
            if(cfg_assembler->lookahead == TOK_LPAREN) {
                match_cfg(TOK_LPAREN);
                int reg_value = cfg_assembler->tokenizer->attrval;
                if(match_cfg(TOK_REGISTER) && match_cfg(TOK_RPAREN)) {
                    node->operand = OPERAND_ADDRESS;
                    node->value.reg = reg_value;
                }
            }
            break;
        }
        case TOK_LPAREN: {
            match_cfg(TOK_LPAREN);
            int reg_value = cfg_assembler->tokenizer->attrval;
            if(match_cfg(TOK_REGISTER) && match_cfg(TOK_RPAREN)) {
                node = (struct operand_node *)malloc(sizeof(struct operand_node));

                if(node == NULL) {
                    perror("CRITICAL ERROR: Failed to allocate memory for operand node: ");
                    exit(EXIT_FAILURE);
                }

                node->operand = OPERAND_ADDRESS;
                node->value.reg = reg_value;
                node->value.integer = 0;
                node->next = NULL;
            }
            break;
        }
        case TOK_EOL:
        case TOK_NULL:
            report_cfg("Expected operand after line %ld, col %ld", cfg_assembler->lineno, cfg_assembler->colno);
            break;
        default:
            report_cfg("Invalid operand '%s' on line %ld, col %ld", cfg_assembler->tokenizer->lexbuf, cfg_assembler->lineno, cfg_assembler->colno);
    }
    
    return node;
}

// Assembly:
pushq %rbp
pushq %r14
pushq %rbx
movq 0x8cbc(%rip), %rax      # 0xc5b8
movl 0x40(%rax), %ecx
cmpq $0xa, %rcx
ja 0x3938
leaq 0x3728(%rip), %rdx      # 0x7034
movslq (%rdx,%rcx,4), %rcx
addq %rdx, %rcx
jmpq *%rcx
movq 0x98(%rax), %rsi
movq 0xa0(%rax), %rdx
leaq 0x3b42(%rip), %rdi      # 0x746c
xorl %ebx, %ebx
xorl %eax, %eax
callq 0x328c
jmp 0x3aca
movq (%rax), %rcx
movq 0x98(%rax), %rdx
movq 0x10(%rcx), %rsi
movq 0xa0(%rax), %rcx
leaq 0x3b41(%rip), %rdi      # 0x7495
xorl %ebx, %ebx
xorl %eax, %eax
callq 0x328c
jmp 0x3aca
movq (%rax), %rax
movl 0x20(%rax), %ebp
pushq $0x9
popq %rdi
callq 0x371d
pushq $0x18
popq %rdi
callq 0x30f0
testq %rax, %rax
je 0x3ad2
movq %rax, %rbx
movb $0x4, (%rax)
xorps %xmm0, %xmm0
movups %xmm0, 0x8(%rax)
movb %bpl, 0xd(%rax)
jmp 0x3aca
movq (%rax), %rax
movq 0x10(%rax), %rdi
callq 0x5469
movq %rax, %r14
pushq $0xa
popq %rdi
callq 0x371d
pushq $0x18
popq %rdi
callq 0x30f0
testq %rax, %rax
je 0x3ad2
movq %rax, %rbx
movb $0x10, (%rax)
jmp 0x39f5
movq (%rax), %rax
movq 0x10(%rax), %rdi
callq 0x5469
movq %rax, %r14
pushq $0x3
popq %rdi
callq 0x371d
pushq $0x18
popq %rdi
callq 0x30f0
testq %rax, %rax
je 0x3ad2
movq %rax, %rbx
movb $0x1, (%rax)
movq %r14, 0x8(%rbx)
andq $0x0, 0x10(%rbx)
jmp 0x3aca
movq (%rax), %rax
movl 0x20(%rax), %ebp
pushq $0x4
popq %rdi
callq 0x371d
pushq $0x18
popq %rdi
callq 0x30f0
testq %rax, %rax
je 0x3ad2
movq %rax, %rbx
movb $0x2, (%rax)
xorps %xmm0, %xmm0
movups %xmm0, 0x8(%rax)
movl %ebp, 0x8(%rax)
movq 0x8b7f(%rip), %rax      # 0xc5b8
cmpl $0x5, 0x40(%rax)
jne 0x3aca
pushq $0x5
popq %rdi
callq 0x371d
movq 0x8b66(%rip), %rax      # 0xc5b8
movq (%rax), %rax
movl 0x20(%rax), %ebp
pushq $0x9
popq %rdi
callq 0x371d
testl %eax, %eax
je 0x3aca
pushq $0x6
popq %rdi
callq 0x371d
testl %eax, %eax
je 0x3aca
movb $0x8, (%rbx)
movb %bpl, 0xd(%rbx)
jmp 0x3aca
pushq $0x5
popq %rdi
callq 0x371d
movq 0x8b30(%rip), %rax      # 0xc5b8
movq (%rax), %rax
movl 0x20(%rax), %ebp
pushq $0x9
popq %rdi
callq 0x371d
testl %eax, %eax
je 0x3ac8
pushq $0x6
popq %rdi
callq 0x371d
testl %eax, %eax
je 0x3ac8
pushq $0x18
popq %rdi
callq 0x30f0
testq %rax, %rax
je 0x3ad2
movq %rax, %rbx
movb $0x8, (%rax)
movb %bpl, 0xd(%rax)
andl $0x0, 0x8(%rax)
andq $0x0, 0x10(%rax)
jmp 0x3aca
xorl %ebx, %ebx
movq %rbx, %rax
popq %rbx
popq %r14
popq %rbp
retq
leaq 0x3956(%rip), %rdi      # 0x742f
callq 0x3130
pushq $0x1
popq %rdi
callq 0x3150