#include <iostream>
#include <map>
#include "map.h"
#include "parameters.h"

extern bool errorOccured;

// Exn stands for exception. A positive number will be the second argument of the instruction
// -1 means : nothing special if not a pseudoinstruction
// -n means that the instruction is not real and has to be translated into n elementary instructions (if it is a pseudoinstruction)

table_instr::table_instr()
{
instr_info instr;

    instr.type = alu;       instr.exn = -1;         instr.nb_int_arg = 3;
        instr.code = 0; table["addu"] = instr;
        instr.code = 1; table["adduc"] = instr;
        instr.code = 2; table["subu"] = instr;
        instr.code = 3; table["sub"] = instr;
        instr.code = 4; table["xor"] = instr;
        instr.code = 5; table["or"] = instr;
        instr.code = 6; table["and"] = instr;

    instr.type = li;        instr.nb_int_arg = 2;
    instr.code = 8;
        instr.type = nt;    instr.exn = 0;         table["move"] = instr;
        instr.type = move;  instr.exn = 1;         table["not"] = instr;
        instr.type = alu;   instr.exn = 2;         table["sra"] = instr;
                            instr.exn = 3;         table["srl"] = instr;
        instr.type = ls;    instr.exn = 4;         table["lh"] = instr;
        instr.type = io;    instr.exn = 5;         table["input"] = instr;
                            instr.nb_int_arg = 0;
        instr.type = slp;   instr.exn = 8;         table["sleep"] = instr;

    instr.code = 9;         instr.nb_int_arg = 2;
        instr.type = jump;
            instr.exn = 8;  table["jmp"] = instr;
            instr.exn = 10;  table["jmpz"] = instr;
            instr.exn = 12; table["jmpc"] = instr;
            instr.exn = 11; table["jmpnz"] = instr;
            instr.exn = 13; table["jmpnc"] = instr;
            // Special jump instruction with only one argument are obtained by decrementing instruction code by 8

    instr.type = ls;        instr.exn = -1;         instr.nb_int_arg = 2;
        instr.code = 10;    table["lhi"] = instr;
        instr.code = 11;    table["lli"] = instr;
        instr.code = 12;    table["sh"] = instr;
        instr.code = 13;    table["output"] = instr;

    instr.code = -1;        instr.type = pseudo;    instr.exn = -2;     instr.nb_int_arg = 1;
        table["la"] = instr;

                            instr.nb_int_arg = 2;   instr.exn = -2;
        table["li"] = instr;

                            instr.nb_int_arg = 3;   instr.exn = -3;
        table["addui"] = instr;
        table["adduci"] = instr;
        table["subui"] = instr;
        table["subi"]  = instr;
    };

instr_info table_instr::get (string name) {
    if (table.count(name) == 0) {
        cerr << "Error : no instruction matching the name " << name << endl; errorOccured = true;
    }
    return table[name];
};


void table_label::add_label(string name, int index) {
    table[name] = index;
};

int table_label::get (string name) {
    if (table.count(name) == 0) {
        cerr << "Error : no instruction matching the label " << name << endl; errorOccured = true;
    }
    return table[name];
};
