#include "Assembleur.h" #include #include #include enum TypeArithmetique { Add = 0, Sub, And, Or, Xor, Sl, Sr, Not, }; enum TypeMemoire { Str = 0, Ld, }; enum TypeSautControle { Jump = 0, Jequ, Jneq, Jsup, Jinf, Call, Ret, }; static std::map INSTRUCTION_KEYS = { {"add", {Arithmetique, Add}}, {"sub", {Arithmetique, Sub}}, {"and", {Arithmetique, And}}, {"or", {Arithmetique, Or}}, {"xor", {Arithmetique, Xor}}, {"sl", {Arithmetique, Sl}}, {"sr", {Arithmetique, Sr}}, {"str", {Memoire, Str}}, {"ld", {Memoire, Ld}}, {"jmp", {SautControle, Jump}}, {"jequ", {SautControle, Jequ}}, {"jneq", {SautControle, Jneq}}, {"jsup", {SautControle, Jsup}}, {"jinf", {SautControle, Jinf}}, {"call", {SautControle, Call}}, {"ret", {SautControle, Ret}}, }; std::uint32_t Assembleur::ParseLabel(const std::string& a_Label) { auto it = m_Labels.find(a_Label); if (it == m_Labels.end()) { throw std::runtime_error("Label " + a_Label + " not found !"); } return it->second; } void Assembleur::AddLabel(const std::string& a_Label, std::uint32_t a_Line) { m_Labels.insert({a_Label, a_Line}); } std::uint32_t Assembleur::IToInt(Instruction a_Instruction) { return static_cast(a_Instruction.m_Instruction) << 30 | static_cast(a_Instruction.m_SubInstruction) << 28; } std::uint32_t Assembleur::ParseOperation(Instruction a_Instruction, std::uint32_t a_R1, std::uint32_t a_R2, std::uint32_t a_R3) { return IToInt(a_Instruction) | a_R1 << 23 | a_R2 << 20 | a_R3 << 17; } std::uint32_t Assembleur::ParseOperationImmediate( Instruction a_Instruction, std::uint32_t a_R1, std::uint32_t a_R2, std::uint32_t a_C1) { return IToInt(a_Instruction) | 1 << 26 | a_R1 << 23 | a_R2 << 20 | a_C1; } std::uint32_t Assembleur::ParseJump(Instruction a_Instruction, const std::string& a_Label) { std::int32_t jump = ParseLabel(a_Label) - a_Instruction.m_Line; if (jump < 0) jump = std::abs(jump) & 0x7FFFFFF | 0x4000000; return IToInt(a_Instruction) | jump; } std::uint32_t Assembleur::ParseJump(Instruction a_Instruction, std::uint8_t a_R1, std::uint8_t a_R2, const std::string& a_Label) { std::int32_t jump = ParseLabel(a_Label) - a_Instruction.m_Line; if (jump < 0) jump = std::abs(jump) & 0xFFFFF | 0x100000; return IToInt(a_Instruction) | a_R1 << 24 | a_R2 << 21 | jump; } std::uint32_t Assembleur::ParseJump(Instruction a_Instruction) { return IToInt(a_Instruction); } std::uint32_t Assembleur::ParseIO(Instruction a_Instruction, std::uint32_t a_R1, std::uint32_t a_R2, std::uint32_t a_R3) { return IToInt(a_Instruction) | a_R1 << 24 | a_R2 << 21 | a_R3 << 18; } static std::uint32_t ParseRegistry(const std::string& a_Str) { if (a_Str.at(0) != 'R') throw std::runtime_error("Registry " + a_Str + " not found !"); return std::stoi(a_Str.substr(1)); } static bool IsConstant(const std::string& a_Str) { return a_Str.at(0) == '#'; } static std::uint32_t ParseConstant(const std::string& a_Str) { if (a_Str.at(0) != '#') throw std::runtime_error("Registry " + a_Str + " not found !"); return std::stoi(a_Str.substr(1)); } std::uint32_t Assembleur::ParseInstruction(const std::string& a_Str, std::uint32_t a_Line, std::uint32_t a_RealLine) { std::stringstream ss{a_Str}; std::string ins; ss >> ins; auto it = INSTRUCTION_KEYS.find(ins); if (it == INSTRUCTION_KEYS.end()) { throw std::runtime_error("[Line " + std::to_string(a_RealLine) + "] " + "Instruction \"" + ins + "\" not found !"); } Instruction instruction = it->second; instruction.m_Line = a_Line; try { switch (instruction.m_Instruction) { case Arithmetique: { std::string R1, R2, R3; ss >> R1 >> R2 >> R3; if (IsConstant(R3)) { return ParseOperationImmediate(instruction, ParseRegistry(R1), ParseRegistry(R2), ParseConstant(R3)); } else { return ParseOperation(instruction, ParseRegistry(R1), ParseRegistry(R2), ParseRegistry(R3)); } } case Memoire: { std::string R1, R2, R3; ss >> R1 >> R2 >> R3; return ParseIO(instruction, ParseRegistry(R1), ParseRegistry(R2), ParseRegistry(R3)); } case SautControle: { switch (instruction.m_SubInstruction) { case Ret: return ParseJump(instruction); case Call: case Jump: { std::string label; ss >> label; return ParseJump(instruction, label); } case Jequ: case Jneq: case Jsup: case Jinf: { std::string R1, R2, label; ss >> R1 >> R2 >> label; return ParseJump(instruction, ParseRegistry(R1), ParseRegistry(R2), label); } } } } } catch (std::runtime_error& e) { throw std::runtime_error("[Line " + std::to_string(a_RealLine) + "] " + e.what()); } return 0; }