summaryrefslogtreecommitdiffhomepage
path: root/Sources
diff options
context:
space:
mode:
authorAmlal El Mahrouss <113760121+Amlal-ElMahrouss@users.noreply.github.com>2024-04-05 04:43:27 +0200
committerAmlal El Mahrouss <113760121+Amlal-ElMahrouss@users.noreply.github.com>2024-04-05 04:43:27 +0200
commit672ec345c6eb5a06500cba10e3f329b8a65ee047 (patch)
tree0e335135dc05ee129770bf5ea17e64f11e831012 /Sources
parent4fd8405b79823c6ce8dcfc3cbe0da29b2a8f5bf2 (diff)
ppcasm: WiP: Add opcode table for PowerPC.
What is needed to be done: - Support registers and jump addresses inside a PowerPC assembly file. - Thoroughly test the output on a PowerPC emulator. Signed-off-by: Amlal El Mahrouss <113760121+Amlal-ElMahrouss@users.noreply.github.com>
Diffstat (limited to 'Sources')
-rw-r--r--Sources/64asm.cc2
-rw-r--r--Sources/i64asm.cc14
-rw-r--r--Sources/ppc-cc.cc4
-rw-r--r--Sources/ppcasm.cc70
4 files changed, 48 insertions, 42 deletions
diff --git a/Sources/64asm.cc b/Sources/64asm.cc
index 78fa590..50b2d0b 100644
--- a/Sources/64asm.cc
+++ b/Sources/64asm.cc
@@ -560,7 +560,7 @@ bool CompilerKit::Encoder64x0::WriteNumber(const std::size_t &pos,
!res) {
if (errno != 0) {
detail::print_error("invalid hex number: " + jump_label, "64asm");
- throw std::runtime_error("invalid_hex");
+ throw std::runtime_error("invalid_hex_number");
}
}
diff --git a/Sources/i64asm.cc b/Sources/i64asm.cc
index 0eae5fc..e578587 100644
--- a/Sources/i64asm.cc
+++ b/Sources/i64asm.cc
@@ -124,29 +124,29 @@ MPCC_MODULE(NewOSAssemblerAMD64) {
"jno", "jnp", "jns", "jnz", "jo", "jp", "jpe", "jpo", "js", "jz"};
for (i64_hword_t i = 0; i < kJumpLimit; i++) {
- CpuCodeAMD64 code{.fName = opcodes_jump[i],
+ CpuOpcodeAMD64 code{.fName = opcodes_jump[i],
.fOpcode = static_cast<i64_hword_t>(kAsmJumpOpcode + i)};
kOpcodesAMD64.push_back(code);
}
- CpuCodeAMD64 code{.fName = "jcxz", .fOpcode = 0xE3};
+ CpuOpcodeAMD64 code{.fName = "jcxz", .fOpcode = 0xE3};
kOpcodesAMD64.push_back(code);
for (i64_hword_t i = kJumpLimitStandard; i < kJumpLimitStandardLimit; i++) {
- CpuCodeAMD64 code{.fName = "jmp", .fOpcode = i};
+ CpuOpcodeAMD64 code{.fName = "jmp", .fOpcode = i};
kOpcodesAMD64.push_back(code);
}
- CpuCodeAMD64 lahf{.fName = "lahf", .fOpcode = 0x9F};
+ CpuOpcodeAMD64 lahf{.fName = "lahf", .fOpcode = 0x9F};
kOpcodesAMD64.push_back(lahf);
- CpuCodeAMD64 lds{.fName = "lds", .fOpcode = 0xC5};
+ CpuOpcodeAMD64 lds{.fName = "lds", .fOpcode = 0xC5};
kOpcodesAMD64.push_back(lds);
- CpuCodeAMD64 lea{.fName = "lea", .fOpcode = 0x8D};
+ CpuOpcodeAMD64 lea{.fName = "lea", .fOpcode = 0x8D};
kOpcodesAMD64.push_back(lea);
- CpuCodeAMD64 nop{.fName = "nop", .fOpcode = 0x90};
+ CpuOpcodeAMD64 nop{.fName = "nop", .fOpcode = 0x90};
kOpcodesAMD64.push_back(nop);
//////////////// CPU OPCODES END ////////////////
diff --git a/Sources/ppc-cc.cc b/Sources/ppc-cc.cc
index 78f9bc1..25dd74e 100644
--- a/Sources/ppc-cc.cc
+++ b/Sources/ppc-cc.cc
@@ -1155,8 +1155,8 @@ class AssemblyMountpointCLang final : public CompilerKit::AssemblyInterface {
if (kAcceptableErrors > 0) return -1;
- std::vector<std::string> keywords = {"ldw", "stw", "lda", "sta",
- "add", "dec", "mv"};
+ std::vector<std::string> keywords = {"ld", "stw",
+ "add", "sub", "or"};
///
/// Replace, optimize, fix assembly output.
diff --git a/Sources/ppcasm.cc b/Sources/ppcasm.cc
index f37a650..0214053 100644
--- a/Sources/ppcasm.cc
+++ b/Sources/ppcasm.cc
@@ -43,7 +43,7 @@
#define kStdOut (std::cout << kWhite)
#define kStdErr (std::cout << kRed)
-static char kOutputArch = CompilerKit::kPefArchPowerPC;
+static CharType kOutputArch = CompilerKit::kPefArchPowerPC;
static Boolean kOutputAsBinary = false;
static UInt32 kErrorLimit = 10;
@@ -56,7 +56,7 @@ static std::vector<std::pair<std::string, std::uintptr_t>> kOriginLabel;
static bool kVerbose = false;
-static std::vector<e64k_num_t> kBytes;
+static std::vector<uint32_t> kBytes;
static CompilerKit::AERecordHeader kCurrentRecord{
.fName = "", .fKind = CompilerKit::kPefCode, .fSize = 0, .fOffset = 0};
@@ -506,15 +506,13 @@ std::string CompilerKit::EncoderPowerPC::CheckLine(
}
// these do take an argument.
- std::vector<std::string> operands_inst = {"stw", "ldw", "lda", "sta"};
+ std::vector<std::string> operands_inst = {"stw", "ld", "lda", "sta"};
// these don't.
- std::vector<std::string> filter_inst = {"jlr", "jrl", "int"};
-
- for (auto &opcode64x0 : kOpcodes64x0) {
- if (line.find(opcode64x0.fName) != std::string::npos) {
- if (opcode64x0.fFunct7 == kAsmNoArgs) return err_str;
+ std::vector<std::string> filter_inst = {"blr", "bl", "sc"};
+ for (auto &opcodePPC : kOpcodesPowerPC) {
+ if (line.find(opcodePPC.name) != std::string::npos) {
for (auto &op : operands_inst) {
// if only the instruction was found.
if (line == op) {
@@ -527,13 +525,13 @@ std::string CompilerKit::EncoderPowerPC::CheckLine(
// if it is like that -> addr1, 0x0
if (auto it = std::find(filter_inst.begin(), filter_inst.end(),
- opcode64x0.fName);
+ opcodePPC.name);
it == filter_inst.cend()) {
- if (ParserKit::find_word(line, opcode64x0.fName)) {
- if (!isspace(line[line.find(opcode64x0.fName) +
- strlen(opcode64x0.fName)])) {
+ if (ParserKit::find_word(line, opcodePPC.name)) {
+ if (!isspace(line[line.find(opcodePPC.name) +
+ strlen(opcodePPC.name)])) {
err_str += "\nMissing space between ";
- err_str += opcode64x0.fName;
+ err_str += opcodePPC.name;
err_str += " and operands.\nhere -> ";
err_str += line;
}
@@ -660,22 +658,20 @@ bool CompilerKit::EncoderPowerPC::WriteLine(std::string &line,
const std::string &file) {
if (ParserKit::find_word(line, "export ")) return true;
- for (auto &opcode64x0 : kOpcodes64x0) {
+ for (auto &opcodePPC : kOpcodesPowerPC) {
// strict check here
- if (ParserKit::find_word(line, opcode64x0.fName) &&
+ if (ParserKit::find_word(line, opcodePPC.name) &&
detail::algorithm::is_valid(line)) {
- std::string name(opcode64x0.fName);
+ std::string name(opcodePPC.name);
std::string jump_label, cpy_jump_label;
- kBytes.emplace_back(opcode64x0.fOpcode);
- kBytes.emplace_back(opcode64x0.fFunct3);
- kBytes.emplace_back(opcode64x0.fFunct7);
+ kBytes.emplace_back(opcodePPC.opcode);
// check funct7 type.
- switch (opcode64x0.fFunct7) {
+ switch (opcodePPC.ops->type) {
// reg to reg means register to register transfer operation.
- case kAsmRegToReg:
- case kAsmImmediate: {
+ case GREG:
+ case G0REG: {
// \brief how many registers we found.
std::size_t found_some = 0UL;
@@ -703,7 +699,7 @@ bool CompilerKit::EncoderPowerPC::WriteLine(std::string &line,
reg_str += line[line_index + 3];
detail::print_error(
"invalid register index, r" + reg_str +
- "\nnote: The PowerPC accepts registers from r0 to r20.",
+ "\nnote: The PowerPC accepts registers from r0 to r30.",
file);
throw std::runtime_error("invalid_register_index");
}
@@ -712,6 +708,15 @@ bool CompilerKit::EncoderPowerPC::WriteLine(std::string &line,
// finally cast to a size_t
std::size_t reg_index = strtol(reg_str.c_str(), nullptr, 10);
+ uint8_t base = 0x08;
+
+ for (size_t i = 0; i != reg_index; i++)
+ {
+ base += 2;
+ }
+
+ kBytes.emplace_back(base);
+
if (reg_index > kAsmRegisterLimit) {
detail::print_error("invalid register index, r" + reg_str,
file);
@@ -730,7 +735,7 @@ bool CompilerKit::EncoderPowerPC::WriteLine(std::string &line,
}
// we're not in immediate addressing, reg to reg.
- if (opcode64x0.fFunct7 != kAsmImmediate) {
+ if (opcodePPC.ops->type != GREG) {
// remember! register to register!
if (found_some == 1) {
detail::print_error(
@@ -738,11 +743,12 @@ bool CompilerKit::EncoderPowerPC::WriteLine(std::string &line,
"starts with 'r'.\nline: " +
line,
file);
+
throw std::runtime_error("not_a_register");
}
}
- if (found_some < 1 && name != "ldw" && name != "lda" &&
+ if (found_some < 1 && name != "ld" &&
name != "stw") {
detail::print_error(
"invalid combination of opcode and registers.\nline: " + line,
@@ -774,12 +780,12 @@ bool CompilerKit::EncoderPowerPC::WriteLine(std::string &line,
}
// try to fetch a number from the name
- if (name == "stw" || name == "ldw" || name == "lda" || name == "sta") {
+ if (name.find("stw") != std::string::npos || name.find("ld") != std::string::npos) {
auto where_string = name;
// if we load something, we'd need it's symbol/literal
- if (name == "stw" || name == "sta" || name == "ldw" || name == "lda" ||
- name == "sta")
+ // @note: Something may jump on it, dont remove that if.
+ if (name.find("stw") != std::string::npos || name.find("ld") != std::string::npos)
where_string = ",";
jump_label = line;
@@ -841,7 +847,7 @@ bool CompilerKit::EncoderPowerPC::WriteLine(std::string &line,
}
// This is the case where we jump to a label, it is also used as a goto.
- if (name == "lda" || name == "sta") {
+ if (name == "ld" || name == "stw") {
asm_write_label:
if (cpy_jump_label.find('\n') != std::string::npos)
cpy_jump_label.erase(cpy_jump_label.find('\n'), 1);
@@ -903,10 +909,10 @@ bool CompilerKit::EncoderPowerPC::WriteLine(std::string &line,
}
/// don't go any further if:
- /// load word (ldw) or store word. (stw)
+ /// load word (ld) or store word. (stw)
- if (name == "ldw" ||
- name == "stw")
+ if (name.find("ld") != std::string::npos ||
+ name.find("st") != std::string::npos)
break;
auto mld_reloc_str = std::to_string(cpy_jump_label.size());