summaryrefslogtreecommitdiffhomepage
path: root/asm/intel64
diff options
context:
space:
mode:
authorRoland Reichwein <mail@reichwein.it>2020-11-22 13:00:06 +0100
committerRoland Reichwein <mail@reichwein.it>2020-11-22 13:00:06 +0100
commit1fae63de23320a1663b7c591e247ad81852ab6dc (patch)
treebfe539b7eeb5a4d7b68aa1bf853898d60e34f784 /asm/intel64
parent739297d8895b08a9ecd8e81b01b7ba8e8dc4a8ae (diff)
Support 16-bit short
Diffstat (limited to 'asm/intel64')
-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
4 files changed, 26 insertions, 10 deletions
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);
}) &&