// File: 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:
subq $0x478, %rsp            # imm = 0x478
movq %rdi, 0x468(%rsp)
movq %rsi, 0x460(%rsp)
movq %rdx, 0x458(%rsp)
movq %rcx, 0x450(%rsp)
movq %r8, 0x448(%rsp)
movq 0x468(%rsp), %rax
movq %rax, 0x88(%rsp)
movq 0x460(%rsp), %rsi
leaq 0x2c8(%rsp), %rdi
movq %rdi, 0x90(%rsp)
movl $0x8, %edx
callq 0x3480
leaq 0x2a8(%rsp), %rdi
movq %rdi, 0x98(%rsp)
callq 0x33e0
movq 0x90(%rsp), %rdi
movq 0x98(%rsp), %rsi
callq 0x33a0
jmp 0x96bd
leaq 0x278(%rsp), %rdi
movq %rdi, 0x80(%rsp)
callq 0x33e0
leaq 0x258(%rsp), %rdi
callq 0x33e0
movq 0x80(%rsp), %rsi
leaq 0x2c8(%rsp), %rdi
callq 0x33a0
jmp 0x96f6
leaq 0x278(%rsp), %rdi
callq 0x3460
testb $0x1, %al
jne 0x970c
jmp 0x9832
movq 0x88(%rsp), %rax
addq $0xc8, %rax
movq %rax, 0x70(%rsp)
movq 0x450(%rsp), %rax
movq %rax, 0x78(%rsp)
leaq 0x210(%rsp), %rdi
movl $0x9, %esi
callq 0xc550
jmp 0x9740
movq 0x78(%rsp), %rsi
leaq 0x230(%rsp), %rdi
leaq 0x210(%rsp), %rdx
callq 0xcb30
jmp 0x975c
movq 0x70(%rsp), %rdi
leaq 0x230(%rsp), %rsi
callq 0xc520
movq %rax, 0x68(%rsp)
jmp 0x9775
movq 0x68(%rsp), %rax
movq %rax, 0x208(%rsp)
leaq 0x230(%rsp), %rdi
callq 0x5cb0
leaq 0x210(%rsp), %rdi
callq 0x5cd0
movl $0xffffffff, 0x474(%rsp) # imm = 0xFFFFFFFF
movl $0x1, 0x204(%rsp)
jmp 0x9e20
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0x2a0(%rsp)
movl %eax, 0x29c(%rsp)
jmp 0x9e7d
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0x2a0(%rsp)
movl %eax, 0x29c(%rsp)
jmp 0x9e63
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0x2a0(%rsp)
movl %eax, 0x29c(%rsp)
jmp 0x9820
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0x2a0(%rsp)
movl %eax, 0x29c(%rsp)
leaq 0x230(%rsp), %rdi
callq 0x5cb0
leaq 0x210(%rsp), %rdi
callq 0x5cd0
jmp 0x9e63
leaq 0x2a8(%rsp), %rdi
leaq 0x278(%rsp), %rsi
callq 0x3040
jmp 0x9849
leaq 0x2c8(%rsp), %rdi
leaq 0x258(%rsp), %rsi
callq 0x33a0
jmp 0x9860
leaq 0x258(%rsp), %rdi
callq 0x3460
testb $0x1, %al
jne 0x9969
movq 0x88(%rsp), %rax
addq $0xc8, %rax
movq %rax, 0x58(%rsp)
movq 0x450(%rsp), %rax
movq %rax, 0x60(%rsp)
leaq 0x1b8(%rsp), %rdi
movl $0x6, %esi
callq 0xc550
jmp 0x98a9
movq 0x60(%rsp), %rsi
leaq 0x1d8(%rsp), %rdi
leaq 0x1b8(%rsp), %rdx
callq 0xcb30
jmp 0x98c5
movq 0x58(%rsp), %rdi
leaq 0x1d8(%rsp), %rsi
callq 0xc520
movq %rax, 0x50(%rsp)
jmp 0x98de
movq 0x50(%rsp), %rax
movq %rax, 0x1b0(%rsp)
leaq 0x1d8(%rsp), %rdi
callq 0x5cb0
leaq 0x1b8(%rsp), %rdi
callq 0x5cd0
movl $0xffffffff, 0x474(%rsp) # imm = 0xFFFFFFFF
movl $0x1, 0x204(%rsp)
jmp 0x9e20
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0x2a0(%rsp)
movl %eax, 0x29c(%rsp)
jmp 0x9957
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0x2a0(%rsp)
movl %eax, 0x29c(%rsp)
leaq 0x1d8(%rsp), %rdi
callq 0x5cb0
leaq 0x1b8(%rsp), %rdi
callq 0x5cd0
jmp 0x9e63
movq 0x88(%rsp), %rdi
leaq 0x2a8(%rsp), %rsi
callq 0x6060
andb $0x1, %al
movzbl %al, %eax
cmpl $0x1, %eax
jne 0x9a03
movq 0x88(%rsp), %rdi
leaq 0x2a8(%rsp), %rsi
callq 0x62b0
movl %eax, 0x4c(%rsp)
jmp 0x99a3
movl 0x4c(%rsp), %eax
movl %eax, 0x1ac(%rsp)
movl 0x1ac(%rsp), %eax
shll $0x8, %eax
movl %eax, 0x1ac(%rsp)
movl 0x1ac(%rsp), %eax
movq 0x458(%rsp), %rcx
addl (%rcx), %eax
movl %eax, 0x1ac(%rsp)
movl 0x1ac(%rsp), %eax
movl %eax, 0x1a8(%rsp)
movl 0x1a8(%rsp), %eax
movl %eax, 0x474(%rsp)
movl $0x1, 0x204(%rsp)
jmp 0x9e20
leaq 0x158(%rsp), %rdi
leaq 0x2a8(%rsp), %rsi
callq 0x3110
jmp 0x9a1a
leaq 0x178(%rsp), %rdi
leaq 0x158(%rsp), %rsi
xorl %edx, %edx
callq 0xc4a0
jmp 0x9a33
leaq 0x158(%rsp), %rdi
callq 0x3180
leaq 0x178(%rsp), %rdi
callq 0x3460
testb $0x1, %al
jne 0x9a56
jmp 0x9b89
movq 0x88(%rsp), %rax
addq $0xc8, %rax
movq %rax, 0x38(%rsp)
movq 0x450(%rsp), %rax
movq %rax, 0x40(%rsp)
leaq 0x110(%rsp), %rdi
movl $0x4, %esi
callq 0xc550
jmp 0x9a8a
movq 0x40(%rsp), %rsi
leaq 0x130(%rsp), %rdi
leaq 0x110(%rsp), %rdx
callq 0xcb30
jmp 0x9aa6
movq 0x38(%rsp), %rdi
leaq 0x130(%rsp), %rsi
callq 0xc520
movq %rax, 0x30(%rsp)
jmp 0x9abf
movq 0x30(%rsp), %rax
movq %rax, 0x108(%rsp)
leaq 0x130(%rsp), %rdi
callq 0x5cb0
leaq 0x110(%rsp), %rdi
callq 0x5cd0
movl $0xffffffff, 0x474(%rsp) # imm = 0xFFFFFFFF
movl $0x1, 0x204(%rsp)
jmp 0x9e02
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0x2a0(%rsp)
movl %eax, 0x29c(%rsp)
leaq 0x158(%rsp), %rdi
callq 0x3180
jmp 0x9e63
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0x2a0(%rsp)
movl %eax, 0x29c(%rsp)
jmp 0x9e11
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0x2a0(%rsp)
movl %eax, 0x29c(%rsp)
jmp 0x9b77
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0x2a0(%rsp)
movl %eax, 0x29c(%rsp)
leaq 0x130(%rsp), %rdi
callq 0x5cb0
leaq 0x110(%rsp), %rdi
callq 0x5cd0
jmp 0x9e11
movq 0x88(%rsp), %rdi
leaq 0x2a8(%rsp), %rsi
callq 0xcb70
movq %rax, 0x28(%rsp)
jmp 0x9ba5
movq 0x88(%rsp), %rdi
movq 0x28(%rsp), %rax
movq %rax, 0x100(%rsp)
callq 0xca60
movq %rax, 0xf8(%rsp)
leaq 0x100(%rsp), %rdi
leaq 0xf8(%rsp), %rsi
callq 0xcba0
testb $0x1, %al
jne 0x9be5
jmp 0x9cd9
movq 0x88(%rsp), %rax
addq $0xc8, %rax
movq %rax, 0x18(%rsp)
movq 0x450(%rsp), %rax
movq %rax, 0x20(%rsp)
leaq 0xb0(%rsp), %rdi
movl $0x2, %esi
callq 0xc550
jmp 0x9c19
movq 0x20(%rsp), %rsi
leaq 0xd0(%rsp), %rdi
leaq 0xb0(%rsp), %rdx
callq 0xcb30
jmp 0x9c35
movq 0x18(%rsp), %rdi
leaq 0xd0(%rsp), %rsi
callq 0xc520
movq %rax, 0x10(%rsp)
jmp 0x9c4e
movq 0x10(%rsp), %rax
movq %rax, 0xa8(%rsp)
leaq 0xd0(%rsp), %rdi
callq 0x5cb0
leaq 0xb0(%rsp), %rdi
callq 0x5cd0
movl $0xffffffff, 0x474(%rsp) # imm = 0xFFFFFFFF
movl $0x1, 0x204(%rsp)
jmp 0x9e02
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0x2a0(%rsp)
movl %eax, 0x29c(%rsp)
jmp 0x9cc7
movq %rax, %rcx
movl %edx, %eax
movq %rcx, 0x2a0(%rsp)
movl %eax, 0x29c(%rsp)
leaq 0xd0(%rsp), %rdi
callq 0x5cb0
leaq 0xb0(%rsp), %rdi
callq 0x5cd0
jmp 0x9e11
leaq 0x100(%rsp), %rdi
callq 0xcbc0
movl 0x44(%rax), %ecx
incl %ecx
movl %ecx, 0x44(%rax)
movq 0x458(%rsp), %rax
movl (%rax), %eax
movl %eax, 0xc(%rsp)
subl $0xd, %eax
je 0x9d15
jmp 0x9d03
movl 0xc(%rsp), %eax
addl $-0xf, %eax
subl $0x2, %eax
ja 0x9da9
jmp 0x9d15
movq 0x448(%rsp), %rax
movq %rax, (%rsp)
leaq 0x100(%rsp), %rdi
callq 0xcbc0
movq 0x88(%rsp), %rdi
movq (%rsp), %rsi
movq %rax, %rdx
addq $0x40, %rdx
callq 0xcbf0
movl %eax, 0x8(%rsp)
jmp 0x9d4c
movl 0x8(%rsp), %eax
movl %eax, 0xa4(%rsp)
movl 0xa4(%rsp), %eax
movl %eax, 0xa0(%rsp)
movl 0xa0(%rsp), %eax
shll $0x8, %eax
movl %eax, 0xa0(%rsp)
movl 0xa0(%rsp), %eax
movq 0x458(%rsp), %rcx
addl (%rcx), %eax
movl %eax, 0xa0(%rsp)
movl 0xa0(%rsp), %eax
movl %eax, 0x474(%rsp)
movl $0x1, 0x204(%rsp)
jmp 0x9e02
leaq 0x100(%rsp), %rdi
callq 0xcbc0
movl 0x40(%rax), %eax
movl %eax, 0xa0(%rsp)
movl 0xa0(%rsp), %eax
shll $0x8, %eax
movl %eax, 0xa0(%rsp)
movl 0xa0(%rsp), %eax
movq 0x458(%rsp), %rcx
addl (%rcx), %eax
movl %eax, 0xa0(%rsp)
movl 0xa0(%rsp), %eax
movl %eax, 0x474(%rsp)
movl $0x1, 0x204(%rsp)
leaq 0x178(%rsp), %rdi
callq 0x5670
jmp 0x9e20
leaq 0x178(%rsp), %rdi
callq 0x5670
jmp 0x9e63
leaq 0x258(%rsp), %rdi
callq 0x3180
leaq 0x278(%rsp), %rdi
callq 0x3180
leaq 0x2a8(%rsp), %rdi
callq 0x3180
leaq 0x2c8(%rsp), %rdi
callq 0x3140
movl 0x474(%rsp), %eax
addq $0x478, %rsp            # imm = 0x478
retq
leaq 0x258(%rsp), %rdi
callq 0x3180
leaq 0x278(%rsp), %rdi
callq 0x3180
leaq 0x2a8(%rsp), %rdi
callq 0x3180
leaq 0x2c8(%rsp), %rdi
callq 0x3140
movq 0x2a0(%rsp), %rdi
callq 0x3490
nopw %cs:(%rax,%rax)