summaryrefslogtreecommitdiffhomepage
path: root/Sources/ppcasm.cc
diff options
context:
space:
mode:
authorAmlal El Mahrouss <amlal.elmahrouss@icloud.com>2024-04-28 08:17:02 +0200
committerAmlal El Mahrouss <amlal.elmahrouss@icloud.com>2024-04-28 08:17:02 +0200
commitf84498ff447cc4bf891999e782ef90bfbc9577bd (patch)
treea29aac9395fb9fc068b59942bf6befb1fb02f3b9 /Sources/ppcasm.cc
parentc18972980351335ef65029aae677bac76c70d161 (diff)
MHR-21: Add support for cmp* instructions in POWER, fix AMD64 assembler,
the origin doesn't get incremented. Signed-off-by: Amlal El Mahrouss <amlal.elmahrouss@icloud.com>
Diffstat (limited to 'Sources/ppcasm.cc')
-rw-r--r--Sources/ppcasm.cc37
1 files changed, 31 insertions, 6 deletions
diff --git a/Sources/ppcasm.cc b/Sources/ppcasm.cc
index f95020e..9d12922 100644
--- a/Sources/ppcasm.cc
+++ b/Sources/ppcasm.cc
@@ -48,6 +48,8 @@
static CharType kOutputArch = CompilerKit::kPefArchPowerPC;
static Boolean kOutputAsBinary = false;
+constexpr auto cPowerIPAlignment = 0x4U;
+
static UInt32 kErrorLimit = 10;
static UInt32 kAcceptableErrors = 0;
@@ -677,6 +679,7 @@ bool CompilerKit::EncoderPowerPC::WriteLine(std::string &line,
if (ParserKit::find_word(line, opcodePPC.name)) {
std::string name(opcodePPC.name);
std::string jump_label, cpy_jump_label;
+ std::vector<size_t> found_registers_index;
// check funct7 type.
switch (opcodePPC.ops->type) {
@@ -833,9 +836,9 @@ bool CompilerKit::EncoderPowerPC::WriteLine(std::string &line,
}
++register_count;
+ ++found_some_count;
}
- /// FIXME: Prompt correct opcode in little endian.
if (opcodeName == "addi") {
if (found_some_count == 2 || found_some_count == 0)
kBytes.emplace_back(reg_index);
@@ -850,6 +853,15 @@ bool CompilerKit::EncoderPowerPC::WriteLine(std::string &line,
}
}
+ if (opcodeName.find("cmp") != std::string::npos) {
+ ++found_some_count;
+
+ if (found_some_count > 3) {
+ detail::print_error("Too much registers. -> " + line, file);
+ throw std::runtime_error("too_much_regs");
+ }
+ }
+
if (opcodeName.find("mf") != std::string::npos ||
opcodeName.find("mt") != std::string::npos) {
char numIndex = 0;
@@ -886,15 +898,29 @@ bool CompilerKit::EncoderPowerPC::WriteLine(std::string &line,
for (auto ch : num.number) {
kBytes.emplace_back(ch);
}
-
- break;
}
+
+ found_registers_index.push_back(reg_index);
}
}
if (opcodeName == "addi") {
kBytes.emplace_back(0x38);
}
+
+ if (opcodeName.find("cmp") != std::string::npos) {
+ char rightReg = 0;
+
+ for (size_t i = 0; i != found_registers_index[0]; i++) {
+ rightReg += 0x08;
+ }
+
+ kBytes.emplace_back(0x00);
+ kBytes.emplace_back(rightReg);
+ kBytes.emplace_back(found_registers_index[1]);
+ kBytes.emplace_back(0x7c);
+ }
+
if ((opcodeName[0] == 's' && opcodeName[1] == 't')) {
size_t offset = 0UL;
@@ -913,8 +939,7 @@ bool CompilerKit::EncoderPowerPC::WriteLine(std::string &line,
if (opcodeName == "mr") {
if (register_count == 1) {
detail::print_error("Too few registers. -> " + line, file);
-
- throw std::runtime_error("not_a_register");
+ throw std::runtime_error("too_few_registers");
}
}
@@ -943,7 +968,7 @@ bool CompilerKit::EncoderPowerPC::WriteLine(std::string &line,
}
}
- kOrigin += 0x04;
+ kOrigin += cPowerIPAlignment;
break;
}
}