diff options
Diffstat (limited to 'asm')
-rw-r--r-- | asm/assembler.cpp | 17 | ||||
-rw-r--r-- | asm/assembler.h | 31 | ||||
-rw-r--r-- | asm/chunk.cpp | 1 | ||||
-rw-r--r-- | asm/chunk.h | 79 | ||||
-rw-r--r-- | asm/intel64/nop.cpp | 11 | ||||
-rw-r--r-- | asm/intel64/nop.h | 11 | ||||
-rw-r--r-- | asm/segment.cpp | 20 | ||||
-rw-r--r-- | asm/segment.h | 15 |
8 files changed, 185 insertions, 0 deletions
diff --git a/asm/assembler.cpp b/asm/assembler.cpp new file mode 100644 index 0000000..275bd4a --- /dev/null +++ b/asm/assembler.cpp @@ -0,0 +1,17 @@ +#include "assembler.h" + +std::unordered_map<std::string, FactoryFunction> ops; + +bool registerOp(const std::string& mnemonic, FactoryFunction f) +{ + if (ops.contains(mnemonic)) { + std::cout << "Warning: mnemonic |" << mnemonic << "| already registered." << std::endl; + return false; + } + + std::cout << "Registering mnemonic |" << mnemonic << "|." << std::endl; + + ops[mnemonic] = f; + + return true; +} diff --git a/asm/assembler.h b/asm/assembler.h new file mode 100644 index 0000000..b9c39a6 --- /dev/null +++ b/asm/assembler.h @@ -0,0 +1,31 @@ +#pragma once + +#include "chunk.h" + +#include <any> +#include <functional> +#include <iostream> +#include <memory> +#include <string> +#include <unordered_map> + +using AsmArgs = std::vector<std::any>; // 0th element is mnemonic +using FactoryFunction = std::function<std::shared_ptr<Op>(AsmArgs&)>; + +bool registerOp(const std::string& mnemonic, FactoryFunction f); + +template<typename T> +std::string mangleNameOne(const std::string& s) +{ + return s + "_" + typeid(T).name(); +} + +template<typename T, typename... Targs> +std::string mangleName(const std::string& s) +{ + if constexpr (sizeof...(Targs) == 0) + return mangleNameOne<T>(s); + else + return mangleName<Targs...>(s + "_" + typeid(T).name()); +} + diff --git a/asm/chunk.cpp b/asm/chunk.cpp new file mode 100644 index 0000000..3a07abc --- /dev/null +++ b/asm/chunk.cpp @@ -0,0 +1 @@ +#include "chunk.h" diff --git a/asm/chunk.h b/asm/chunk.h new file mode 100644 index 0000000..723e711 --- /dev/null +++ b/asm/chunk.h @@ -0,0 +1,79 @@ +// Chunk data type, and derived types + +#pragma once + +#include <cstdint> +#include <string> +#include <vector> + +class Chunk +{ +public: + virtual ~Chunk(){} + virtual std::vector<uint8_t> getCode() = 0; + virtual size_t size() = 0; ///< returns size in bytes +}; + +class Label: public Chunk +{ +public: + Label(const std::string& name) : m_name(name) {} + std::string name(){return m_name;} + std::vector<uint8_t> getCode() override { return {}; } + size_t size() override { return 0; } + +private: + std::string m_name; +}; + +class Data: public Chunk +{ +public: + Data(std::vector<uint8_t> data): m_data(data) {} + virtual ~Data(){} + + std::vector<uint8_t> getCode() override + { + return m_data; + } + + size_t size() override + { + return m_data.size(); + } + +protected: + std::vector<uint8_t> m_data; +}; + +class Op: public Chunk +{ +public: + virtual ~Op(){}; + virtual bool optimize() = 0; ///< returns true if changed +}; + +class OpSimple: public Op +{ +public: + OpSimple(std::vector<uint8_t> machine_code): machine_code(machine_code) {} + + std::vector<uint8_t> getCode() override + { + return machine_code; + } + + size_t size() override + { + return machine_code.size(); + } + + bool optimize() override ///< returns true if changed + { + return false; + } + +protected: + std::vector<uint8_t> machine_code; +}; + diff --git a/asm/intel64/nop.cpp b/asm/intel64/nop.cpp new file mode 100644 index 0000000..450de46 --- /dev/null +++ b/asm/intel64/nop.cpp @@ -0,0 +1,11 @@ +#include "nop.h" + +#include <asm/assembler.h> + +namespace { + +bool registered { registerOp("nop", [](AsmArgs& args) -> std::shared_ptr<Op>{ + return std::make_shared<Op_nop>(); + }) }; + +} diff --git a/asm/intel64/nop.h b/asm/intel64/nop.h new file mode 100644 index 0000000..72d6d1b --- /dev/null +++ b/asm/intel64/nop.h @@ -0,0 +1,11 @@ +#pragma once + +#include <asm/chunk.h> + +class Op_nop: public OpSimple +{ +public: + Op_nop() : OpSimple({ 0x90 }) {} + +}; + diff --git a/asm/segment.cpp b/asm/segment.cpp new file mode 100644 index 0000000..db83941 --- /dev/null +++ b/asm/segment.cpp @@ -0,0 +1,20 @@ +#include "segment.h" + +using namespace std::string_literals; + +size_t Segment::getAddressOfLabel(const std::string& label) + { + size_t address{0}; + auto i{begin()}; + while (i != end()) { + Chunk& chunk{**i}; + address += chunk.size(); + if (typeid(chunk) == typeid(Label)) { + if (dynamic_cast<Label&>(chunk).name() == label) { + return address; + } + } + } + + throw std::runtime_error("Bad label: "s + label); + } diff --git a/asm/segment.h b/asm/segment.h new file mode 100644 index 0000000..1c080d3 --- /dev/null +++ b/asm/segment.h @@ -0,0 +1,15 @@ +#pragma once + +#include "chunk.h" + +#include <exception> +#include <memory> +#include <string> +#include <vector> + +class Segment: public std::vector<std::shared_ptr<Chunk>> +{ + size_t getAddressOfLabel(const std::string& label); +}; + + |