summaryrefslogtreecommitdiffhomepage
path: root/asm/intel64
diff options
context:
space:
mode:
authorRoland Reichwein <mail@reichwein.it>2020-11-09 10:40:16 +0100
committerRoland Reichwein <mail@reichwein.it>2020-11-09 10:40:16 +0100
commit414953eba1b1cc3570da1e59dc2392ce1b1ae5ef (patch)
tree3b4ab9ebefd57e847b99195887d5b221be2423ae /asm/intel64
parent6ab3715ee2622e293f7c4924511f31347b327e6e (diff)
Move encode.h|cpp to intel specific
Diffstat (limited to 'asm/intel64')
-rw-r--r--asm/intel64/encode.cpp68
-rw-r--r--asm/intel64/encode.h14
2 files changed, 82 insertions, 0 deletions
diff --git a/asm/intel64/encode.cpp b/asm/intel64/encode.cpp
new file mode 100644
index 0000000..8bf33c0
--- /dev/null
+++ b/asm/intel64/encode.cpp
@@ -0,0 +1,68 @@
+// Intel specific conversion: Abstract Graph -> Machine specific segment
+#include "encode.h"
+
+#include "asm/assembler.h"
+#include "minicc.h"
+
+#include <boost/endian/conversion.hpp>
+
+#include <exception>
+
+void Asm::toMachineCode(const FlowGraph::Graph& graph, Segment& segment)
+{
+ segment.clear();
+
+ for (const std::shared_ptr<FlowGraph::Node>& node: graph) {
+ try {
+ FlowGraph::BinaryOperation& op {dynamic_cast<FlowGraph::BinaryOperation&>(*node)};
+
+ auto operands {op.operands()};
+ // TODO: ignore destination (0) for now
+
+ 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[2].type() != FlowGraph::DataType::Int) {
+ std::runtime_error("Bad type for operand 2: "s + std::to_string(int(operands[2].type())));
+ }
+
+ if (!operands[1].storage())
+ throw std::runtime_error("ICE: Operand 1 storage is 0");
+ if (!operands[2].storage())
+ throw std::runtime_error("ICE: Operand 2 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");
+ }
+
+ uint32_t immediate2{};
+ try {
+ FlowGraph::Constant& value2 {dynamic_cast<FlowGraph::Constant&>(*operands[2].storage())};
+ if (value2.value().size() < sizeof(uint32_t))
+ throw std::runtime_error("ICE: Int data from operand 2 needs at least 4 bytes, got "s + std::to_string(value2.value().size()));
+
+ immediate2 = boost::endian::little_to_native(*(reinterpret_cast<const uint32_t*>(value2.value().data())));
+ } catch (const std::bad_cast& ex) {
+ std::runtime_error("Bad value for operand 2: Constant expected");
+ }
+
+ Asm::Args args1{{Asm::Args::Register32("edi"), Asm::Args::Immediate32(immediate1)}};
+ segment.push_back(makeOp("mov", args1));
+
+ Asm::Args args2{{Asm::Args::Register32("edi"), Asm::Args::Immediate32(immediate2)}};
+ segment.push_back(makeOp("add", args2));
+
+ } catch (const std::bad_cast& ex) {
+ std::runtime_error("ICE: Encoding: Unsupported node: "s + ex.what());
+ }
+ }
+}
+
diff --git a/asm/intel64/encode.h b/asm/intel64/encode.h
new file mode 100644
index 0000000..7fd23d6
--- /dev/null
+++ b/asm/intel64/encode.h
@@ -0,0 +1,14 @@
+// Convert: Abstract FlowGraph to Machine dependent Code
+
+#pragma once
+
+#include "asm/segment.h"
+#include "flowgraph/graph.h"
+
+namespace Asm {
+
+// in: graph
+// out: segment
+void toMachineCode(const FlowGraph::Graph& graph, Segment& segment);
+
+} // namespace Asm