// File: /workspace/github_c_makefile_star2_O0/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
movq %rsp, %rbp
subq $0x40, %rsp
movq $0x0, -0x8(%rbp)
movq 0xb941(%rip), %rax      # 0xf5a8
movl 0x40(%rax), %eax
movq %rax, -0x38(%rbp)
subq $0xa, %rax
ja 0x3f69
movq -0x38(%rbp), %rax
leaq 0x64e1(%rip), %rcx      # 0xa164
movslq (%rcx,%rax,4), %rax
addq %rcx, %rax
jmpq *%rax
movq 0xb915(%rip), %rax      # 0xf5a8
movq (%rax), %rax
movl 0x20(%rax), %eax
movl %eax, -0xc(%rbp)
movl $0x9, %edi
callq 0x3900
movl $0x18, %edi
callq 0x30e0
movq %rax, -0x8(%rbp)
cmpq $0x0, -0x8(%rbp)
jne 0x3cd1
leaq 0x694d(%rip), %rdi      # 0xa60f
callq 0x3120
movl $0x1, %edi
callq 0x3140
movq -0x8(%rbp), %rax
movb $0x4, (%rax)
movq -0x8(%rbp), %rax
movq $0x0, 0x8(%rax)
movl -0xc(%rbp), %eax
movb %al, %cl
movq -0x8(%rbp), %rax
movb %cl, 0xd(%rax)
movq -0x8(%rbp), %rax
movq $0x0, 0x10(%rax)
jmp 0x3fa1
movq 0xb8a0(%rip), %rax      # 0xf5a8
movq (%rax), %rax
movq 0x10(%rax), %rdi
callq 0x71a0
movq %rax, -0x18(%rbp)
movl $0x3, %edi
callq 0x3900
movl $0x18, %edi
callq 0x30e0
movq %rax, -0x8(%rbp)
cmpq $0x0, -0x8(%rbp)
jne 0x3d4d
leaq 0x68d1(%rip), %rdi      # 0xa60f
callq 0x3120
movl $0x1, %edi
callq 0x3140
movq -0x8(%rbp), %rax
movb $0x1, (%rax)
movq -0x18(%rbp), %rcx
movq -0x8(%rbp), %rax
movq %rcx, 0x8(%rax)
movq -0x8(%rbp), %rax
movq $0x0, 0x10(%rax)
jmp 0x3fa1
movq 0xb830(%rip), %rax      # 0xf5a8
movq (%rax), %rax
movq 0x10(%rax), %rdi
callq 0x71a0
movq %rax, -0x20(%rbp)
movl $0xa, %edi
callq 0x3900
movl $0x18, %edi
callq 0x30e0
movq %rax, -0x8(%rbp)
cmpq $0x0, -0x8(%rbp)
jne 0x3dbd
leaq 0x6861(%rip), %rdi      # 0xa60f
callq 0x3120
movl $0x1, %edi
callq 0x3140
movq -0x8(%rbp), %rax
movb $0x10, (%rax)
movq -0x20(%rbp), %rcx
movq -0x8(%rbp), %rax
movq %rcx, 0x8(%rax)
movq -0x8(%rbp), %rax
movq $0x0, 0x10(%rax)
jmp 0x3fa1
movq 0xb7c0(%rip), %rax      # 0xf5a8
movq (%rax), %rax
movl 0x20(%rax), %eax
movl %eax, -0x24(%rbp)
movl $0x4, %edi
callq 0x3900
movl $0x18, %edi
callq 0x30e0
movq %rax, -0x8(%rbp)
cmpq $0x0, -0x8(%rbp)
jne 0x3e26
leaq 0x67f8(%rip), %rdi      # 0xa60f
callq 0x3120
movl $0x1, %edi
callq 0x3140
movq -0x8(%rbp), %rax
movb $0x2, (%rax)
movq -0x8(%rbp), %rax
movq $0x0, 0x8(%rax)
movl -0x24(%rbp), %ecx
movq -0x8(%rbp), %rax
movl %ecx, 0x8(%rax)
movq -0x8(%rbp), %rax
movq $0x0, 0x10(%rax)
movq 0xb752(%rip), %rax      # 0xf5a8
cmpl $0x5, 0x40(%rax)
jne 0x3ea9
movl $0x5, %edi
callq 0x3900
movq 0xb73b(%rip), %rax      # 0xf5a8
movq (%rax), %rax
movl 0x20(%rax), %eax
movl %eax, -0x28(%rbp)
movl $0x9, %edi
callq 0x3900
cmpl $0x0, %eax
je 0x3ea7
movl $0x6, %edi
callq 0x3900
cmpl $0x0, %eax
je 0x3ea7
movq -0x8(%rbp), %rax
movb $0x8, (%rax)
movl -0x28(%rbp), %eax
movb %al, %cl
movq -0x8(%rbp), %rax
movb %cl, 0xd(%rax)
jmp 0x3ea9
jmp 0x3fa1
movl $0x5, %edi
callq 0x3900
movq 0xb6e9(%rip), %rax      # 0xf5a8
movq (%rax), %rax
movl 0x20(%rax), %eax
movl %eax, -0x2c(%rbp)
movl $0x9, %edi
callq 0x3900
cmpl $0x0, %eax
je 0x3f3b
movl $0x6, %edi
callq 0x3900
cmpl $0x0, %eax
je 0x3f3b
movl $0x18, %edi
callq 0x30e0
movq %rax, -0x8(%rbp)
cmpq $0x0, -0x8(%rbp)
jne 0x3f11
leaq 0x670d(%rip), %rdi      # 0xa60f
callq 0x3120
movl $0x1, %edi
callq 0x3140
movq -0x8(%rbp), %rax
movb $0x8, (%rax)
movl -0x2c(%rbp), %eax
movb %al, %cl
movq -0x8(%rbp), %rax
movb %cl, 0xd(%rax)
movq -0x8(%rbp), %rax
movl $0x0, 0x8(%rax)
movq -0x8(%rbp), %rax
movq $0x0, 0x10(%rax)
jmp 0x3fa1
movq 0xb664(%rip), %rax      # 0xf5a8
movq 0x98(%rax), %rsi
movq 0xb656(%rip), %rax      # 0xf5a8
movq 0xa0(%rax), %rdx
leaq 0x66ec(%rip), %rdi      # 0xa64c
movb $0x0, %al
callq 0x3280
jmp 0x3fa1
movq 0xb638(%rip), %rax      # 0xf5a8
movq (%rax), %rax
movq 0x10(%rax), %rsi
movq 0xb62a(%rip), %rax      # 0xf5a8
movq 0x98(%rax), %rdx
movq 0xb61c(%rip), %rax      # 0xf5a8
movq 0xa0(%rax), %rcx
leaq 0x66db(%rip), %rdi      # 0xa675
movb $0x0, %al
callq 0x3280
movq -0x8(%rbp), %rax
addq $0x40, %rsp
popq %rbp
retq
nopl (%rax,%rax)