fxos/include/fxos/lang.h

137 lines
3.3 KiB
C++

//---
// fxos.lang: Assembler language specification
//---
#ifndef LIBFXOS_LANG_H
#define LIBFXOS_LANG_H
#include <string>
#include <vector>
#include <cstdint>
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<Argument> args;
};
} /* namespace FxOS */
#endif /* LIBFXOS_LANG_H */