From 39bccce4fdd1d5ebe312321c963e0325e4d696c5 Mon Sep 17 00:00:00 2001
From: Roland Reichwein <mail@reichwein.it>
Date: Sat, 21 Nov 2020 21:38:56 +0100
Subject: Bugfixing of stack (WIP)

---
 asm/intel64/add.cpp    | 18 ++++++++++++------
 asm/intel64/and.cpp    | 12 ++++++++----
 asm/intel64/bsf.cpp    |  6 ++++--
 asm/intel64/bsr.cpp    |  6 ++++--
 asm/intel64/codes.cpp  |  2 +-
 asm/intel64/div.cpp    |  9 ++++++---
 asm/intel64/encode.cpp | 10 +++++-----
 asm/intel64/mov.cpp    | 12 ++++++++----
 asm/intel64/mul.cpp    |  9 ++++++---
 asm/intel64/or.cpp     | 12 ++++++++----
 10 files changed, 62 insertions(+), 34 deletions(-)

(limited to 'asm/intel64')

diff --git a/asm/intel64/add.cpp b/asm/intel64/add.cpp
index 07b14a1..12d1b94 100644
--- a/asm/intel64/add.cpp
+++ b/asm/intel64/add.cpp
@@ -38,23 +38,29 @@ Op_add::Op_add(const Asm::Args& args)
   machine_code = REX("W") + std::vector<uint8_t>{ 0x01 } + ModRM(std::any_cast<Asm::Args::Register64>(args[1]).name(), std::any_cast<Asm::Args::Register64>(args[0]).name());
 
  } else if (args[0].type() == typeid(Asm::Args::Register32) && args[1].type() == typeid(Asm::Args::Mem32Ptr64)) { // add reg32, [reg64]
-  machine_code = std::vector<uint8_t>{ 0x03 } + ModRM(std::any_cast<Asm::Args::Register32>(args[0]).name(), std::any_cast<Asm::Args::Mem32Ptr64>(args[1]).reg());
+  Asm::Args::Mem32Ptr64 ptr{std::any_cast<Asm::Args::Mem32Ptr64>(args[1])};
+  machine_code = std::vector<uint8_t>{ 0x03 } + ModRM(std::any_cast<Asm::Args::Register32>(args[0]).name(), ptr.reg(), ptr.offs());
 
  } else if (args[0].type() == typeid(Asm::Args::Register64) && args[1].type() == typeid(Asm::Args::Mem64Ptr64)) { // add reg64, [reg64]
-  machine_code = REX("W") + std::vector<uint8_t>{ 0x03 } + ModRM(std::any_cast<Asm::Args::Register64>(args[0]).name(), std::any_cast<Asm::Args::Mem64Ptr64>(args[1]).reg());
+  Asm::Args::Mem64Ptr64 ptr{std::any_cast<Asm::Args::Mem64Ptr64>(args[1])};
+  machine_code = REX("W") + std::vector<uint8_t>{ 0x03 } + ModRM(std::any_cast<Asm::Args::Register64>(args[0]).name(), ptr.reg(), ptr.offs());
 
  } else if (args[0].type() == typeid(Asm::Args::Mem8Ptr64) && args[1].type() == typeid(Asm::Args::Immediate8)) { // add [reg64], imm8
-  machine_code = std::vector<uint8_t>{ 0x80 } + ModRM("/0", std::any_cast<Asm::Args::Mem8Ptr64>(args[0]).reg()) + std::any_cast<Asm::Args::Immediate8>(args[1]).getCode();
+  Asm::Args::Mem8Ptr64 ptr{std::any_cast<Asm::Args::Mem8Ptr64>(args[0])};
+  machine_code = std::vector<uint8_t>{ 0x80 } + 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)) { // add [reg64], imm32
-  machine_code = std::vector<uint8_t>{ 0x81 } + ModRM("/0", std::any_cast<Asm::Args::Mem32Ptr64>(args[0]).reg()) + std::any_cast<Asm::Args::Immediate32>(args[1]).getCode();
+  Asm::Args::Mem32Ptr64 ptr{std::any_cast<Asm::Args::Mem32Ptr64>(args[0])};
+  machine_code = std::vector<uint8_t>{ 0x81 } + 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)) { // add qword ptr [reg64], imm32 (sign-extended)
-  machine_code = REX("W") + std::vector<uint8_t>{ 0x81 } + ModRM("/0", std::any_cast<Asm::Args::Mem64Ptr64>(args[0]).reg()) + std::any_cast<Asm::Args::Immediate32>(args[1]).getCode();
+  Asm::Args::Mem64Ptr64 ptr{std::any_cast<Asm::Args::Mem64Ptr64>(args[0])};
+  machine_code = REX("W") + std::vector<uint8_t>{ 0x81 } + 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)) { // add qword ptr [reg64], imm32 (sign-extended) - reduce imm64 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>{ 0x81 } + ModRM("/0", std::any_cast<Asm::Args::Mem64Ptr64>(args[0]).reg()) + imm32.getCode();
+  machine_code = REX("W") + std::vector<uint8_t>{ 0x81 } + ModRM("/0", ptr.reg(), ptr.offs()) + imm32.getCode();
 
  } else {
   throw std::runtime_error("Unimplemented: add "s + args[0].type().name() + " "s + args[1].type().name());
diff --git a/asm/intel64/and.cpp b/asm/intel64/and.cpp
index a2e110b..b87d408 100644
--- a/asm/intel64/and.cpp
+++ b/asm/intel64/and.cpp
@@ -30,16 +30,20 @@ Op_and::Op_and(const Asm::Args& args)
   machine_code = std::vector<uint8_t>{ 0x81 } + ModRM("/4", std::any_cast<Asm::Args::Register32>(args[0]).name()) + std::any_cast<Asm::Args::Immediate32>(args[1]).getCode();
 
  } else if (args[0].type() == typeid(Asm::Args::Register32) && args[1].type() == typeid(Asm::Args::Mem32Ptr64)) { // and reg32, [reg64]
-  machine_code = std::vector<uint8_t>{ 0x23 } + ModRM(std::any_cast<Asm::Args::Register32>(args[0]).name(), std::any_cast<Asm::Args::Mem32Ptr64>(args[1]).reg());
+  Asm::Args::Mem32Ptr64 ptr{std::any_cast<Asm::Args::Mem32Ptr64>(args[1])};
+  machine_code = std::vector<uint8_t>{ 0x23 } + ModRM(std::any_cast<Asm::Args::Register32>(args[0]).name(), ptr.reg(), ptr.offs());
 
  } else if (args[0].type() == typeid(Asm::Args::Register64) && args[1].type() == typeid(Asm::Args::Mem64Ptr64)) { // and reg64, [reg64]
-  machine_code = REX("W") + std::vector<uint8_t>{ 0x23 } + ModRM(std::any_cast<Asm::Args::Register64>(args[0]).name(), std::any_cast<Asm::Args::Mem64Ptr64>(args[1]).reg());
+  Asm::Args::Mem64Ptr64 ptr{std::any_cast<Asm::Args::Mem64Ptr64>(args[1])};
+  machine_code = REX("W") + std::vector<uint8_t>{ 0x23 } + ModRM(std::any_cast<Asm::Args::Register64>(args[0]).name(), ptr.reg(), ptr.offs());
 
  } else if (args[0].type() == typeid(Asm::Args::Mem32Ptr64) && args[1].type() == typeid(Asm::Args::Register32)) { // and [reg64], reg32
-  machine_code = std::vector<uint8_t>{ 0x21 } + ModRM(std::any_cast<Asm::Args::Register32>(args[1]).name(), std::any_cast<Asm::Args::Mem32Ptr64>(args[0]).reg());
+  Asm::Args::Mem32Ptr64 ptr{std::any_cast<Asm::Args::Mem32Ptr64>(args[0])};
+  machine_code = std::vector<uint8_t>{ 0x21 } + ModRM(std::any_cast<Asm::Args::Register32>(args[1]).name(), ptr.reg(), ptr.offs());
 
  } else if (args[0].type() == typeid(Asm::Args::Mem64Ptr64) && args[1].type() == typeid(Asm::Args::Register64)) { // and [reg64], reg64
-  machine_code = REX("W") + std::vector<uint8_t>{ 0x21 } + ModRM(std::any_cast<Asm::Args::Register64>(args[1]).name(), std::any_cast<Asm::Args::Mem64Ptr64>(args[0]).reg());
+  Asm::Args::Mem64Ptr64 ptr{std::any_cast<Asm::Args::Mem64Ptr64>(args[0])};
+  machine_code = REX("W") + std::vector<uint8_t>{ 0x21 } + ModRM(std::any_cast<Asm::Args::Register64>(args[1]).name(), ptr.reg(), ptr.offs());
 
  } else if (args[0].type() == typeid(Asm::Args::Register64) && args[1].type() == typeid(Asm::Args::Immediate32)) { // and reg64, imm32 (sign-extended)
   machine_code = REX("W") + std::vector<uint8_t>{ 0x81 } + ModRM("/4", std::any_cast<Asm::Args::Register64>(args[0]).name()) + std::any_cast<Asm::Args::Immediate32>(args[1]).getCode();
diff --git a/asm/intel64/bsf.cpp b/asm/intel64/bsf.cpp
index 974be43..24a0ae0 100644
--- a/asm/intel64/bsf.cpp
+++ b/asm/intel64/bsf.cpp
@@ -16,10 +16,12 @@ Op_bsf::Op_bsf(const Asm::Args& args)
   machine_code = REX("W") + std::vector<uint8_t>{ 0x0F, 0xBC } + ModRM(std::any_cast<Asm::Args::Register64>(args[0]).name(), std::any_cast<Asm::Args::Register64>(args[1]).name());
 
  } else if (args[0].type() == typeid(Asm::Args::Register32) && args[1].type() == typeid(Asm::Args::Mem32Ptr64)) { // bsf reg32, [reg64]
-  machine_code = std::vector<uint8_t>{ 0x0F, 0xBC } + ModRM(std::any_cast<Asm::Args::Register32>(args[0]).name(), std::any_cast<Asm::Args::Mem32Ptr64>(args[1]).reg());
+  Asm::Args::Mem32Ptr64 ptr{std::any_cast<Asm::Args::Mem32Ptr64>(args[1])};
+  machine_code = std::vector<uint8_t>{ 0x0F, 0xBC } + ModRM(std::any_cast<Asm::Args::Register32>(args[0]).name(), ptr.reg(), ptr.offs());
 
  } else if (args[0].type() == typeid(Asm::Args::Register64) && args[1].type() == typeid(Asm::Args::Mem64Ptr64)) { // bsf reg64, [reg64]
-  machine_code = REX("W") + std::vector<uint8_t>{ 0x0F, 0xBC } + ModRM(std::any_cast<Asm::Args::Register64>(args[0]).name(), std::any_cast<Asm::Args::Mem64Ptr64>(args[1]).reg());
+  Asm::Args::Mem64Ptr64 ptr{std::any_cast<Asm::Args::Mem64Ptr64>(args[1])};
+  machine_code = REX("W") + std::vector<uint8_t>{ 0x0F, 0xBC } + ModRM(std::any_cast<Asm::Args::Register64>(args[0]).name(), ptr.reg(), ptr.offs());
 
  } else {
   throw std::runtime_error("Unimplemented: bsf "s + args[0].type().name() + " "s + args[1].type().name());
diff --git a/asm/intel64/bsr.cpp b/asm/intel64/bsr.cpp
index 099c7d2..5935402 100644
--- a/asm/intel64/bsr.cpp
+++ b/asm/intel64/bsr.cpp
@@ -16,10 +16,12 @@ Op_bsr::Op_bsr(const Asm::Args& args)
   machine_code = REX("W") + std::vector<uint8_t>{ 0x0F, 0xBD } + ModRM(std::any_cast<Asm::Args::Register64>(args[0]).name(), std::any_cast<Asm::Args::Register64>(args[1]).name());
 
  } else if (args[0].type() == typeid(Asm::Args::Register32) && args[1].type() == typeid(Asm::Args::Mem32Ptr64)) { // bsr reg32, [reg64]
-  machine_code = std::vector<uint8_t>{ 0x0F, 0xBD } + ModRM(std::any_cast<Asm::Args::Register32>(args[0]).name(), std::any_cast<Asm::Args::Mem32Ptr64>(args[1]).reg());
+  Asm::Args::Mem32Ptr64 ptr{std::any_cast<Asm::Args::Mem32Ptr64>(args[1])};
+  machine_code = std::vector<uint8_t>{ 0x0F, 0xBD } + ModRM(std::any_cast<Asm::Args::Register32>(args[0]).name(), ptr.reg(), ptr.offs());
 
  } else if (args[0].type() == typeid(Asm::Args::Register64) && args[1].type() == typeid(Asm::Args::Mem64Ptr64)) { // bsr reg64, [reg64]
-  machine_code = REX("W") + std::vector<uint8_t>{ 0x0F, 0xBD } + ModRM(std::any_cast<Asm::Args::Register64>(args[0]).name(), std::any_cast<Asm::Args::Mem64Ptr64>(args[1]).reg());
+  Asm::Args::Mem64Ptr64 ptr{std::any_cast<Asm::Args::Mem64Ptr64>(args[1])};
+  machine_code = REX("W") + std::vector<uint8_t>{ 0x0F, 0xBD } + ModRM(std::any_cast<Asm::Args::Register64>(args[0]).name(), ptr.reg(), ptr.offs());
 
  } else {
   throw std::runtime_error("Unimplemented: bsr "s + args[0].type().name() + " "s + args[1].type().name());
diff --git a/asm/intel64/codes.cpp b/asm/intel64/codes.cpp
index 9f82d37..76108a1 100644
--- a/asm/intel64/codes.cpp
+++ b/asm/intel64/codes.cpp
@@ -78,7 +78,7 @@ std::vector<uint8_t> ModRM(const std::string& reg, const std::string& rm, int32_
   if (disp == 0 && rm_bits != 5) { // no displacement
    // ignore: keep MOD == 00, no displacement bytes
    if (rm_bits == 5)
-    throw std::runtime_error("ICE: [rbp] with now displacement is not supported"); // TODO: Support this, and SIB byte
+    throw std::runtime_error("ICE: [rbp] with no displacement is not supported"); // TODO: Support this, and SIB byte
   } else if (disp >= -128 && disp < 128) {
    result |= 0b01000000; // 8 bit displacement
    displacement_bytes.push_back(uint8_t(disp));
diff --git a/asm/intel64/div.cpp b/asm/intel64/div.cpp
index 1e98b7b..cfe2503 100644
--- a/asm/intel64/div.cpp
+++ b/asm/intel64/div.cpp
@@ -21,14 +21,17 @@ Op_div::Op_div(const Asm::Args& args)
   machine_code = REX("W") + std::vector<uint8_t>{ 0xF7 } +
    ModRM("/6", std::any_cast<Asm::Args::Register64>(args[0]).name());
  } else if (args[0].type() == typeid(Asm::Args::Mem8Ptr64)) { // div byte ptr [reg64] (accu is al (remainder=ah) <- ah / x)
+  Asm::Args::Mem8Ptr64 ptr{std::any_cast<Asm::Args::Mem8Ptr64>(args[0])};
   machine_code = std::vector<uint8_t>{ 0xF6 } +
-   ModRM("/6", std::any_cast<Asm::Args::Mem8Ptr64>(args[0]).reg());
+   ModRM("/6", ptr.reg(), ptr.offs());
  } else if (args[0].type() == typeid(Asm::Args::Mem32Ptr64)) { // div dword ptr [reg64] (accu is eax (remainder=edx) <- edx:eax / x)
+  Asm::Args::Mem32Ptr64 ptr{std::any_cast<Asm::Args::Mem32Ptr64>(args[0])};
   machine_code = std::vector<uint8_t>{ 0xF7 } +
-   ModRM("/6", std::any_cast<Asm::Args::Mem32Ptr64>(args[0]).reg());
+   ModRM("/6", ptr.reg(), ptr.offs());
  } else if (args[0].type() == typeid(Asm::Args::Mem64Ptr64)) { // div qword ptr [reg64] (accu is rax (remainder=rdx) <- rdx:rax / x)
+  Asm::Args::Mem64Ptr64 ptr{std::any_cast<Asm::Args::Mem64Ptr64>(args[0])};
   machine_code = REX("W") + std::vector<uint8_t>{ 0xF7 } +
-   ModRM("/6", std::any_cast<Asm::Args::Mem64Ptr64>(args[0]).reg());
+   ModRM("/6", ptr.reg(), ptr.offs());
  } else {
   throw std::runtime_error("Unimplemented: div "s + args[0].type().name());
  }
diff --git a/asm/intel64/encode.cpp b/asm/intel64/encode.cpp
index a2434fd..4e72933 100644
--- a/asm/intel64/encode.cpp
+++ b/asm/intel64/encode.cpp
@@ -33,7 +33,7 @@ std::shared_ptr<Op> makeLoadValue(const FlowGraph::Data& data, const FlowGraph::
   //FlowGraph::TemporaryStorage& storage {dynamic_cast<FlowGraph::TemporaryStorage&>(data_storage)};
 
   index_t index { graph.scope()->indexOfData(data)};
-  return makeOp("mov", Asm::Args{{Asm::Args::Register32("eax"), Asm::Args::Mem32Ptr64("rbp", int32_t(index) * -4)}});
+  return makeOp("mov", Asm::Args{{Asm::Args::Register32("eax"), Asm::Args::Mem32Ptr64("rbp", int32_t(index + 1) * -4)}});
  } else
   throw std::runtime_error("ICE: Unsupported type for operand data at load: "s + demangle(typeid(data_storage)));
 }
@@ -52,7 +52,7 @@ std::shared_ptr<Op> makeStoreValue(const FlowGraph::Data& data, const FlowGraph:
   //FlowGraph::TemporaryStorage& storage {dynamic_cast<FlowGraph::TemporaryStorage&>(data_storage)};
 
   index_t index { graph.scope()->indexOfData(data)};
-  return makeOp("mov", Asm::Args{{Asm::Args::Mem32Ptr64("rbp", int32_t(index) * -4), Asm::Args::Register32("eax")}});
+  return makeOp("mov", Asm::Args{{Asm::Args::Mem32Ptr64("rbp", int32_t(index + 1) * -4), Asm::Args::Register32("eax")}});
  } else
   throw std::runtime_error("ICE: Unsupported type for operand data at store: "s  + demangle(typeid(data_storage)));
 }
