diff options
| -rw-r--r-- | Makefile | 4 | ||||
| -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 | ||||
| -rw-r--r-- | intel.cpp | 136 | 
10 files changed, 189 insertions, 136 deletions
| @@ -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<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); +}; + + @@ -314,142 +314,6 @@ namespace {  } // namespace -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 Segment: public std::vector<std::shared_ptr<Chunk>> -{ - 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<Label&>(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<std::any>; // 0th element is mnemonic -using FactoryFunction = std::function<std::shared_ptr<Op>(AsmArgs&)>; - -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; -} - -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; -}; - -class Op_nop: public OpSimple -{ -public: - Op_nop() : OpSimple({ 0x90 }) {} - -}; - -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()); -} - -bool registered { registerOp("nop", [](AsmArgs& args) -> std::shared_ptr<Op>{ -                             return std::make_shared<Op_nop>(); -                             }) }; -  class Assembler {   std::unordered_map<std::string, size_t> labels; ///< labels with their positions in instruction list | 
