// File: /workspace/github_cpp_makefile_star2_O2/saumya-prakash[P]AssemblerEmulator/Assembler.cpp
// Function: Assembler::encode_first(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char>> const&, unsigned int const&, unsigned int const&, unsigned int const&)
unsigned Assembler::encode_first(const string& s, const unsigned& opcode, const unsigned& line_no, const unsigned& pc)
{
    istringstream iss(s);

    string t;
    iss>>t;     // 'dump' mnemonic

    string less, more;

    iss>>less;
    if(less.empty())    // no operand - generate too few operands error
    {
        errors.insert({line_no, Error(9)});
        return 0xffffffff;
    }

    t = less;

    iss>>more;
    if(!more.empty())   // more than 1 operand - generate too many operands error
    {
        errors.insert({line_no, Error(6)});
        return 0xffffffff;
    }

    if(valid_number(t)==true)   // a numeric operand - applicable to all mnemonics of one-operand type
    {
        int a = str_to_int(t);

        a = a<<8;
        a = a + opcode;
                                // HOPE CONVERSION DOESN'T POSE ANY PROBLEMS
        unsigned tmp = a;

        return tmp;
    }

    else        // either a label or an invalid operand
    {
        struct label tmp(t, 0);
        if(tmp.name.empty())    // not a label -> so, an invalid operand
        {
            errors.insert({line_no, Error(4)});
            return 0xffffffff;
        }

                        // a label name is there
                        // first check if it is in the symbol table
        map<string, struct label>::iterator st = symtab.find(t);

        if(st==symtab.end())    // label not in symbol table - generate unknown label name error
        {
            errors.insert({line_no, Error(2)});
            return 0xffffffff;
        }

        ++(st->second.use_cnt);

        int offset;     // all one-operand mnemonics can have label as operand as well
        unsigned b;

        switch(opcode)
        {
            case 13:    // call
            case 15:    // brz
            case 16:    // brlz
            case 17:    // br
                    offset = calculate_offset(pc, st->second.addr);

                    b = offset;
                    b = b<<8;
                    b = b + opcode;

                    return b;
                    break;

            default:        // others directly take the address as operand
                        b = st->second.addr;
                        b = b<<8;
                        b = b + opcode;
                        return b;
                        break;
        }
    }
}