@@ -79,7 +79,7 @@ std::shared_ptr<Op> makeAddValue(const FlowGraph::Data& data, const FlowGraph::G
   //FlowGraph::TemporaryStorage& storage {dynamic_cast<FlowGraph::TemporaryStorage&>(data_storage)};
 
   index_t index { graph.scope()->indexOfData(data)};
-  return makeOp("add", Asm::Args{{Asm::Args::Register32("eax"), Asm::Args::Mem32Ptr64("rbp", int32_t(index) * -4)}});
+  return makeOp("add", Asm::Args{{Asm::Args::Register32("eax"), Asm::Args::Mem32Ptr64("rbp", int32_t(index + 1) * -4)}});
  } else
   throw std::runtime_error("ICE: Unsupported type for operand data at add: "s + demangle(typeid(data_storage)));
 }
@@ -109,7 +109,7 @@ std::vector<std::shared_ptr<Chunk>> makeMulValue(const FlowGraph::Data& data, co
   //FlowGraph::TemporaryStorage& storage {dynamic_cast<FlowGraph::TemporaryStorage&>(data_storage)};
 
   index_t index { graph.scope()->indexOfData(data)};
-  return {{makeOp("mul", Asm::Args{{Asm::Args::Mem32Ptr64("rbp", int32_t(index) * -4)}})}};
+  return {{makeOp("mul", Asm::Args{{Asm::Args::Mem32Ptr64("rbp", int32_t(index + 1) * -4)}})}};
  } else
   throw std::runtime_error("ICE: Unsupported type for operand data at mul: "s + demangle(typeid(data_storage)));
 }
