// File: /workspace/github_c_makefile_star2_O2/tstword[P]MIPSAssemblerC/src/assembler.c
// Function: assemble_psuedo_instruction
int assemble_psuedo_instruction(struct instruction_node *instr) {
    struct opcode_entry *entry = (struct opcode_entry *)instr->mnemonic->attrptr;
    
    int assemble_status = 1; /* Assume instruction is assembled */

    switch(entry - opcode_table) {
        case MNEMONIC_MOVE: {
            struct operand_node *rd = instr->operand_list;
            struct operand_node *rs = instr->operand_list->next;
            write_instruction(CREATE_INSTRUCTION_R(0, 0, rs->value.reg, rd->value.reg, 0, 0x21));
            break;
        }
        case MNEMONIC_LI: {
            struct operand_node *rd = instr->operand_list;
            struct operand_node *imm = instr->operand_list->next;
            uint32_t immediate = imm->value.integer;
            if(((immediate >> 15) & 0x1FFFF) != 0x1FFFF && ((immediate >> 16) & 0xFFFF) != 0x0000) {
                /* 32-bit sign extended or unsigned value */
                write_instruction(CREATE_INSTRUCTION_I(0x0F, 0, 1, (immediate >> 16)));
                write_instruction(CREATE_INSTRUCTION_I(0x0D, 1, rd->value.reg, immediate));
            }
            else if(((immediate >> 16) & 0xFFFF) == 0x0000 && ((immediate >> 15) & 0x1)) {
                /* Cannot sign-extend, must use ORI */
                write_instruction(CREATE_INSTRUCTION_I(0x0D, 0, rd->value.reg, immediate));
            }
            else {
                write_instruction(CREATE_INSTRUCTION_I(0x09, 0, rd->value.reg, immediate));
            }
            break;
        }
        case MNEMONIC_LA: {
            struct operand_node *rd = instr->operand_list;
            struct operand_node *label = instr->operand_list->next;
            /* Check if label has been defined */
            struct symbol_table_entry *sym_entry = get_symbol_table(cfg_assembler->symbol_table, label->identifier);
            if(sym_entry->status == SYMBOL_UNDEFINED) {
                insert_front(sym_entry->instr_list, (void *)instr);
                assemble_status = 0;
            }
            else {
                write_instruction(CREATE_INSTRUCTION_I(0x0F, 0, 1, (sym_entry->offset >> 16)));
                write_instruction(CREATE_INSTRUCTION_I(0x0D, 1, rd->value.reg, sym_entry->offset));
            }   
            break;
        }
        case MNEMONIC_NOT: {
            struct operand_node *rd = instr->operand_list;
            struct operand_node *rs = instr->operand_list->next;
            write_instruction(CREATE_INSTRUCTION_R(0, rs->value.reg, 0, rd->value.reg, 0, 0x27));
            break; 
        }
        case MNEMONIC_BEQZ: {
            struct operand_node *rs = instr->operand_list;
            struct operand_node *label = instr->operand_list->next;
            /* Check if label has been defined */
            struct symbol_table_entry *sym_entry = get_symbol_table(cfg_assembler->symbol_table, label->identifier);
            if(sym_entry->status == SYMBOL_UNDEFINED) {
                insert_front(sym_entry->instr_list, (void *)instr);
                assemble_status = 0;
            }
            else {
                write_instruction(CREATE_INSTRUCTION_I(0x04, rs->value.reg, 0, get_branch_offset(sym_entry)));
            }   
            break;
        }
        case MNEMONIC_BGE: {
            struct operand_node *rs = instr->operand_list;
            struct operand_node *rt = instr->operand_list->next;
            struct operand_node *label = instr->operand_list->next->next;
            int rt_imm = rt->operand & OPERAND_IMMEDIATE;

            /* Check if label has been defined */
            struct symbol_table_entry *sym_entry = get_symbol_table(cfg_assembler->symbol_table, label->identifier);
            if(sym_entry->status == SYMBOL_UNDEFINED) {
                assemble_status = 0;
                insert_front(sym_entry->instr_list, (void *)instr);
            }
            else {
                if(rt_imm)
                    write_instruction(CREATE_INSTRUCTION_I(0x0A, rs->value.reg, 1, rt->value.integer));
                else
                    write_instruction(CREATE_INSTRUCTION_R(0, rs->value.reg, rt->value.reg, 1, 0, 0x2A));
                write_instruction(CREATE_INSTRUCTION_I(0x04, 1, 0, get_branch_offset(sym_entry))); 
            }
            break;
        }
        case MNEMONIC_BLE: {
            struct operand_node *rs = instr->operand_list;
            struct operand_node *rt = instr->operand_list->next;
            struct operand_node *label = instr->operand_list->next->next;
            int rt_imm = rt->operand & OPERAND_IMMEDIATE;

            /* Check if label has been defined */
            struct symbol_table_entry *sym_entry = get_symbol_table(cfg_assembler->symbol_table, label->identifier);
            if(sym_entry->status == SYMBOL_UNDEFINED) {
                assemble_status = 0;
                if(rt_imm) incr_segment_offset(0x4);
                insert_front(sym_entry->instr_list, (void *)instr);
            }
            else {
                if(rt_imm) {
                    write_instruction(CREATE_INSTRUCTION_I(0x08, rs->value.reg, 1, -1));
                    write_instruction(CREATE_INSTRUCTION_I(0x0A, 1, 1, rt->value.integer));
                    write_instruction(CREATE_INSTRUCTION_I(0x05, 1, 0, get_branch_offset(sym_entry)));
                }
                else {
                    write_instruction(CREATE_INSTRUCTION_R(0, rt->value.reg, rs->value.reg, 1, 0, 0x2A));
                    write_instruction(CREATE_INSTRUCTION_I(0x04, 1, 0, get_branch_offset(sym_entry)));
                }
            }
            break;
        }
        case MNEMONIC_BNEZ: {
            struct operand_node *rs = instr->operand_list;
            struct operand_node *label = instr->operand_list->next;
            /* Check if label has been defined */
            struct symbol_table_entry *sym_entry = get_symbol_table(cfg_assembler->symbol_table, label->identifier);
            if(sym_entry->status == SYMBOL_UNDEFINED) {
                insert_front(sym_entry->instr_list, (void *)instr);
                assemble_status = 0;
            }
            else {
                write_instruction(CREATE_INSTRUCTION_I(0x05, rs->value.reg, 0, get_branch_offset(sym_entry)));  
            }
            break;
        }
        case MNEMONIC_BLT: {
            struct operand_node *rs = instr->operand_list;
            struct operand_node *rt = instr->operand_list->next;
            struct operand_node *label = instr->operand_list->next->next;
            int rt_imm = rt->operand & OPERAND_IMMEDIATE;

            /* Check if label has been defined */
            struct symbol_table_entry *sym_entry = get_symbol_table(cfg_assembler->symbol_table, label->identifier);
            if(sym_entry->status == SYMBOL_UNDEFINED) {
                insert_front(sym_entry->instr_list, (void *)instr);
                assemble_status = 0;
            }
            else {
                if(rt_imm)
                    write_instruction(CREATE_INSTRUCTION_I(0x0A, rs->value.reg, 1, rt->value.integer));
                else
                    write_instruction(CREATE_INSTRUCTION_R(0, rs->value.reg, rt->value.reg, 1, 0, 0x2A));
                write_instruction(CREATE_INSTRUCTION_I(0x05, 1, 0, get_branch_offset(sym_entry)));
            }
            break;
        }
        case MNEMONIC_BGT: {
            struct operand_node *rs = instr->operand_list;
            struct operand_node *rt = instr->operand_list->next;
            struct operand_node *label = instr->operand_list->next->next;
            int rt_imm = rt->operand & OPERAND_IMMEDIATE;

            /* Check if label has been defined */
            struct symbol_table_entry *sym_entry = get_symbol_table(cfg_assembler->symbol_table, label->identifier);
            if(sym_entry->status == SYMBOL_UNDEFINED) {
                if(rt_imm) incr_segment_offset(0x4);
                insert_front(sym_entry->instr_list, (void *)instr);
                assemble_status = 0;
            }
            else {
                if(rt_imm) {
                    write_instruction(CREATE_INSTRUCTION_I(0x08, 0, 1, rt->value.integer));
                    write_instruction(CREATE_INSTRUCTION_R(0, 1, rs->value.reg, 1, 0, 0x2A));
                    write_instruction(CREATE_INSTRUCTION_I(0x05, 1, 0, get_branch_offset(sym_entry)));
                }
                else {
                    write_instruction(CREATE_INSTRUCTION_R(0, rt->value.reg, rs->value.reg, 1, 0, 0x2A));
                    write_instruction(CREATE_INSTRUCTION_I(0x05, 1, 0, get_branch_offset(sym_entry))); 
                }
            }
            break;
        }
        /* Apparently, MARS doesn't treat mul as a psuedo-instruction it is a core instruction 
         * I'll leave this here for now until I decide if I want to keep it a psuedo or not */
        case MNEMONIC_MUL: {
            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, 0, 0, 0x18));
            write_instruction(CREATE_INSTRUCTION_R(0, 0, 0, rd->value.reg, 0, 0x12));
            break;
        }
        case MNEMONIC_ABS: {
            struct operand_node *rd = instr->operand_list;
            struct operand_node *rs = instr->operand_list->next;
            write_instruction(CREATE_INSTRUCTION_R(0, 0, rs->value.reg, 1, 31, 0x03));
            write_instruction(CREATE_INSTRUCTION_R(0, 1, rs->value.reg, rd->value.reg, 0, 0x26));
            write_instruction(CREATE_INSTRUCTION_R(0, rd->value.reg, 1, rd->value.reg, 0, 0x23));
            break;
        }
        case MNEMONIC_NEG: {
            struct operand_node *rd = instr->operand_list;
            struct operand_node *rs = instr->operand_list->next;
            write_instruction(CREATE_INSTRUCTION_R(0, 0, rs->value.reg, rd->value.reg, 0, 0x22));
            break;
        }
        case MNEMONIC_ROR: {
            struct operand_node *rd = instr->operand_list;
            struct operand_node *rs = instr->operand_list->next;
            struct operand_node *imm = instr->operand_list->next->next;
            write_instruction(CREATE_INSTRUCTION_R(0, 0, rs->value.reg, 1, 32 - imm->value.integer, 0x00));
            write_instruction(CREATE_INSTRUCTION_R(0, 0, rs->value.reg, rd->value.reg, imm->value.integer, 0x02));
            write_instruction(CREATE_INSTRUCTION_R(0, rd->value.reg, 1, rd->value.reg, 0, 0x25));
            break;
        }
        case MNEMONIC_ROL: {
            struct operand_node *rd = instr->operand_list;
            struct operand_node *rs = instr->operand_list->next;
            struct operand_node *imm = instr->operand_list->next->next;
            write_instruction(CREATE_INSTRUCTION_R(0, 0, rs->value.reg, 1, 32 - imm->value.integer, 0x02));
            write_instruction(CREATE_INSTRUCTION_R(0, 0, rs->value.reg, rd->value.reg, imm->value.integer, 0x00));
            write_instruction(CREATE_INSTRUCTION_R(0, rd->value.reg, 1, rd->value.reg, 0, 0x25));
            break;
        }
        case MNEMONIC_SGT: {
            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, rt->value.reg, rs->value.reg, rd->value.reg, 0, 0x2A));
            break;
        }
        case MNEMONIC_B: {
            struct operand_node *label = instr->operand_list;
            /* Check if label has been defined */
            struct symbol_table_entry *sym_entry = get_symbol_table(cfg_assembler->symbol_table, label->identifier);
            if(sym_entry->status == SYMBOL_UNDEFINED) {
                insert_front(sym_entry->instr_list, (void *)instr);
                assemble_status = 0;
            }
            else {
                write_instruction(CREATE_INSTRUCTION_I(0x01, 0, 0x01, get_branch_offset(sym_entry)));
            }
            break;
        }
        case MNEMONIC_SNE: {
            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, 0x23));
            write_instruction(CREATE_INSTRUCTION_R(0, 0, rd->value.reg, rd->value.reg, 0, 0x2B));
            break;
        }
        case MNEMONIC_BLEU: {
            struct operand_node *rs = instr->operand_list;
            struct operand_node *rt = instr->operand_list->next;
            struct operand_node *label = instr->operand_list->next->next;
            int rt_imm = rt->operand & OPERAND_IMMEDIATE;
            
            /* Check if label has been defined */
            struct symbol_table_entry *sym_entry = get_symbol_table(cfg_assembler->symbol_table, label->identifier);
            if(sym_entry->status == SYMBOL_UNDEFINED) {
                assemble_status = 0;
                if(rt_imm) incr_segment_offset(0x4); /* Immediate operand requires an extra instruction */
                insert_front(sym_entry->instr_list, (void *)instr);
            }
            else {
                if(rt_imm) {
                    write_instruction(CREATE_INSTRUCTION_I(0x08, 0, 1, rt->value.integer));
                    write_instruction(CREATE_INSTRUCTION_R(0, 1, rs->value.reg, 1, 0, 0x2B));
                    write_instruction(CREATE_INSTRUCTION_I(0x04, 1, 0, get_branch_offset(sym_entry))); 
                }
                else {
                    write_instruction(CREATE_INSTRUCTION_R(0, rt->value.reg, rs->value.reg, 1, 0, 0x2B));
                    write_instruction(CREATE_INSTRUCTION_I(0x04, 1, 0, get_branch_offset(sym_entry))); 
                }
            }
            break;
        }
        case MNEMONIC_BGEU: {
            struct operand_node *rs = instr->operand_list;
            struct operand_node *rt = instr->operand_list->next;
            struct operand_node *label = instr->operand_list->next->next;
            int rt_imm = rt->operand & OPERAND_IMMEDIATE;

            /* Check if label has been defined */
            struct symbol_table_entry *sym_entry = get_symbol_table(cfg_assembler->symbol_table, label->identifier);
            if(sym_entry->status == SYMBOL_UNDEFINED) {
                assemble_status = 0;
                insert_front(sym_entry->instr_list, (void *)instr);
            }
            else {
                if(rt_imm)
                    write_instruction(CREATE_INSTRUCTION_I(0x0B, rs->value.reg, 1, rt->value.integer));
                else
                    write_instruction(CREATE_INSTRUCTION_R(0, rs->value.reg, rt->value.reg, 1, 0, 0x2B));
                write_instruction(CREATE_INSTRUCTION_I(0x04, 1, 0, get_branch_offset(sym_entry))); 
            }
            break;
        }
        case MNEMONIC_BLTU: {
            struct operand_node *rs = instr->operand_list;
            struct operand_node *rt = instr->operand_list->next;
            struct operand_node *label = instr->operand_list->next->next;
            int rt_imm = rt->operand & OPERAND_IMMEDIATE;

            /* Check if label has been defined */
            struct symbol_table_entry *sym_entry = get_symbol_table(cfg_assembler->symbol_table, label->identifier);
            if(sym_entry->status == SYMBOL_UNDEFINED) {
                insert_front(sym_entry->instr_list, (void *)instr);
                assemble_status = 0;
            }
            else {
                if(rt_imm)
                    write_instruction(CREATE_INSTRUCTION_I(0x0B, rs->value.reg, 1, rt->value.integer));
                else
                    write_instruction(CREATE_INSTRUCTION_R(0, rs->value.reg, rt->value.reg, 1, 0, 0x2B));
                write_instruction(CREATE_INSTRUCTION_I(0x05, 1, 0, get_branch_offset(sym_entry)));
            }
            break;
        }
        case MNEMONIC_BGTU: {
            struct operand_node *rs = instr->operand_list;
            struct operand_node *rt = instr->operand_list->next;
            struct operand_node *label = instr->operand_list->next->next;
            int rt_imm = rt->operand & OPERAND_IMMEDIATE;

            /* Check if label has been defined */
            struct symbol_table_entry *sym_entry = get_symbol_table(cfg_assembler->symbol_table, label->identifier);
            if(sym_entry->status == SYMBOL_UNDEFINED) {
                if(rt_imm) incr_segment_offset(0x4);
                insert_front(sym_entry->instr_list, (void *)instr);
                assemble_status = 0;
            }
            else {
                if(rt_imm) {
                    write_instruction(CREATE_INSTRUCTION_I(0x08, 0, 1, rt->value.integer));
                    write_instruction(CREATE_INSTRUCTION_R(0, 1, rs->value.reg, 1, 0, 0x2B));
                    write_instruction(CREATE_INSTRUCTION_I(0x05, 1, 0, get_branch_offset(sym_entry)));
                }
                else {
                    write_instruction(CREATE_INSTRUCTION_R(0, rt->value.reg, rs->value.reg, 1, 0, 0x2B));
                    write_instruction(CREATE_INSTRUCTION_I(0x05, 1, 0, get_branch_offset(sym_entry))); 
                }
            }
            break;
        }
    }

    if(!assemble_status) incr_segment_offset(entry->size);

    return assemble_status;
}

