summaryrefslogtreecommitdiffhomepage
path: root/asm
diff options
context:
space:
mode:
authorRoland Reichwein <mail@reichwein.it>2020-11-14 22:06:10 +0100
committerRoland Reichwein <mail@reichwein.it>2020-11-14 22:06:10 +0100
commit9e7f4c9d43b310c280cd6432cd4150411f4b914e (patch)
treec7be57a91602c228f05ff1cab2f186dcc6635733 /asm
parent009e450626194299ee4b5ccb8463ac64e127fde6 (diff)
Added system tests
Diffstat (limited to 'asm')
-rw-r--r--asm/intel64/encode.cpp141
1 files changed, 87 insertions, 54 deletions
diff --git a/asm/intel64/encode.cpp b/asm/intel64/encode.cpp
index 702efaf..b26bf9c 100644
--- a/asm/intel64/encode.cpp
+++ b/asm/intel64/encode.cpp
@@ -13,61 +13,94 @@ 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");
+ if (node.get()) {
+ auto& node_deref = *node.get();
+ if (typeid(node_deref) == typeid(FlowGraph::UnaryOperation)) {
+ 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::Store) {
+ Asm::Args args1{{Asm::Args::Register32("edi"), Asm::Args::Immediate32(immediate1)}};
+ segment.push_back(makeOp("mov", args1));
+ } else
+ throw std::runtime_error("ICE: Asm: Unsupported unary operation type: "s + std::to_string(static_cast<int>(op.type())));
+
+ } else if (typeid(node_deref) == typeid(FlowGraph::BinaryOperation)) {
+ 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)}};
+
+ if (op.type() == FlowGraph::BinaryOperationType::Add)
+ segment.push_back(makeOp("add", args2));
+ else if (op.type() == FlowGraph::BinaryOperationType::Multiply)
+ segment.push_back(makeOp("mul", args2));
+ else
+ throw std::runtime_error("ICE: Asm: Unsupported binary operation type: "s + std::to_string(static_cast<int>(op.type())));
+
+ } else {
+ throw std::runtime_error("ICE: Encoding: Unsupported node");
}
-
- 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)}};
-
- if (op.type() == FlowGraph::BinaryOperationType::Add)
- segment.push_back(makeOp("add", args2));
- else if (op.type() == FlowGraph::BinaryOperationType::Multiply)
- segment.push_back(makeOp("mul", args2));
- else
- throw std::runtime_error("ICE: Asm: Unsupported binary operation type: "s + std::to_string(static_cast<int>(FlowGraph::BinaryOperationType::Multiply)));
-
- } catch (const std::bad_cast& ex) {
- std::runtime_error("ICE: Encoding: Unsupported node: "s + ex.what());
+ } else {
+ throw std::runtime_error("ICE: encode: flowgraph node is null");
}
}
}