summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
-rw-r--r--Makefile1
-rw-r--r--asm/assembler.cpp182
-rw-r--r--asm/assembler.h77
-rw-r--r--asm/intel64/codes.cpp9
-rw-r--r--asm/intel64/codes.h2
-rw-r--r--asm/intel64/encode.cpp17
-rw-r--r--asm/intel64/mov.cpp8
-rw-r--r--asm/parse.cpp42
-rw-r--r--byteorder.cpp40
-rw-r--r--byteorder.h17
-rw-r--r--flowgraph/data.h2
-rw-r--r--flowgraph/node.cpp5
-rw-r--r--minicc.cpp14
-rw-r--r--minicc.h2
-rw-r--r--tests/test-asm.cpp9
15 files changed, 358 insertions, 69 deletions
diff --git a/Makefile b/Makefile
index 5182643..dd8347d 100644
--- a/Makefile
+++ b/Makefile
@@ -82,6 +82,7 @@ PROGSRC=\
asm/parse.cpp \
asm/segment.cpp \
bnf.cpp \
+ byteorder.cpp \
cpp.cpp \
cppbnf.cpp \
coff.cpp \
diff --git a/asm/assembler.cpp b/asm/assembler.cpp
index 35e971b..88481bc 100644
--- a/asm/assembler.cpp
+++ b/asm/assembler.cpp
@@ -1,7 +1,38 @@
#include "assembler.h"
+#include "byteorder.h"
+
using namespace std::string_literals;
+Asm::Args::Immediate8::Immediate8(uint8_t value): m_value(value)
+{}
+
+uint8_t Asm::Args::Immediate8::value() const
+{
+ return m_value;
+}
+
+std::vector<uint8_t> Asm::Args::Immediate8::getCode() const
+{
+ return {m_value};
+}
+
+Asm::Args::Immediate16::Immediate16(uint16_t value): m_value(value)
+{}
+
+uint16_t Asm::Args::Immediate16::value() const
+{
+ return m_value;
+}
+
+std::vector<uint8_t> Asm::Args::Immediate16::getCode() const
+{
+ return endian::to_little(m_value);
+}
+
+Asm::Args::Immediate32::Immediate32(uint32_t value): m_value(value)
+{}
+
Asm::Args::Immediate32::Immediate32(const Asm::Args::Immediate64& imm64)
{
if (imm64.value() < 0x100000000)
@@ -10,23 +41,144 @@ Asm::Args::Immediate32::Immediate32(const Asm::Args::Immediate64& imm64)
throw std::runtime_error("Immediate32: Constructed from too big Immediate64");
}
-Asm::Args::Mem8Ptr64::Mem8Ptr64(const std::string& reg, int32_t offs): m_reg(reg), m_offs(offs) {}
-Asm::Args::Mem8Ptr64::Mem8Ptr64(const std::string& reg, const std::string& reg2, int32_t offs): m_reg(reg), m_reg2(reg2), m_offs(offs) {}
-std::string Asm::Args::Mem8Ptr64::reg() const { return "["s + m_reg + "]"s; }
-std::string Asm::Args::Mem8Ptr64::reg2() const { return "["s + m_reg2 + "]"s; }
-int32_t Asm::Args::Mem8Ptr64::offs() const { return m_offs; }
+uint32_t Asm::Args::Immediate32::value() const
+{
+ return m_value;
+}
+
+std::vector<uint8_t> Asm::Args::Immediate32::getCode() const
+{
+ return endian::to_little(m_value);
+}
+
+Asm::Args::Immediate64::Immediate64(uint64_t value): m_value(value)
+{}
+
+uint64_t Asm::Args::Immediate64::value() const
+{
+ return m_value;
+}
+
+std::vector<uint8_t> Asm::Args::Immediate64::getCode() const
+{
+ return endian::to_little(m_value);
+}
+
+Asm::Args::Register8::Register8(const std::string& name): m_name(name)
+{}
+
+std::string Asm::Args::Register8::name() const
+{
+ return m_name;
+}
+
+Asm::Args::Register16::Register16(const std::string& name): m_name(name)
+{}
+
+std::string Asm::Args::Register16::name() const
+{
+ return m_name;
+}
+
+Asm::Args::Register32::Register32(const std::string& name): m_name(name)
+{}
+
+std::string Asm::Args::Register32::name() const
+{
+ return m_name;
+}
+
+Asm::Args::Register64::Register64(const std::string& name): m_name(name)
+{}
+
+std::string Asm::Args::Register64::name() const
+{
+ return m_name;
+}
+
+Asm::Args::Mem8Ptr64::Mem8Ptr64(const std::string& reg, int32_t offs): m_reg(reg), m_offs(offs)
+{}
+
+Asm::Args::Mem8Ptr64::Mem8Ptr64(const std::string& reg, const std::string& reg2, int32_t offs): m_reg(reg), m_reg2(reg2), m_offs(offs)
+{}
+
+std::string Asm::Args::Mem8Ptr64::reg() const
+{
+ return "["s + m_reg + "]"s;
+}
+
+std::string Asm::Args::Mem8Ptr64::reg2() const
+{
+ return "["s + m_reg2 + "]"s;
+}
+
+int32_t Asm::Args::Mem8Ptr64::offs() const
+{
+ return m_offs;
+}
+
+Asm::Args::Mem16Ptr64::Mem16Ptr64(const std::string& reg, int32_t offs): m_reg(reg), m_offs(offs)
+{}
+
+Asm::Args::Mem16Ptr64::Mem16Ptr64(const std::string& reg, const std::string& reg2, int32_t offs): m_reg(reg), m_reg2(reg2), m_offs(offs)
+{}
+
+std::string Asm::Args::Mem16Ptr64::reg() const
+{
+ return "["s + m_reg + "]"s;
+}
-Asm::Args::Mem32Ptr64::Mem32Ptr64(const std::string& reg, int32_t offs): m_reg(reg), m_offs(offs) {}
-Asm::Args::Mem32Ptr64::Mem32Ptr64(const std::string& reg, const std::string& reg2, int32_t offs): m_reg(reg), m_reg2(reg2), m_offs(offs) {}
-std::string Asm::Args::Mem32Ptr64::reg() const { return "["s + m_reg + "]"s; }
-std::string Asm::Args::Mem32Ptr64::reg2() const { return "["s + m_reg2 + "]"s; }
-int32_t Asm::Args::Mem32Ptr64::offs() const { return m_offs; }
+std::string Asm::Args::Mem16Ptr64::reg2() const
+{
+ return "["s + m_reg2 + "]"s;
+}
+
+int32_t Asm::Args::Mem16Ptr64::offs() const
+{
+ return m_offs;
+}
-Asm::Args::Mem64Ptr64::Mem64Ptr64(const std::string& reg, int32_t offs): m_reg(reg), m_offs(offs) {}
-Asm::Args::Mem64Ptr64::Mem64Ptr64(const std::string& reg, const std::string& reg2, int32_t offs): m_reg(reg), m_reg2(reg2), m_offs(offs) {}
-std::string Asm::Args::Mem64Ptr64::reg() const { return "["s + m_reg + "]"s; }
-std::string Asm::Args::Mem64Ptr64::reg2() const { return "["s + m_reg2 + "]"s; }
-int32_t Asm::Args::Mem64Ptr64::offs() const { return m_offs; }
+Asm::Args::Mem32Ptr64::Mem32Ptr64(const std::string& reg, int32_t offs): m_reg(reg), m_offs(offs)
+{}
+
+Asm::Args::Mem32Ptr64::Mem32Ptr64(const std::string& reg, const std::string& reg2, int32_t offs): m_reg(reg), m_reg2(reg2), m_offs(offs)
+{}
+
+std::string Asm::Args::Mem32Ptr64::reg() const
+{
+ return "["s + m_reg + "]"s;
+}
+
+std::string Asm::Args::Mem32Ptr64::reg2() const
+{
+ return "["s + m_reg2 + "]"s;
+}
+
+int32_t Asm::Args::Mem32Ptr64::offs() const
+{
+ return m_offs;
+}
+
+Asm::Args::Mem64Ptr64::Mem64Ptr64(const std::string& reg, int32_t offs): m_reg(reg), m_offs(offs)
+{}
+
+Asm::Args::Mem64Ptr64::Mem64Ptr64(const std::string& reg, const std::string& reg2, int32_t offs): m_reg(reg), m_reg2(reg2), m_offs(offs)
+{}
+
+std::string Asm::Args::Mem64Ptr64::reg() const
+{
+ return "["s + m_reg + "]"s;
+}
+
+std::string Asm::Args::Mem64Ptr64::reg2() const
+{
+ return "["s + m_reg2 + "]"s;
+}
+
+int32_t Asm::Args::Mem64Ptr64::offs() const
+{
+ return m_offs;
+}
namespace {
diff --git a/asm/assembler.h b/asm/assembler.h
index 1fdc658..12e7c4e 100644
--- a/asm/assembler.h
+++ b/asm/assembler.h
@@ -6,8 +6,6 @@
#include "../minicc.h"
-#include <boost/endian/conversion.hpp>
-
#include <any>
#include <functional>
#include <iostream>
@@ -27,27 +25,34 @@ public:
class Immediate8
{
public:
- Immediate8(uint8_t value): m_value(value) {}
- uint8_t value() const {return m_value;}
- std::vector<uint8_t> getCode() {return {m_value};};
+ Immediate8(uint8_t value);
+ uint8_t value() const;
+ std::vector<uint8_t> getCode() const;
private:
uint8_t m_value;
};
+ class Immediate16
+ {
+ public:
+ Immediate16(uint16_t value);
+ uint16_t value() const;
+ std::vector<uint8_t> getCode() const;
+
+ private:
+ uint16_t m_value;
+ };
+
class Immediate64;
class Immediate32
{
public:
- Immediate32(uint32_t value): m_value(value) {}
+ Immediate32(uint32_t value);
Immediate32(const Immediate64&); ///< Convert from Immediate64 if data is small enough
- uint32_t value() const { return m_value; }
- std::vector<uint8_t> getCode() {
- std::vector<uint8_t> result(size_t(4));
- *(reinterpret_cast<uint32_t*>(result.data())) = boost::endian::native_to_little(m_value);
- return result;
- };
+ uint32_t value() const;
+ std::vector<uint8_t> getCode() const;
private:
uint32_t m_value;
@@ -56,13 +61,9 @@ public:
class Immediate64
{
public:
- Immediate64(uint64_t value): m_value(value) {}
- uint64_t value() const { return m_value; }
- std::vector<uint8_t> getCode() {
- std::vector<uint8_t> result(size_t(8));
- *(reinterpret_cast<uint64_t*>(result.data())) = boost::endian::native_to_little(m_value);
- return result;
- };
+ Immediate64(uint64_t value);
+ uint64_t value() const;
+ std::vector<uint8_t> getCode() const;
private:
uint64_t m_value;
@@ -71,8 +72,18 @@ public:
class Register8
{
public:
- Register8(const std::string& name): m_name(name) {}
- std::string name() const { return m_name; }
+ Register8(const std::string& name);
+ std::string name() const;
+
+ private:
+ std::string m_name;
+ };
+
+ class Register16
+ {
+ public:
+ Register16(const std::string& name);
+ std::string name() const;
private:
std::string m_name;
@@ -81,8 +92,8 @@ public:
class Register32
{
public:
- Register32(const std::string& name): m_name(name) {}
- std::string name() const { return m_name; }
+ Register32(const std::string& name);
+ std::string name() const;
private:
std::string m_name;
@@ -91,8 +102,8 @@ public:
class Register64
{
public:
- Register64(const std::string& name): m_name(name) {}
- std::string name() const { return m_name; }
+ Register64(const std::string& name);
+ std::string name() const;
private:
std::string m_name;
@@ -114,6 +125,22 @@ public:
int32_t m_offs;
};
+ // 64 bit Ptr to 16 bit Memory
+ class Mem16Ptr64
+ {
+ public:
+ Mem16Ptr64(const std::string& reg, int32_t offs = 0);
+ Mem16Ptr64(const std::string& reg, const std::string& reg2, int32_t offs = 0);
+ std::string reg() const;
+ std::string reg2() const;
+ int32_t offs() const;
+
+ 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/codes.cpp b/asm/intel64/codes.cpp
index 76108a1..18980bd 100644
--- a/asm/intel64/codes.cpp
+++ b/asm/intel64/codes.cpp
@@ -1,5 +1,6 @@
#include "codes.h"
+#include "byteorder.h"
#include "minicc.h"
#include "../operators.h"
@@ -84,7 +85,7 @@ std::vector<uint8_t> ModRM(const std::string& reg, const std::string& rm, int32_
displacement_bytes.push_back(uint8_t(disp));
} else {
result |= 0b10000000; // 32 bit displacement
- displacement_bytes += to_little_endian(disp);
+ displacement_bytes += endian::to_little(uint32_t(disp));
}
result |= rm_bits;
} else { // normal register access
@@ -104,6 +105,12 @@ uint8_t RegNo(const std::string& reg)
return index->second;
}
+// Switch from operand size 64bit to 32bit
+std::vector<uint8_t> OpSizePrefix()
+{
+ return {0x66};
+}
+
#if 0
prefixes{
"lock", 0xf0,
diff --git a/asm/intel64/codes.h b/asm/intel64/codes.h
index ba378a6..9d737e0 100644
--- a/asm/intel64/codes.h
+++ b/asm/intel64/codes.h
@@ -15,3 +15,5 @@ std::vector<uint8_t> ModRM(const std::string& reg, const std::string& rm, int32_
// Just the number of reg, e.g. for encoding inside primary opcode
uint8_t RegNo(const std::string& reg);
+
+std::vector<uint8_t> OpSizePrefix();
diff --git a/asm/intel64/encode.cpp b/asm/intel64/encode.cpp
index 62101f3..a51854a 100644
--- a/asm/intel64/encode.cpp
+++ b/asm/intel64/encode.cpp
@@ -3,10 +3,9 @@
#include "asm/assembler.h"
#include "asm/parse.h"
+#include "byteorder.h"
#include "minicc.h"
-#include <boost/endian/conversion.hpp>
-
#include <exception>
namespace {
@@ -26,7 +25,7 @@ std::shared_ptr<Op> makeLoadValue(const FlowGraph::Data& data, const FlowGraph::
if (value.value().size() < sizeof(uint32_t))
throw std::runtime_error("ICE: Int data from operand needs at least 4 bytes, got "s + std::to_string(value.value().size()));
- uint32_t immediate = from_little_endian(value.value());
+ uint32_t immediate = endian::from_little32(value.value());
return makeOp("mov", Asm::Args{{Asm::Args::Register32("eax"), Asm::Args::Immediate32(immediate)}});
} else if (typeid(data_storage) == typeid(FlowGraph::TemporaryStorage)) {
@@ -72,7 +71,7 @@ std::shared_ptr<Op> makeAddValue(const FlowGraph::Data& data, const FlowGraph::G
if (value.value().size() < sizeof(uint32_t))
throw std::runtime_error("ICE: Int data from operand needs at least 4 bytes, got "s + std::to_string(value.value().size()));
- uint32_t immediate = from_little_endian(value.value());
+ uint32_t immediate = endian::from_little32(value.value());
return makeOp("add", Asm::Args{{Asm::Args::Register32("eax"), Asm::Args::Immediate32(immediate)}});
} else if (typeid(data_storage) == typeid(FlowGraph::TemporaryStorage)) {
@@ -99,7 +98,7 @@ std::vector<std::shared_ptr<Chunk>> makeMulValue(const FlowGraph::Data& data, co
if (value.value().size() < sizeof(uint32_t))
throw std::runtime_error("ICE: Int data from operand needs at least 4 bytes, got "s + std::to_string(value.value().size()));
- uint32_t immediate = from_little_endian(value.value());
+ uint32_t immediate = endian::from_little32(value.value());
return {{
makeOp("mov", Asm::Args{{Asm::Args::Register32("ebx"), Asm::Args::Immediate32(immediate)}}),
@@ -129,7 +128,7 @@ std::vector<std::shared_ptr<Chunk>> makeDivValue(const FlowGraph::Data& data, co
if (value.value().size() < sizeof(uint32_t))
throw std::runtime_error("ICE: Int data from operand needs at least 4 bytes, got "s + std::to_string(value.value().size()));
- uint32_t immediate = from_little_endian(value.value());
+ uint32_t immediate = endian::from_little32(value.value());
return {{
makeOp("mov", Asm::Args{{Asm::Args::Register32("ebx"), Asm::Args::Immediate32(immediate)}}),
@@ -211,12 +210,12 @@ void Asm::toMachineCode(const FlowGraph::Graph& graph, Segment& segment)
} else if (typeid(node_deref) == typeid(FlowGraph::CreateScopeOp)) {
//FlowGraph::CreateScopeOp& op {dynamic_cast<FlowGraph::CreateScopeOp&>(*node)}; // TODO: Create stack frame
- //segment.push_back(makeOp("push", Asm::Args{{Asm::Args::Register64("rbp")}}));
- //segment.push_back(makeOp("mov", Asm::Args{{Asm::Args::Register64("rbp"), Asm::Args::Register64("rsp")}}));
+ segment.push_back(makeOp("push", Asm::Args{{Asm::Args::Register64("rbp")}}));
+ segment.push_back(makeOp("mov", Asm::Args{{Asm::Args::Register64("rbp"), Asm::Args::Register64("rsp")}}));
} else if (typeid(node_deref) == typeid(FlowGraph::DestroyScopeOp)) {
//FlowGraph::DestroyScopeOp& op {dynamic_cast<FlowGraph::DestroyScopeOp&>(*node)}; // TODO: Destroy stack frame
- //segment.push_back(makeOp("pop", Asm::Args{{Asm::Args::Register64("rbp")}}));
+ segment.push_back(makeOp("pop", Asm::Args{{Asm::Args::Register64("rbp")}}));
segment.push_back(makeLoadValue(graph.lastOp()->destination(), graph)); // TODO: Just get last operation result to eax for now
segment.push_back(makeOp("xor", Asm::Args{{Asm::Args::Register64("rdi"), Asm::Args::Register64("rdi")}}));
diff --git a/asm/intel64/mov.cpp b/asm/intel64/mov.cpp
index 805675a..9382a76 100644
--- a/asm/intel64/mov.cpp
+++ b/asm/intel64/mov.cpp
@@ -16,6 +16,11 @@ Op_mov::Op_mov(const Asm::Args& args)
machine_code = std::vector<uint8_t>{ 0x88 } +
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::Register16) && args[1].type() == typeid(Asm::Args::Register16)) { // mov reg16, reg16
+ // r/m16, r16: ModRM:r/m (w), ModRM:reg (r)
+ machine_code = OpSizePrefix() + std::vector<uint8_t>{ 0x89 } +
+ ModRM(std::any_cast<Asm::Args::Register16>(args[1]).name(), std::any_cast<Asm::Args::Register16>(args[0]).name());
+
} else if (args[0].type() == typeid(Asm::Args::Register32) && args[1].type() == typeid(Asm::Args::Register32)) { // mov reg32, reg32
// r/m32, r32: ModRM:r/m (w), ModRM:reg (r)
machine_code = std::vector<uint8_t>{ 0x89 } +
@@ -79,6 +84,9 @@ bool registered {
registerOp(mangleName<Asm::Args::Register8, Asm::Args::Register8>("mov"), [](const Asm::Args& args) -> std::shared_ptr<Op>{
return std::make_shared<Op_mov>(args);
}) &&
+ registerOp(mangleName<Asm::Args::Register16, Asm::Args::Register16>("mov"), [](const Asm::Args& args) -> std::shared_ptr<Op>{
+ return std::make_shared<Op_mov>(args);
+ }) &&
registerOp(mangleName<Asm::Args::Register32, Asm::Args::Register32>("mov"), [](const Asm::Args& args) -> std::shared_ptr<Op>{
return std::make_shared<Op_mov>(args);
}) &&
diff --git a/asm/parse.cpp b/asm/parse.cpp
index 28e79f3..a3156c2 100644
--- a/asm/parse.cpp
+++ b/asm/parse.cpp
@@ -106,6 +106,25 @@ namespace {
return false;
}
+ bool parseRegister16(const std::string& asm_code, size_t& pos, std::any& result, size_t& size_hint) {
+ parseWhitespace(asm_code, pos);
+
+ std::regex re_name(reg_re, std::regex_constants::ECMAScript);
+
+ std::smatch match;
+ if (std::regex_search(asm_code.cbegin() + pos, asm_code.cend(), match, re_name, std::regex_constants::match_continuous)) {
+ std::string name {boost::algorithm::to_lower_copy(match[0].str())};
+ if (reg16.contains(name)) {
+ pos += name.size();
+ result = Asm::Args::Register16(name);
+ size_hint = 16;
+ return true;
+ }
+ }
+
+ return false;
+ }
+
bool parseRegister32(const std::string& asm_code, size_t& pos, std::any& result, size_t& size_hint) {
parseWhitespace(asm_code, pos);
@@ -163,6 +182,25 @@ namespace {
return false;
}
+ bool parseMem16Ptr64(const std::string& asm_code, size_t& pos, std::any& result, size_t& size_hint) {
+ parseWhitespace(asm_code, pos);
+
+ std::regex re_name("(word ptr *)?\\[("s + reg_re + ")\\]"s, std::regex_constants::ECMAScript);
+
+ std::smatch match;
+ if (std::regex_search(asm_code.cbegin() + pos, asm_code.cend(), match, re_name, std::regex_constants::match_continuous)) {
+ std::string name {boost::algorithm::to_lower_copy(match[2].str())};
+ if (reg16.contains(name)) {
+ pos += match[0].length();
+ result = Asm::Args::Mem16Ptr64(name);
+ size_hint = 16;
+ return true;
+ }
+ }
+
+ return false;
+ }
+
bool parseMem32Ptr64(const std::string& asm_code, size_t& pos, std::any& result, size_t& size_hint) {
parseWhitespace(asm_code, pos);
@@ -283,6 +321,8 @@ namespace {
if (parseRegister8(asm_code, pos, result, size_hint))
return true;
+ if (parseRegister16(asm_code, pos, result, size_hint))
+ return true;
if (parseRegister32(asm_code, pos, result, size_hint))
return true;
if (parseRegister64(asm_code, pos, result, size_hint))
@@ -290,6 +330,8 @@ namespace {
if (parseMem8Ptr64(asm_code, pos, result, size_hint))
return true;
+ if (parseMem16Ptr64(asm_code, pos, result, size_hint))
+ return true;
if (parseMem32Ptr64(asm_code, pos, result, size_hint))
return true;
if (parseMem64Ptr64(asm_code, pos, result, size_hint))
diff --git a/byteorder.cpp b/byteorder.cpp
new file mode 100644
index 0000000..16f7537
--- /dev/null
+++ b/byteorder.cpp
@@ -0,0 +1,40 @@
+#include "byteorder.h"
+
+#include <boost/endian/conversion.hpp>
+
+std::vector<uint8_t> endian::to_little(uint16_t value)
+{
+ std::vector<uint8_t> result(sizeof(uint16_t));
+ *(reinterpret_cast<uint16_t*>(result.data())) = boost::endian::native_to_little(value);
+ return result;
+}
+
+uint16_t endian::from_little16(const std::vector<uint8_t>& value)
+{
+ return boost::endian::little_to_native(*(reinterpret_cast<const uint16_t*>(value.data())));
+}
+
+std::vector<uint8_t> endian::to_little(uint32_t value)
+{
+ std::vector<uint8_t> result(sizeof(uint32_t));
+ *(reinterpret_cast<uint32_t*>(result.data())) = boost::endian::native_to_little(value);
+ return result;
+}
+
+uint32_t endian::from_little32(const std::vector<uint8_t>& value)
+{
+ return boost::endian::little_to_native(*(reinterpret_cast<const uint32_t*>(value.data())));
+}
+
+std::vector<uint8_t> endian::to_little(uint64_t value)
+{
+ std::vector<uint8_t> result(sizeof(uint64_t));
+ *(reinterpret_cast<uint16_t*>(result.data())) = boost::endian::native_to_little(value);
+ return result;
+}
+
+uint64_t endian::from_little64(const std::vector<uint8_t>& value)
+{
+ return boost::endian::little_to_native(*(reinterpret_cast<const uint64_t*>(value.data())));
+}
+
diff --git a/byteorder.h b/byteorder.h
new file mode 100644
index 0000000..56555b7
--- /dev/null
+++ b/byteorder.h
@@ -0,0 +1,17 @@
+#pragma once
+
+#include <cstdint>
+#include <vector>
+
+namespace endian {
+
+ std::vector<uint8_t> to_little(uint16_t value);
+ uint16_t from_little16(const std::vector<uint8_t>& value);
+
+ std::vector<uint8_t> to_little(uint32_t value);
+ uint32_t from_little32(const std::vector<uint8_t>& value);
+
+ std::vector<uint8_t> to_little(uint64_t value);
+ uint64_t from_little64(const std::vector<uint8_t>& value);
+
+}
diff --git a/flowgraph/data.h b/flowgraph/data.h
index a52627d..2b92b2e 100644
--- a/flowgraph/data.h
+++ b/flowgraph/data.h
@@ -18,6 +18,8 @@ namespace FlowGraph {
Bool,
Char,
UChar,
+ Short,
+ UShort
};
class Storage; ///< forward declaration
diff --git a/flowgraph/node.cpp b/flowgraph/node.cpp
index 8e8b5eb..d7ed939 100644
--- a/flowgraph/node.cpp
+++ b/flowgraph/node.cpp
@@ -1,10 +1,9 @@
#include "node.h"
+#include "byteorder.h"
#include "data.h"
#include "minicc.h"
-#include <boost/endian/conversion.hpp>
-
#include <memory>
using namespace FlowGraph;
@@ -20,7 +19,7 @@ FlowGraph::Data& Node::destination()
// 4 byte for now
Data FlowGraph::MakeConstantInt(int i)
{
- return Data{DataType::Int, std::make_shared<Constant>(to_little_endian(int32_t(i)))};
+ return Data{DataType::Int, std::make_shared<Constant>(endian::to_little(uint32_t(i)))};
}
Data FlowGraph::MakeLocalPointer(std::shared_ptr<FlowGraph::LocalScope> scope, const std::string& name)
diff --git a/minicc.cpp b/minicc.cpp
index a843254..9f5e906 100644
--- a/minicc.cpp
+++ b/minicc.cpp
@@ -4,7 +4,6 @@
#include "minicc.h"
#include <boost/algorithm/string.hpp>
-#include <boost/endian/conversion.hpp>
#include <algorithm>
#include <cctype>
@@ -65,16 +64,3 @@ std::string demangle(const std::type_info& type)
{
return boost::core::demangle(type.name());
}
-
-std::vector<uint8_t> to_little_endian(uint32_t value)
-{
- std::vector<uint8_t> result(size_t(4));
- *(reinterpret_cast<uint32_t*>(result.data())) = boost::endian::native_to_little(value);
- return result;
-}
-
-uint32_t from_little_endian(const std::vector<uint8_t>& value)
-{
- return boost::endian::little_to_native(*(reinterpret_cast<const uint32_t*>(value.data())));
-}
-
diff --git a/minicc.h b/minicc.h
index e9d5569..7542c2e 100644
--- a/minicc.h
+++ b/minicc.h
@@ -52,5 +52,3 @@ struct PairHashSS {
std::string demangle(const std::type_info& type);
-std::vector<uint8_t> to_little_endian(uint32_t value);
-uint32_t from_little_endian(const std::vector<uint8_t>& value);
diff --git a/tests/test-asm.cpp b/tests/test-asm.cpp
index 6c03f48..fd0446f 100644
--- a/tests/test-asm.cpp
+++ b/tests/test-asm.cpp
@@ -192,6 +192,15 @@ TEST_F(AsmParseTest, parse_empty) {
ASSERT_EQ(chunks2.size(), 0u);
}
+TEST_F(AsmParseTest, parse_mov_0) {
+ Segment segment;
+
+ segment.append(parseAsm("mov ax, bx"));
+
+ ASSERT_EQ(segment.size(), 1u);
+ ASSERT_EQ(segment.getCode(), std::vector<uint8_t>({ 0x66, 0x89, 0xD8}));
+}
+
TEST_F(AsmParseTest, parse_op_0) {
std::vector<std::shared_ptr<Chunk>> chunks0{parseAsm("nop")};
ASSERT_EQ(chunks0.size(), 1u);