//--- // fxos.lang: Assembler language specification //--- #ifndef LIBFXOS_LANG_H #define LIBFXOS_LANG_H #include #include #include namespace FxOS { /* CPU register names, with a little meat for conversion to and from string */ class CpuRegister { public: enum CpuRegisterName { /* Caller-saved general-purpose registers */ R0, R1, R2, R3, R4, R5, R6, R7, /* Banked general-purpose registers. fxos does not account for banking identities, these are just for naming and output. */ R0B, R1B, R2B, R3B, R4B, R5B, R6B, R7B, /* Callee-saved general-purpose registers */ R8, R9, R10, R11, R12, R13, R14, R15, /* System registers */ MACH, MACL, PR, PC, /* Control registers */ SR, SSR, SPC, GBR, VBR, DBR, SGR, }; CpuRegister() = default; /* Construction from CpuRegisterName */ constexpr CpuRegister(CpuRegisterName name): m_name(name) {} /* Construction from string */ CpuRegister(std::string register_name); /* Conversion to string */ std::string str() const noexcept; /* Conversion to CpuRegisterName for switch statements */ constexpr operator CpuRegisterName() noexcept { return m_name; } /* Comparison operators */ constexpr bool operator==(CpuRegister r) const { return m_name == r.m_name; } constexpr bool operator!=(CpuRegister r) const { return m_name != r.m_name; } private: CpuRegisterName m_name; }; /* Addressing modes for arguments */ struct Argument { /* Various addressing modes in the language */ enum Kind { Reg, /* rn */ Deref, /* @rn */ PostInc, /* @rn+ */ PreDec, /* @-rn */ StructDeref, /* @(disp,rn) or @(disp,gbr) */ ArrayDeref, /* @(r0,rn) or @(r0,gbr) */ PcRel, /* @(disp,pc) with 4-alignment correction */ PcJump, /* disp */ Imm, /* #imm */ }; Argument() = default; /* String representation */ std::string str() const; /* Addressing mode */ Kind kind; /* Base register. Valid for all modes except Imm */ CpuRegister base; /* Index register. Valid for ArrayDeref */ CpuRegister index; /* Displacement in bytes. Valid for StructDeref, PcRel and PcJump */ int disp; /* Operation size. Generally a multiplier for disp */ int opsize; /* Immediate value. Valid for Imm */ int imm; }; /* Argument constructors */ Argument Argument_Reg(CpuRegister base); Argument Argument_Deref(CpuRegister base); Argument Argument_PostInc(CpuRegister base); Argument Argument_PreDec(CpuRegister base); Argument Argument_StructDeref(int disp, int opsize, CpuRegister base); Argument Argument_ArrayDeref(CpuRegister index, CpuRegister base); Argument Argument_PcRel(int disp, int opsize); Argument Argument_PcJump(int disp); Argument Argument_Imm(int imm); /* Assembler instruction */ struct Instruction { Instruction() = default; /* Construct with one or several arguments */ Instruction(std::string mnemonic); Instruction(std::string mnemonic, Argument arg); Instruction(std::string mnemonic, Argument arg1, Argument arg2); /* Original opcode. Initialized to 0 when unset, which is an invalid instruction by design. */ uint16_t opcode; /* Mnemonic **without the size indicator** */ std::string mnemonic; /* Operation size (0, 1, 2 or 4) */ int opsize; /* Arguments */ std::vector args; }; } /* namespace FxOS */ #endif /* LIBFXOS_LANG_H */