summaryrefslogtreecommitdiffhomepage
path: root/dev
diff options
context:
space:
mode:
authorAmlal El Mahrouss <amlal@nekernel.org>2025-05-17 17:31:38 +0200
committerAmlal El Mahrouss <amlal@nekernel.org>2025-05-17 17:31:38 +0200
commit47608deee7f20b0ac23d1dbf4c15f1e1aa584b54 (patch)
tree7e8c9ff4808ad67742753f7c22ade16578f81ec9 /dev
parent9c74ca0db3d5a49f95220989aec0778d6bfbb842 (diff)
feat(codegen/amd64): new opcode support: xor, and syscall.
Signed-off-by: Amlal El Mahrouss <amlal@nekernel.org>
Diffstat (limited to 'dev')
-rw-r--r--dev/LibCompiler/Backend/Amd64.h2
-rw-r--r--dev/LibCompiler/src/AssemblerAMD64.cc212
2 files changed, 116 insertions, 98 deletions
diff --git a/dev/LibCompiler/Backend/Amd64.h b/dev/LibCompiler/Backend/Amd64.h
index a3fb8a2..b6d9530 100644
--- a/dev/LibCompiler/Backend/Amd64.h
+++ b/dev/LibCompiler/Backend/Amd64.h
@@ -43,6 +43,6 @@ inline std::vector<CpuOpcodeAMD64> kOpcodesAMD64 = {
kAsmOpcodeDecl("int3", 0xC3) kAsmOpcodeDecl("iret", 0xCF) kAsmOpcodeDecl("retf", 0xCB)
kAsmOpcodeDecl("retn", 0xC3) kAsmOpcodeDecl("ret", 0xC3) kAsmOpcodeDecl("sti", 0xfb)
kAsmOpcodeDecl("cli", 0xfa) kAsmOpcodeDecl("hlt", 0xf4) kAsmOpcodeDecl("nop", 0x90)
- kAsmOpcodeDecl("mov", 0x48) kAsmOpcodeDecl("call", 0xFF)};
+ kAsmOpcodeDecl("mov", 0x48) kAsmOpcodeDecl("call", 0xFF) kAsmOpcodeDecl("syscall", 0x0F) kAsmOpcodeDecl("xor", 0x48)};
#define kAsmRegisterLimit 16
diff --git a/dev/LibCompiler/src/AssemblerAMD64.cc b/dev/LibCompiler/src/AssemblerAMD64.cc
index 3fdb197..9054a62 100644
--- a/dev/LibCompiler/src/AssemblerAMD64.cc
+++ b/dev/LibCompiler/src/AssemblerAMD64.cc
@@ -965,13 +965,9 @@ bool LibCompiler::EncoderAMD64::WriteLine(std::string line, std::string file) {
{.fName = "dx", .fModRM = 0x2}, {.fName = "bx", .fModRM = 3},
{.fName = "sp", .fModRM = 0x4}, {.fName = "bp", .fModRM = 5},
{.fName = "si", .fModRM = 0x6}, {.fName = "di", .fModRM = 7},
- {.fName = "r8", .fModRM = 8}, {.fName = "r13", .fModRM = 9},
- {.fName = "r9", .fModRM = 10}, {.fName = "r14", .fModRM = 11},
- {.fName = "r10", .fModRM = 12}, {.fName = "r15", .fModRM = 13},
- {.fName = "r11", .fModRM = 14},
};
- bool foundInstruction = false;
+ BOOL foundInstruction = false;
for (auto& opcodeAMD64 : kOpcodesAMD64) {
// strict check here
@@ -981,140 +977,157 @@ bool LibCompiler::EncoderAMD64::WriteLine(std::string line, std::string file) {
std::string name(opcodeAMD64.fName);
/// Move instruction handler.
- if (line.find(name) != std::string::npos && name == "mov") {
- std::string substr = line.substr(line.find(name) + name.size());
+ if (line.find(name) != std::string::npos) {
+ if (name == "mov" || name == "xor") {
+ std::string substr = line.substr(line.find(name) + name.size());
- uint64_t bits = kRegisterBitWidth;
+ uint64_t bits = kRegisterBitWidth;
- if (substr.find(",") == std::string::npos) {
- Detail::print_error("Syntax error: missing right operand.", "LibCompiler");
- throw std::runtime_error("syntax_err");
- }
+ if (substr.find(",") == std::string::npos) {
+ Detail::print_error("Syntax error: missing right operand.", "LibCompiler");
+ throw std::runtime_error("syntax_err");
+ }
- bool onlyOneReg = true;
+ bool onlyOneReg = true;
- std::vector<RegMapAMD64> currentRegList;
+ std::vector<RegMapAMD64> currentRegList;
- for (auto& reg : kRegisterList) {
- std::vector<char> regExt = {'e', 'r'};
+ for (auto& reg : kRegisterList) {
+ std::vector<char> regExt = {'e', 'r'};
- for (auto& ext : regExt) {
- std::string registerName;
+ for (auto& ext : regExt) {
+ std::string registerName;
- if (bits > 16) registerName.push_back(ext);
+ if (bits > 16) registerName.push_back(ext);
- registerName += reg.fName;
+ registerName += reg.fName;
- while (line.find(registerName) != std::string::npos) {
- line.erase(line.find(registerName), registerName.size());
+ while (line.find(registerName) != std::string::npos) {
+ line.erase(line.find(registerName), registerName.size());
- if (bits == 16) {
- if (registerName[0] == 'r') {
- Detail::print_error("invalid size for register, current bit width is: " +
- std::to_string(kRegisterBitWidth),
- file);
- throw std::runtime_error("invalid_reg_size");
+ if (bits == 16) {
+ if (registerName[0] == 'r') {
+ Detail::print_error("invalid size for register, current bit width is: " +
+ std::to_string(kRegisterBitWidth),
+ file);
+ throw std::runtime_error("invalid_reg_size");
+ }
}
- }
- currentRegList.push_back({.fName = registerName, .fModRM = reg.fModRM});
+ currentRegList.push_back({.fName = registerName, .fModRM = reg.fModRM});
+ }
}
}
- }
-
- if (currentRegList.size() > 1) onlyOneReg = false;
-
- bool hasRBasedRegs = false;
- if (!onlyOneReg) {
- /// very tricky to understand.
- /// but this checks for a r8 through r15 register.
- if (currentRegList[0].fName[0] == 'r' || currentRegList[1].fName[0] == 'r') {
- if (isdigit(currentRegList[0].fName[1]) && isdigit(currentRegList[1].fName[1])) {
- kAppBytes.emplace_back(0x4d);
- hasRBasedRegs = true;
- } else if (isdigit(currentRegList[0].fName[1]) || isdigit(currentRegList[1].fName[1])) {
- kAppBytes.emplace_back(0x4c);
- hasRBasedRegs = true;
+ if (currentRegList.size() > 1) onlyOneReg = false;
+
+ bool hasRBasedRegs = false;
+
+ if (!onlyOneReg) {
+ /// very tricky to understand.
+ /// but this checks for a r8 through r15 register.
+ if (currentRegList[0].fName[0] == 'r' || currentRegList[1].fName[0] == 'r') {
+ if (isdigit(currentRegList[0].fName[1]) && isdigit(currentRegList[1].fName[1])) {
+ kAppBytes.emplace_back(0x4d);
+ hasRBasedRegs = true;
+ } else if (isdigit(currentRegList[0].fName[1]) ||
+ isdigit(currentRegList[1].fName[1])) {
+ kAppBytes.emplace_back(0x4c);
+ hasRBasedRegs = true;
+ }
}
}
- }
- if (bits == 64 || bits == 32) {
- if (!hasRBasedRegs && bits >= 32) {
- kAppBytes.emplace_back(opcodeAMD64.fOpcode);
- }
+ if (name == "mov") {
+ if (bits == 64 || bits == 32) {
+ if (!hasRBasedRegs && bits >= 32) {
+ kAppBytes.emplace_back(opcodeAMD64.fOpcode);
+ }
- if (!onlyOneReg) kAppBytes.emplace_back(0x89);
- } else if (bits == 16) {
- if (hasRBasedRegs) {
- Detail::print_error("Invalid combination of operands and registers.", "LibCompiler");
- throw std::runtime_error("comb_op_reg");
+ if (!onlyOneReg) kAppBytes.emplace_back(0x89);
+ } else if (bits == 16) {
+ if (hasRBasedRegs) {
+ Detail::print_error("Invalid combination of operands and registers.",
+ "LibCompiler");
+ throw std::runtime_error("comb_op_reg");
+ } else {
+ kAppBytes.emplace_back(0x66);
+ kAppBytes.emplace_back(0x89);
+ }
+ }
} else {
- kAppBytes.emplace_back(0x66);
- kAppBytes.emplace_back(0x89);
- }
- }
-
- if (onlyOneReg) {
- auto num = GetNumber32(line, ",");
+ if (!hasRBasedRegs && bits >= 32) {
+ kAppBytes.emplace_back(opcodeAMD64.fOpcode);
+ }
- for (auto& num_idx : num.number) {
- if (num_idx == 0) num_idx = 0xFF;
+ kAppBytes.emplace_back(0x31);
}
- auto modrm = (0x3 << 6 | currentRegList[0].fModRM);
+ if (onlyOneReg) {
+ auto num = GetNumber32(line, ",");
- kAppBytes.emplace_back(0xC7); // prefixed before placing the modrm and then the number.
- kAppBytes.emplace_back(modrm);
- kAppBytes.emplace_back(num.number[0]);
- kAppBytes.emplace_back(num.number[1]);
- kAppBytes.emplace_back(num.number[2]);
- kAppBytes.emplace_back(num.number[3]);
+ for (auto& num_idx : num.number) {
+ if (num_idx == 0) num_idx = 0xFF;
+ }
- break;
- }
+ auto modrm = (0x3 << 6 | currentRegList[0].fModRM);
- if (currentRegList[1].fName[0] == 'r' && currentRegList[0].fName[0] == 'e') {
- Detail::print_error("Invalid combination of operands and registers.", "LibCompiler");
- throw std::runtime_error("comb_op_reg");
- }
+ kAppBytes.emplace_back(0xC7); // prefixed before placing the modrm and then the number.
+ kAppBytes.emplace_back(modrm);
- if (currentRegList[0].fName[0] == 'r' && currentRegList[1].fName[0] == 'e') {
- Detail::print_error("Invalid combination of operands and registers.", "LibCompiler");
- throw std::runtime_error("comb_op_reg");
- }
+ if (name != "xor") {
+ kAppBytes.emplace_back(num.number[0]);
+ kAppBytes.emplace_back(num.number[1]);
+ kAppBytes.emplace_back(num.number[2]);
+ kAppBytes.emplace_back(num.number[3]);
+ }
- if (bits == 16) {
- if (currentRegList[0].fName[0] == 'r' || currentRegList[0].fName[0] == 'e') {
- Detail::print_error("Invalid combination of operands and registers.", "LibCompiler");
- throw std::runtime_error("comb_op_reg");
+ break;
}
- if (currentRegList[1].fName[0] == 'r' || currentRegList[1].fName[0] == 'e') {
+ if (currentRegList[1].fName[0] == 'r' && currentRegList[0].fName[0] == 'e') {
Detail::print_error("Invalid combination of operands and registers.", "LibCompiler");
throw std::runtime_error("comb_op_reg");
}
- } else {
- if (currentRegList[0].fName[0] != 'r' || currentRegList[0].fName[0] == 'e') {
+
+ if (currentRegList[0].fName[0] == 'r' && currentRegList[1].fName[0] == 'e') {
Detail::print_error("Invalid combination of operands and registers.", "LibCompiler");
throw std::runtime_error("comb_op_reg");
}
- if (currentRegList[1].fName[0] != 'r' || currentRegList[1].fName[0] == 'e') {
- Detail::print_error("Invalid combination of operands and registers.", "LibCompiler");
- throw std::runtime_error("comb_op_reg");
+ if (bits == 16) {
+ if (currentRegList[0].fName[0] == 'r' || currentRegList[0].fName[0] == 'e') {
+ Detail::print_error("Invalid combination of operands and registers.", "LibCompiler");
+ throw std::runtime_error("comb_op_reg");
+ }
+
+ if (currentRegList[1].fName[0] == 'r' || currentRegList[1].fName[0] == 'e') {
+ Detail::print_error("Invalid combination of operands and registers.", "LibCompiler");
+ throw std::runtime_error("comb_op_reg");
+ }
+ } else {
+ if (currentRegList[0].fName[0] != 'r' || currentRegList[0].fName[0] == 'e') {
+ Detail::print_error("Invalid combination of operands and registers.", "LibCompiler");
+ throw std::runtime_error("comb_op_reg");
+ }
+
+ if (currentRegList[1].fName[0] != 'r' || currentRegList[1].fName[0] == 'e') {
+ Detail::print_error("Invalid combination of operands and registers.", "LibCompiler");
+ throw std::runtime_error("comb_op_reg");
+ }
}
- }
- /// encode register using the modrm encoding.
+ /// encode register using the modrm encoding.
- auto modrm = (0x3 << 6 | currentRegList[1].fModRM << 3 | currentRegList[0].fModRM);
+ auto modrm = (0x3 << 6 | currentRegList[1].fModRM << 3 | currentRegList[0].fModRM);
- kAppBytes.emplace_back(modrm);
+ kAppBytes.emplace_back(modrm);
- break;
- } else if (name == "int" || name == "into" || name == "intd") {
+ break;
+ }
+ }
+
+ if (name == "int" || name == "into" || name == "intd") {
kAppBytes.emplace_back(opcodeAMD64.fOpcode);
this->WriteNumber8(line.find(name) + name.size() + 1, line);
@@ -1127,6 +1140,11 @@ bool LibCompiler::EncoderAMD64::WriteLine(std::string line, std::string file) {
}
break;
+ } else if (name == "syscall") {
+ kAppBytes.emplace_back(opcodeAMD64.fOpcode);
+ kAppBytes.emplace_back(0x05);
+
+ break;
} else {
kAppBytes.emplace_back(opcodeAMD64.fOpcode);