From 031bfef600e7021c8bd72e2e663f368e7386b131 Mon Sep 17 00:00:00 2001 From: Roland Reichwein Date: Wed, 18 Nov 2020 17:55:27 +0100 Subject: Added Asm ops --- Makefile | 13 ++++++++ TODO | 4 +-- asm/assembler.h | 16 +++++++++ asm/intel64/all_ops.h | 12 +++++++ asm/intel64/and.cpp | 84 ++++++++++++++++++++++++++++++++++++++++++++++++ asm/intel64/and.h | 31 ++++++++++++++++++ asm/intel64/bsf.cpp | 47 +++++++++++++++++++++++++++ asm/intel64/bsf.h | 31 ++++++++++++++++++ asm/intel64/bsr.cpp | 47 +++++++++++++++++++++++++++ asm/intel64/bsr.h | 31 ++++++++++++++++++ asm/intel64/encode.cpp | 45 +++++++++++++------------- asm/intel64/neg.cpp | 59 ++++++++++++++++++++++++++++++++++ asm/intel64/neg.h | 31 ++++++++++++++++++ asm/intel64/not.cpp | 59 ++++++++++++++++++++++++++++++++++ asm/intel64/not.h | 31 ++++++++++++++++++ asm/intel64/rcl.cpp | 61 +++++++++++++++++++++++++++++++++++ asm/intel64/rcl.h | 31 ++++++++++++++++++ asm/intel64/rcr.cpp | 61 +++++++++++++++++++++++++++++++++++ asm/intel64/rcr.h | 31 ++++++++++++++++++ asm/intel64/rol.cpp | 61 +++++++++++++++++++++++++++++++++++ asm/intel64/rol.h | 31 ++++++++++++++++++ asm/intel64/ror.cpp | 61 +++++++++++++++++++++++++++++++++++ asm/intel64/ror.h | 31 ++++++++++++++++++ asm/intel64/sal_shl.cpp | 79 +++++++++++++++++++++++++++++++++++++++++++++ asm/intel64/sal_shl.h | 31 ++++++++++++++++++ asm/intel64/sar.cpp | 61 +++++++++++++++++++++++++++++++++++ asm/intel64/sar.h | 31 ++++++++++++++++++ asm/intel64/shr.cpp | 61 +++++++++++++++++++++++++++++++++++ asm/intel64/shr.h | 31 ++++++++++++++++++ asm/intel64/trivials.cpp | 12 +++++-- asm/intel64/trivials.h | 5 +++ asm/parse.cpp | 8 +++++ asm/parse.h | 8 +++++ flowgraph/node.h | 6 ++-- 34 files changed, 1213 insertions(+), 29 deletions(-) create mode 100644 asm/intel64/and.cpp create mode 100644 asm/intel64/and.h create mode 100644 asm/intel64/bsf.cpp create mode 100644 asm/intel64/bsf.h create mode 100644 asm/intel64/bsr.cpp create mode 100644 asm/intel64/bsr.h create mode 100644 asm/intel64/neg.cpp create mode 100644 asm/intel64/neg.h create mode 100644 asm/intel64/not.cpp create mode 100644 asm/intel64/not.h create mode 100644 asm/intel64/rcl.cpp create mode 100644 asm/intel64/rcl.h create mode 100644 asm/intel64/rcr.cpp create mode 100644 asm/intel64/rcr.h create mode 100644 asm/intel64/rol.cpp create mode 100644 asm/intel64/rol.h create mode 100644 asm/intel64/ror.cpp create mode 100644 asm/intel64/ror.h create mode 100644 asm/intel64/sal_shl.cpp create mode 100644 asm/intel64/sal_shl.h create mode 100644 asm/intel64/sar.cpp create mode 100644 asm/intel64/sar.h create mode 100644 asm/intel64/shr.cpp create mode 100644 asm/intel64/shr.h create mode 100644 asm/parse.cpp create mode 100644 asm/parse.h diff --git a/Makefile b/Makefile index 1ef9a12..c2d1850 100644 --- a/Makefile +++ b/Makefile @@ -48,6 +48,9 @@ PROGSRC=\ asm/assembler.cpp \ asm/chunk.cpp \ asm/intel64/add.cpp \ + asm/intel64/and.cpp \ + asm/intel64/bsf.cpp \ + asm/intel64/bsr.cpp \ asm/intel64/dec.cpp \ asm/intel64/div.cpp \ asm/intel64/idiv.cpp \ @@ -57,14 +60,24 @@ PROGSRC=\ asm/intel64/jmp.cpp \ asm/intel64/mov.cpp \ asm/intel64/mul.cpp \ + asm/intel64/neg.cpp \ + asm/intel64/not.cpp \ asm/intel64/pop.cpp \ asm/intel64/push.cpp \ + asm/intel64/rcl.cpp \ + asm/intel64/rcr.cpp \ + asm/intel64/rol.cpp \ + asm/intel64/ror.cpp \ + asm/intel64/sal_shl.cpp \ + asm/intel64/sar.cpp \ + asm/intel64/shr.cpp \ asm/intel64/sub.cpp \ asm/intel64/trivials.cpp \ asm/intel64/xor.cpp \ asm/intel64/codes.cpp \ asm/intel64/encode.cpp \ asm/operators.cpp \ + asm/parse.cpp \ asm/segment.cpp \ bnf.cpp \ cpp.cpp \ diff --git a/TODO b/TODO index 0607485..3c8bc93 100644 --- a/TODO +++ b/TODO @@ -1,6 +1,6 @@ -Fix stack encode.cpp: UnaryOperation asm parser -ICE class + +Fix stack grammer.cpp: match() : return point of match error ("Compile error") diff --git a/asm/assembler.h b/asm/assembler.h index e719ea4..ea23fbc 100644 --- a/asm/assembler.h +++ b/asm/assembler.h @@ -95,6 +95,22 @@ public: std::string m_name; }; + // 64 bit Ptr to 8 bit Memory + class Mem8Ptr64 + { + public: + Mem8Ptr64(const std::string& reg, int32_t offs = 0): m_reg(reg), m_offs(offs) {} + Mem8Ptr64(const std::string& reg, const std::string& reg2 = ""s, int32_t offs = 0): m_reg(reg), m_reg2(reg2), m_offs(offs) {} + std::string reg() { return m_reg; } + std::string reg2() { return m_reg2; } + int32_t offs() { return m_offs; } + + private: + std::string m_reg; + std::string m_reg2; + int32_t m_offs; + }; + // 64 bit Ptr to 32 bit Memory class Mem32Ptr64 { diff --git a/asm/intel64/all_ops.h b/asm/intel64/all_ops.h index 779506d..4da0a0b 100644 --- a/asm/intel64/all_ops.h +++ b/asm/intel64/all_ops.h @@ -1,6 +1,9 @@ #pragma once #include "add.h" +#include "and.h" +#include "bsf.h" +#include "bsr.h" #include "dec.h" #include "div.h" #include "idiv.h" @@ -8,10 +11,19 @@ #include "inc.h" #include "int.h" #include "jmp.h" +#include "neg.h" +#include "not.h" #include "mov.h" #include "mul.h" #include "pop.h" #include "push.h" +#include "rcl.h" +#include "rcr.h" +#include "rol.h" +#include "ror.h" +#include "sal_shl.h" +#include "sar.h" +#include "shr.h" #include "sub.h" #include "trivials.h" #include "xor.h" diff --git a/asm/intel64/and.cpp b/asm/intel64/and.cpp new file mode 100644 index 0000000..a2e110b --- /dev/null +++ b/asm/intel64/and.cpp @@ -0,0 +1,84 @@ +#include "and.h" + +#include "codes.h" + +#include +#include + +#include + +using namespace std::string_literals; + +Op_and::Op_and(const Asm::Args& args) +{ + if (args[0].type() == typeid(Asm::Args::Register8) && args[1].type() == typeid(Asm::Args::Register8)) { // and reg8, reg8 + // r/m8, r8: ModRM:r/m (w), ModRM:reg (r) + machine_code = std::vector{ 0x20 } + + ModRM(std::any_cast(args[1]).name(), std::any_cast(args[0]).name()); + + } else if (args[0].type() == typeid(Asm::Args::Register32) && args[1].type() == typeid(Asm::Args::Register32)) { // and reg32, reg32 + // r/m32, r32: ModRM:r/m (w), ModRM:reg (r) + machine_code = std::vector{ 0x21 } + + ModRM(std::any_cast(args[1]).name(), std::any_cast(args[0]).name()); + + } else if (args[0].type() == typeid(Asm::Args::Register64) && args[1].type() == typeid(Asm::Args::Register64)) { // and reg64, reg64 + // r/m64, r64: ModRM:r/m (w), ModRM:reg (r) + machine_code = REX("W") + std::vector{ 0x21 } + + ModRM(std::any_cast(args[1]).name(), std::any_cast(args[0]).name()); + + } else if (args[0].type() == typeid(Asm::Args::Register32) && args[1].type() == typeid(Asm::Args::Immediate32)) { // and reg32, imm32 + machine_code = std::vector{ 0x81 } + ModRM("/4", std::any_cast(args[0]).name()) + std::any_cast(args[1]).getCode(); + + } else if (args[0].type() == typeid(Asm::Args::Register32) && args[1].type() == typeid(Asm::Args::Mem32Ptr64)) { // and reg32, [reg64] + machine_code = std::vector{ 0x23 } + ModRM(std::any_cast(args[0]).name(), std::any_cast(args[1]).reg()); + + } else if (args[0].type() == typeid(Asm::Args::Register64) && args[1].type() == typeid(Asm::Args::Mem64Ptr64)) { // and reg64, [reg64] + machine_code = REX("W") + std::vector{ 0x23 } + ModRM(std::any_cast(args[0]).name(), std::any_cast(args[1]).reg()); + + } else if (args[0].type() == typeid(Asm::Args::Mem32Ptr64) && args[1].type() == typeid(Asm::Args::Register32)) { // and [reg64], reg32 + machine_code = std::vector{ 0x21 } + ModRM(std::any_cast(args[1]).name(), std::any_cast(args[0]).reg()); + + } else if (args[0].type() == typeid(Asm::Args::Mem64Ptr64) && args[1].type() == typeid(Asm::Args::Register64)) { // and [reg64], reg64 + machine_code = REX("W") + std::vector{ 0x21 } + ModRM(std::any_cast(args[1]).name(), std::any_cast(args[0]).reg()); + + } else if (args[0].type() == typeid(Asm::Args::Register64) && args[1].type() == typeid(Asm::Args::Immediate32)) { // and reg64, imm32 (sign-extended) + machine_code = REX("W") + std::vector{ 0x81 } + ModRM("/4", std::any_cast(args[0]).name()) + std::any_cast(args[1]).getCode(); + + } else { + throw std::runtime_error("Unimplemented: and "s + args[0].type().name() + " "s + args[1].type().name()); + } +} + +namespace { + +bool registered { + registerOp(mangleName("and"), [](const Asm::Args& args) -> std::shared_ptr{ + return std::make_shared(args); + }) && + registerOp(mangleName("and"), [](const Asm::Args& args) -> std::shared_ptr{ + return std::make_shared(args); + }) && + registerOp(mangleName("and"), [](const Asm::Args& args) -> std::shared_ptr{ + return std::make_shared(args); + }) && + registerOp(mangleName("and"), [](const Asm::Args& args) -> std::shared_ptr{ + return std::make_shared(args); + }) && + registerOp(mangleName("and"), [](const Asm::Args& args) -> std::shared_ptr{ + return std::make_shared(args); + }) && + registerOp(mangleName("and"), [](const Asm::Args& args) -> std::shared_ptr{ + return std::make_shared(args); + }) && + registerOp(mangleName("and"), [](const Asm::Args& args) -> std::shared_ptr{ + return std::make_shared(args); + }) && + registerOp(mangleName("and"), [](const Asm::Args& args) -> std::shared_ptr{ + return std::make_shared(args); + }) && + registerOp(mangleName("and"), [](const Asm::Args& args) -> std::shared_ptr{ + return std::make_shared(args); + }) +}; + +} diff --git a/asm/intel64/and.h b/asm/intel64/and.h new file mode 100644 index 0000000..f488730 --- /dev/null +++ b/asm/intel64/and.h @@ -0,0 +1,31 @@ +// AND + +#pragma once + +#include + +class Op_and: public Op +{ +public: + Op_and(const Asm::Args& 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/bsf.cpp b/asm/intel64/bsf.cpp new file mode 100644 index 0000000..974be43 --- /dev/null +++ b/asm/intel64/bsf.cpp @@ -0,0 +1,47 @@ +#include "bsf.h" + +#include "codes.h" + +#include +#include + +using namespace std::string_literals; + +Op_bsf::Op_bsf(const Asm::Args& args) +{ + if (args[0].type() == typeid(Asm::Args::Register32) && args[1].type() == typeid(Asm::Args::Register32)) { // bsf reg32, reg32 + machine_code = std::vector{ 0x0F, 0xBC } + ModRM(std::any_cast(args[0]).name(), std::any_cast(args[1]).name()); + + } else if (args[0].type() == typeid(Asm::Args::Register64) && args[1].type() == typeid(Asm::Args::Register64)) { // bsf reg64, reg64 + machine_code = REX("W") + std::vector{ 0x0F, 0xBC } + ModRM(std::any_cast(args[0]).name(), std::any_cast(args[1]).name()); + + } else if (args[0].type() == typeid(Asm::Args::Register32) && args[1].type() == typeid(Asm::Args::Mem32Ptr64)) { // bsf reg32, [reg64] + machine_code = std::vector{ 0x0F, 0xBC } + ModRM(std::any_cast(args[0]).name(), std::any_cast(args[1]).reg()); + + } else if (args[0].type() == typeid(Asm::Args::Register64) && args[1].type() == typeid(Asm::Args::Mem64Ptr64)) { // bsf reg64, [reg64] + machine_code = REX("W") + std::vector{ 0x0F, 0xBC } + ModRM(std::any_cast(args[0]).name(), std::any_cast(args[1]).reg()); + + } else { + throw std::runtime_error("Unimplemented: bsf "s + args[0].type().name() + " "s + args[1].type().name()); + } +} + +namespace { + +bool registered { + registerOp(mangleName("bsf"), [](const Asm::Args& args) -> std::shared_ptr{ + return std::make_shared(args); + }) && + registerOp(mangleName("bsf"), [](const Asm::Args& args) -> std::shared_ptr{ + return std::make_shared(args); + }) && + registerOp(mangleName("bsf"), [](const Asm::Args& args) -> std::shared_ptr{ + return std::make_shared(args); + }) && + registerOp(mangleName("bsf"), [](const Asm::Args& args) -> std::shared_ptr{ + return std::make_shared(args); + }) +}; + +} + diff --git a/asm/intel64/bsf.h b/asm/intel64/bsf.h new file mode 100644 index 0000000..699c093 --- /dev/null +++ b/asm/intel64/bsf.h @@ -0,0 +1,31 @@ +// Bit Scan Forward + +#pragma once + +#include + +class Op_bsf: public Op +{ +public: + Op_bsf(const Asm::Args& 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/bsr.cpp b/asm/intel64/bsr.cpp new file mode 100644 index 0000000..099c7d2 --- /dev/null +++ b/asm/intel64/bsr.cpp @@ -0,0 +1,47 @@ +#include "bsr.h" + +#include "codes.h" + +#include +#include + +using namespace std::string_literals; + +Op_bsr::Op_bsr(const Asm::Args& args) +{ + if (args[0].type() == typeid(Asm::Args::Register32) && args[1].type() == typeid(Asm::Args::Register32)) { // bsr reg32, reg32 + machine_code = std::vector{ 0x0F, 0xBD } + ModRM(std::any_cast(args[0]).name(), std::any_cast(args[1]).name()); + + } else if (args[0].type() == typeid(Asm::Args::Register64) && args[1].type() == typeid(Asm::Args::Register64)) { // bsr reg64, reg64 + machine_code = REX("W") + std::vector{ 0x0F, 0xBD } + ModRM(std::any_cast(args[0]).name(), std::any_cast(args[1]).name()); + + } else if (args[0].type() == typeid(Asm::Args::Register32) && args[1].type() == typeid(Asm::Args::Mem32Ptr64)) { // bsr reg32, [reg64] + machine_code = std::vector{ 0x0F, 0xBD } + ModRM(std::any_cast(args[0]).name(), std::any_cast(args[1]).reg()); + + } else if (args[0].type() == typeid(Asm::Args::Register64) && args[1].type() == typeid(Asm::Args::Mem64Ptr64)) { // bsr reg64, [reg64] + machine_code = REX("W") + std::vector{ 0x0F, 0xBD } + ModRM(std::any_cast(args[0]).name(), std::any_cast(args[1]).reg()); + + } else { + throw std::runtime_error("Unimplemented: bsr "s + args[0].type().name() + " "s + args[1].type().name()); + } +} + +namespace { + +bool registered { + registerOp(mangleName("bsr"), [](const Asm::Args& args) -> std::shared_ptr{ + return std::make_shared(args); + }) && + registerOp(mangleName("bsr"), [](const Asm::Args& args) -> std::shared_ptr{ + return std::make_shared(args); + }) && + registerOp(mangleName("bsr"), [](const Asm::Args& args) -> std::shared_ptr{ + return std::make_shared(args); + }) && + registerOp(mangleName("bsr"), [](const Asm::Args& args) -> std::shared_ptr{ + return std::make_shared(args); + }) +}; + +} + diff --git a/asm/intel64/bsr.h b/asm/intel64/bsr.h new file mode 100644 index 0000000..423a6bf --- /dev/null +++ b/asm/intel64/bsr.h @@ -0,0 +1,31 @@ +// Bit Scan Reverse + +#pragma once + +#include + +class Op_bsr: public Op +{ +public: + Op_bsr(const Asm::Args& 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/encode.cpp b/asm/intel64/encode.cpp index 4648194..21b6629 100644 --- a/asm/intel64/encode.cpp +++ b/asm/intel64/encode.cpp @@ -2,6 +2,7 @@ #include "encode.h" #include "asm/assembler.h" +#include "asm/parse.h" #include "minicc.h" #include @@ -123,31 +124,28 @@ void Asm::toMachineCode(const FlowGraph::Graph& graph, Segment& segment) if (node.get()) { auto& node_deref = *node.get(); if (typeid(node_deref) == typeid(FlowGraph::UnaryOperation)) { - // TODO: FlowGraph::UnaryOperation& op {dynamic_cast(*node)}; + auto operands {op.operands()}; - if (operands[1].type() != FlowGraph::DataType::Int) { - std::runtime_error("Bad type for operand 1: "s + std::to_string(int(operands[1].type()))); - } - - if (!operands[1].storage()) - throw std::runtime_error("ICE: Operand 1 storage is 0"); - - uint32_t immediate1{}; - try { - FlowGraph::Constant& value1 {dynamic_cast(*operands[1].storage())}; - if (value1.value().size() < sizeof(uint32_t)) - throw std::runtime_error("ICE: Int data from operand 1 needs at least 4 bytes, got "s + std::to_string(value1.value().size())); - - immediate1 = boost::endian::little_to_native(*(reinterpret_cast(value1.value().data()))); - } catch (const std::bad_cast& ex) { - std::runtime_error("Bad value for operand 1: Constant expected"); - } - - if (op.type() == FlowGraph::UnaryOperationType::Negate) { - Asm::Args args1{{Asm::Args::Register32("edi"), Asm::Args::Immediate32(immediate1)}}; - segment.push_back(makeOp("mov", args1)); + if (operands.size() != 2) + throw std::runtime_error("ICE: Bad number of operands for UnaryOperation: "s + std::to_string(operands.size())); + + if (op.type() == FlowGraph::UnaryOperationType::BitwiseNot) { + segment.push_back(makeLoadValue(operands[1], graph)); + segment.push_back(parseAsm("not eax")); + segment.push_back(makeStoreValue(operands[0], graph)); + } else if (op.type() == FlowGraph::UnaryOperationType::LogicalNot) { + segment.push_back(makeLoadValue(operands[1], graph)); + segment.push_back(parseAsm("bsr eax")); // ZF=1 iff eax=0 + segment.push_back(parseAsm("lahf")); // ZF in AH bit 6 + segment.push_back(parseAsm("shr eax, 14")); // ZF in eax bit 0 + segment.push_back(parseAsm("and eax, 1")); // now, 0 or 1 is in eax, negated because of zero flag + segment.push_back(makeStoreValue(operands[0], graph)); + } else if (op.type() == FlowGraph::UnaryOperationType::Minus) { + segment.push_back(makeLoadValue(operands[1], graph)); + segment.push_back(parseAsm("neg eax")); + segment.push_back(makeStoreValue(operands[0], graph)); } else throw std::runtime_error("ICE: Asm: Unsupported unary operation type: "s + std::to_string(static_cast(op.type()))); @@ -156,6 +154,9 @@ void Asm::toMachineCode(const FlowGraph::Graph& graph, Segment& segment) auto operands {op.operands()}; + if (operands.size() != 3) + throw std::runtime_error("ICE: Bad number of operands for BinaryOperation: "s + std::to_string(operands.size())); + if (op.type() == FlowGraph::BinaryOperationType::Add) { segment.push_back(makeLoadValue(operands[1], graph)); segment.push_back(makeAddValue(operands[2], graph)); diff --git a/asm/intel64/neg.cpp b/asm/intel64/neg.cpp new file mode 100644 index 0000000..121a54f --- /dev/null +++ b/asm/intel64/neg.cpp @@ -0,0 +1,59 @@ +#include "neg.h" + +#include "codes.h" + +#include +#include + +using namespace std::string_literals; + +Op_neg::Op_neg(const Asm::Args& args) +{ + if (args[0].type() == typeid(Asm::Args::Register8)) { // neg reg8 + machine_code = std::vector{ 0xF6 } + ModRM("/3", std::any_cast(args[0]).name()); + + } else if (args[0].type() == typeid(Asm::Args::Register32)) { // neg reg32 + machine_code = std::vector{ 0xF7 } + ModRM("/3", std::any_cast(args[0]).name()); + + } else if (args[0].type() == typeid(Asm::Args::Register64)) { // neg reg64 + machine_code = REX("W") + std::vector{ 0xF7 } + ModRM("/3", std::any_cast(args[0]).name()); + + } else if (args[0].type() == typeid(Asm::Args::Mem8Ptr64)) { // neg byte ptr [reg64] + machine_code = std::vector{ 0xF6 } + ModRM("/3", std::any_cast(args[0]).name()); + + } else if (args[0].type() == typeid(Asm::Args::Mem32Ptr64)) { // neg dword ptr [reg64] + machine_code = std::vector{ 0xF7 } + ModRM("/3", std::any_cast(args[0]).name()); + + } else if (args[0].type() == typeid(Asm::Args::Mem64Ptr64)) { // neg qword ptr [reg64] + machine_code = REX("W") + std::vector{ 0xF7 } + ModRM("/3", std::any_cast(args[0]).name()); + + } else { + throw std::runtime_error("Unimplemented: neg "s + args[0].type().name() + " "s + args[1].type().name()); + } +} + +namespace { + +bool registered { + registerOp(mangleName("neg"), [](const Asm::Args& args) -> std::shared_ptr{ + return std::make_shared(args); + }) && + registerOp(mangleName("neg"), [](const Asm::Args& args) -> std::shared_ptr{ + return std::make_shared(args); + }) && + registerOp(mangleName("neg"), [](const Asm::Args& args) -> std::shared_ptr{ + return std::make_shared(args); + }) && + registerOp(mangleName("neg"), [](const Asm::Args& args) -> std::shared_ptr{ + return std::make_shared(args); + }) && + registerOp(mangleName("neg"), [](const Asm::Args& args) -> std::shared_ptr{ + return std::make_shared(args); + }) && + registerOp(mangleName("neg"), [](const Asm::Args& args) -> std::shared_ptr{ + return std::make_shared(args); + }) +}; + +} + diff --git a/asm/intel64/neg.h b/asm/intel64/neg.h new file mode 100644 index 0000000..226b632 --- /dev/null +++ b/asm/intel64/neg.h @@ -0,0 +1,31 @@ +// Two's Complement Negation + +#pragma once + +#include + +class Op_neg: public Op +{ +public: + Op_neg(const Asm::Args& 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/not.cpp b/asm/intel64/not.cpp new file mode 100644 index 0000000..58604f4 --- /dev/null +++ b/asm/intel64/not.cpp @@ -0,0 +1,59 @@ +#include "not.h" + +#include "codes.h" + +#include +#include + +using namespace std::string_literals; + +Op_not::Op_not(const Asm::Args& args) +{ + if (args[0].type() == typeid(Asm::Args::Register8)) { // not reg8 + machine_code = std::vector{ 0xF6 } + ModRM("/2", std::any_cast(args[0]).name()); + + } else if (args[0].type() == typeid(Asm::Args::Register32)) { // not reg32 + machine_code = std::vector{ 0xF7 } + ModRM("/2", std::any_cast(args[0]).name()); + + } else if (args[0].type() == typeid(Asm::Args::Register64)) { // not reg64 + machine_code = REX("W") + std::vector{ 0xF7 } + ModRM("/2", std::any_cast(args[0]).name()); + + } else if (args[0].type() == typeid(Asm::Args::Mem8Ptr64)) { // not byte ptr [reg64] + machine_code = std::vector{ 0xF6 } + ModRM("/2", std::any_cast(args[0]).name()); + + } else if (args[0].type() == typeid(Asm::Args::Mem32Ptr64)) { // not dword ptr [reg64] + machine_code = std::vector{ 0xF7 } + ModRM("/2", std::any_cast(args[0]).name()); + + } else if (args[0].type() == typeid(Asm::Args::Mem64Ptr64)) { // not qword ptr [reg64] + machine_code = REX("W") + std::vector{ 0xF7 } + ModRM("/2", std::any_cast(args[0]).name()); + + } else { + throw std::runtime_error("Unimplemented: not "s + args[0].type().name() + " "s + args[1].type().name()); + } +} + +namespace { + +bool registered { + registerOp(mangleName("not"), [](const Asm::Args& args) -> std::shared_ptr{ + return std::make_shared(args); + }) && + registerOp(mangleName("not"), [](const Asm::Args& args) -> std::shared_ptr{ + return std::make_shared(args); + }) && + registerOp(mangleName("not"), [](const Asm::Args& args) -> std::shared_ptr{ + return std::make_shared(args); + }) && + registerOp(mangleName("not"), [](const Asm::Args& args) -> std::shared_ptr{ + return std::make_shared(args); + }) && + registerOp(mangleName("not"), [](const Asm::Args& args) -> std::shared_ptr{ + return std::make_shared(args); + }) && + registerOp(mangleName("not"), [](const Asm::Args& args) -> std::shared_ptr{ + return std::make_shared(args); + }) +}; + +} + diff --git a/asm/intel64/not.h b/asm/intel64/not.h new file mode 100644 index 0000000..105daf8 --- /dev/null +++ b/asm/intel64/not.h @@ -0,0 +1,31 @@ +// One's Complement Negation + +#pragma once + +#include + +class Op_not: public Op +{ +public: + Op_not(const Asm::Args& 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/rcl.cpp b/asm/intel64/rcl.cpp new file mode 100644 index 0000000..038f3d3 --- /dev/null +++ b/asm/intel64/rcl.cpp @@ -0,0 +1,61 @@ +#include "rcl.h" + +#include "codes.h" + +#include +#include + +using namespace std::string_literals; + +Op_rcl::Op_rcl(const Asm::Args& args) +{ + if (args[1].type() == typeid(Asm::Args::Immediate8)) { + std::vector shift_offset{std::any_cast(args[1]).getCode()}; + if (shift_offset == std::vector{ 0x01 }) { // 1 bit version is shorter + if (args[0].type() == typeid(Asm::Args::Register8)) { // rcl reg8, 1 + machine_code = std::vector{ 0xD0 } + ModRM("/2", std::any_cast(args[0]).name()); + } else if (args[0].type() == typeid(Asm::Args::Register32)) { // rcl reg32, 1 + machine_code = std::vector{ 0xD1 } + ModRM("/2", std::any_cast(args[0]).name()); + } else if (args[0].type() == typeid(Asm::Args::Register64)) { // rcl reg64, 1 + machine_code = REX("W") + std::vector{ 0xD1 } + ModRM("/2", std::any_cast(args[0]).name()); + } + } else { // general version >= 2 bits shift + if (args[0].type() == typeid(Asm::Args::Register8)) { // rcl reg8, imm8 + machine_code = std::vector{ 0xC0 } + ModRM("/2", std::any_cast(args[0]).name()) + shift_offset; + } else if (args[0].type() == typeid(Asm::Args::Register32)) { // rcl reg32, imm8 + machine_code = std::vector{ 0xC1 } + ModRM("/2", std::any_cast(args[0]).name()) + shift_offset; + } else if (args[0].type() == typeid(Asm::Args::Register64)) { // rcl reg64, imm8 + machine_code = REX("W") + std::vector{ 0xC1 } + ModRM("/2", std::any_cast(args[0]).name()) + shift_offset; + } + } + + } else { + throw std::runtime_error("Unimplemented: rcl "s + args[0].type().name() + " "s + args[1].type().name()); + } +} + +namespace { + +bool registered { + registerOp(mangleName("rcl"), [](const Asm::Args& args) -> std::shared_ptr{ + return std::make_shared(args); + }) && + registerOp(mangleName("rcl"), [](const Asm::Args& args) -> std::shared_ptr{ + return std::make_shared(args); + }) && + registerOp(mangleName("rcl"), [](const Asm::Args& args) -> std::shared_ptr{ + return std::make_shared(args); + }) && + registerOp(mangleName("rcl"), [](const Asm::Args& args) -> std::shared_ptr{ + return std::make_shared(args); + }) && + registerOp(mangleName("rcl"), [](const Asm::Args& args) -> std::shared_ptr{ + return std::make_shared(args); + }) && + registerOp(mangleName("rcl"), [](const Asm::Args& args) -> std::shared_ptr{ + return std::make_shared(args); + }) +}; + +} + diff --git a/asm/intel64/rcl.h b/asm/intel64/rcl.h new file mode 100644 index 0000000..f530ff1 --- /dev/null +++ b/asm/intel64/rcl.h @@ -0,0 +1,31 @@ +// Rotate Through Carry Left + +#pragma once + +#include + +class Op_rcl: public Op +{ +public: + Op_rcl(const Asm::Args& 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/rcr.cpp b/asm/intel64/rcr.cpp new file mode 100644 index 0000000..27b688c --- /dev/null +++ b/asm/intel64/rcr.cpp @@ -0,0 +1,61 @@ +#include "rcr.h" + +#include "codes.h" + +#include +#include + +using namespace std::string_literals; + +Op_rcr::Op_rcr(const Asm::Args& args) +{ + if (args[1].type() == typeid(Asm::Args::Immediate8)) { + std::vector shift_offset{std::any_cast(args[1]).getCode()}; + if (shift_offset == std::vector{ 0x01 }) { // 1 bit version is shorter + if (args[0].type() == typeid(Asm::Args::Register8)) { // rcr reg8, 1 + machine_code = std::vector{ 0xD0 } + ModRM("/3", std::any_cast(args[0]).name()); + } else if (args[0].type() == typeid(Asm::Args::Register32)) { // rcr reg32, 1 + machine_code = std::vector{ 0xD1 } + ModRM("/3", std::any_cast(args[0]).name()); + } else if (args[0].type() == typeid(Asm::Args::Register64)) { // rcr reg64, 1 + machine_code = REX("W") + std::vector{ 0xD1 } + ModRM("/3", std::any_cast(args[0]).name()); + } + } else { // general version >= 2 bits shift + if (args[0].type() == typeid(Asm::Args::Register8)) { // rcr reg8, imm8 + machine_code = std::vector{ 0xC0 } + ModRM("/3", std::any_cast(args[0]).name()) + shift_offset; + } else if (args[0].type() == typeid(Asm::Args::Register32)) { // rcr reg32, imm8 + machine_code = std::vector{ 0xC1 } + ModRM("/3", std::any_cast(args[0]).name()) + shift_offset; + } else if (args[0].type() == typeid(Asm::Args::Register64)) { // rcr reg64, imm8 + machine_code = REX("W") + std::vector{ 0xC1 } + ModRM("/3", std::any_cast(args[0]).name()) + shift_offset; + } + } + + } else { + throw std::runtime_error("Unimplemented: rcr "s + args[0].type().name() + " "s + args[1].type().name()); + } +} + +namespace { + +bool registered { + registerOp(mangleName("rcr"), [](const Asm::Args& args) -> std::shared_ptr{ + return std::make_shared(args); + }) && + registerOp(mangleName("rcr"), [](const Asm::Args& args) -> std::shared_ptr{ + return std::make_shared(args); + }) && + registerOp(mangleName("rcr"), [](const Asm::Args& args) -> std::shared_ptr{ + return std::make_shared(args); + }) && + registerOp(mangleName("rcr"), [](const Asm::Args& args) -> std::shared_ptr{ + return std::make_shared(args); + }) && + registerOp(mangleName("rcr"), [](const Asm::Args& args) -> std::shared_ptr{ + return std::make_shared(args); + }) && + registerOp(mangleName("rcr"), [](const Asm::Args& args) -> std::shared_ptr{ + return std::make_shared(args); + }) +}; + +} + diff --git a/asm/intel64/rcr.h b/asm/intel64/rcr.h new file mode 100644 index 0000000..ab0bf57 --- /dev/null +++ b/asm/intel64/rcr.h @@ -0,0 +1,31 @@ +// Rotate Throught Carry Right + +#pragma once + +#include + +class Op_rcr: public Op +{ +public: + Op_rcr(const Asm::Args& 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/rol.cpp b/asm/intel64/rol.cpp new file mode 100644 index 0000000..98d69d9 --- /dev/null +++ b/asm/intel64/rol.cpp @@ -0,0 +1,61 @@ +#include "rol.h" + +#include "codes.h" + +#include +#include + +using namespace std::string_literals; + +Op_rol::Op_rol(const Asm::Args& args) +{ + if (args[1].type() == typeid(Asm::Args::Immediate8)) { + std::vector shift_offset{std::any_cast(args[1]).getCode()}; + if (shift_offset == std::vector{ 0x01 }) { // 1 bit version is shorter + if (args[0].type() == typeid(Asm::Args::Register8)) { // rol reg8, 1 + machine_code = std::vector{ 0xD0 } + ModRM("/0", std::any_cast(args[0]).name()); + } else if (args[0].type() == typeid(Asm::Args::Register32)) { // rol reg32, 1 + machine_code = std::vector{ 0xD1 } + ModRM("/0", std::any_cast(args[0]).name()); + } else if (args[0].type() == typeid(Asm::Args::Register64)) { // rol reg64, 1 + machine_code = REX("W") + std::vector{ 0xD1 } + ModRM("/0", std::any_cast(args[0]).name()); + } + } else { // general version >= 2 bits shift + if (args[0].type() == typeid(Asm::Args::Register8)) { // rol reg8, imm8 + machine_code = std::vector{ 0xC0 } + ModRM("/0", std::any_cast(args[0]).name()) + shift_offset; + } else if (args[0].type() == typeid(Asm::Args::Register32)) { // rol reg32, imm8 + machine_code = std::vector{ 0xC1 } + ModRM("/0", std::any_cast(args[0]).name()) + shift_offset; + } else if (args[0].type() == typeid(Asm::Args::Register64)) { // rol reg64, imm8 + machine_code = REX("W") + std::vector{ 0xC1 } + ModRM("/0", std::any_cast(args[0]).name()) + shift_offset; + } + } + + } else { + throw std::runtime_error("Unimplemented: rol "s + args[0].type().name() + " "s + args[1].type().name()); + } +} + +namespace { + +bool registered { + registerOp(mangleName("rol"), [](const Asm::Args& args) -> std::shared_ptr{ + return std::make_shared(args); + }) && + registerOp(mangleName("rol"), [](const Asm::Args& args) -> std::shared_ptr{ + return std::make_shared(args); + }) && + registerOp(mangleName("rol"), [](const Asm::Args& args) -> std::shared_ptr{ + return std::make_shared(args); + }) && + registerOp(mangleName("rol"), [](const Asm::Args& args) -> std::shared_ptr{ + return std::make_shared(args); + }) && + registerOp(mangleName("rol"), [](const Asm::Args& args) -> std::shared_ptr{ + return std::make_shared(args); + }) && + registerOp(mangleName("rol"), [](const Asm::Args& args) -> std::shared_ptr{ + return std::make_shared(args); + }) +}; + +} + diff --git a/asm/intel64/rol.h b/asm/intel64/rol.h new file mode 100644 index 0000000..ae1a0b7 --- /dev/null +++ b/asm/intel64/rol.h @@ -0,0 +1,31 @@ +// Rotate Left + +#pragma once + +#include + +class Op_rol: public Op +{ +public: + Op_rol(const Asm::Args& 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/ror.cpp b/asm/intel64/ror.cpp new file mode 100644 index 0000000..70a7a6b --- /dev/null +++ b/asm/intel64/ror.cpp @@ -0,0 +1,61 @@ +#include "ror.h" + +#include "codes.h" + +#include +#include + +using namespace std::string_literals; + +Op_ror::Op_ror(const Asm::Args& args) +{ + if (args[1].type() == typeid(Asm::Args::Immediate8)) { + std::vector shift_offset{std::any_cast(args[1]).getCode()}; + if (shift_offset == std::vector{ 0x01 }) { // 1 bit version is shorter + if (args[0].type() == typeid(Asm::Args::Register8)) { // ror reg8, 1 + machine_code = std::vector{ 0xD0 } + ModRM("/1", std::any_cast(args[0]).name()); + } else if (args[0].type() == typeid(Asm::Args::Register32)) { // ror reg32, 1 + machine_code = std::vector{ 0xD1 } + ModRM("/1", std::any_cast(args[0]).name()); + } else if (args[0].type() == typeid(Asm::Args::Register64)) { // ror reg64, 1 + machine_code = REX("W") + std::vector{ 0xD1 } + ModRM("/1", std::any_cast(args[0]).name()); + } + } else { // general version >= 2 bits shift + if (args[0].type() == typeid(Asm::Args::Register8)) { // ror reg8, imm8 + machine_code = std::vector{ 0xC0 } + ModRM("/1", std::any_cast(args[0]).name()) + shift_offset; + } else if (args[0].type() == typeid(Asm::Args::Register32)) { // ror reg32, imm8 + machine_code = std::vector{ 0xC1 } + ModRM("/1", std::any_cast(args[0]).name()) + shift_offset; + } else if (args[0].type() == typeid(Asm::Args::Register64)) { // ror reg64, imm8 + machine_code = REX("W") + std::vector{ 0xC1 } + ModRM("/1", std::any_cast(args[0]).name()) + shift_offset; + } + } + + } else { + throw std::runtime_error("Unimplemented: ror "s + args[0].type().name() + " "s + args[1].type().name()); + } +} + +namespace { + +bool registered { + registerOp(mangleName("ror"), [](const Asm::Args& args) -> std::shared_ptr{ + return std::make_shared(args); + }) && + registerOp(mangleName("ror"), [](const Asm::Args& args) -> std::shared_ptr{ + return std::make_shared(args); + }) && + registerOp(mangleName("ror"), [](const Asm::Args& args) -> std::shared_ptr{ + return std::make_shared(args); + }) && + registerOp(mangleName("ror"), [](const Asm::Args& args) -> std::shared_ptr{ + return std::make_shared(args); + }) && + registerOp(mangleName("ror"), [](const Asm::Args& args) -> std::shared_ptr{ + return std::make_shared(args); + }) && + registerOp(mangleName("ror"), [](const Asm::Args& args) -> std::shared_ptr{ + return std::make_shared(args); + }) +}; + +} + diff --git a/asm/intel64/ror.h b/asm/intel64/ror.h new file mode 100644 index 0000000..d33c49a --- /dev/null +++ b/asm/intel64/ror.h @@ -0,0 +1,31 @@ +// Rotate Right + +#pragma once + +#include + +class Op_ror: public Op +{ +public: + Op_ror(const Asm::Args& 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/sal_shl.cpp b/asm/intel64/sal_shl.cpp new file mode 100644 index 0000000..c822666 --- /dev/null +++ b/asm/intel64/sal_shl.cpp @@ -0,0 +1,79 @@ +#include "sal_shl.h" + +#include "codes.h" + +#include +#include + +using namespace std::string_literals; + +Op_sal::Op_sal(const Asm::Args& args) +{ + if (args[1].type() == typeid(Asm::Args::Immediate8)) { + std::vector shift_offset{std::any_cast(args[1]).getCode()}; + if (shift_offset == std::vector{ 0x01 }) { // 1 bit version is shorter + if (args[0].type() == typeid(Asm::Args::Register8)) { // sal reg8, 1 + machine_code = std::vector{ 0xD0 } + ModRM("/4", std::any_cast(args[0]).name()); + } else if (args[0].type() == typeid(Asm::Args::Register32)) { // sal reg32, 1 + machine_code = std::vector{ 0xD1 } + ModRM("/4", std::any_cast(args[0]).name()); + } else if (args[0].type() == typeid(Asm::Args::Register64)) { // sal reg64, 1 + machine_code = REX("W") + std::vector{ 0xD1 } + ModRM("/4", std::any_cast(args[0]).name()); + } + } else { // general version >= 2 bits shift + if (args[0].type() == typeid(Asm::Args::Register8)) { // sal reg8, imm8 + machine_code = std::vector{ 0xC0 } + ModRM("/4", std::any_cast(args[0]).name()) + shift_offset; + } else if (args[0].type() == typeid(Asm::Args::Register32)) { // sal reg32, imm8 + machine_code = std::vector{ 0xC1 } + ModRM("/4", std::any_cast(args[0]).name()) + shift_offset; + } else if (args[0].type() == typeid(Asm::Args::Register64)) { // sal reg64, imm8 + machine_code = REX("W") + std::vector{ 0xC1 } + ModRM("/4", std::any_cast(args[0]).name()) + shift_offset; + } + } + + } else { + throw std::runtime_error("Unimplemented: sal(shl) "s + args[0].type().name() + " "s + args[1].type().name()); + } +} + +namespace { + +bool registered { + registerOp(mangleName("sal"), [](const Asm::Args& args) -> std::shared_ptr{ + return std::make_shared(args); + }) && + registerOp(mangleName("sal"), [](const Asm::Args& args) -> std::shared_ptr{ + return std::make_shared(args); + }) && + registerOp(mangleName("sal"), [](const Asm::Args& args) -> std::shared_ptr{ + return std::make_shared(args); + }) && + registerOp(mangleName("sal"), [](const Asm::Args& args) -> std::shared_ptr{ + return std::make_shared(args); + }) && + registerOp(mangleName("sal"), [](const Asm::Args& args) -> std::shared_ptr{ + return std::make_shared(args); + }) && + registerOp(mangleName("sal"), [](const Asm::Args& args) -> std::shared_ptr{ + return std::make_shared(args); + }) && + registerOp(mangleName("shl"), [](const Asm::Args& args) -> std::shared_ptr{ + return std::make_shared(args); + }) && + registerOp(mangleName("shl"), [](const Asm::Args& args) -> std::shared_ptr{ + return std::make_shared(args); + }) && + registerOp(mangleName("shl"), [](const Asm::Args& args) -> std::shared_ptr{ + return std::make_shared(args); + }) && + registerOp(mangleName("shl"), [](const Asm::Args& args) -> std::shared_ptr{ + return std::make_shared(args); + }) && + registerOp(mangleName("shl"), [](const Asm::Args& args) -> std::shared_ptr{ + return std::make_shared(args); + }) && + registerOp(mangleName("shl"), [](const Asm::Args& args) -> std::shared_ptr{ + return std::make_shared(args); + }) +}; + +} + diff --git a/asm/intel64/sal_shl.h b/asm/intel64/sal_shl.h new file mode 100644 index 0000000..e7a44b2 --- /dev/null +++ b/asm/intel64/sal_shl.h @@ -0,0 +1,31 @@ +// Shift Left + +#pragma once + +#include + +class Op_sal: public Op +{ +public: + Op_sal(const Asm::Args& 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/sar.cpp b/asm/intel64/sar.cpp new file mode 100644 index 0000000..fccd738 --- /dev/null +++ b/asm/intel64/sar.cpp @@ -0,0 +1,61 @@ +#include "sar.h" + +#include "codes.h" + +#include +#include + +using namespace std::string_literals; + +Op_sar::Op_sar(const Asm::Args& args) +{ + if (args[1].type() == typeid(Asm::Args::Immediate8)) { + std::vector shift_offset{std::any_cast(args[1]).getCode()}; + if (shift_offset == std::vector{ 0x01 }) { // 1 bit version is shorter + if (args[0].type() == typeid(Asm::Args::Register8)) { // sar reg8, 1 + machine_code = std::vector{ 0xD0 } + ModRM("/7", std::any_cast(args[0]).name()); + } else if (args[0].type() == typeid(Asm::Args::Register32)) { // sar reg32, 1 + machine_code = std::vector{ 0xD1 } + ModRM("/7", std::any_cast(args[0]).name()); + } else if (args[0].type() == typeid(Asm::Args::Register64)) { // sar reg64, 1 + machine_code = REX("W") + std::vector{ 0xD1 } + ModRM("/7", std::any_cast(args[0]).name()); + } + } else { // general version >= 2 bits shift + if (args[0].type() == typeid(Asm::Args::Register8)) { // sar reg8, imm8 + machine_code = std::vector{ 0xC0 } + ModRM("/7", std::any_cast(args[0]).name()) + shift_offset; + } else if (args[0].type() == typeid(Asm::Args::Register32)) { // sar reg32, imm8 + machine_code = std::vector{ 0xC1 } + ModRM("/7", std::any_cast(args[0]).name()) + shift_offset; + } else if (args[0].type() == typeid(Asm::Args::Register64)) { // sar reg64, imm8 + machine_code = REX("W") + std::vector{ 0xC1 } + ModRM("/7", std::any_cast(args[0]).name()) + shift_offset; + } + } + + } else { + throw std::runtime_error("Unimplemented: sar "s + args[0].type().name() + " "s + args[1].type().name()); + } +} + +namespace { + +bool registered { + registerOp(mangleName("sar"), [](const Asm::Args& args) -> std::shared_ptr{ + return std::make_shared(args); + }) && + registerOp(mangleName("sar"), [](const Asm::Args& args) -> std::shared_ptr{ + return std::make_shared(args); + }) && + registerOp(mangleName("sar"), [](const Asm::Args& args) -> std::shared_ptr{ + return std::make_shared(args); + }) && + registerOp(mangleName("sar"), [](const Asm::Args& args) -> std::shared_ptr{ + return std::make_shared(args); + }) && + registerOp(mangleName("sar"), [](const Asm::Args& args) -> std::shared_ptr{ + return std::make_shared(args); + }) && + registerOp(mangleName("sar"), [](const Asm::Args& args) -> std::shared_ptr{ + return std::make_shared(args); + }) +}; + +} + diff --git a/asm/intel64/sar.h b/asm/intel64/sar.h new file mode 100644 index 0000000..531532d --- /dev/null +++ b/asm/intel64/sar.h @@ -0,0 +1,31 @@ +// Shift Arithmetic Right + +#pragma once + +#include + +class Op_sar: public Op +{ +public: + Op_sar(const Asm::Args& 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/shr.cpp b/asm/intel64/shr.cpp new file mode 100644 index 0000000..01977b0 --- /dev/null +++ b/asm/intel64/shr.cpp @@ -0,0 +1,61 @@ +#include "shr.h" + +#include "codes.h" + +#include +#include + +using namespace std::string_literals; + +Op_shr::Op_shr(const Asm::Args& args) +{ + if (args[1].type() == typeid(Asm::Args::Immediate8)) { + std::vector shift_offset{std::any_cast(args[1]).getCode()}; + if (shift_offset == std::vector{ 0x01 }) { // 1 bit version is shorter + if (args[0].type() == typeid(Asm::Args::Register8)) { // shr reg8, 1 + machine_code = std::vector{ 0xD0 } + ModRM("/5", std::any_cast(args[0]).name()); + } else if (args[0].type() == typeid(Asm::Args::Register32)) { // shr reg32, 1 + machine_code = std::vector{ 0xD1 } + ModRM("/5", std::any_cast(args[0]).name()); + } else if (args[0].type() == typeid(Asm::Args::Register64)) { // shr reg64, 1 + machine_code = REX("W") + std::vector{ 0xD1 } + ModRM("/5", std::any_cast(args[0]).name()); + } + } else { // general version >= 2 bits shift + if (args[0].type() == typeid(Asm::Args::Register8)) { // shr reg8, imm8 + machine_code = std::vector{ 0xC0 } + ModRM("/5", std::any_cast(args[0]).name()) + shift_offset; + } else if (args[0].type() == typeid(Asm::Args::Register32)) { // shr reg32, imm8 + machine_code = std::vector{ 0xC1 } + ModRM("/5", std::any_cast(args[0]).name()) + shift_offset; + } else if (args[0].type() == typeid(Asm::Args::Register64)) { // shr reg64, imm8 + machine_code = REX("W") + std::vector{ 0xC1 } + ModRM("/5", std::any_cast(args[0]).name()) + shift_offset; + } + } + + } else { + throw std::runtime_error("Unimplemented: shr "s + args[0].type().name() + " "s + args[1].type().name()); + } +} + +namespace { + +bool registered { + registerOp(mangleName("shr"), [](const Asm::Args& args) -> std::shared_ptr{ + return std::make_shared(args); + }) && + registerOp(mangleName("shr"), [](const Asm::Args& args) -> std::shared_ptr{ + return std::make_shared(args); + }) && + registerOp(mangleName("shr"), [](const Asm::Args& args) -> std::shared_ptr{ + return std::make_shared(args); + }) && + registerOp(mangleName("shr"), [](const Asm::Args& args) -> std::shared_ptr{ + return std::make_shared(args); + }) && + registerOp(mangleName("shr"), [](const Asm::Args& args) -> std::shared_ptr{ + return std::make_shared(args); + }) && + registerOp(mangleName("shr"), [](const Asm::Args& args) -> std::shared_ptr{ + return std::make_shared(args); + }) +}; + +} + diff --git a/asm/intel64/shr.h b/asm/intel64/shr.h new file mode 100644 index 0000000..be724c9 --- /dev/null +++ b/asm/intel64/shr.h @@ -0,0 +1,31 @@ +// Shift Right + +#pragma once + +#include + +class Op_shr: public Op +{ +public: + Op_shr(const Asm::Args& 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/trivials.cpp b/asm/intel64/trivials.cpp index eb1bbb8..ef537b6 100644 --- a/asm/intel64/trivials.cpp +++ b/asm/intel64/trivials.cpp @@ -2,13 +2,18 @@ #include -Op_nop::Op_nop(): OpSimple({ 0x90 }) {} +Op_lahf::Op_lahf(): OpSimple({ 0x9F }) {} // Load flags to AH +Op_nop::Op_nop(): OpSimple({ 0x90 }) {} // No operation Op_ret::Op_ret(): OpSimple({ 0xC3 }) {} // near return; TODO: far return is 0xCB -Op_syscall::Op_syscall(): OpSimple({ 0x0F, 0x05 }) {} +Op_syscall::Op_syscall(): OpSimple({ 0x0F, 0x05 }) {} // Syscall +Op_ud2::Op_ud2(): OpSimple({ 0x0F, 0x0B }) {} // Undefined Instruction, variant 2: with no operands namespace { bool registered { + registerOp("lahf", [](const Asm::Args& args) -> std::shared_ptr{ + return std::make_shared(); + }) && registerOp("nop", [](const Asm::Args& args) -> std::shared_ptr{ return std::make_shared(); }) && @@ -17,6 +22,9 @@ bool registered { }) && registerOp("syscall", [](const Asm::Args& args) -> std::shared_ptr{ return std::make_shared(); + }) && + registerOp("ud2", [](const Asm::Args& args) -> std::shared_ptr{ + return std::make_shared(); }) }; diff --git a/asm/intel64/trivials.h b/asm/intel64/trivials.h index 898001e..2ec1b53 100644 --- a/asm/intel64/trivials.h +++ b/asm/intel64/trivials.h @@ -4,6 +4,9 @@ #include +// Copy Flags to AH +class Op_lahf: public OpSimple { public: Op_lahf(); }; + // No Operation class Op_nop: public OpSimple { public: Op_nop(); }; @@ -13,3 +16,5 @@ class Op_ret: public OpSimple { public: Op_ret(); }; // Syscall class Op_syscall: public OpSimple { public: Op_syscall(); }; +// Undefined Instruction, variant 2: with no operands +class Op_ud2: public OpSimple { public: Op_ud2(); }; diff --git a/asm/parse.cpp b/asm/parse.cpp new file mode 100644 index 0000000..350d86e --- /dev/null +++ b/asm/parse.cpp @@ -0,0 +1,8 @@ +#include "parse.h" + +#include "asm/assembler.h" + +std::shared_ptr parseAsm(const std::string& line) +{ + return makeOp("lahf"); // TODO +} diff --git a/asm/parse.h b/asm/parse.h new file mode 100644 index 0000000..1e6a202 --- /dev/null +++ b/asm/parse.h @@ -0,0 +1,8 @@ +#pragma once + +#include "asm/chunk.h" + +#include +#include + +std::shared_ptr parseAsm(const std::string& line); diff --git a/flowgraph/node.h b/flowgraph/node.h index 6a3ef14..def3c04 100644 --- a/flowgraph/node.h +++ b/flowgraph/node.h @@ -117,9 +117,9 @@ namespace FlowGraph { enum class UnaryOperationType: int { - Increment, - Decrement, - Negate, + LogicalNot, + BitwiseNot, + Minus, }; class UnaryOperation: public Node -- cgit v1.2.3