@@ -139,7 +139,7 @@ std::vector<std::shared_ptr<Chunk>> makeDivValue(const FlowGraph::Data& data, co
   //FlowGraph::TemporaryStorage& storage {dynamic_cast<FlowGraph::TemporaryStorage&>(data_storage)};
 
   index_t index { graph.scope()->indexOfData(data)};
-  return {{makeOp("div", Asm::Args{{Asm::Args::Mem32Ptr64("rbp", int32_t(index) * -4)}})}};
+  return {{makeOp("div", Asm::Args{{Asm::Args::Mem32Ptr64("rbp", int32_t(index + 1) * -4)}})}};
  } else
   throw std::runtime_error("ICE: Unsupported type for operand data at div: "s + demangle(typeid(data_storage)));
 }
diff --git a/asm/intel64/mov.cpp b/asm/intel64/mov.cpp
index 5f09c82..5d09def 100644
--- a/asm/intel64/mov.cpp
+++ b/asm/intel64/mov.cpp
@@ -33,16 +33,20 @@ Op_mov::Op_mov(const Asm::Args& args)
   machine_code = std::vector<uint8_t>{ REX("W") + static_cast<uint8_t>(0xB8 + RegNo(std::any_cast<Asm::Args::Register64>(args[0]).name())) } + std::any_cast<Asm::Args::Immediate64>(args[1]).getCode();
 
  } else if (args[0].type() == typeid(Asm::Args::Register32) && args[1].type() == typeid(Asm::Args::Mem32Ptr64)) { // mov reg32, [reg64]
-  machine_code = std::vector<uint8_t>{ 0x8B } + ModRM(std::any_cast<Asm::Args::Register32>(args[0]).name(), std::any_cast<Asm::Args::Mem32Ptr64>(args[1]).reg());
+  Asm::Args::Mem32Ptr64 ptr{std::any_cast<Asm::Args::Mem32Ptr64>(args[1])};
+  machine_code = std::vector<uint8_t>{ 0x8B } + ModRM(std::any_cast<Asm::Args::Register32>(args[0]).name(), ptr.reg(), ptr.offs());
 
  } else if (args[0].type() == typeid(Asm::Args::Register64) && args[1].type() == typeid(Asm::Args::Mem64Ptr64)) { // mov reg64, [reg64]
-  machine_code = REX("W") + std::vector<uint8_t>{ 0x8B } + ModRM(std::any_cast<Asm::Args::Register64>(args[0]).name(), std::any_cast<Asm::Args::Mem64Ptr64>(args[1]).reg());
+  Asm::Args::Mem64Ptr64 ptr{std::any_cast<Asm::Args::Mem64Ptr64>(args[1])};
+  machine_code = REX("W") + std::vector<uint8_t>{ 0x8B } + ModRM(std::any_cast<Asm::Args::Register64>(args[0]).name(), ptr.reg(), ptr.offs());
 
  } else if (args[0].type() == typeid(Asm::Args::Mem32Ptr64) && args[1].type() == typeid(Asm::Args::Register32)) { // mov [reg64], reg32
-  machine_code = std::vector<uint8_t>{ 0x89 } + ModRM(std::any_cast<Asm::Args::Register32>(args[1]).name(), std::any_cast<Asm::Args::Mem32Ptr64>(args[0]).reg());
+  Asm::Args::Mem32Ptr64 ptr{std::any_cast<Asm::Args::Mem32Ptr64>(args[0])};
+  machine_code = std::vector<uint8_t>{ 0x89 } + ModRM(std::any_cast<Asm::Args::Register32>(args[1]).name(), ptr.reg(), ptr.offs());
 
  } else if (args[0].type() == typeid(Asm::Args::Mem64Ptr64) && args[1].type() == typeid(Asm::Args::Register64)) { // mov [reg64], reg64
-  machine_code = REX("W") + std::vector<uint8_t>{ 0x89 } + ModRM(std::any_cast<Asm::Args::Register64>(args[1]).name(), std::any_cast<Asm::Args::Mem64Ptr64>(args[0]).reg());
+  Asm::Args::Mem64Ptr64 ptr{std::any_cast<Asm::Args::Mem64Ptr64>(args[0])};
+  machine_code = REX("W") + std::vector<uint8_t>{ 0x89 } + ModRM(std::any_cast<Asm::Args::Register64>(args[1]).name(), ptr.reg(), ptr.offs());
 
  } 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();