// Assembly:
pushq %rbp
pushq %r15
pushq %r14
pushq %r13
pushq %r12
pushq %rbx
pushq %rax
movq (%rdi), %rax
movq 0x10(%rax), %r12
movq %r12, %rax
subq 0x7211(%rip), %rax      # 0xafb8
sarq $0x3, %rax
pushq $0x1
popq %rbp
addq $-0x29, %rax
cmpq $0x27, %rax
ja 0x46b5
movq %rdi, %r15
leaq 0x329a(%rip), %rcx      # 0x7060
movslq (%rcx,%rax,4), %rax
addq %rcx, %rax
jmpq *%rax
movq 0x8(%r15), %rax
movq 0x10(%rax), %rcx
movzbl 0xd(%rcx), %ecx
andl $0x1f, %ecx
shll $0x10, %ecx
movzbl 0xd(%rax), %eax
andl $0x1f, %eax
shll $0xb, %eax
leal (%rax,%rcx), %edi
addl $0x21, %edi
jmp 0x46b0
movq 0x8(%r15), %r13
movq 0x10(%r13), %rbp
movq 0x10(%rbp), %rax
movb (%rbp), %bl
movq 0x87ac(%rip), %rcx      # 0xc5b8
movq 0x10(%rcx), %rdi
movq 0x8(%rax), %rsi
callq 0x5c1a
movq %rax, %r14
cmpb $0x0, 0x8(%rax)
je 0x436e
testb $0x2, %bl
jne 0x4531
movzbl 0xd(%rbp), %eax
andl $0x1f, %eax
shll $0x15, %eax
movzbl 0xd(%r13), %ecx
andl $0x1f, %ecx
shll $0x10, %ecx
leal (%rcx,%rax), %edi
addl $0x82b, %edi            # imm = 0x82B
jmp 0x4551
movq 0x8(%r15), %r13
movq 0x10(%r13), %rbp
movq 0x10(%rbp), %rax
movb (%rbp), %bl
movq 0x8750(%rip), %rcx      # 0xc5b8
movq 0x10(%rcx), %rdi
movq 0x8(%rax), %rsi
callq 0x5c1a
movq %rax, %r14
cmpb $0x0, 0x8(%rax)
je 0x436e
testb $0x2, %bl
jne 0x457f
movzbl 0xd(%rbp), %eax
andl $0x1f, %eax
shll $0x15, %eax
movzbl 0xd(%r13), %ecx
andl $0x1f, %ecx
shll $0x10, %ecx
leal (%rcx,%rax), %edi
addl $0x82b, %edi            # imm = 0x82B
jmp 0x4634
movq 0x8(%r15), %r14
movq 0x10(%r14), %rbx
movq 0x10(%rbx), %r15
movzbl 0xd(%rbx), %eax
andl $0x1f, %eax
xorl %ecx, %ecx
subl 0x8(%r15), %ecx
shll $0x10, %eax
andl $0x1f, %ecx
shll $0x6, %ecx
leal (%rax,%rcx), %edi
addl $0x800, %edi            # imm = 0x800
callq 0x35e0
movzbl 0xd(%rbx), %eax
andl $0x1f, %eax
shll $0x10, %eax
movzbl 0xd(%r14), %ecx
andl $0x1f, %ecx
shll $0xb, %ecx
orl %eax, %ecx
movl 0x8(%r15), %eax
andl $0x1f, %eax
shll $0x6, %eax
leal (%rax,%rcx), %edi
addl $0x2, %edi
jmp 0x423a
movq 0x8(%r15), %rbx
movq 0x10(%rbx), %rax
movq 0x10(%rax), %rcx
movzbl 0xd(%rax), %eax
andl $0x1f, %eax
shll $0x15, %eax
movzbl 0xd(%rcx), %ecx
andl $0x1f, %ecx
shll $0x10, %ecx
leal (%rcx,%rax), %edi
addl $0x18, %edi
callq 0x35e0
movzbl 0xd(%rbx), %edi
andl $0x1f, %edi
shll $0xb, %edi
orl $0x12, %edi
jmp 0x46b0
movq 0x8(%r15), %rax
movq 0x10(%rax), %rcx
movzbl 0xd(%rcx), %ecx
andl $0x1f, %ecx
shll $0x10, %ecx
movzbl 0xd(%rax), %eax
andl $0x1f, %eax
shll $0xb, %eax
leal (%rax,%rcx), %edi
addl $0x22, %edi
jmp 0x46b0
movl %ebp, %ebx
movq 0x8(%r15), %rbp
movq 0x10(%rbp), %r13
movq 0x10(%r13), %rax
movb (%r13), %cl
movb %cl, 0x7(%rsp)
movq 0x862d(%rip), %rcx      # 0xc5b8
movq 0x10(%rcx), %rdi
movq 0x8(%rax), %rsi
callq 0x5c1a
movq %rax, %r14
cmpb $0x0, 0x8(%rax)
je 0x44e2
movzbl 0xd(%rbp), %eax
andl $0x1f, %eax
shll $0x15, %eax
testb $0x2, 0x7(%rsp)
jne 0x45a4
movzbl 0xd(%r13), %edi
andl $0x1f, %edi
shll $0x10, %edi
orl %eax, %edi
orl $0x82b, %edi            # imm = 0x82B
jmp 0x45c2
movq 0x8(%r15), %r13
movq 0x10(%r13), %rax
movq 0x85d7(%rip), %rcx      # 0xc5b8
movq 0x10(%rcx), %rdi
movq 0x8(%rax), %rsi
callq 0x5c1a
movq %rax, %r14
cmpb $0x0, 0x8(%rax)
je 0x44e2
movzwl 0xe(%r14), %edi
orl $0x3c010000, %edi       # imm = 0x3C010000
callq 0x35e0
movzbl 0xd(%r13), %eax
andl $0x1f, %eax
shll $0x10, %eax
movzwl 0xc(%r14), %ecx
jmp 0x4523
movl %ebp, %ebx
movq 0x8(%r15), %rbp
movq 0x10(%rbp), %r13
movq 0x10(%r13), %rax
movb (%r13), %cl
movb %cl, 0x7(%rsp)
movq 0x857b(%rip), %rcx      # 0xc5b8
movq 0x10(%rcx), %rdi
movq 0x8(%rax), %rsi
callq 0x5c1a
movq %rax, %r14
cmpb $0x0, 0x8(%rax)
je 0x44e2
movzbl 0xd(%rbp), %eax
andl $0x1f, %eax
shll $0x15, %eax
testb $0x2, 0x7(%rsp)
jne 0x45b4
movzbl 0xd(%r13), %edi
andl $0x1f, %edi
shll $0x10, %edi
orl %eax, %edi
orl $0x82a, %edi            # imm = 0x82A
jmp 0x45c2
movq 0x8(%r15), %rbx
movq 0x10(%rbx), %r14
movzbl 0xd(%r14), %edi
andl $0x1f, %edi
shll $0x10, %edi
orl $0xfc3, %edi            # imm = 0xFC3
callq 0x35e0
movzbl 0xd(%r14), %eax
andl $0x1f, %eax
shll $0x10, %eax
movzbl 0xd(%rbx), %ecx
andl $0x1f, %ecx
shll $0xb, %ecx
leal (%rcx,%rax), %edi
addl $0x200026, %edi         # imm = 0x200026
callq 0x35e0
movzbl 0xd(%rbx), %eax
andl $0x1f, %eax
imull $0x200800, %eax, %edi   # imm = 0x200800
addl $0x10023, %edi          # imm = 0x10023
jmp 0x46b0
movq 0x8(%r15), %r15
movq 0x10(%r15), %rax
movl 0x8(%rax), %r14d
leal 0x8000(%r14), %eax
cmpl $0x18000, %eax          # imm = 0x18000
jae 0x4503
movl %r14d, %ecx
andl $0xffff8000, %ecx       # imm = 0xFFFF8000
movzbl 0xd(%r15), %eax
andl $0x1f, %eax
shll $0x10, %eax
cmpl $0x8000, %ecx           # imm = 0x8000
jne 0x46c6
leal (%rax,%r14), %edi
addl $0x34000000, %edi       # imm = 0x34000000
jmp 0x46b0
movq 0x8(%r15), %rbp
movq 0x10(%rbp), %r13
movq 0x10(%r13), %rax
movb (%r13), %bl
movq 0x8477(%rip), %rcx      # 0xc5b8
movq 0x10(%rcx), %rdi
movq 0x8(%rax), %rsi
callq 0x5c1a
movq %rax, %r14
cmpb $0x0, 0x8(%rax)
je 0x436e
testb $0x2, %bl
jne 0x45f2
movzbl 0xd(%r13), %eax
andl $0x1f, %eax
shll $0x15, %eax
movzbl 0xd(%rbp), %ecx
andl $0x1f, %ecx
shll $0x10, %ecx
leal (%rcx,%rax), %edi
addl $0x82a, %edi            # imm = 0x82A
jmp 0x4551
movq 0x8(%r15), %rbx
movq 0x10(%rbx), %rax
movq 0x8422(%rip), %rcx      # 0xc5b8
movq 0x10(%rcx), %rdi
movq 0x8(%rax), %rsi
callq 0x5c1a
movq %rax, %r14
cmpb $0x0, 0x8(%rax)
je 0x44e2
movzbl 0xd(%rbx), %eax
andl $0x1f, %eax
shll $0x15, %eax
movl 0xc(%r14), %ecx
movq 0x83f3(%rip), %rdx      # 0xc5b8
movzbl 0x45(%rdx), %esi
subl 0x48(%rdx,%rsi,4), %ecx
addl $0x3fffc, %ecx          # imm = 0x3FFFC
shrl $0x2, %ecx
movzwl %cx, %ecx
leal (%rcx,%rax), %edi
addl $0x14000000, %edi       # imm = 0x14000000
jmp 0x46b0
movq 0x8(%r15), %r14
movq 0x10(%r14), %rbx
movq 0x10(%rbx), %r15
movzbl 0xd(%rbx), %eax
andl $0x1f, %eax
xorl %ecx, %ecx
subl 0x8(%r15), %ecx
shll $0x10, %eax
andl $0x1f, %ecx
shll $0x6, %ecx
leal (%rax,%rcx), %edi
addl $0x802, %edi            # imm = 0x802
callq 0x35e0
movzbl 0xd(%rbx), %eax
andl $0x1f, %eax
shll $0x10, %eax
movzbl 0xd(%r14), %ecx
andl $0x1f, %ecx
shll $0xb, %ecx
orl %eax, %ecx
movl 0x8(%r15), %edi
andl $0x1f, %edi
shll $0x6, %edi
orl %ecx, %edi
callq 0x35e0
movzbl 0xd(%r14), %eax
andl $0x1f, %eax
imull $0x200800, %eax, %edi   # imm = 0x200800
addl $0x10025, %edi          # imm = 0x10025
jmp 0x46b0
movq 0x8(%r15), %rax
movq 0x10(%rax), %rcx
movq 0x10(%rcx), %rdx
movzbl 0xd(%rdx), %edx
andl $0x1f, %edx
shll $0x15, %edx
movzbl 0xd(%rcx), %ecx
andl $0x1f, %ecx
shll $0x10, %ecx
orl %edx, %ecx
movzbl 0xd(%rax), %eax
andl $0x1f, %eax
shll $0xb, %eax
leal (%rax,%rcx), %edi
addl $0x2a, %edi
jmp 0x46b0
movq 0x8(%r15), %rax
movq 0x10(%rax), %rcx
movzbl 0xd(%rcx), %ecx
andl $0x1f, %ecx
shll $0x15, %ecx
movzbl 0xd(%rax), %eax
andl $0x1f, %eax
shll $0xb, %eax
leal (%rax,%rcx), %edi
addl $0x27, %edi
jmp 0x46b0
movq 0x8(%r15), %rbx
movq 0x10(%rbx), %rax
movq 0x82f3(%rip), %rcx      # 0xc5b8
movq 0x10(%rcx), %rdi
movq 0x8(%rax), %rsi
callq 0x5c1a
movq %rax, %r14
cmpb $0x0, 0x8(%rax)
je 0x44e2
movzbl 0xd(%rbx), %eax
andl $0x1f, %eax
shll $0x15, %eax
movl 0xc(%r14), %ecx
movq 0x82c4(%rip), %rdx      # 0xc5b8
movzbl 0x45(%rdx), %esi
subl 0x48(%rdx,%rsi,4), %ecx
addl $0x3fffc, %ecx          # imm = 0x3FFFC
shrl $0x2, %ecx
movzwl %cx, %ecx
leal (%rcx,%rax), %edi
addl $0x10000000, %edi       # imm = 0x10000000
jmp 0x46b0
movq 0x8(%r15), %r13
movq 0x10(%r13), %rbp
movq 0x10(%rbp), %rax
movb (%rbp), %bl
movq 0x828c(%rip), %rcx      # 0xc5b8
movq 0x10(%rcx), %rdi
movq 0x8(%rax), %rsi
callq 0x5c1a
movq %rax, %r14
cmpb $0x0, 0x8(%rax)
je 0x436e
testb $0x2, %bl
jne 0x4614
movzbl 0xd(%rbp), %eax
andl $0x1f, %eax
shll $0x15, %eax
movzbl 0xd(%r13), %ecx
andl $0x1f, %ecx
shll $0x10, %ecx
leal (%rcx,%rax), %edi
addl $0x82a, %edi            # imm = 0x82A
jmp 0x4634
testb $0x2, %bl
je 0x44e2
pushq $0x4
popq %rdi
callq 0x3411
jmp 0x44e2
movl %ebp, %ebx
movq 0x8(%r15), %rbp
movq 0x10(%rbp), %r13
movq 0x10(%r13), %rax
movb (%r13), %cl
movb %cl, 0x7(%rsp)
movq 0x8217(%rip), %rcx      # 0xc5b8
movq 0x10(%rcx), %rdi
movq 0x8(%rax), %rsi
callq 0x5c1a
movq %rax, %r14
cmpb $0x0, 0x8(%rax)
je 0x44e2
movzbl 0xd(%rbp), %eax
andl $0x1f, %eax
shll $0x15, %eax
testb $0x2, 0x7(%rsp)
jne 0x4667
movzbl 0xd(%r13), %edi
andl $0x1f, %edi
shll $0x10, %edi
orl %eax, %edi
orl $0x82a, %edi            # imm = 0x82A
jmp 0x4685
movq 0x8(%r15), %rbx
movq 0x10(%rbx), %rax
movq 0x10(%rax), %rcx
movzbl 0xd(%rax), %eax
andl $0x1f, %eax
shll $0x15, %eax
movzbl 0xd(%rcx), %ecx
andl $0x1f, %ecx
shll $0x10, %ecx
orl %eax, %ecx
movzbl 0xd(%rbx), %eax
andl $0x1f, %eax
shll $0xb, %eax
leal (%rax,%rcx), %edi
addl $0x23, %edi
callq 0x35e0
movzbl 0xd(%rbx), %eax
andl $0x1f, %eax
imull $0x10800, %eax, %edi    # imm = 0x10800
orl $0x2b, %edi
jmp 0x46b0
movq 0x8(%r15), %rax
movq 0x8179(%rip), %rcx      # 0xc5b8
movq 0x10(%rcx), %rdi
movq 0x8(%rax), %rsi
callq 0x5c1a
movq %rax, %r14
cmpb $0x0, 0x8(%rax)
je 0x44e2
movl 0xc(%r14), %eax
movq 0x8154(%rip), %rcx      # 0xc5b8
movzbl 0x45(%rcx), %edx
subl 0x48(%rcx,%rdx,4), %eax
addl $0x3fffc, %eax          # imm = 0x3FFFC
shrl $0x2, %eax
movzwl %ax, %edi
orl $0x4010000, %edi        # imm = 0x4010000
jmp 0x46b0
movl %ebp, %ebx
movq 0x8(%r15), %rbp
movq 0x10(%rbp), %r13
movq 0x10(%r13), %rax
movb (%r13), %cl
movb %cl, 0x7(%rsp)
movq 0x8119(%rip), %rcx      # 0xc5b8
movq 0x10(%rcx), %rdi
movq 0x8(%rax), %rsi
callq 0x5c1a
movq %rax, %r14
cmpb $0x0, 0x8(%rax)
je 0x44e2
movzbl 0xd(%rbp), %eax
andl $0x1f, %eax
shll $0x15, %eax
testb $0x2, 0x7(%rsp)
jne 0x4677
movzbl 0xd(%r13), %edi
andl $0x1f, %edi
shll $0x10, %edi
orl %eax, %edi
orl $0x82b, %edi            # imm = 0x82B
jmp 0x4685
movq 0x18(%r14), %rdi
movq %r15, %rsi
callq 0x547b
movzbl 0x7(%r12), %edi
andl $0x7f, %edi
callq 0x3411
xorl %ebp, %ebp
jmp 0x46b5
movl %r14d, %edi
shrl $0x10, %edi
orl $0x3c010000, %edi       # imm = 0x3C010000
callq 0x35e0
movzbl 0xd(%r15), %eax
andl $0x1f, %eax
shll $0x10, %eax
movzwl %r14w, %ecx
leal (%rax,%rcx), %edi
addl $0x34200000, %edi       # imm = 0x34200000
jmp 0x46b0
movzwl 0x8(%rbp), %edi
orl $0x20010000, %edi       # imm = 0x20010000
callq 0x35e0
movzbl 0xd(%r13), %edi
andl $0x1f, %edi
shll $0x10, %edi
orl $0x20082b, %edi         # imm = 0x20082B
callq 0x35e0
movl 0xc(%r14), %eax
movq 0x8057(%rip), %rcx      # 0xc5b8
movzbl 0x45(%rcx), %edx
subl 0x48(%rcx,%rdx,4), %eax
addl $0x3fffc, %eax          # imm = 0x3FFFC
shrl $0x2, %eax
movzwl %ax, %edi
orl $0x10200000, %edi       # imm = 0x10200000
jmp 0x465d
movzwl 0x8(%rbp), %edi
orl $0x20010000, %edi       # imm = 0x20010000
callq 0x35e0
movzbl 0xd(%r13), %edi
andl $0x1f, %edi
shll $0x10, %edi
orl $0x20082b, %edi         # imm = 0x20082B
jmp 0x4634
movzwl 0x8(%r13), %ecx
leal (%rax,%rcx), %edi
addl $0x2c010000, %edi       # imm = 0x2C010000
jmp 0x45c2
movzwl 0x8(%r13), %ecx
leal (%rax,%rcx), %edi
addl $0x28010000, %edi       # imm = 0x28010000
movl %ebx, %ebp
callq 0x35e0
movl 0xc(%r14), %eax
movq 0x7fe4(%rip), %rcx      # 0xc5b8
movzbl 0x45(%rcx), %edx
subl 0x48(%rcx,%rdx,4), %eax
addl $0x3fffc, %eax          # imm = 0x3FFFC
shrl $0x2, %eax
movzwl %ax, %edi
orl $0x10200000, %edi       # imm = 0x10200000
jmp 0x46b0
movzbl 0xd(%rbp), %edi
andl $0x1f, %edi
shll $0x15, %edi
orl $0x2001ffff, %edi       # imm = 0x2001FFFF
callq 0x35e0
movzwl 0x8(%r13), %edi
orl $0x28210000, %edi       # imm = 0x28210000
jmp 0x4634
movzwl 0x8(%rbp), %edi
orl $0x20010000, %edi       # imm = 0x20010000
callq 0x35e0
movzbl 0xd(%r13), %edi
andl $0x1f, %edi
shll $0x10, %edi
orl $0x20082a, %edi         # imm = 0x20082A
callq 0x35e0
movl 0xc(%r14), %eax
movq 0x7f74(%rip), %rcx      # 0xc5b8
movzbl 0x45(%rcx), %edx
subl 0x48(%rcx,%rdx,4), %eax
addl $0x3fffc, %eax          # imm = 0x3FFFC
shrl $0x2, %eax
movzwl %ax, %edi
orl $0x14200000, %edi       # imm = 0x14200000
callq 0x35e0
pushq $0x1
popq %rbp
jmp 0x46b5
movzwl 0x8(%r13), %ecx
leal (%rax,%rcx), %edi
addl $0x28010000, %edi       # imm = 0x28010000
jmp 0x4685
movzwl 0x8(%r13), %ecx
leal (%rax,%rcx), %edi
addl $0x2c010000, %edi       # imm = 0x2C010000
movl %ebx, %ebp
callq 0x35e0
movl 0xc(%r14), %eax
movq 0x7f21(%rip), %rcx      # 0xc5b8
movzbl 0x45(%rcx), %edx
subl 0x48(%rcx,%rdx,4), %eax
addl $0x3fffc, %eax          # imm = 0x3FFFC
shrl $0x2, %eax
movzwl %ax, %edi
orl $0x14200000, %edi       # imm = 0x14200000
callq 0x35e0
movl %ebp, %eax
addq $0x8, %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq
movzwl %r14w, %ecx
leal (%rax,%rcx), %edi
addl $0x24000000, %edi       # imm = 0x24000000
jmp 0x46b0