#include #include #include #include #include namespace FxOS { //--- // CPU registers //--- using Reg = CpuRegister::CpuRegisterName; static std::map regnames = { { Reg::R0, "r0" }, { Reg::R1, "r1" }, { Reg::R2, "r2" }, { Reg::R3, "r3" }, { Reg::R4, "r4" }, { Reg::R5, "r5" }, { Reg::R6, "r6" }, { Reg::R7, "r7" }, { Reg::R0B, "r0_bank" }, { Reg::R1B, "r1_bank" }, { Reg::R2B, "r2_bank" }, { Reg::R3B, "r3_bank" }, { Reg::R4B, "r4_bank" }, { Reg::R5B, "r5_bank" }, { Reg::R6B, "r6_bank" }, { Reg::R7B, "r7_bank" }, { Reg::R8, "r8" }, { Reg::R9, "r9" }, { Reg::R10, "r10" }, { Reg::R11, "r11" }, { Reg::R12, "r12" }, { Reg::R13, "r13" }, { Reg::R14, "r14" }, { Reg::R15, "r15" }, { Reg::MACH, "mach" }, { Reg::MACL, "macl" }, { Reg::PR, "pr" }, { Reg::PC, "pc" }, { Reg::SR, "sr" }, { Reg::SSR, "ssr" }, { Reg::SPC, "spc" }, { Reg::GBR, "gbr" }, { Reg::VBR, "vbr" }, { Reg::DBR, "dbr" }, { Reg::SGR, "sgr" }, }; /* Construction from string - pretty slow */ CpuRegister::CpuRegister(std::string name) { for(auto it = regnames.begin(); it != regnames.end(); it++) { if(it->second == name) { m_name = it->first; return; } } throw std::invalid_argument("invalid CpuRegister name"); } /* Conversion to string */ std::string CpuRegister::str() const noexcept { return regnames.at(m_name); } //--- // Instruction arguments //--- /* External constructors */ Argument Argument_Reg(CpuRegister base) { Argument arg; arg.kind = Argument::Reg; arg.base = base; return arg; } Argument Argument_Deref(CpuRegister base) { Argument arg; arg.kind = Argument::Deref; arg.base = base; return arg; } Argument Argument_PostInc(CpuRegister base) { Argument arg; arg.kind = Argument::PostInc; arg.base = base; return arg; } Argument Argument_PreDec(CpuRegister base) { Argument arg; arg.kind = Argument::PreDec; arg.base = base; return arg; } Argument Argument_StructDeref(int disp, int opsize, CpuRegister base) { Argument arg; arg.kind = Argument::StructDeref; arg.base = base; arg.disp = disp; arg.opsize = opsize; return arg; } Argument Argument_ArrayDeref(CpuRegister index, CpuRegister base) { Argument arg; arg.kind = Argument::ArrayDeref; arg.base = base; arg.index = index; return arg; } Argument Argument_PcRel(int disp, int opsize) { Argument arg; arg.kind = Argument::PcRel; arg.disp = disp; arg.opsize = opsize; return arg; } Argument Argument_PcJump(int disp) { Argument arg; arg.kind = Argument::PcJump; arg.disp = disp; return arg; } Argument Argument_Imm(int imm) { Argument arg; arg.kind = Argument::Imm; arg.imm = imm; return arg; } /* String representation */ std::string Argument::str() const { switch(kind) { case Argument::Reg: return format("r%d", base); case Argument::Deref: return format("@r%d", base); case Argument::PostInc: return format("@r%d+", base); case Argument::PreDec: return format("@-%dr", base); case Argument::StructDeref: return format("@(%d,%s)", disp, base.str().c_str()); case Argument::ArrayDeref: return format("@(%s,%s)", index.str().c_str(), base.str().c_str()); case Argument::PcRel: return format("@(%d,pc)", disp); case Argument::PcJump: return format("pc+%d", disp); default: return "(invalid)"; } } //--- // Instruction creation //--- Instruction::Instruction(std::string mn): opcode(0), opsize(0) { int pos = std::max(0, (int)mn.size() - 2); if(mn.substr(pos, 2) == ".b") { opsize = 1; mn.erase(pos, 2); } else if(mn.substr(pos, 2) == ".w") { opsize = 2; mn.erase(pos, 2); } else if(mn.substr(pos, 2) == ".l") { opsize = 4; mn.erase(pos, 2); } mnemonic = mn; } Instruction::Instruction(std::string mn, Argument arg): Instruction(mn) { args.push_back(arg); } Instruction::Instruction(std::string mn, Argument arg1, Argument arg2): Instruction(mn) { args.push_back(arg1); args.push_back(arg2); } } /* namespace FxOS */