diff options
-rw-r--r-- | asm/intel64/encode.cpp | 9 | ||||
-rw-r--r-- | asm/intel64/mov.cpp | 29 | ||||
-rw-r--r-- | asm/intel64/pop.cpp | 2 | ||||
-rw-r--r-- | asm/intel64/push.cpp | 2 | ||||
-rw-r--r-- | tests/test-asm.cpp | 35 |
5 files changed, 75 insertions, 2 deletions
diff --git a/asm/intel64/encode.cpp b/asm/intel64/encode.cpp index 4e72933..62101f3 100644 --- a/asm/intel64/encode.cpp +++ b/asm/intel64/encode.cpp @@ -221,6 +221,15 @@ void Asm::toMachineCode(const FlowGraph::Graph& graph, Segment& segment) 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")}})); segment.push_back(makeOp("mov", Asm::Args{{Asm::Args::Register32("edi"), Asm::Args::Register32("eax")}})); + +#if 0 + segment.push_back(makeOp("xor", Asm::Args{{Asm::Args::Register64("rbp"), Asm::Args::Register64("rbp")}})); + segment.push_back(makeOp("dec", Asm::Args{{Asm::Args::Register64("rbp")}})); + segment.push_back(makeOp("mov", Asm::Args{{Asm::Args::Mem32Ptr64("rbp", -4), Asm::Args::Immediate32(3)}})); + segment.push_back(makeOp("mov", Asm::Args{{Asm::Args::Register32("edi"), Asm::Args::Mem32Ptr64("rbp", -4)}})); + //segment.push_back(makeOp("mov", Asm::Args{{Asm::Args::Register32("edi"), Asm::Args::Immediate32(3)}})); +#endif + segment.push_back(makeOp("mov", Asm::Args{{Asm::Args::Register64("rax"), Asm::Args::Immediate32(60)}})); // syscall 60: exit() segment.push_back(makeOp("syscall")); // rax: #syscall, rdi: exit code value } else if (typeid(node_deref) == typeid(FlowGraph::DataNode)) { diff --git a/asm/intel64/mov.cpp b/asm/intel64/mov.cpp index 5d09def..805675a 100644 --- a/asm/intel64/mov.cpp +++ b/asm/intel64/mov.cpp @@ -51,6 +51,23 @@ Op_mov::Op_mov(const Asm::Args& args) } else if (args[0].type() == typeid(Asm::Args::Register64) && args[1].type() == typeid(Asm::Args::Immediate32)) { // mov reg64, imm32 (sign-extended) machine_code = REX("W") + std::vector<uint8_t>{ 0xC7 } + ModRM("/0", std::any_cast<Asm::Args::Register64>(args[0]).name()) + std::any_cast<Asm::Args::Immediate32>(args[1]).getCode(); + } else if (args[0].type() == typeid(Asm::Args::Mem8Ptr64) && args[1].type() == typeid(Asm::Args::Immediate8)) { // mov [reg64], imm8 + Asm::Args::Mem8Ptr64 ptr{std::any_cast<Asm::Args::Mem8Ptr64>(args[0])}; + machine_code = std::vector<uint8_t>{ 0xC6 } + ModRM("/0", ptr.reg(), ptr.offs()) + std::any_cast<Asm::Args::Immediate8>(args[1]).getCode(); + + } else if (args[0].type() == typeid(Asm::Args::Mem32Ptr64) && args[1].type() == typeid(Asm::Args::Immediate32)) { // mov [reg64], imm32 + Asm::Args::Mem32Ptr64 ptr{std::any_cast<Asm::Args::Mem32Ptr64>(args[0])}; + machine_code = std::vector<uint8_t>{ 0xC7 } + ModRM("/0", ptr.reg(), ptr.offs()) + std::any_cast<Asm::Args::Immediate32>(args[1]).getCode(); + + } else if (args[0].type() == typeid(Asm::Args::Mem64Ptr64) && args[1].type() == typeid(Asm::Args::Immediate32)) { // mov [reg64], imm32 (sign-extended to imm64) + Asm::Args::Mem64Ptr64 ptr{std::any_cast<Asm::Args::Mem64Ptr64>(args[0])}; + machine_code = REX("W") + std::vector<uint8_t>{ 0xC7 } + ModRM("/0", ptr.reg(), ptr.offs()) + std::any_cast<Asm::Args::Immediate32>(args[1]).getCode(); + + } else if (args[0].type() == typeid(Asm::Args::Mem64Ptr64) && args[1].type() == typeid(Asm::Args::Immediate64)) { // mov [reg64], imm64 (cut to imm32) + Asm::Args::Mem64Ptr64 ptr{std::any_cast<Asm::Args::Mem64Ptr64>(args[0])}; + Asm::Args::Immediate32 imm32{std::any_cast<Asm::Args::Immediate64>(args[1])}; + machine_code = REX("W") + std::vector<uint8_t>{ 0xC7 } + ModRM("/0", ptr.reg(), ptr.offs()) + imm32.getCode(); + } else { throw std::runtime_error("Unimplemented: mov "s + args[0].type().name() + " "s + args[1].type().name()); } @@ -88,6 +105,18 @@ bool registered { }) && registerOp(mangleName<Asm::Args::Register64, Asm::Args::Immediate32>("mov"), [](const Asm::Args& args) -> std::shared_ptr<Op>{ return std::make_shared<Op_mov>(args); + }) && + registerOp(mangleName<Asm::Args::Mem8Ptr64, Asm::Args::Immediate8>("mov"), [](const Asm::Args& args) -> std::shared_ptr<Op>{ + return std::make_shared<Op_mov>(args); + }) && + registerOp(mangleName<Asm::Args::Mem32Ptr64, Asm::Args::Immediate32>("mov"), [](const Asm::Args& args) -> std::shared_ptr<Op>{ + return std::make_shared<Op_mov>(args); + }) && + registerOp(mangleName<Asm::Args::Mem64Ptr64, Asm::Args::Immediate32>("mov"), [](const Asm::Args& args) -> std::shared_ptr<Op>{ + return std::make_shared<Op_mov>(args); + }) && + registerOp(mangleName<Asm::Args::Mem64Ptr64, Asm::Args::Immediate64>("mov"), [](const Asm::Args& args) -> std::shared_ptr<Op>{ + return std::make_shared<Op_mov>(args); }) }; diff --git a/asm/intel64/pop.cpp b/asm/intel64/pop.cpp index 6d8b734..6b396a2 100644 --- a/asm/intel64/pop.cpp +++ b/asm/intel64/pop.cpp @@ -12,7 +12,7 @@ using namespace std::string_literals; Op_pop::Op_pop(const Asm::Args& args) { if (args[0].type() == typeid(Asm::Args::Register64)) { // pop reg64 - machine_code = std::vector<uint8_t>{ 0x58 } + RegNo(std::any_cast<Asm::Args::Register64>(args[0]).name()); + machine_code = std::vector<uint8_t>{ static_cast<uint8_t>(0x58 + RegNo(std::any_cast<Asm::Args::Register64>(args[0]).name())) }; } else { throw std::runtime_error("Unimplemented: pop "s + args[0].type().name()); } diff --git a/asm/intel64/push.cpp b/asm/intel64/push.cpp index 37acec9..9fb5955 100644 --- a/asm/intel64/push.cpp +++ b/asm/intel64/push.cpp @@ -12,7 +12,7 @@ using namespace std::string_literals; Op_push::Op_push(const Asm::Args& args) { if (args[0].type() == typeid(Asm::Args::Register64)) { // push reg64 - machine_code = std::vector<uint8_t>{ 0x50 } + RegNo(std::any_cast<Asm::Args::Register64>(args[0]).name()); + machine_code = std::vector<uint8_t>{ static_cast<uint8_t>(0x50 + RegNo(std::any_cast<Asm::Args::Register64>(args[0]).name())) }; } else { throw std::runtime_error("Unimplemented: push "s + args[0].type().name()); } diff --git a/tests/test-asm.cpp b/tests/test-asm.cpp index 650a48a..6c03f48 100644 --- a/tests/test-asm.cpp +++ b/tests/test-asm.cpp @@ -146,6 +146,41 @@ TEST_F(AsmTest, Intel64_multiple) { })); } +TEST_F(AsmTest, indexed_to) { + Segment segment; + + segment.push_back(makeOp("mov", Asm::Args{{Asm::Args::Mem32Ptr64("rbp", -4), Asm::Args::Immediate32(3)}})); + + ASSERT_EQ(segment.size(), size_t(1)); + ASSERT_EQ(segment.getCode(), std::vector<uint8_t>({0xC7, 0x45, 0xFC, 0x03, 0x00, 0x00, 0x00})); +} + +TEST_F(AsmTest, indexed_from) { + Segment segment; + + segment.push_back(makeOp("mov", Asm::Args{{Asm::Args::Register32("edi"), Asm::Args::Mem32Ptr64("rbp", -4)}})); + + ASSERT_EQ(segment.size(), size_t(1)); + ASSERT_EQ(segment.getCode(), std::vector<uint8_t>({0x8B, 0x7D, 0xFC})); +} + +TEST_F(AsmTest, frame_pointer) { + Segment segment; + + 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")}})); + + // frame at [rbp-...] available here ... + + segment.push_back(makeOp("pop", Asm::Args{{Asm::Args::Register64("rbp")}})); + + ASSERT_EQ(segment.size(), size_t(3)); + ASSERT_EQ(segment.getCode(), std::vector<uint8_t>({ + 0x55, + 0x48, 0x89, 0xE5, + 0x5D})); +} + TEST_F(AsmParseTest, parse_empty) { std::vector<std::shared_ptr<Chunk>> chunks0{parseAsm("")}; ASSERT_EQ(chunks0.size(), 0u); |