From f86999e137f43372236f2dccd1fe3572a85c0dcd Mon Sep 17 00:00:00 2001 From: Roland Reichwein Date: Sat, 17 Oct 2020 14:16:46 +0200 Subject: Separate-out assembler --- Makefile | 4 ++ asm/assembler.cpp | 17 +++++++ asm/assembler.h | 31 ++++++++++++ asm/chunk.cpp | 1 + asm/chunk.h | 79 ++++++++++++++++++++++++++++++ asm/intel64/nop.cpp | 11 +++++ asm/intel64/nop.h | 11 +++++ asm/segment.cpp | 20 ++++++++ asm/segment.h | 15 ++++++ intel.cpp | 136 ---------------------------------------------------- 10 files changed, 189 insertions(+), 136 deletions(-) create mode 100644 asm/assembler.cpp create mode 100644 asm/assembler.h create mode 100644 asm/chunk.cpp create mode 100644 asm/chunk.h create mode 100644 asm/intel64/nop.cpp create mode 100644 asm/intel64/nop.h create mode 100644 asm/segment.cpp create mode 100644 asm/segment.h diff --git a/Makefile b/Makefile index e907b75..5971b19 100644 --- a/Makefile +++ b/Makefile @@ -45,6 +45,10 @@ LIBS+= \ endif PROGSRC=\ + asm/assembler.cpp \ + asm/chunk.cpp \ + asm/segment.cpp \ + asm/intel64/nop.cpp \ bnf.cpp \ cpp.cpp \ cppbnf.cpp \ 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 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 +#include +#include +#include +#include +#include + +using AsmArgs = std::vector; // 0th element is mnemonic +using FactoryFunction = std::function(AsmArgs&)>; + +bool registerOp(const std::string& mnemonic, FactoryFunction f); + +template +std::string mangleNameOne(const std::string& s) +{ + return s + "_" + typeid(T).name(); +} + +template +std::string mangleName(const std::string& s) +{ + if constexpr (sizeof...(Targs) == 0) + return mangleNameOne(s); + else + return mangleName(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 +#include +#include + +class Chunk +{ +public: + virtual ~Chunk(){} + virtual std::vector 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 getCode() override { return {}; } + size_t size() override { return 0; } + +private: + std::string m_name; +}; + +class Data: public Chunk +{ +public: + Data(std::vector data): m_data(data) {} + virtual ~Data(){} + + std::vector getCode() override + { + return m_data; + } + + size_t size() override + { + return m_data.size(); + } + +protected: + std::vector 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 machine_code): machine_code(machine_code) {} + + std::vector 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 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 + +namespace { + +bool registered { registerOp("nop", [](AsmArgs& args) -> std::shared_ptr{ + return std::make_shared(); + }) }; + +} 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 + +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(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 +#include +#include +#include + +class Segment: public std::vector> +{ + size_t getAddressOfLabel(const std::string& label); +}; + + diff --git a/intel.cpp b/intel.cpp index 7ef6be3..9dac6c0 100644 --- a/intel.cpp +++ b/intel.cpp @@ -314,142 +314,6 @@ namespace { } // namespace -class Chunk -{ -public: - virtual ~Chunk(){} - virtual std::vector 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 getCode() override { return {}; } - size_t size() override { return 0; } - -private: - std::string m_name; -}; - -class Data: public Chunk -{ -public: - Data(std::vector data): m_data(data) {} - virtual ~Data(){} - - std::vector getCode() override - { - return m_data; - } - - size_t size() override - { - return m_data.size(); - } - -protected: - std::vector m_data; -}; - -class Segment: public std::vector> -{ - size_t 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(chunk).name() == label) { - return address; - } - } - } - - throw std::runtime_error("Bad label: "s + label); - } -}; - -class Op: public Chunk -{ -public: - virtual ~Op(){}; - virtual bool optimize() = 0; ///< returns true if changed -}; - -using AsmArgs = std::vector; // 0th element is mnemonic -using FactoryFunction = std::function(AsmArgs&)>; - -std::unordered_map 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; -} - -class OpSimple: public Op -{ -public: - OpSimple(std::vector machine_code): machine_code(machine_code) {} - - std::vector 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 machine_code; -}; - -class Op_nop: public OpSimple -{ -public: - Op_nop() : OpSimple({ 0x90 }) {} - -}; - -template -std::string mangleNameOne(const std::string& s) -{ - return s + "_" + typeid(T).name(); -} - -template -std::string mangleName(const std::string& s) -{ - if constexpr (sizeof...(Targs) == 0) - return mangleNameOne(s); - else - return mangleName(s + "_" + typeid(T).name()); -} - -bool registered { registerOp("nop", [](AsmArgs& args) -> std::shared_ptr{ - return std::make_shared(); - }) }; - class Assembler { std::unordered_map labels; ///< labels with their positions in instruction list -- cgit v1.2.3