summaryrefslogtreecommitdiffhomepage
path: root/asm/intel64/encode.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'asm/intel64/encode.cpp')
-rw-r--r--asm/intel64/encode.cpp45
1 files changed, 23 insertions, 22 deletions
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));