#include "assembler.h" #include "byteorder.h" using namespace std::string_literals; Asm::Args::Immediate8::Immediate8(uint8_t value): m_value(value) {} uint8_t Asm::Args::Immediate8::value() const { return m_value; } std::vector Asm::Args::Immediate8::getCode() const { return {m_value}; } Asm::Args::Immediate16::Immediate16(uint16_t value): m_value(value) {} uint16_t Asm::Args::Immediate16::value() const { return m_value; } std::vector Asm::Args::Immediate16::getCode() const { return endian::to_little(m_value); } Asm::Args::Immediate32::Immediate32(uint32_t value): m_value(value) {} Asm::Args::Immediate32::Immediate32(const Asm::Args::Immediate64& imm64) { if (imm64.value() < 0x100000000) m_value = static_cast(imm64.value()); else throw std::runtime_error("Immediate32: Constructed from too big Immediate64"); } uint32_t Asm::Args::Immediate32::value() const { return m_value; } std::vector Asm::Args::Immediate32::getCode() const { return endian::to_little(m_value); } Asm::Args::Immediate64::Immediate64(uint64_t value): m_value(value) {} uint64_t Asm::Args::Immediate64::value() const { return m_value; } std::vector Asm::Args::Immediate64::getCode() const { return endian::to_little(m_value); } Asm::Args::Register8::Register8(const std::string& name): m_name(name) {} std::string Asm::Args::Register8::name() const { return m_name; } Asm::Args::Register16::Register16(const std::string& name): m_name(name) {} std::string Asm::Args::Register16::name() const { return m_name; } Asm::Args::Register32::Register32(const std::string& name): m_name(name) {} std::string Asm::Args::Register32::name() const { return m_name; } Asm::Args::Register64::Register64(const std::string& name): m_name(name) {} std::string Asm::Args::Register64::name() const { return m_name; } Asm::Args::Mem8Ptr64::Mem8Ptr64(const std::string& reg, int32_t offs): m_reg(reg), m_offs(offs) {} Asm::Args::Mem8Ptr64::Mem8Ptr64(const std::string& reg, const std::string& reg2, int32_t offs): m_reg(reg), m_reg2(reg2), m_offs(offs) {} std::string Asm::Args::Mem8Ptr64::reg() const { return "["s + m_reg + "]"s; } std::string Asm::Args::Mem8Ptr64::reg2() const { return "["s + m_reg2 + "]"s; } int32_t Asm::Args::Mem8Ptr64::offs() const { return m_offs; } Asm::Args::Mem16Ptr64::Mem16Ptr64(const std::string& reg, int32_t offs): m_reg(reg), m_offs(offs) {} Asm::Args::Mem16Ptr64::Mem16Ptr64(const std::string& reg, const std::string& reg2, int32_t offs): m_reg(reg), m_reg2(reg2), m_offs(offs) {} std::string Asm::Args::Mem16Ptr64::reg() const { return "["s + m_reg + "]"s; } std::string Asm::Args::Mem16Ptr64::reg2() const { return "["s + m_reg2 + "]"s; } int32_t Asm::Args::Mem16Ptr64::offs() const { return m_offs; } Asm::Args::Mem32Ptr64::Mem32Ptr64(const std::string& reg, int32_t offs): m_reg(reg), m_offs(offs) {} Asm::Args::Mem32Ptr64::Mem32Ptr64(const std::string& reg, const std::string& reg2, int32_t offs): m_reg(reg), m_reg2(reg2), m_offs(offs) {} std::string Asm::Args::Mem32Ptr64::reg() const { return "["s + m_reg + "]"s; } std::string Asm::Args::Mem32Ptr64::reg2() const { return "["s + m_reg2 + "]"s; } int32_t Asm::Args::Mem32Ptr64::offs() const { return m_offs; } Asm::Args::Mem64Ptr64::Mem64Ptr64(const std::string& reg, int32_t offs): m_reg(reg), m_offs(offs) {} Asm::Args::Mem64Ptr64::Mem64Ptr64(const std::string& reg, const std::string& reg2, int32_t offs): m_reg(reg), m_reg2(reg2), m_offs(offs) {} std::string Asm::Args::Mem64Ptr64::reg() const { return "["s + m_reg + "]"s; } std::string Asm::Args::Mem64Ptr64::reg2() const { return "["s + m_reg2 + "]"s; } int32_t Asm::Args::Mem64Ptr64::offs() const { return m_offs; } namespace { std::unordered_map ops; } bool registerOp(const std::string& mnemonic, FactoryFunction f) { if (ops.contains(mnemonic)) { std::cerr << "Warning: mnemonic |" << mnemonic << "| already registered." << std::endl; return false; } //std::cout << "Registering mnemonic |" << mnemonic << "|." << std::endl; ops[mnemonic] = f; return true; } std::string mangleName(const std::string& s, const Asm::Args& args) { std::string result {s}; for (const auto& arg: args) { result += "_"s + arg.type().name(); } return result; } std::shared_ptr makeOp(const std::string& mnemonic, const Asm::Args& args) { std::string mangled{mangleName(mnemonic, args)}; const auto& i{ops.find(mangled)}; if (i == ops.end()) throw std::runtime_error("Instruction "s + mangled + " not implemented."); return i->second(args); } std::shared_ptr makeOp(const std::string& mnemonic) { Asm::Args dummy; // empty list of arguments return makeOp(mnemonic, dummy); } std::shared_ptr