diff --git a/Debug/BasicBlock.obj b/Debug/BasicBlock.obj deleted file mode 100644 index a3fe885..0000000 Binary files a/Debug/BasicBlock.obj and /dev/null differ diff --git a/Debug/Function.obj b/Debug/Function.obj deleted file mode 100644 index 712ee62..0000000 Binary files a/Debug/Function.obj and /dev/null differ diff --git a/Debug/Instrucion.obj b/Debug/Instrucion.obj deleted file mode 100644 index 0f4dc39..0000000 Binary files a/Debug/Instrucion.obj and /dev/null differ diff --git a/Debug/Module.obj b/Debug/Module.obj deleted file mode 100644 index a633ca7..0000000 Binary files a/Debug/Module.obj and /dev/null differ diff --git a/Debug/compiler.Build.CppClean.log b/Debug/compiler.Build.CppClean.log deleted file mode 100644 index 3537c53..0000000 --- a/Debug/compiler.Build.CppClean.log +++ /dev/null @@ -1,18 +0,0 @@ -c:\users\wzy\source\repos\compiler\compiler\debug\vc142.pdb -c:\users\wzy\source\repos\compiler\compiler\debug\vc142.idb -c:\users\wzy\source\repos\compiler\compiler\debug\tokens.obj -c:\users\wzy\source\repos\compiler\compiler\debug\module.obj -c:\users\wzy\source\repos\compiler\compiler\debug\main.obj -c:\users\wzy\source\repos\compiler\compiler\debug\instrucion.obj -c:\users\wzy\source\repos\compiler\compiler\debug\function.obj -c:\users\wzy\source\repos\compiler\compiler\debug\parser.obj -c:\users\wzy\source\repos\compiler\compiler\debug\node.obj -c:\users\wzy\source\repos\compiler\debug\compiler.exe -c:\users\wzy\source\repos\compiler\debug\compiler.ilk -c:\users\wzy\source\repos\compiler\debug\compiler.pdb -c:\users\wzy\source\repos\compiler\compiler\debug\compiler.tlog\cl.command.1.tlog -c:\users\wzy\source\repos\compiler\compiler\debug\compiler.tlog\cl.read.1.tlog -c:\users\wzy\source\repos\compiler\compiler\debug\compiler.tlog\cl.write.1.tlog -c:\users\wzy\source\repos\compiler\compiler\debug\compiler.tlog\link.command.1.tlog -c:\users\wzy\source\repos\compiler\compiler\debug\compiler.tlog\link.read.1.tlog -c:\users\wzy\source\repos\compiler\compiler\debug\compiler.tlog\link.write.1.tlog diff --git a/Debug/compiler.exe.recipe b/Debug/compiler.exe.recipe deleted file mode 100644 index bcc409f..0000000 --- a/Debug/compiler.exe.recipe +++ /dev/null @@ -1,11 +0,0 @@ - - - - - C:\Users\wzy\source\repos\compiler\Debug\compiler.exe - - - - - - \ No newline at end of file diff --git a/Debug/compiler.log b/Debug/compiler.log deleted file mode 100644 index c81607c..0000000 --- a/Debug/compiler.log +++ /dev/null @@ -1,19 +0,0 @@ - Function.cpp -C:\Users\wzy\source\repos\compiler\compiler\include\Instruction.h(1,1): warning C4819: 该文件包含不能在当前代码页(936)中表示的字符。请将该文件保存为 Unicode 格式以防止数据丢失 -C:\Users\wzy\source\repos\compiler\compiler\include\Instruction.h(313,21): warning C4018: “<”: 有符号/无符号不匹配 -C:\Users\wzy\source\repos\compiler\compiler\include\Instruction.h(342,21): warning C4018: “<”: 有符号/无符号不匹配 -C:\Users\wzy\source\repos\compiler\compiler\src\Function.cpp(215,22): warning C4018: “<”: 有符号/无符号不匹配 -C:\Users\wzy\source\repos\compiler\compiler\src\Function.cpp(268,21): warning C4018: “<”: 有符号/无符号不匹配 -C:\Users\wzy\source\repos\compiler\compiler\src\Function.cpp(483,20): warning C4018: “<”: 有符号/无符号不匹配 -C:\Users\wzy\source\repos\compiler\compiler\src\Function.cpp(602,19): warning C4018: “<”: 有符号/无符号不匹配 -C:\Users\wzy\source\repos\compiler\compiler\src\Function.cpp(655,20): warning C4018: “<”: 有符号/无符号不匹配 - main.cpp -C:\Users\wzy\source\repos\compiler\compiler\include\Instruction.h(1,1): warning C4819: 该文件包含不能在当前代码页(936)中表示的字符。请将该文件保存为 Unicode 格式以防止数据丢失 -C:\Users\wzy\source\repos\compiler\compiler\include\Instruction.h(313,21): warning C4018: “<”: 有符号/无符号不匹配 -C:\Users\wzy\source\repos\compiler\compiler\include\Instruction.h(342,21): warning C4018: “<”: 有符号/无符号不匹配 - 正在生成代码... -C:\Users\wzy\source\repos\compiler\compiler\src\Function.cpp(175): warning C4715: “getOpId”: 不是所有的控件路径都返回值 -C:\Users\wzy\source\repos\compiler\compiler\src\Function.cpp(199): warning C4715: “judgeExp”: 不是所有的控件路径都返回值 -C:\Users\wzy\source\repos\compiler\compiler\src\Function.cpp(287): warning C4715: “Function::getInstFromExp”: 不是所有的控件路径都返回值 -C:\Users\wzy\source\repos\compiler\compiler\src\Function.cpp(476): warning C4715: “judgeStmt”: 不是所有的控件路径都返回值 - compiler.vcxproj -> C:\Users\wzy\source\repos\compiler\Debug\compiler.exe diff --git a/Debug/compiler.tlog/CL.command.1.tlog b/Debug/compiler.tlog/CL.command.1.tlog deleted file mode 100644 index d9265fa..0000000 Binary files a/Debug/compiler.tlog/CL.command.1.tlog and /dev/null differ diff --git a/Debug/compiler.tlog/CL.read.1.tlog b/Debug/compiler.tlog/CL.read.1.tlog deleted file mode 100644 index 69e9a9c..0000000 Binary files a/Debug/compiler.tlog/CL.read.1.tlog and /dev/null differ diff --git a/Debug/compiler.tlog/CL.write.1.tlog b/Debug/compiler.tlog/CL.write.1.tlog deleted file mode 100644 index 2e45027..0000000 Binary files a/Debug/compiler.tlog/CL.write.1.tlog and /dev/null differ diff --git a/Debug/compiler.tlog/compiler.lastbuildstate b/Debug/compiler.tlog/compiler.lastbuildstate deleted file mode 100644 index 2d1a8b7..0000000 --- a/Debug/compiler.tlog/compiler.lastbuildstate +++ /dev/null @@ -1,2 +0,0 @@ -PlatformToolSet=v142:VCToolArchitecture=Native32Bit:VCToolsVersion=14.28.29910:TargetPlatformVersion=10.0.19041.0: -Debug|Win32|C:\Users\wzy\source\repos\compiler\| diff --git a/Debug/compiler.tlog/link.command.1.tlog b/Debug/compiler.tlog/link.command.1.tlog deleted file mode 100644 index 479cfcb..0000000 Binary files a/Debug/compiler.tlog/link.command.1.tlog and /dev/null differ diff --git a/Debug/compiler.tlog/link.read.1.tlog b/Debug/compiler.tlog/link.read.1.tlog deleted file mode 100644 index 06242e4..0000000 Binary files a/Debug/compiler.tlog/link.read.1.tlog and /dev/null differ diff --git a/Debug/compiler.tlog/link.write.1.tlog b/Debug/compiler.tlog/link.write.1.tlog deleted file mode 100644 index af78349..0000000 Binary files a/Debug/compiler.tlog/link.write.1.tlog and /dev/null differ diff --git a/Debug/compiler.vcxproj.FileListAbsolute.txt b/Debug/compiler.vcxproj.FileListAbsolute.txt deleted file mode 100644 index e69de29..0000000 diff --git a/Debug/function.obj.enc b/Debug/function.obj.enc deleted file mode 100644 index 351ac43..0000000 Binary files a/Debug/function.obj.enc and /dev/null differ diff --git a/Debug/main.obj b/Debug/main.obj deleted file mode 100644 index 96fe133..0000000 Binary files a/Debug/main.obj and /dev/null differ diff --git a/Debug/node.obj b/Debug/node.obj deleted file mode 100644 index ec2cccc..0000000 Binary files a/Debug/node.obj and /dev/null differ diff --git a/Debug/parser.obj b/Debug/parser.obj deleted file mode 100644 index 82ba03b..0000000 Binary files a/Debug/parser.obj and /dev/null differ diff --git a/Debug/tokens.obj b/Debug/tokens.obj deleted file mode 100644 index 6535a9c..0000000 Binary files a/Debug/tokens.obj and /dev/null differ diff --git a/Debug/vc142.idb b/Debug/vc142.idb deleted file mode 100644 index 8bbec14..0000000 Binary files a/Debug/vc142.idb and /dev/null differ diff --git a/Debug/vc142.pdb b/Debug/vc142.pdb deleted file mode 100644 index 4da0a49..0000000 Binary files a/Debug/vc142.pdb and /dev/null differ diff --git a/README.md b/README.md deleted file mode 100644 index b74c2bd..0000000 --- a/README.md +++ /dev/null @@ -1,3 +0,0 @@ -# compiler - -2021编译器比赛,中层IR优化 diff --git a/assembly/AsmInstruction.cpp b/assembly/AsmInstruction.cpp new file mode 100644 index 0000000..0ab3dea --- /dev/null +++ b/assembly/AsmInstruction.cpp @@ -0,0 +1,341 @@ +#include "AsmInstruction.h" + +namespace Assembly +{ + std::string getRegName(int reg) + { + if (reg < 0 || reg > 15) + { + Error::exit("Assembly::getRegName: Reg id out of range"); + } + return REG_NAME[reg]; + } + + std::string getCondCode(Condition cond) + { + return COND_CODE[static_cast(cond)]; + } + + std::string getShiftCode(ShiftType shft) + { + return INSTR_CODE[static_cast(shft)]; + } + + std::string getInstrCode(InstrType instr) + { + return INSTR_CODE[static_cast(instr)]; + } + + std::string getAutoIncCode(AutoIncType inc) + { + return AUTO_INC_CODE[static_cast(inc)]; + } + + Imm8m::Imm8m(uint32_t val) : val(val) + { + testValid(val); + } + + bool Imm8m::isValid(uint32_t val) + { + int lZeros = 0; + int rZeros = 0; + int mZeros = 0; + + for (int i = 0; i < 32; i++) + { + if (val & (1 << i)) break; + lZeros++; + } + + for (int i = 31; i >= 0; i--) + { + if (val & (1 << i)) break; + rZeros++; + } + + int tmp = 0; + for (int i = 0; i < 32; i++) + { + if (val & (1 << i)) + { + mZeros = std::max(mZeros, tmp); + tmp = 0; + continue; + } + tmp++; + } + return std::max(mZeros, lZeros + rZeros) >= 24; + } + + void Imm8m::testValid(uint32_t val) + { + if (!isValid(val)) + { + Error::exit("Assembly::Imm8m: invalid value"); + } + } + + std::string Imm8m::toString() const + { + return "#" + std::to_string(val); + } + + std::vector Imm8m::exclusiveSplit(uint32_t val) + { + // TODO: find the best split + uint64_t extVal = static_cast(val) << 32 | val; + std::vector ret; + ret.push_back(val & 0x000000ff); + ret.push_back(val & 0x0000ff00); + ret.push_back(val & 0x00ff0000); + ret.push_back(val & 0xff000000); + return ret; + } + + std::vector Imm8m::inclusiveSplit(uint32_t val) + { + std::vector ret; + ret.push_back(val & 0x000000ff | 0xffffff00); + ret.push_back(val & 0x0000ff00 | 0xffff00ff); + ret.push_back(val & 0x00ff0000 | 0xff00ffff); + ret.push_back(val & 0xff000000 | 0x00ffffff); + return ret; + } + + Register::Register(int id) : id(id) + { + if (id < 0 || id > 15) + { + Error::exit("Assembly::Register: reg id out of range"); + } + } + + std::string Register::toString() const + { + return REG_NAME[id]; + } + + RegShift::RegShift(Register reg, ShiftType sftType, int bits) : + reg(reg), sftType(sftType), shift(bits) + { + if ((sftType == ShiftType::Lsl && (bits < 0 || bits > 31)) || + (sftType == ShiftType::Lsr && (bits < 1 || bits > 32)) || + (sftType == ShiftType::Asr && (bits < 1 || bits > 32))) + { + Error::exit("Assembly::RegShift: shift bits out of range"); + } + } + + std::string RegShift::toString() const + { + if (shift.index() == 1) + { + return reg.toString() + ", " + getShiftCode(sftType) + " " + std::get<1>(shift).toString(); + } + + int bits = std::get<0>(shift); + if (sftType == ShiftType::Lsl && bits == 0) + { + return reg.toString(); + } + return reg.toString() + ", " + getShiftCode(sftType) + " #" + std::to_string(bits); + } + + bool RegShift::operator == (const RegShift &rhs) const + { + return (sftType == rhs.sftType) && (shift == rhs.shift); + } + + std::string Operand2::toString() const + { + return (val.index() == 0) ? + std::get<0>(val).toString() : + std::get<1>(val).toString(); + } + + void AsmInstruction::setModifyFlags(bool modifyFlags) + { + setFlags = modifyFlags; + if (!canSetFlags() && modifyFlags) + { + Error::exit("Assembly::Instruction: instruction doesn't have 's' suffix"); + } + } + + void AsmInstruction::setSuffix(Condition condCode, bool modifyFlags) + { + setCondition(condCode); + setModifyFlags(modifyFlags); + } + + std::string AsmInstruction::getFuncSuffix() const + { + if (!setFlags) + { + return getCondCode(cond); + } + return "s" + getCondCode(cond); + } + + std::string BinOpInstr::toString() const + { + return getFuncFullCode() + "\t" + + rd.toString() + ", " + + rn.toString() + ", " + + op2.toString(); + } + + std::shared_ptr BinOpInstr::alternative() const + { + switch (type()) + { + case InstrType::Add: + case InstrType::Adc: + case InstrType::Sub: + if (rd == rn && op2 == 0) + { + return std::make_shared(); + } + break; + default: + break; + } + return nullptr; + } + + std::string MulInstr::toString() const + { + return getFuncFullCode() + "\t" + + rd.toString() + ", " + + rm.toString() + ", " + + rs.toString(); + } + + bool MulAddInstr::canSetFlags() const + { + return type() == InstrType::Mla; + } + + std::string MulAddInstr::toString() const + { + return getFuncFullCode() + "\t" + + rd.toString() + ", " + + rm.toString() + ", " + + rs.toString() + ", " + + rn.toString(); + } + + std::string Mul64Instr::toString() const + { + return getFuncFullCode() + "\t" + + rl.toString() + ", " + + rh.toString() + ", " + + rm.toString() + ", " + + rs.toString(); + } + + std::string SdivInstr::toString() const + { + return getFuncFullCode() + "\t" + + rd.toString() + ", " + + rn.toString() + ", " + + rm.toString(); + } + + std::string MovInstr::toString() const + { + return getFuncFullCode() + "\t" + + rd.toString() + ", " + + op2.toString(); + } + + std::string ShiftInstr::toString() const + { + return getFuncFullCode() + "\t" + + rd.toString() + ", " + + regShift.toString(); + } + + std::string CmpInstr::toString() const + { + return getFuncFullCode() + "\t" + + rn.toString() + ", " + + op2.toString(); + } + + std::string BrcInstr::toString() const + { + auto addrStr = (addr.index() == 0) ? + std::get<0>(addr) : + std::get<1>(addr).toString(); + + return getFuncFullCode() + "\t" + addrStr; + } + + MonoMemInstr::MonoMemInstr(Register rd, Register rn, Imm12 offset, Type type, AutoIncType inc) : + rd(rd), rn(rn), offset(offset), inc(inc), AsmInstruction(InstrType(type)) + { + if (inc == AutoIncType::Da || inc == AutoIncType::Db) + { + Error::exit("Ldr|Str is not compatible with auto decrease"); + } + } + + MonoMemInstr::MonoMemInstr(Register rd, Register rn, RegShift offset, Type type, AutoIncType inc) : + rd(rd), rn(rn), offset(offset), inc(inc), AsmInstruction(InstrType(type)) + { + if (inc == AutoIncType::Da || inc == AutoIncType::Db) + { + Error::exit("Ldr|Str is not compatible with auto decrease"); + } + } + + std::string MonoMemInstr::toString() const + { + if (offset.index() == 2) + return getFuncFullCode() + "\t" + rn.toString() + ", =" + std::get<2>(offset); + // TODO: + // 符号问题 + std::string code; + code += getFuncFullCode() + "\t" + rn.toString() + ", [" + rd.toString(); + + std::string offStr = (offset.index() == 1) ? + std::get<1>(offset).toString() : + std::get<0>(offset).toString(); + + if (inc == AutoIncType::Ia) + { + return code + "], " + offStr; + } + + code += ", " + offStr + "]"; + return (inc == AutoIncType::Ib) ? code + "!" : code; + } + + std::string MultiMemInstr::toString() const + { + std::string code = getFuncFullCode(); + + if (type() == InstrType::Ldm || type() == InstrType::Stm) + { + code += getAutoIncCode(inc) + "\t"; + code += rn.toString(); + code += updateRn ? "!, {" : ", {"; + } + else + { + code += "\t{"; + } + + for (auto it = regList.begin(); it != regList.end(); it++) + { + code += it->toString(); + if (it != regList.end() - 1) + { + code += ", "; + } + } + return code + "}"; + } +} \ No newline at end of file diff --git a/assembly/AsmInstruction.h b/assembly/AsmInstruction.h new file mode 100644 index 0000000..0352194 --- /dev/null +++ b/assembly/AsmInstruction.h @@ -0,0 +1,434 @@ +#pragma once + +#include +#include +#include +#include +#include + +#include "../utils/Error.h" + +namespace Assembly +{ + const std::string REG_NAME[] = + { + "r0", "r1", "r2", "r3", "r4", "r5", "r6", "fp", + "r8", "r9", "r10", "r11", "r12", "sp", "lr", "pc" + }; + + const std::string COND_CODE[] = + { + "", "eq", "ne", "gt", "lt", "ge", "le" + }; + + const std::string INSTR_CODE[] = + { + "nop", + "add", "adc", "sub", "sbc", "rsb", "rsc", + "and", "eor", "orr", "orn", "bic", + "mul", "mla", "mls", "smull", "smlal", "sdiv", + "mov", "mvn", + "asr", "lsr", "lsl", + "cmp", "cmn", "tst", "teq", + "b", "bl", "blx", "bx", + "ldr", "str", "ldrd", "strd", "ldm", "stm", "push", "pop", + "pld", "pli", + }; + + const std::string AUTO_INC_CODE[] = + { + "", "ia", "ib", "da", "db" + }; + + enum class Condition + { + None = 0, Eq, Ne, Gt, Lt, Ge, Le + }; + + enum class InstrType + { + Nop = 0, + Add, Adc, Sub, Sbc, Rsb, Rsc, + And, Eor, Orr, Orn, Bic, + Mul, Mla, Mls, Smull, Smlal, Sdiv, + Mov, Mvn, + Asr, Lsr, Lsl, + Cmp, Cmn, Tst, Teq, + B, Bl, Blx, Bx, + Ldr, Str, Ldrd, Strd, Ldm, Stm, Push, Pop, + Pld, Pli, + }; + + enum class ShiftType + { + Asr = int(InstrType::Asr), Lsr, Lsl + }; + + enum class ValueType + { + Reg, RegShift, Imm, Imm8m, Offset12, Op2, Mem, Addr + }; + + enum class AutoIncType + { + None = 0, Ia, Ib, Da, Db + }; + + std::string getRegName(int reg); + std::string getCondCode(Condition cond); + std::string getShiftCode(ShiftType shft); + std::string getInstrCode(InstrType instr); + std::string getAutoIncCode(AutoIncType inc); + + class Line + { + public: + enum class Type { Label, Instr, Others }; + + Line(Type type) : _type(type) {} + Type type() const { return _type; } + virtual std::string toString() const = 0; + + private: + Type _type; + }; + + typedef std::shared_ptr LinePtr; + + class Value + { + public: + virtual ValueType type() const = 0; + virtual std::string toString() const = 0; + }; + + template + class Immediate : public Value + { + public: + Immediate(int val) : val(val) + { + constexpr const int lo = Signed ? -(1 << (Bits - 1)) : 0; + constexpr const int hi = Signed ? (1 << (Bits - 1)) : (1 << Bits); + if (val < lo || val >= hi) + { + Error::exit("Assembly::Immediate<" + std::to_string(Bits) + ", " + std::to_string(Signed) + ">: value out of range"); + } + } + ValueType type() const { return ValueType::Imm; } + + std::string toString() const + { + return "#" + std::to_string(val); + } + + bool operator == (const Immediate &rhs) const { return val == rhs.val; } + + private: + int val; + }; + + typedef Immediate<12, false> Imm12u; + typedef Immediate<12, true> Imm12; + + class Imm8m : public Value + { + public: + Imm8m(uint32_t val); + Imm8m(uint8_t val, int rol); + ValueType type() const { return ValueType::Imm8m; } + std::string toString() const; + + bool operator == (const Imm8m &rhs) const { return val == rhs.val; } + + static bool isValid(uint32_t val); + static void testValid(uint32_t val); + // Split an integer into several valid Imm8ms that satisfy: + // XorSum imm8m[i] = imm32, imm8m[i] & imm8m[j] = 0 + // Can be used for Add/Sub, Or/Xor + static std::vector exclusiveSplit(uint32_t val); + // Split an integer into several valid Imm8ms that satisfy: + // AndSum imm8m[i] = imm32 + // Can be used for And + static std::vector inclusiveSplit(uint32_t val); + + private: + uint32_t val; + }; + + class Register : public Value + { + public: + enum { Fp = 7, Sp = 13, Lr = 14, Pc = 15 }; + + Register() : id(Pc) {} + Register(int id); + ValueType type() const { return ValueType::Reg; } + std::string toString() const; + + bool operator == (const Register &rhs) const { return id == rhs.id; } + bool operator < (const Register &rhs) const { return id < rhs.id; } + + private: + int id; + }; + + const Register R0(0); + const Register R1(1); + const Register R2(2); + const Register R3(3); + const Register R4(4); + const Register R5(5); + const Register R6(6); + const Register R7(7); + const Register R8(8); + const Register R9(9); + const Register R10(10); + const Register R11(11); + const Register R12(12); + const Register R13(13); + const Register R14(14); + const Register R15(15); + + class RegShift : public Value + { + public: + RegShift(Register reg) : + reg(reg), sftType(ShiftType::Lsl), shift(0) {} + RegShift(Register reg, ShiftType sftType, int bits); + RegShift(Register reg, ShiftType sftType, Register rs) : + reg(reg), sftType(sftType), shift(rs) {} + ValueType type() const { return ValueType::RegShift; } + ShiftType shiftType() const { return sftType; } + std::string toString() const; + + bool operator == (const RegShift &rhs) const; + + private: + Register reg; + ShiftType sftType; + std::variant shift; + }; + + class Operand2 : public Value + { + public: + Operand2(uint32_t imm8m) : val(imm8m) {} + Operand2(Imm8m imm) : val(imm) {}; + Operand2(Register reg) : val(RegShift(reg)) {} + Operand2(RegShift regShift) : val(regShift) {} + ValueType type() const { return ValueType::Op2; } + std::string toString() const; + + bool operator == (const Operand2 &rhs) const { return val == rhs.val; } + + private: + std::variant val; + }; + + class AsmInstruction : public Line + { + public: + AsmInstruction(InstrType type) : + func(type), Line(Type::Instr) {} + + virtual bool canSetFlags() const = 0; + + void setModifyFlags(bool modifyFlags); + void setCondition(Condition condCode) { cond = condCode; } + void setSuffix(Condition condCode, bool modifyFlags = false); + + InstrType type() const { return func; } + std::string getFuncCode() const { return getInstrCode(func); } + std::string getFuncSuffix() const ; + std::string getFuncFullCode() const { return getFuncCode() + getFuncSuffix(); } + // Returns a faster and more simplified alternative of current instruction if exists, otherwise nullptr + virtual std::shared_ptr alternative() const { return nullptr; } + + protected: + InstrType func; + Condition cond = Condition::None; + bool setFlags = false; + }; + + typedef std::shared_ptr AsmInstrPtr; + + class NopInstr : public AsmInstruction + { + public: + NopInstr() : AsmInstruction(InstrType::Nop) {} + bool canSetFlags() const override { return false; } + std::string toString() const override { return "nop"; } + }; + + class BinOpInstr : public AsmInstruction + { + public: + enum class Type { Add = int(InstrType::Add), Adc, Sub, Sbc, Rsb, Rsc, And, Eor, Orr, Orn, Bic }; + + BinOpInstr(Register rd, Register rn, Operand2 op2, Type func) : + rd(rd), rn(rn), op2(op2), AsmInstruction(InstrType(func)) {} + bool canSetFlags() const override { return true; } + std::string toString() const override; + std::shared_ptr alternative() const override; + + private: + Register rd, rn; + Operand2 op2; + }; + + class MulInstr : public AsmInstruction + { + public: + MulInstr(Register rd, Register rm, Register rs) : + rd(rd), rm(rm), rs(rs), AsmInstruction(InstrType::Mul) {} + bool canSetFlags() const override { return true; } + std::string toString() const override; + //std::shared_ptr alternative() const override; + + private: + Register rd, rm, rs; + }; + + class MulAddInstr : public AsmInstruction + { + public: + enum class Type { Mla = int(InstrType::Mla), Mls }; + + MulAddInstr(Register rd, Register rm, Register rs, Register rn) : + rd(rd), rm(rm), rs(rs), rn(rn), AsmInstruction(InstrType::Mla) {} + bool canSetFlags() const override; + std::string toString() const override; + + private: + Register rd, rm, rs, rn; + }; + + class Mul64Instr : public AsmInstruction + { + public: + enum class Type { Smull = int(InstrType::Smull), Smlal }; + + Mul64Instr(Register rl, Register rh, Register rm, Register rs, Type type) : + rl(rl), rh(rh), rm(rm), rs(rs), AsmInstruction(InstrType(type)) {} + bool canSetFlags() const override { return true; } + std::string toString() const override; + + private: + Register rl, rh, rm, rs; + }; + + class SdivInstr : public AsmInstruction + { + public: + SdivInstr(Register rd, Register rn, Register rm) : + rd(rd), rn(rn), rm(rm), AsmInstruction(InstrType::Sdiv) {} + bool canSetFlags() const override { return false; } + std::string toString() const override; + //std::shared_ptr alternative() const override; + + private: + Register rd, rn, rm; + }; + + class MovInstr : public AsmInstruction + { + public: + enum class Type { Mov = int(InstrType::Mov), Mvn }; + + MovInstr(Register rd, Operand2 op2, Type type) : + rd(rd), op2(op2), AsmInstruction(InstrType(type)) {} + bool canSetFlags() const override { return true; } + std::string toString() const override; + + private: + Register rd; + Operand2 op2; + }; + + class ShiftInstr : public AsmInstruction + { + public: + ShiftInstr(Register rd, RegShift shift) : + rd(rd), regShift(shift), AsmInstruction(InstrType(shift.shiftType())) {} + bool canSetFlags() const override { return true; } + std::string toString() const override; + + private: + Register rd; + RegShift regShift; + }; + + class CmpInstr : public AsmInstruction + { + public: + enum class Type { Cmp = int(InstrType::Cmp), Cmn, Tst, Teq }; + + CmpInstr(Register rn, Operand2 op2, Type type) : + rn(rn), op2(op2), AsmInstruction(InstrType(type)) {} + bool canSetFlags() const override { return false; } + std::string toString() const override; + + private: + Register rn; + Operand2 op2; + }; + + class BrcInstr : public AsmInstruction + { + public: + enum class LabelType { B = int(InstrType::B), Bl = int(InstrType::Bl), Blx = int(InstrType::Blx) }; + enum class RegType { Bx = int(InstrType::Bx), Blx = int(InstrType::Blx) }; + + BrcInstr(const std::string &label, LabelType type) : + addr(label), AsmInstruction(InstrType(type)) {} + BrcInstr(Register reg, RegType type) : + addr(reg), AsmInstruction(InstrType(type)) {} + bool canSetFlags() const override { return false; } + std::string toString() const override; + + private: + std::variant addr; + }; + + class MonoMemInstr : public AsmInstruction + { + public: + enum class Type { Ldr = int(InstrType::Ldr), Str }; + + MonoMemInstr(Register rn, const std::string &label, Type type) : + rd(rn), rn(rn), offset(label), AsmInstruction(InstrType(type)) {} + MonoMemInstr(Register rd, Register rn, Imm12 offset, Type type, AutoIncType inc = AutoIncType::None); + MonoMemInstr(Register rd, Register rn, RegShift offset, Type type, AutoIncType inc = AutoIncType::None); + bool canSetFlags() const override { return false; } + std::string toString() const override; + + void setOffsetDir(bool plus) { sub = !plus; } + + private: + Register rd, rn; + std::variant offset; + AutoIncType inc; + bool sub; + }; + + class MultiMemInstr : public AsmInstruction + { + public: + enum class MoveType { Ldm = int(InstrType::Ldm), Stm }; + enum class StackType { Push = int(InstrType::Push), Pop }; + + MultiMemInstr(Register rn, const std::vector ®List, MoveType type, AutoIncType inc, bool updateRn) : + rn(rn), regList(regList), AsmInstruction(InstrType(type)), inc(inc), updateRn(updateRn) {} + MultiMemInstr(const std::vector ®List, StackType type) : + rn(Register::Sp), regList(regList), AsmInstruction(InstrType(type)) {} + bool canSetFlags() const override { return false; } + std::string toString() const override; + + private: + Register rn; + bool updateRn; + AutoIncType inc; + std::vector regList; + }; +} \ No newline at end of file diff --git a/assembly/AsmTranslate.cpp b/assembly/AsmTranslate.cpp new file mode 100644 index 0000000..4195426 --- /dev/null +++ b/assembly/AsmTranslate.cpp @@ -0,0 +1,515 @@ +#include "AsmTranslate.h" + +namespace Assembly +{ + std::vector GlobalVal::toLines() + { + std::vector ret; + appendLine(ret, TabSpace + ".align" + TabSpace + std::to_string(align)); + appendLine