summaryrefslogtreecommitdiffhomepage
path: root/asm/intel64/codes.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'asm/intel64/codes.cpp')
-rw-r--r--asm/intel64/codes.cpp43
1 files changed, 30 insertions, 13 deletions
diff --git a/asm/intel64/codes.cpp b/asm/intel64/codes.cpp
index 58d921f..9f82d37 100644
--- a/asm/intel64/codes.cpp
+++ b/asm/intel64/codes.cpp
@@ -1,5 +1,8 @@
#include "codes.h"
+#include "minicc.h"
+#include "../operators.h"
+
#include <exception>
#include <unordered_map>
@@ -44,12 +47,13 @@ namespace {
{"rdx", 2}, {"rdi", 7},
};
-}
+} // namespace
// Manual, page 530
// Reg + Reg/Memory
-uint8_t ModRM(const std::string& reg, const std::string& rm) {
- uint8_t result{0b11000000}; // TODO: other than 11: Indexed forms of r/m
+std::vector<uint8_t> ModRM(const std::string& reg, const std::string& rm, int32_t disp) {
+ uint8_t result{}; // MOD is highest 2 bits, then 3 bits Reg, the 3 bits R/M
+ std::vector<uint8_t> displacement_bytes;
size_t val_reg{};
// reg
@@ -60,22 +64,35 @@ uint8_t ModRM(const std::string& reg, const std::string& rm) {
throw std::runtime_error("ModRM: Bad digit in arg1: "s + reg);
}
} else { // reg
- auto index1{ IndexOfRegister.find(reg) };
- if (index1 == IndexOfRegister.end())
- throw std::runtime_error("ModRM: Unknown register for arg1: "s + reg);
- val_reg = index1->second;
+ val_reg = RegNo(reg);
}
result |= (val_reg << 3);
// rm
- auto index2{ IndexOfRegister.find(rm) };
- if (index2 == IndexOfRegister.end())
- throw std::runtime_error("Unknown register for arg2: "s + rm);
-
- result |= index2->second;
+ if (rm.size() > 2 && rm.front() == '[' && rm.back() == ']') { // indexed / MemPtr
+ uint8_t rm_bits {RegNo(rm.substr(1, rm.size() - 2))};
+ if (rm_bits == 4)
+ throw std::runtime_error("ICE: SIB byte not yet supported");
+
+ 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
+ } else if (disp >= -128 && disp < 128) {
+ result |= 0b01000000; // 8 bit displacement
+ displacement_bytes.push_back(uint8_t(disp));
+ } else {
+ result |= 0b10000000; // 32 bit displacement
+ displacement_bytes += to_little_endian(disp);
+ }
+ result |= rm_bits;
+ } else { // normal register access
+ result |= 0b11000000;
+ result |= RegNo(rm);
+ }
- return result;
+ return std::vector<uint8_t>{result} + displacement_bytes;
}
uint8_t RegNo(const std::string& reg)