From 7b49d17f90f26394a116348befb5edcdffcedcb6 Mon Sep 17 00:00:00 2001 From: Roland Reichwein Date: Sat, 17 Oct 2020 17:37:50 +0200 Subject: Add ret and int --- asm/assembler.cpp | 34 ++++++++++++++++++++++++++++++++++ asm/assembler.h | 25 +++++++++++++++++++++++-- asm/intel64/all_ops.h | 5 +++++ asm/intel64/int.cpp | 28 ++++++++++++++++++++++++++++ asm/intel64/int.h | 31 +++++++++++++++++++++++++++++++ asm/intel64/nop.h | 2 ++ asm/intel64/ret.cpp | 12 ++++++++++++ asm/intel64/ret.h | 12 ++++++++++++ asm/operators.cpp | 13 +++++++++++++ asm/operators.h | 8 ++++++++ asm/segment.cpp | 36 ++++++++++++++++++++++++------------ asm/segment.h | 2 ++ 12 files changed, 194 insertions(+), 14 deletions(-) create mode 100644 asm/intel64/all_ops.h create mode 100644 asm/intel64/int.cpp create mode 100644 asm/intel64/int.h create mode 100644 asm/intel64/ret.cpp create mode 100644 asm/intel64/ret.h create mode 100644 asm/operators.cpp create mode 100644 asm/operators.h (limited to 'asm') diff --git a/asm/assembler.cpp b/asm/assembler.cpp index 275bd4a..7a9f6cf 100644 --- a/asm/assembler.cpp +++ b/asm/assembler.cpp @@ -1,7 +1,13 @@ #include "assembler.h" +using namespace std::string_literals; + +namespace { + std::unordered_map ops; +} + bool registerOp(const std::string& mnemonic, FactoryFunction f) { if (ops.contains(mnemonic)) { @@ -15,3 +21,31 @@ bool registerOp(const std::string& mnemonic, FactoryFunction f) return true; } + +std::string mangleName(const std::string& s, AsmArgs& 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, AsmArgs& 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) +{ + AsmArgs dummy; // empty list of arguments + return makeOp(mnemonic, dummy); +} diff --git a/asm/assembler.h b/asm/assembler.h index b9c39a6..42b5f8d 100644 --- a/asm/assembler.h +++ b/asm/assembler.h @@ -1,6 +1,7 @@ #pragma once -#include "chunk.h" +//#include "chunk.h" +//#include "segment.h" #include #include @@ -9,11 +10,19 @@ #include #include -using AsmArgs = std::vector; // 0th element is mnemonic +using AsmArgs = std::vector; using FactoryFunction = std::function(AsmArgs&)>; +// mnemonic: mnemonic including argument types bool registerOp(const std::string& mnemonic, FactoryFunction f); +// Create Op from a registered mnemonic +// mnemonic: just the mnemonic name +std::shared_ptr makeOp(const std::string& mnemonic, AsmArgs& args); + +// overload for empty list of arguments +std::shared_ptr makeOp(const std::string& mnemonic); + template std::string mangleNameOne(const std::string& s) { @@ -29,3 +38,15 @@ std::string mangleName(const std::string& s) return mangleName(s + "_" + typeid(T).name()); } +std::string mangleName(const std::string& s, AsmArgs& args); + +class Immediate8 +{ +public: + Immediate8(uint8_t value): m_value(value) {} + uint8_t value() {return m_value;} + +private: + uint8_t m_value; +}; + diff --git a/asm/intel64/all_ops.h b/asm/intel64/all_ops.h new file mode 100644 index 0000000..83b654b --- /dev/null +++ b/asm/intel64/all_ops.h @@ -0,0 +1,5 @@ +#pragma once + +#include "int.h" +#include "nop.h" +#include "ret.h" diff --git a/asm/intel64/int.cpp b/asm/intel64/int.cpp new file mode 100644 index 0000000..7b682ab --- /dev/null +++ b/asm/intel64/int.cpp @@ -0,0 +1,28 @@ +#include "int.h" + +#include + +Op_int::Op_int(AsmArgs& args) +{ + // At this point, the registration already ensured the number and types of args + + Immediate8 i {std::any_cast(args[0])}; + + if (i.value() == 0) { // INT 0 + machine_code = { 0xCE }; + } else if (i.value() == 1) { // INT 1 + machine_code = { 0xF1 }; + } else if (i.value() == 3) { // INT 3 + machine_code = { 0xCC }; + } else { // INT <...> + machine_code = std::vector{ 0xCD, i.value() }; + } +} + +namespace { + +bool registered { registerOp(mangleName("int"), [](AsmArgs& args) -> std::shared_ptr{ + return std::make_shared(args); + }) }; + +} diff --git a/asm/intel64/int.h b/asm/intel64/int.h new file mode 100644 index 0000000..7bd60c8 --- /dev/null +++ b/asm/intel64/int.h @@ -0,0 +1,31 @@ +// Interrupt + +#pragma once + +#include + +class Op_int: public Op +{ +public: + Op_int(AsmArgs& args); + +public: + 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.h b/asm/intel64/nop.h index 72d6d1b..233b2ef 100644 --- a/asm/intel64/nop.h +++ b/asm/intel64/nop.h @@ -1,3 +1,5 @@ +// No Operation + #pragma once #include diff --git a/asm/intel64/ret.cpp b/asm/intel64/ret.cpp new file mode 100644 index 0000000..cd9ddd4 --- /dev/null +++ b/asm/intel64/ret.cpp @@ -0,0 +1,12 @@ +#include "ret.h" + +#include + +namespace { + +bool registered { registerOp("ret", [](AsmArgs& args) -> std::shared_ptr{ + return std::make_shared(); + }) }; + +} + diff --git a/asm/intel64/ret.h b/asm/intel64/ret.h new file mode 100644 index 0000000..7e7f68c --- /dev/null +++ b/asm/intel64/ret.h @@ -0,0 +1,12 @@ +// Return from procedure + +#pragma once + +#include + +class Op_ret: public OpSimple +{ +public: + Op_ret() : OpSimple({ 0xC3 }) {} // near return; TODO: far return is 0xCB +}; + diff --git a/asm/operators.cpp b/asm/operators.cpp new file mode 100644 index 0000000..9f7d5d9 --- /dev/null +++ b/asm/operators.cpp @@ -0,0 +1,13 @@ +#include "operators.h" + +// binary code operators +std::vector operator+(std::vector a, const std::vector& b) { + a.insert(a.end(), b.begin(), b.end()); + return a; +} + +std::vector operator+(std::vector a, const uint8_t& b) { + a.push_back(b); + return a; +} + diff --git a/asm/operators.h b/asm/operators.h new file mode 100644 index 0000000..93dc15e --- /dev/null +++ b/asm/operators.h @@ -0,0 +1,8 @@ +#pragma once + +#include +#include + +std::vector operator+(std::vector a, const std::vector& b); +std::vector operator+(std::vector a, const uint8_t& b); + diff --git a/asm/segment.cpp b/asm/segment.cpp index db83941..60b8348 100644 --- a/asm/segment.cpp +++ b/asm/segment.cpp @@ -1,20 +1,32 @@ #include "segment.h" +#include "operators.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; - } +{ + 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); } + + throw std::runtime_error("Bad label: "s + label); +} + +std::vector Segment::getCode() +{ + std::vector result; + + for (const auto& chunk: *this) + result = result + chunk->getCode(); + + return result; +} diff --git a/asm/segment.h b/asm/segment.h index 1c080d3..f0a758e 100644 --- a/asm/segment.h +++ b/asm/segment.h @@ -9,7 +9,9 @@ class Segment: public std::vector> { +public: size_t getAddressOfLabel(const std::string& label); + std::vector getCode(); }; -- cgit v1.2.3