diff options
author | Roland Reichwein <mail@reichwein.it> | 2020-11-18 17:55:27 +0100 |
---|---|---|
committer | Roland Reichwein <mail@reichwein.it> | 2020-11-18 17:55:27 +0100 |
commit | 031bfef600e7021c8bd72e2e663f368e7386b131 (patch) | |
tree | 4e724c3b13278e5c6fb90a9380d19dc1d253b4b3 | |
parent | 927eb99e75325164a541c2638e1e607294019381 (diff) |
Added Asm ops
34 files changed, 1213 insertions, 29 deletions
@@ -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 \ @@ -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 <asm/assembler.h> +#include <asm/operators.h> + +#include <asm/intel64/codes.h> + +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<uint8_t>{ 0x20 } + + ModRM(std::any_cast<Asm::Args::Register8>(args[1]).name(), std::any_cast<Asm::Args::Register8>(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<uint8_t>{ 0x21 } + + ModRM(std::any_cast<Asm::Args::Register32>(args[1]).name(), std::any_cast<Asm::Args::Register32>(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<uint8_t>{ 0x21 } + + ModRM(std::any_cast<Asm::Args::Register64>(args[1]).name(), std::any_cast<Asm::Args::Register64>(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<uint8_t>{ 0x81 } + ModRM("/4", std::any_cast<Asm::Args::Register32>(args[0]).name()) + std::any_cast<Asm::Args::Immediate32>(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<uint8_t>{ 0x23 } + ModRM(std::any_cast<Asm::Args::Register32>(args[0]).name(), std::any_cast<Asm::Args::Mem32Ptr64>(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<uint8_t>{ 0x23 } + ModRM(std::any_cast<Asm::Args::Register64>(args[0]).name(), std::any_cast<Asm::Args::Mem64Ptr64>(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<uint8_t>{ 0x21 } + ModRM(std::any_cast<Asm::Args::Register32>(args[1]).name(), std::any_cast<Asm::Args::Mem32Ptr64>(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<uint8_t>{ 0x21 } + ModRM(std::any_cast<Asm::Args::Register64>(args[1]).name(), std::any_cast<Asm::Args::Mem64Ptr64>(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<uint8_t>{ 0x81 } + ModRM("/4", std::any_cast<Asm::Args::Register64>(args[0]).name()) + std::any_cast<Asm::Args::Immediate32>(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<Asm::Args::Register8, Asm::Args::Register8>("and"), [](const Asm::Args& args) -> std::shared_ptr<Op>{ + return std::make_shared<Op_and>(args); + }) && + registerOp(mangleName<Asm::Args::Register32, Asm::Args::Register32>("and"), [](const Asm::Args& args) -> std::shared_ptr<Op>{ + return std::make_shared<Op_and>(args); + }) && + registerOp(mangleName<Asm::Args::Register64, Asm::Args::Register64>("and"), [](const Asm::Args& args) -> std::shared_ptr<Op>{ + return std::make_shared<Op_and>(args); + }) && + registerOp(mangleName<Asm::Args::Register32, Asm::Args::Immediate32>("and"), [](const Asm::Args& args) -> std::shared_ptr<Op>{ + return std::make_shared<Op_and>(args); + }) && + registerOp(mangleName<Asm::Args::Register32, Asm::Args::Mem32Ptr64>("and"), [](const Asm::Args& args) -> std::shared_ptr<Op>{ + return std::make_shared<Op_and>(args); + }) && + registerOp(mangleName<Asm::Args::Mem32Ptr64, Asm::Args::Register32>("and"), [](const Asm::Args& args) -> std::shared_ptr<Op>{ + return std::make_shared<Op_and>(args); + }) && + registerOp(mangleName<Asm::Args::Register64, Asm::Args::Mem64Ptr64>("and"), [](const Asm::Args& args) -> std::shared_ptr<Op>{ + return std::make_shared<Op_and>(args); + }) && + registerOp(mangleName<Asm::Args::Mem64Ptr64, Asm::Args::Register64>("and"), [](const Asm::Args& args) -> std::shared_ptr<Op>{ + return std::make_shared<Op_and>(args); + }) && + registerOp(mangleName<Asm::Args::Register64, Asm::Args::Immediate32>("and"), [](const Asm::Args& args) -> std::shared_ptr<Op>{ + return std::make_shared<Op_and>(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 <asm/assembler.h> + +class Op_and: public Op +{ +public: + Op_and(const Asm::Args& args); + +public: + 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/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 <asm/assembler.h> +#include <asm/operators.h> + +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<uint8_t>{ 0x0F, 0xBC } + ModRM(std::any_cast<Asm::Args::Register32>(args[0]).name(), std::any_cast<Asm::Args::Register32>(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<uint8_t>{ 0x0F, 0xBC } + ModRM(std::any_cast<Asm::Args::Register64>(args[0]).name(), std::any_cast<Asm::Args::Register64>(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<uint8_t>{ 0x0F, 0xBC } + ModRM(std::any_cast<Asm::Args::Register32>(args[0]).name(), std::any_cast<Asm::Args::Mem32Ptr64>(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<uint8_t>{ 0x0F, 0xBC } + ModRM(std::any_cast<Asm::Args::Register64>(args[0]).name(), std::any_cast<Asm::Args::Mem64Ptr64>(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<Asm::Args::Register32, Asm::Args::Register32>("bsf"), [](const Asm::Args& args) -> std::shared_ptr<Op>{ + return std::make_shared<Op_bsf>(args); + }) && + registerOp(mangleName<Asm::Args::Register64, Asm::Args::Register64>("bsf"), [](const Asm::Args& args) -> std::shared_ptr<Op>{ + return std::make_shared<Op_bsf>(args); + }) && + registerOp(mangleName<Asm::Args::Register32, Asm::Args::Mem32Ptr64>("bsf"), [](const Asm::Args& args) -> std::shared_ptr<Op>{ + return std::make_shared<Op_bsf>(args); + }) && + registerOp(mangleName<Asm::Args::Register64, Asm::Args::Mem64Ptr64>("bsf"), [](const Asm::Args& args) -> std::shared_ptr<Op>{ + return std::make_shared<Op_bsf>(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 <asm/assembler.h> + +class Op_bsf: public Op +{ +public: + Op_bsf(const Asm::Args& args); + +public: + 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/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 <asm/assembler.h> +#include <asm/operators.h> + +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<uint8_t>{ 0x0F, 0xBD } + ModRM(std::any_cast<Asm::Args::Register32>(args[0]).name(), std::any_cast<Asm::Args::Register32>(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<uint8_t>{ 0x0F, 0xBD } + ModRM(std::any_cast<Asm::Args::Register64>(args[0]).name(), std::any_cast<Asm::Args::Register64>(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<uint8_t>{ 0x0F, 0xBD } + ModRM(std::any_cast<Asm::Args::Register32>(args[0]).name(), std::any_cast<Asm::Args::Mem32Ptr64>(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<uint8_t>{ 0x0F, 0xBD } + ModRM(std::any_cast<Asm::Args::Register64>(args[0]).name(), std::any_cast<Asm::Args::Mem64Ptr64>(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<Asm::Args::Register32, Asm::Args::Register32>("bsr"), [](const Asm::Args& args) -> std::shared_ptr<Op>{ + return std::make_shared<Op_bsr>(args); + }) && + registerOp(mangleName<Asm::Args::Register64, Asm::Args::Register64>("bsr"), [](const Asm::Args& args) -> std::shared_ptr<Op>{ + return std::make_shared<Op_bsr>(args); + }) && + registerOp(mangleName<Asm::Args::Register32, Asm::Args::Mem32Ptr64>("bsr"), [](const Asm::Args& args) -> std::shared_ptr<Op>{ + return std::make_shared<Op_bsr>(args); + }) && + registerOp(mangleName<Asm::Args::Register64, Asm::Args::Mem64Ptr64>("bsr"), [](const Asm::Args& args) -> std::shared_ptr<Op>{ + return std::make_shared<Op_bsr>(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 <asm/assembler.h> + +class Op_bsr: public Op +{ +public: + Op_bsr(const Asm::Args& args); + +public: + 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/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 <boost/endian/conversion.hpp> @@ -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<FlowGraph::UnaryOperation&>(*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<FlowGraph::Constant&>(*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<const uint32_t*>(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<int>(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 <asm/assembler.h> +#include <asm/operators.h> + +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<uint8_t>{ 0xF6 } + ModRM("/3", std::any_cast<Asm::Args::Register8>(args[0]).name()); + + } else if (args[0].type() == typeid(Asm::Args::Register32)) { // neg reg32 + machine_code = std::vector<uint8_t>{ 0xF7 } + ModRM("/3", std::any_cast<Asm::Args::Register32>(args[0]).name()); + + } else if (args[0].type() == typeid(Asm::Args::Register64)) { // neg reg64 + machine_code = REX("W") + std::vector<uint8_t>{ 0xF7 } + ModRM("/3", std::any_cast<Asm::Args::Register32>(args[0]).name()); + + } else if (args[0].type() == typeid(Asm::Args::Mem8Ptr64)) { // neg byte ptr [reg64] + machine_code = std::vector<uint8_t>{ 0xF6 } + ModRM("/3", std::any_cast<Asm::Args::Register8>(args[0]).name()); + + } else if (args[0].type() == typeid(Asm::Args::Mem32Ptr64)) { // neg dword ptr [reg64] + machine_code = std::vector<uint8_t>{ 0xF7 } + ModRM("/3", std::any_cast<Asm::Args::Register32>(args[0]).name()); + + } else if (args[0].type() == typeid(Asm::Args::Mem64Ptr64)) { // neg qword ptr [reg64] + machine_code = REX("W") + std::vector<uint8_t>{ 0xF7 } + ModRM("/3", std::any_cast<Asm::Args::Register32>(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<Asm::Args::Register8>("neg"), [](const Asm::Args& args) -> std::shared_ptr<Op>{ + return std::make_shared<Op_neg>(args); + }) && + registerOp(mangleName<Asm::Args::Register32>("neg"), [](const Asm::Args& args) -> std::shared_ptr<Op>{ + return std::make_shared<Op_neg>(args); + }) && + registerOp(mangleName<Asm::Args::Register64>("neg"), [](const Asm::Args& args) -> std::shared_ptr<Op>{ + return std::make_shared<Op_neg>(args); + }) && + registerOp(mangleName<Asm::Args::Mem8Ptr64>("neg"), [](const Asm::Args& args) -> std::shared_ptr<Op>{ + return std::make_shared<Op_neg>(args); + }) && + registerOp(mangleName<Asm::Args::Mem32Ptr64>("neg"), [](const Asm::Args& args) -> std::shared_ptr<Op>{ + return std::make_shared<Op_neg>(args); + }) && + registerOp(mangleName<Asm::Args::Mem64Ptr64>("neg"), [](const Asm::Args& args) -> std::shared_ptr<Op>{ + return std::make_shared<Op_neg>(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 <asm/assembler.h> + +class Op_neg: public Op +{ +public: + Op_neg(const Asm::Args& args); + +public: + 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/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 <asm/assembler.h> +#include <asm/operators.h> + +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<uint8_t>{ 0xF6 } + ModRM("/2", std::any_cast<Asm::Args::Register8>(args[0]).name()); + + } else if (args[0].type() == typeid(Asm::Args::Register32)) { // not reg32 + machine_code = std::vector<uint8_t>{ 0xF7 } + ModRM("/2", std::any_cast<Asm::Args::Register32>(args[0]).name()); + + } else if (args[0].type() == typeid(Asm::Args::Register64)) { // not reg64 + machine_code = REX("W") + std::vector<uint8_t>{ 0xF7 } + ModRM("/2", std::any_cast<Asm::Args::Register32>(args[0]).name()); + + } else if (args[0].type() == typeid(Asm::Args::Mem8Ptr64)) { // not byte ptr [reg64] + machine_code = std::vector<uint8_t>{ 0xF6 } + ModRM("/2", std::any_cast<Asm::Args::Register8>(args[0]).name()); + + } else if (args[0].type() == typeid(Asm::Args::Mem32Ptr64)) { // not dword ptr [reg64] + machine_code = std::vector<uint8_t>{ 0xF7 } + ModRM("/2", std::any_cast<Asm::Args::Register32>(args[0]).name()); + + } else if (args[0].type() == typeid(Asm::Args::Mem64Ptr64)) { // not qword ptr [reg64] + machine_code = REX("W") + std::vector<uint8_t>{ 0xF7 } + ModRM("/2", std::any_cast<Asm::Args::Register32>(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<Asm::Args::Register8>("not"), [](const Asm::Args& args) -> std::shared_ptr<Op>{ + return std::make_shared<Op_not>(args); + }) && + registerOp(mangleName<Asm::Args::Register32>("not"), [](const Asm::Args& args) -> std::shared_ptr<Op>{ + return std::make_shared<Op_not>(args); + }) && + registerOp(mangleName<Asm::Args::Register64>("not"), [](const Asm::Args& args) -> std::shared_ptr<Op>{ + return std::make_shared<Op_not>(args); + }) && + registerOp(mangleName<Asm::Args::Mem8Ptr64>("not"), [](const Asm::Args& args) -> std::shared_ptr<Op>{ + return std::make_shared<Op_not>(args); + }) && + registerOp(mangleName<Asm::Args::Mem32Ptr64>("not"), [](const Asm::Args& args) -> std::shared_ptr<Op>{ + return std::make_shared<Op_not>(args); + }) && + registerOp(mangleName<Asm::Args::Mem64Ptr64>("not"), [](const Asm::Args& args) -> std::shared_ptr<Op>{ + return std::make_shared<Op_not>(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 <asm/assembler.h> + +class Op_not: public Op +{ +public: + Op_not(const Asm::Args& args); + +public: + 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/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 <asm/assembler.h> +#include <asm/operators.h> + +using namespace std::string_literals; + +Op_rcl::Op_rcl(const Asm::Args& args) +{ + if (args[1].type() == typeid(Asm::Args::Immediate8)) { + std::vector<uint8_t> shift_offset{std::any_cast<Asm::Args::Immediate8>(args[1]).getCode()}; + if (shift_offset == std::vector<uint8_t>{ 0x01 }) { // 1 bit version is shorter + if (args[0].type() == typeid(Asm::Args::Register8)) { // rcl reg8, 1 + machine_code = std::vector<uint8_t>{ 0xD0 } + ModRM("/2", std::any_cast<Asm::Args::Register8>(args[0]).name()); + } else if (args[0].type() == typeid(Asm::Args::Register32)) { // rcl reg32, 1 + machine_code = std::vector<uint8_t>{ 0xD1 } + ModRM("/2", std::any_cast<Asm::Args::Register8>(args[0]).name()); + } else if (args[0].type() == typeid(Asm::Args::Register64)) { // rcl reg64, 1 + machine_code = REX("W") + std::vector<uint8_t>{ 0xD1 } + ModRM("/2", std::any_cast<Asm::Args::Register8>(args[0]).name()); + } + } else { // general version >= 2 bits shift + if (args[0].type() == typeid(Asm::Args::Register8)) { // rcl reg8, imm8 + machine_code = std::vector<uint8_t>{ 0xC0 } + ModRM("/2", std::any_cast<Asm::Args::Register8>(args[0]).name()) + shift_offset; + } else if (args[0].type() == typeid(Asm::Args::Register32)) { // rcl reg32, imm8 + machine_code = std::vector<uint8_t>{ 0xC1 } + ModRM("/2", std::any_cast<Asm::Args::Register8>(args[0]).name()) + shift_offset; + } else if (args[0].type() == typeid(Asm::Args::Register64)) { // rcl reg64, imm8 + machine_code = REX("W") + std::vector<uint8_t>{ 0xC1 } + ModRM("/2", std::any_cast<Asm::Args::Register8>(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<Asm::Args::Register8, Asm::Args::Immediate8>("rcl"), [](const Asm::Args& args) -> std::shared_ptr<Op>{ + return std::make_shared<Op_rcl>(args); + }) && + registerOp(mangleName<Asm::Args::Register32, Asm::Args::Immediate8>("rcl"), [](const Asm::Args& args) -> std::shared_ptr<Op>{ + return std::make_shared<Op_rcl>(args); + }) && + registerOp(mangleName<Asm::Args::Register64, Asm::Args::Immediate8>("rcl"), [](const Asm::Args& args) -> std::shared_ptr<Op>{ + return std::make_shared<Op_rcl>(args); + }) && + registerOp(mangleName<Asm::Args::Mem8Ptr64, Asm::Args::Immediate8>("rcl"), [](const Asm::Args& args) -> std::shared_ptr<Op>{ + return std::make_shared<Op_rcl>(args); + }) && + registerOp(mangleName<Asm::Args::Mem32Ptr64, Asm::Args::Immediate8>("rcl"), [](const Asm::Args& args) -> std::shared_ptr<Op>{ + return std::make_shared<Op_rcl>(args); + }) && + registerOp(mangleName<Asm::Args::Mem64Ptr64, Asm::Args::Immediate8>("rcl"), [](const Asm::Args& args) -> std::shared_ptr<Op>{ + return std::make_shared<Op_rcl>(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 <asm/assembler.h> + +class Op_rcl: public Op +{ +public: + Op_rcl(const Asm::Args& args); + +public: + 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/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 <asm/assembler.h> +#include <asm/operators.h> + +using namespace std::string_literals; + +Op_rcr::Op_rcr(const Asm::Args& args) +{ + if (args[1].type() == typeid(Asm::Args::Immediate8)) { + std::vector<uint8_t> shift_offset{std::any_cast<Asm::Args::Immediate8>(args[1]).getCode()}; + if (shift_offset == std::vector<uint8_t>{ 0x01 }) { // 1 bit version is shorter + if (args[0].type() == typeid(Asm::Args::Register8)) { // rcr reg8, 1 + machine_code = std::vector<uint8_t>{ 0xD0 } + ModRM("/3", std::any_cast<Asm::Args::Register8>(args[0]).name()); + } else if (args[0].type() == typeid(Asm::Args::Register32)) { // rcr reg32, 1 + machine_code = std::vector<uint8_t>{ 0xD1 } + ModRM("/3", std::any_cast<Asm::Args::Register8>(args[0]).name()); + } else if (args[0].type() == typeid(Asm::Args::Register64)) { // rcr reg64, 1 + machine_code = REX("W") + std::vector<uint8_t>{ 0xD1 } + ModRM("/3", std::any_cast<Asm::Args::Register8>(args[0]).name()); + } + } else { // general version >= 2 bits shift + if (args[0].type() == typeid(Asm::Args::Register8)) { // rcr reg8, imm8 + machine_code = std::vector<uint8_t>{ 0xC0 } + ModRM("/3", std::any_cast<Asm::Args::Register8>(args[0]).name()) + shift_offset; + } else if (args[0].type() == typeid(Asm::Args::Register32)) { // rcr reg32, imm8 + machine_code = std::vector<uint8_t>{ 0xC1 } + ModRM("/3", std::any_cast<Asm::Args::Register8>(args[0]).name()) + shift_offset; + } else if (args[0].type() == typeid(Asm::Args::Register64)) { // rcr reg64, imm8 + machine_code = REX("W") + std::vector<uint8_t>{ 0xC1 } + ModRM("/3", std::any_cast<Asm::Args::Register8>(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<Asm::Args::Register8, Asm::Args::Immediate8>("rcr"), [](const Asm::Args& args) -> std::shared_ptr<Op>{ + return std::make_shared<Op_rcr>(args); + }) && + registerOp(mangleName<Asm::Args::Register32, Asm::Args::Immediate8>("rcr"), [](const Asm::Args& args) -> std::shared_ptr<Op>{ + return std::make_shared<Op_rcr>(args); + }) && + registerOp(mangleName<Asm::Args::Register64, Asm::Args::Immediate8>("rcr"), [](const Asm::Args& args) -> std::shared_ptr<Op>{ + return std::make_shared<Op_rcr>(args); + }) && + registerOp(mangleName<Asm::Args::Mem8Ptr64, Asm::Args::Immediate8>("rcr"), [](const Asm::Args& args) -> std::shared_ptr<Op>{ + return std::make_shared<Op_rcr>(args); + }) && + registerOp(mangleName<Asm::Args::Mem32Ptr64, Asm::Args::Immediate8>("rcr"), [](const Asm::Args& args) -> std::shared_ptr<Op>{ + return std::make_shared<Op_rcr>(args); + }) && + registerOp(mangleName<Asm::Args::Mem64Ptr64, Asm::Args::Immediate8>("rcr"), [](const Asm::Args& args) -> std::shared_ptr<Op>{ + return std::make_shared<Op_rcr>(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 <asm/assembler.h> + +class Op_rcr: public Op +{ +public: + Op_rcr(const Asm::Args& args); + +public: + 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/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 <asm/assembler.h> +#include <asm/operators.h> + +using namespace std::string_literals; + +Op_rol::Op_rol(const Asm::Args& args) +{ + if (args[1].type() == typeid(Asm::Args::Immediate8)) { + std::vector<uint8_t> shift_offset{std::any_cast<Asm::Args::Immediate8>(args[1]).getCode()}; + if (shift_offset == std::vector<uint8_t>{ 0x01 }) { // 1 bit version is shorter + if (args[0].type() == typeid(Asm::Args::Register8)) { // rol reg8, 1 + machine_code = std::vector<uint8_t>{ 0xD0 } + ModRM("/0", std::any_cast<Asm::Args::Register8>(args[0]).name()); + } else if (args[0].type() == typeid(Asm::Args::Register32)) { // rol reg32, 1 + machine_code = std::vector<uint8_t>{ 0xD1 } + ModRM("/0", std::any_cast<Asm::Args::Register8>(args[0]).name()); + } else if (args[0].type() == typeid(Asm::Args::Register64)) { // rol reg64, 1 + machine_code = REX("W") + std::vector<uint8_t>{ 0xD1 } + ModRM("/0", std::any_cast<Asm::Args::Register8>(args[0]).name()); + } + } else { // general version >= 2 bits shift + if (args[0].type() == typeid(Asm::Args::Register8)) { // rol reg8, imm8 + machine_code = std::vector<uint8_t>{ 0xC0 } + ModRM("/0", std::any_cast<Asm::Args::Register8>(args[0]).name()) + shift_offset; + } else if (args[0].type() == typeid(Asm::Args::Register32)) { // rol reg32, imm8 + machine_code = std::vector<uint8_t>{ 0xC1 } + ModRM("/0", std::any_cast<Asm::Args::Register8>(args[0]).name()) + shift_offset; + } else if (args[0].type() == typeid(Asm::Args::Register64)) { // rol reg64, imm8 + machine_code = REX("W") + std::vector<uint8_t>{ 0xC1 } + ModRM("/0", std::any_cast<Asm::Args::Register8>(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<Asm::Args::Register8, Asm::Args::Immediate8>("rol"), [](const Asm::Args& args) -> std::shared_ptr<Op>{ + return std::make_shared<Op_rol>(args); + }) && + registerOp(mangleName<Asm::Args::Register32, Asm::Args::Immediate8>("rol"), [](const Asm::Args& args) -> std::shared_ptr<Op>{ + return std::make_shared<Op_rol>(args); + }) && + registerOp(mangleName<Asm::Args::Register64, Asm::Args::Immediate8>("rol"), [](const Asm::Args& args) -> std::shared_ptr<Op>{ + return std::make_shared<Op_rol>(args); + }) && + registerOp(mangleName<Asm::Args::Mem8Ptr64, Asm::Args::Immediate8>("rol"), [](const Asm::Args& args) -> std::shared_ptr<Op>{ + return std::make_shared<Op_rol>(args); + }) && + registerOp(mangleName<Asm::Args::Mem32Ptr64, Asm::Args::Immediate8>("rol"), [](const Asm::Args& args) -> std::shared_ptr<Op>{ + return std::make_shared<Op_rol>(args); + }) && + registerOp(mangleName<Asm::Args::Mem64Ptr64, Asm::Args::Immediate8>("rol"), [](const Asm::Args& args) -> std::shared_ptr<Op>{ + return std::make_shared<Op_rol>(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 <asm/assembler.h> + +class Op_rol: public Op +{ +public: + Op_rol(const Asm::Args& args); + +public: + 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/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 <asm/assembler.h> +#include <asm/operators.h> + +using namespace std::string_literals; + +Op_ror::Op_ror(const Asm::Args& args) +{ + if (args[1].type() == typeid(Asm::Args::Immediate8)) { + std::vector<uint8_t> shift_offset{std::any_cast<Asm::Args::Immediate8>(args[1]).getCode()}; + if (shift_offset == std::vector<uint8_t>{ 0x01 }) { // 1 bit version is shorter + if (args[0].type() == typeid(Asm::Args::Register8)) { // ror reg8, 1 + machine_code = std::vector<uint8_t>{ 0xD0 } + ModRM("/1", std::any_cast<Asm::Args::Register8>(args[0]).name()); + } else if (args[0].type() == typeid(Asm::Args::Register32)) { // ror reg32, 1 + machine_code = std::vector<uint8_t>{ 0xD1 } + ModRM("/1", std::any_cast<Asm::Args::Register8>(args[0]).name()); + } else if (args[0].type() == typeid(Asm::Args::Register64)) { // ror reg64, 1 + machine_code = REX("W") + std::vector<uint8_t>{ 0xD1 } + ModRM("/1", std::any_cast<Asm::Args::Register8>(args[0]).name()); + } + } else { // general version >= 2 bits shift + if (args[0].type() == typeid(Asm::Args::Register8)) { // ror reg8, imm8 + machine_code = std::vector<uint8_t>{ 0xC0 } + ModRM("/1", std::any_cast<Asm::Args::Register8>(args[0]).name()) + shift_offset; + } else if (args[0].type() == typeid(Asm::Args::Register32)) { // ror reg32, imm8 + machine_code = std::vector<uint8_t>{ 0xC1 } + ModRM("/1", std::any_cast<Asm::Args::Register8>(args[0]).name()) + shift_offset; + } else if (args[0].type() == typeid(Asm::Args::Register64)) { // ror reg64, imm8 + machine_code = REX("W") + std::vector<uint8_t>{ 0xC1 } + ModRM("/1", std::any_cast<Asm::Args::Register8>(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<Asm::Args::Register8, Asm::Args::Immediate8>("ror"), [](const Asm::Args& args) -> std::shared_ptr<Op>{ + return std::make_shared<Op_ror>(args); + }) && + registerOp(mangleName<Asm::Args::Register32, Asm::Args::Immediate8>("ror"), [](const Asm::Args& args) -> std::shared_ptr<Op>{ + return std::make_shared<Op_ror>(args); + }) && + registerOp(mangleName<Asm::Args::Register64, Asm::Args::Immediate8>("ror"), [](const Asm::Args& args) -> std::shared_ptr<Op>{ + return std::make_shared<Op_ror>(args); + }) && + registerOp(mangleName<Asm::Args::Mem8Ptr64, Asm::Args::Immediate8>("ror"), [](const Asm::Args& args) -> std::shared_ptr<Op>{ + return std::make_shared<Op_ror>(args); + }) && + registerOp(mangleName<Asm::Args::Mem32Ptr64, Asm::Args::Immediate8>("ror"), [](const Asm::Args& args) -> std::shared_ptr<Op>{ + return std::make_shared<Op_ror>(args); + }) && + registerOp(mangleName<Asm::Args::Mem64Ptr64, Asm::Args::Immediate8>("ror"), [](const Asm::Args& args) -> std::shared_ptr<Op>{ + return std::make_shared<Op_ror>(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 <asm/assembler.h> + +class Op_ror: public Op +{ +public: + Op_ror(const Asm::Args& args); + +public: + 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/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 <asm/assembler.h> +#include <asm/operators.h> + +using namespace std::string_literals; + +Op_sal::Op_sal(const Asm::Args& args) +{ + if (args[1].type() == typeid(Asm::Args::Immediate8)) { + std::vector<uint8_t> shift_offset{std::any_cast<Asm::Args::Immediate8>(args[1]).getCode()}; + if (shift_offset == std::vector<uint8_t>{ 0x01 }) { // 1 bit version is shorter + if (args[0].type() == typeid(Asm::Args::Register8)) { // sal reg8, 1 + machine_code = std::vector<uint8_t>{ 0xD0 } + ModRM("/4", std::any_cast<Asm::Args::Register8>(args[0]).name()); + } else if (args[0].type() == typeid(Asm::Args::Register32)) { // sal reg32, 1 + machine_code = std::vector<uint8_t>{ 0xD1 } + ModRM("/4", std::any_cast<Asm::Args::Register8>(args[0]).name()); + } else if (args[0].type() == typeid(Asm::Args::Register64)) { // sal reg64, 1 + machine_code = REX("W") + std::vector<uint8_t>{ 0xD1 } + ModRM("/4", std::any_cast<Asm::Args::Register8>(args[0]).name()); + } + } else { // general version >= 2 bits shift + if (args[0].type() == typeid(Asm::Args::Register8)) { // sal reg8, imm8 + machine_code = std::vector<uint8_t>{ 0xC0 } + ModRM("/4", std::any_cast<Asm::Args::Register8>(args[0]).name()) + shift_offset; + } else if (args[0].type() == typeid(Asm::Args::Register32)) { // sal reg32, imm8 + machine_code = std::vector<uint8_t>{ 0xC1 } + ModRM("/4", std::any_cast<Asm::Args::Register8>(args[0]).name()) + shift_offset; + } else if (args[0].type() == typeid(Asm::Args::Register64)) { // sal reg64, imm8 + machine_code = REX("W") + std::vector<uint8_t>{ 0xC1 } + ModRM("/4", std::any_cast<Asm::Args::Register8>(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<Asm::Args::Register8, Asm::Args::Immediate8>("sal"), [](const Asm::Args& args) -> std::shared_ptr<Op>{ + return std::make_shared<Op_sal>(args); + }) && + registerOp(mangleName<Asm::Args::Register32, Asm::Args::Immediate8>("sal"), [](const Asm::Args& args) -> std::shared_ptr<Op>{ + return std::make_shared<Op_sal>(args); + }) && + registerOp(mangleName<Asm::Args::Register64, Asm::Args::Immediate8>("sal"), [](const Asm::Args& args) -> std::shared_ptr<Op>{ + return std::make_shared<Op_sal>(args); + }) && + registerOp(mangleName<Asm::Args::Mem8Ptr64, Asm::Args::Immediate8>("sal"), [](const Asm::Args& args) -> std::shared_ptr<Op>{ + return std::make_shared<Op_sal>(args); + }) && + registerOp(mangleName<Asm::Args::Mem32Ptr64, Asm::Args::Immediate8>("sal"), [](const Asm::Args& args) -> std::shared_ptr<Op>{ + return std::make_shared<Op_sal>(args); + }) && + registerOp(mangleName<Asm::Args::Mem64Ptr64, Asm::Args::Immediate8>("sal"), [](const Asm::Args& args) -> std::shared_ptr<Op>{ + return std::make_shared<Op_sal>(args); + }) && + registerOp(mangleName<Asm::Args::Register8, Asm::Args::Immediate8>("shl"), [](const Asm::Args& args) -> std::shared_ptr<Op>{ + return std::make_shared<Op_sal>(args); + }) && + registerOp(mangleName<Asm::Args::Register32, Asm::Args::Immediate8>("shl"), [](const Asm::Args& args) -> std::shared_ptr<Op>{ + return std::make_shared<Op_sal>(args); + }) && + registerOp(mangleName<Asm::Args::Register64, Asm::Args::Immediate8>("shl"), [](const Asm::Args& args) -> std::shared_ptr<Op>{ + return std::make_shared<Op_sal>(args); + }) && + registerOp(mangleName<Asm::Args::Mem8Ptr64, Asm::Args::Immediate8>("shl"), [](const Asm::Args& args) -> std::shared_ptr<Op>{ + return std::make_shared<Op_sal>(args); + }) && + registerOp(mangleName<Asm::Args::Mem32Ptr64, Asm::Args::Immediate8>("shl"), [](const Asm::Args& args) -> std::shared_ptr<Op>{ + return std::make_shared<Op_sal>(args); + }) && + registerOp(mangleName<Asm::Args::Mem64Ptr64, Asm::Args::Immediate8>("shl"), [](const Asm::Args& args) -> std::shared_ptr<Op>{ + return std::make_shared<Op_sal>(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 <asm/assembler.h> + +class Op_sal: public Op +{ +public: + Op_sal(const Asm::Args& args); + +public: + 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/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 <asm/assembler.h> +#include <asm/operators.h> + +using namespace std::string_literals; + +Op_sar::Op_sar(const Asm::Args& args) +{ + if (args[1].type() == typeid(Asm::Args::Immediate8)) { + std::vector<uint8_t> shift_offset{std::any_cast<Asm::Args::Immediate8>(args[1]).getCode()}; + if (shift_offset == std::vector<uint8_t>{ 0x01 }) { // 1 bit version is shorter + if (args[0].type() == typeid(Asm::Args::Register8)) { // sar reg8, 1 + machine_code = std::vector<uint8_t>{ 0xD0 } + ModRM("/7", std::any_cast<Asm::Args::Register8>(args[0]).name()); + } else if (args[0].type() == typeid(Asm::Args::Register32)) { // sar reg32, 1 + machine_code = std::vector<uint8_t>{ 0xD1 } + ModRM("/7", std::any_cast<Asm::Args::Register8>(args[0]).name()); + } else if (args[0].type() == typeid(Asm::Args::Register64)) { // sar reg64, 1 + machine_code = REX("W") + std::vector<uint8_t>{ 0xD1 } + ModRM("/7", std::any_cast<Asm::Args::Register8>(args[0]).name()); + } + } else { // general version >= 2 bits shift + if (args[0].type() == typeid(Asm::Args::Register8)) { // sar reg8, imm8 + machine_code = std::vector<uint8_t>{ 0xC0 } + ModRM("/7", std::any_cast<Asm::Args::Register8>(args[0]).name()) + shift_offset; + } else if (args[0].type() == typeid(Asm::Args::Register32)) { // sar reg32, imm8 + machine_code = std::vector<uint8_t>{ 0xC1 } + ModRM("/7", std::any_cast<Asm::Args::Register8>(args[0]).name()) + shift_offset; + } else if (args[0].type() == typeid(Asm::Args::Register64)) { // sar reg64, imm8 + machine_code = REX("W") + std::vector<uint8_t>{ 0xC1 } + ModRM("/7", std::any_cast<Asm::Args::Register8>(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<Asm::Args::Register8, Asm::Args::Immediate8>("sar"), [](const Asm::Args& args) -> std::shared_ptr<Op>{ + return std::make_shared<Op_sar>(args); + }) && + registerOp(mangleName<Asm::Args::Register32, Asm::Args::Immediate8>("sar"), [](const Asm::Args& args) -> std::shared_ptr<Op>{ + return std::make_shared<Op_sar>(args); + }) && + registerOp(mangleName<Asm::Args::Register64, Asm::Args::Immediate8>("sar"), [](const Asm::Args& args) -> std::shared_ptr<Op>{ + return std::make_shared<Op_sar>(args); + }) && + registerOp(mangleName<Asm::Args::Mem8Ptr64, Asm::Args::Immediate8>("sar"), [](const Asm::Args& args) -> std::shared_ptr<Op>{ + return std::make_shared<Op_sar>(args); + }) && + registerOp(mangleName<Asm::Args::Mem32Ptr64, Asm::Args::Immediate8>("sar"), [](const Asm::Args& args) -> std::shared_ptr<Op>{ + return std::make_shared<Op_sar>(args); + }) && + registerOp(mangleName<Asm::Args::Mem64Ptr64, Asm::Args::Immediate8>("sar"), [](const Asm::Args& args) -> std::shared_ptr<Op>{ + return std::make_shared<Op_sar>(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 <asm/assembler.h> + +class Op_sar: public Op +{ +public: + Op_sar(const Asm::Args& args); + +public: + 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/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 <asm/assembler.h> +#include <asm/operators.h> + +using namespace std::string_literals; + +Op_shr::Op_shr(const Asm::Args& args) +{ + if (args[1].type() == typeid(Asm::Args::Immediate8)) { + std::vector<uint8_t> shift_offset{std::any_cast<Asm::Args::Immediate8>(args[1]).getCode()}; + if (shift_offset == std::vector<uint8_t>{ 0x01 }) { // 1 bit version is shorter + if (args[0].type() == typeid(Asm::Args::Register8)) { // shr reg8, 1 + machine_code = std::vector<uint8_t>{ 0xD0 } + ModRM("/5", std::any_cast<Asm::Args::Register8>(args[0]).name()); + } else if (args[0].type() == typeid(Asm::Args::Register32)) { // shr reg32, 1 + machine_code = std::vector<uint8_t>{ 0xD1 } + ModRM("/5", std::any_cast<Asm::Args::Register8>(args[0]).name()); + } else if (args[0].type() == typeid(Asm::Args::Register64)) { // shr reg64, 1 + machine_code = REX("W") + std::vector<uint8_t>{ 0xD1 } + ModRM("/5", std::any_cast<Asm::Args::Register8>(args[0]).name()); + } + } else { // general version >= 2 bits shift + if (args[0].type() == typeid(Asm::Args::Register8)) { // shr reg8, imm8 + machine_code = std::vector<uint8_t>{ 0xC0 } + ModRM("/5", std::any_cast<Asm::Args::Register8>(args[0]).name()) + shift_offset; + } else if (args[0].type() == typeid(Asm::Args::Register32)) { // shr reg32, imm8 + machine_code = std::vector<uint8_t>{ 0xC1 } + ModRM("/5", std::any_cast<Asm::Args::Register8>(args[0]).name()) + shift_offset; + } else if (args[0].type() == typeid(Asm::Args::Register64)) { // shr reg64, imm8 + machine_code = REX("W") + std::vector<uint8_t>{ 0xC1 } + ModRM("/5", std::any_cast<Asm::Args::Register8>(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<Asm::Args::Register8, Asm::Args::Immediate8>("shr"), [](const Asm::Args& args) -> std::shared_ptr<Op>{ + return std::make_shared<Op_shr>(args); + }) && + registerOp(mangleName<Asm::Args::Register32, Asm::Args::Immediate8>("shr"), [](const Asm::Args& args) -> std::shared_ptr<Op>{ + return std::make_shared<Op_shr>(args); + }) && + registerOp(mangleName<Asm::Args::Register64, Asm::Args::Immediate8>("shr"), [](const Asm::Args& args) -> std::shared_ptr<Op>{ + return std::make_shared<Op_shr>(args); + }) && + registerOp(mangleName<Asm::Args::Mem8Ptr64, Asm::Args::Immediate8>("shr"), [](const Asm::Args& args) -> std::shared_ptr<Op>{ + return std::make_shared<Op_shr>(args); + }) && + registerOp(mangleName<Asm::Args::Mem32Ptr64, Asm::Args::Immediate8>("shr"), [](const Asm::Args& args) -> std::shared_ptr<Op>{ + return std::make_shared<Op_shr>(args); + }) && + registerOp(mangleName<Asm::Args::Mem64Ptr64, Asm::Args::Immediate8>("shr"), [](const Asm::Args& args) -> std::shared_ptr<Op>{ + return std::make_shared<Op_shr>(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 <asm/assembler.h> + +class Op_shr: public Op +{ +public: + Op_shr(const Asm::Args& args); + +public: + 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/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 <asm/assembler.h> -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<Op>{ + return std::make_shared<Op_lahf>(); + }) && registerOp("nop", [](const Asm::Args& args) -> std::shared_ptr<Op>{ return std::make_shared<Op_nop>(); }) && @@ -17,6 +22,9 @@ bool registered { }) && registerOp("syscall", [](const Asm::Args& args) -> std::shared_ptr<Op>{ return std::make_shared<Op_syscall>(); + }) && + registerOp("ud2", [](const Asm::Args& args) -> std::shared_ptr<Op>{ + return std::make_shared<Op_ud2>(); }) }; 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 <asm/chunk.h> +// 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<Chunk> 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 <memory> +#include <string> + +std::shared_ptr<Chunk> 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 |