// File: /workspace/github_c_makefile_star2_O3/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 0x88a0(%rip), %rax      # 0xc5b8
movl 0x40(%rax), %ecx
cmpq $0xa, %rcx
ja 0x3d54
leaq 0x330c(%rip), %rdx      # 0x7034
movslq (%rdx,%rcx,4), %rcx
addq %rdx, %rcx
jmpq *%rcx
movq 0x98(%rax), %rsi
movq 0xa0(%rax), %rdx
leaq 0x3726(%rip), %rdi      # 0x746c
xorl %ebx, %ebx
xorl %eax, %eax
callq 0x365c
jmp 0x3f0d
movq (%rax), %rcx
movq 0x98(%rax), %rdx
movq 0x10(%rcx), %rsi
movq 0xa0(%rax), %rcx
leaq 0x3725(%rip), %rdi      # 0x7495
xorl %ebx, %ebx
xorl %eax, %eax
callq 0x365c
jmp 0x3f0d
movq (%rax), %rax
movl 0x20(%rax), %ebp
movl $0x9, %edi
callq 0x3b21
movl $0x18, %edi
callq 0x30f0
testq %rax, %rax
je 0x3f15
movq %rax, %rbx
movb $0x4, (%rax)
xorps %xmm0, %xmm0
movups %xmm0, 0x8(%rax)
movb %bpl, 0xd(%rax)
jmp 0x3f0d
movq (%rax), %rax
movq 0x10(%rax), %rdi
callq 0x594d
movq %rax, %r14
movl $0xa, %edi
callq 0x3b21
movl $0x18, %edi
callq 0x30f0
testq %rax, %rax
je 0x3f1a
movq %rax, %rbx
movb $0x10, (%rax)
jmp 0x3e1d
movq (%rax), %rax
movq 0x10(%rax), %rdi
callq 0x594d
movq %rax, %r14
movl $0x3, %edi
callq 0x3b21
movl $0x18, %edi
callq 0x30f0
testq %rax, %rax
je 0x3f1f
movq %rax, %rbx
movb $0x1, (%rax)
movq %r14, 0x8(%rbx)
movq $0x0, 0x10(%rbx)
jmp 0x3f0d
movq (%rax), %rax
movl 0x20(%rax), %ebp
movl $0x4, %edi
callq 0x3b21
movl $0x18, %edi
callq 0x30f0
testq %rax, %rax
je 0x3f24
movq %rax, %rbx
movb $0x2, (%rax)
xorps %xmm0, %xmm0
movups %xmm0, 0x8(%rax)
movl %ebp, 0x8(%rax)
movq 0x8750(%rip), %rax      # 0xc5b8
cmpl $0x5, 0x40(%rax)
jne 0x3f0d
movl $0x5, %edi
callq 0x3b21
movq 0x8735(%rip), %rax      # 0xc5b8
movq (%rax), %rax
movl 0x20(%rax), %ebp
movl $0x9, %edi
callq 0x3b21
testl %eax, %eax
je 0x3f0d
movl $0x6, %edi
callq 0x3b21
testl %eax, %eax
je 0x3f0d
movb $0x8, (%rbx)
movb %bpl, 0xd(%rbx)
jmp 0x3f0d
movl $0x5, %edi
callq 0x3b21
movq 0x86f9(%rip), %rax      # 0xc5b8
movq (%rax), %rax
movl 0x20(%rax), %ebp
movl $0x9, %edi
callq 0x3b21
testl %eax, %eax
je 0x3f0b
movl $0x6, %edi
callq 0x3b21
testl %eax, %eax
je 0x3f0b
movl $0x18, %edi
callq 0x30f0
testq %rax, %rax
je 0x3f29
movq %rax, %rbx
movb $0x8, (%rax)
movb %bpl, 0xd(%rax)
movl $0x0, 0x8(%rax)
movq $0x0, 0x10(%rax)
jmp 0x3f0d
xorl %ebx, %ebx
movq %rbx, %rax
popq %rbx
popq %r14
popq %rbp
retq
callq 0x3226
callq 0x31fc
callq 0x3211
callq 0x31e7
callq 0x31d2