diff --git a/asm/intel64/mul.cpp b/asm/intel64/mul.cpp
index 5825e2a..14810dc 100644
--- a/asm/intel64/mul.cpp
+++ b/asm/intel64/mul.cpp
@@ -21,14 +21,17 @@ Op_mul::Op_mul(const Asm::Args& args)
   machine_code = REX("W") + std::vector<uint8_t>{ 0xF7 } +
    ModRM("/4", std::any_cast<Asm::Args::Register64>(args[0]).name());
  } else if (args[0].type() == typeid(Asm::Args::Mem8Ptr64)) { // mul byte ptr [reg64] (accu is ax <- al)
+  Asm::Args::Mem8Ptr64 ptr{std::any_cast<Asm::Args::Mem8Ptr64>(args[0])};
   machine_code = std::vector<uint8_t>{ 0xF6 } +
-   ModRM("/4", std::any_cast<Asm::Args::Mem8Ptr64>(args[0]).reg());
+   ModRM("/4", ptr.reg(), ptr.offs());
  } else if (args[0].type() == typeid(Asm::Args::Mem32Ptr64)) { // mul dword ptr [reg64] (accu is edx:eax <- eax)
+  Asm::Args::Mem32Ptr64 ptr{std::any_cast<Asm::Args::Mem32Ptr64>(args[0])};
   machine_code = std::vector<uint8_t>{ 0xF7 } +
-   ModRM("/4", std::any_cast<Asm::Args::Mem32Ptr64>(args[0]).reg());
+   ModRM("/4", ptr.reg(), ptr.offs());
  } else if (args[0].type() == typeid(Asm::Args::Mem64Ptr64)) { // mul qword ptr [reg64] (accu is rdx:rax <- rax)
+  Asm::Args::Mem64Ptr64 ptr{std::any_cast<Asm::Args::Mem64Ptr64>(args[0])};
   machine_code = REX("W") + std::vector<uint8_t>{ 0xF7 } +
-   ModRM("/4", std::any_cast<Asm::Args::Mem64Ptr64>(args[0]).reg());
+   ModRM("/4", ptr.reg(), ptr.offs());
  } else {
   throw std::runtime_error("Unimplemented: mul "s + args[0].type().name());
  }
