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