// Assembly:
pushq %r15
pushq %r14
pushq %r13
pushq %r12
pushq %rbx
subq $0x280, %rsp            # imm = 0x280
movq %r8, %r12
movq %rcx, %r14
movq %rdx, %r15
movq %rdi, %rbx
leaq 0x100(%rsp), %r13
pushq $0x8
popq %rdx
movq %r13, %rdi
callq 0x2300
leaq 0x40(%rsp), %rax
movq %rax, -0x10(%rax)
andq $0x0, -0x8(%rax)
movb $0x0, (%rax)
leaq 0x30(%rsp), %rsi
movq %r13, %rdi
callq 0x2240
leaq 0xb0(%rsp), %rax
movq %rax, -0x10(%rax)
andq $0x0, -0x8(%rax)
xorl %ecx, %ecx
movb %cl, (%rax)
leaq 0xd0(%rsp), %rax
movq %rax, -0x10(%rax)
andq $0x0, -0x8(%rax)
movb %cl, (%rax)
leaq 0x100(%rsp), %rdi
leaq 0xa0(%rsp), %rsi
callq 0x2240
cmpq $0x0, 0xa8(%rsp)
je 0x4b77
leaq 0x30(%rsp), %rdi
leaq 0xa0(%rsp), %rsi
callq 0x2110
leaq 0x100(%rsp), %rdi
leaq 0xc0(%rsp), %rsi
callq 0x2240
cmpq $0x0, 0xc8(%rsp)
je 0x4c06
leaq 0x8(%rsp), %rdi
pushq $0x6
popq %rsi
callq 0x5ba0
addq $0xc8, %rbx
leaq 0x70(%rsp), %r15
leaq 0x8(%rsp), %rdx
movq %r15, %rdi
movq %r14, %rsi
callq 0x5ce4
movq %rbx, %rdi
movq %r15, %rsi
callq 0x674a
jmp 0x4bab
leaq 0x8(%rsp), %rdi
pushq $0x9
popq %rsi
callq 0x5ba0
addq $0xc8, %rbx
leaq 0x70(%rsp), %r15
leaq 0x8(%rsp), %rdx
movq %r15, %rdi
movq %r14, %rsi
callq 0x5ce4
movq %rbx, %rdi
movq %r15, %rsi
callq 0x674a
leaq 0x78(%rsp), %rdi
callq 0x20e0
leaq 0x8(%rsp), %rdi
callq 0x20e0
pushq $-0x1
popq %rbx
leaq 0xc0(%rsp), %rdi
callq 0x20e0
leaq 0xa0(%rsp), %rdi
callq 0x20e0
leaq 0x30(%rsp), %rdi
callq 0x20e0
leaq 0x100(%rsp), %rdi
callq 0x20f0
movl %ebx, %eax
addq $0x280, %rsp            # imm = 0x280
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
retq
leaq 0x30(%rsp), %rsi
callq 0x31f0
testb %al, %al
je 0x4c28
leaq 0x30(%rsp), %rsi
callq 0x3288
movl %eax, %ebx
shll $0x8, %ebx
addl (%r15), %ebx
jmp 0x4bc2
leaq 0xe0(%rsp), %rdi
leaq 0x30(%rsp), %rsi
callq 0x2280
leaq 0x70(%rsp), %rdi
leaq 0xe0(%rsp), %rsi
xorl %edx, %edx
callq 0x5b6e
leaq 0xe0(%rsp), %rdi
callq 0x20e0
cmpq $0x0, 0x78(%rsp)
je 0x4ca9
leaq 0x30(%rsp), %rsi
movq %rbx, %rdi
callq 0x6d9e
leaq 0x8(%rbx), %rcx
cmpq %rcx, %rax
je 0x4cdf
incl 0x64(%rax)
movl (%r15), %ecx
cmpl $0x11, %ecx
ja 0x4d39
movl $0x3a000, %edx          # imm = 0x3A000
btl %ecx, %edx
jae 0x4d39
movl (%r12), %ebx
notl %ebx
addl 0x60(%rax), %ebx
shll $0x8, %ebx
addl %ecx, %ebx
jmp 0x4d2a
leaq 0x50(%rsp), %rdi
pushq $0x4
popq %rsi
callq 0x5ba0
addq $0xc8, %rbx
leaq 0x8(%rsp), %r15
leaq 0x50(%rsp), %rdx
movq %r15, %rdi
movq %r14, %rsi
callq 0x5ce4
movq %rbx, %rdi
movq %r15, %rsi
callq 0x674a
jmp 0x4d13
leaq 0x50(%rsp), %rdi
pushq $0x2
popq %rsi
callq 0x5ba0
addq $0xc8, %rbx
leaq 0x8(%rsp), %r15
leaq 0x50(%rsp), %rdx
movq %r15, %rdi
movq %r14, %rsi
callq 0x5ce4
movq %rbx, %rdi
movq %r15, %rsi
callq 0x674a
leaq 0x10(%rsp), %rdi
callq 0x20e0
leaq 0x50(%rsp), %rdi
callq 0x20e0
pushq $-0x1
popq %rbx
leaq 0x70(%rsp), %rdi
callq 0x20e0
jmp 0x4bc2
movl 0x60(%rax), %ebx
jmp 0x4c9f
jmp 0x4d45
jmp 0x4d60
movq %rax, %rbx
leaq 0x10(%rsp), %rdi
callq 0x20e0
leaq 0x50(%rsp), %rdi
callq 0x20e0
jmp 0x4d63
jmp 0x4d60
movq %rax, %rbx
leaq 0x70(%rsp), %rdi
jmp 0x4d91
movq %rax, %rbx
leaq 0xe0(%rsp), %rdi
jmp 0x4d91
jmp 0x4d9f
jmp 0x4d9f
jmp 0x4d7f
jmp 0x4d9f
movq %rax, %rbx
leaq 0x78(%rsp), %rdi
callq 0x20e0
leaq 0x8(%rsp), %rdi
callq 0x20e0
jmp 0x4da2
jmp 0x4d9f
movq %rax, %rbx
jmp 0x4dbc
movq %rax, %rbx
leaq 0xc0(%rsp), %rdi
callq 0x20e0
leaq 0xa0(%rsp), %rdi
callq 0x20e0
leaq 0x30(%rsp), %rdi
callq 0x20e0
leaq 0x100(%rsp), %rdi
callq 0x20f0
movq %rbx, %rdi
callq 0x2310