diff --git a/asm/intel64/or.cpp b/asm/intel64/or.cpp
index c5be55c..27daf07 100644
--- a/asm/intel64/or.cpp
+++ b/asm/intel64/or.cpp
@@ -30,16 +30,20 @@ Op_or::Op_or(const Asm::Args& args)
   machine_code = std::vector<uint8_t>{ 0x81 } + ModRM("/1", std::any_cast<Asm::Args::Register32>(args[0]).name()) + std::any_cast<Asm::Args::Immediate32>(args[1]).getCode();
 
  } else if (args[0].type() == typeid(Asm::Args::Register32) && args[1].type() == typeid(Asm::Args::Mem32Ptr64)) { // or reg32, [reg64]
-  machine_code = std::vector<uint8_t>{ 0x0B } + ModRM(std::any_cast<Asm::Args::Register32>(args[0]).name(), std::any_cast<Asm::Args::Mem32Ptr64>(args[1]).reg());
+  Asm::Args::Mem32Ptr64 ptr{std::any_cast<Asm::Args::Mem32Ptr64>(args[1])};
+  machine_code = std::vector<uint8_t>{ 0x0B } + ModRM(std::any_cast<Asm::Args::Register32>(args[0]).name(), ptr.reg(), ptr.offs());
 
  } else if (args[0].type() == typeid(Asm::Args::Register64) && args[1].type() == typeid(Asm::Args::Mem64Ptr64)) { // or reg64, [reg64]
-  machine_code = REX("W") + std::vector<uint8_t>{ 0x0B } + ModRM(std::any_cast<Asm::Args::Register64>(args[0]).name(), std::any_cast<Asm::Args::Mem64Ptr64>(args[1]).reg());
+  Asm::Args::Mem64Ptr64 ptr{std::any_cast<Asm::Args::Mem64Ptr64>(args[1])};
+  machine_code = REX("W") + std::vector<uint8_t>{ 0x0B } + ModRM(std::any_cast<Asm::Args::Register64>(args[0]).name(), ptr.reg(), ptr.offs());
 
  } else if (args[0].type() == typeid(Asm::Args::Mem32Ptr64) && args[1].type() == typeid(Asm::Args::Register32)) { // or [reg64], reg32
-  machine_code = std::vector<uint8_t>{ 0x09 } + ModRM(std::any_cast<Asm::Args::Register32>(args[1]).name(), std::any_cast<Asm::Args::Mem32Ptr64>(args[0]).reg());
+  Asm::Args::Mem32Ptr64 ptr{std::any_cast<Asm::Args::Mem32Ptr64>(args[0])};
+  machine_code = std::vector<uint8_t>{ 0x09 } + ModRM(std::any_cast<Asm::Args::Register32>(args[1]).name(), ptr.reg(), ptr.offs());
 
  } else if (args[0].type() == typeid(Asm::Args::Mem64Ptr64) && args[1].type() == typeid(Asm::Args::Register64)) { // or [reg64], reg64
-  machine_code = REX("W") + std::vector<uint8_t>{ 0x09 } + ModRM(std::any_cast<Asm::Args::Register64>(args[1]).name(), std::any_cast<Asm::Args::Mem64Ptr64>(args[0]).reg());
+  Asm::Args::Mem64Ptr64 ptr{std::any_cast<Asm::Args::Mem64Ptr64>(args[0])};
+  machine_code = REX("W") + std::vector<uint8_t>{ 0x09 } + ModRM(std::any_cast<Asm::Args::Register64>(args[1]).name(), ptr.reg(), ptr.offs());
 
  } else if (args[0].type() == typeid(Asm::Args::Register64) && args[1].type() == typeid(Asm::Args::Immediate32)) { // or reg64, imm32 (sign-extended)
   machine_code = REX("W") + std::vector<uint8_t>{ 0x81 } + ModRM("/1", std::any_cast<Asm::Args::Register64>(args[0]).name()) + std::any_cast<Asm::Args::Immediate32>(args[1]).getCode();
-- 
cgit v1.2.3