#pragma once #include "vm.hpp" #include #include #define BINARY_INSTRUCTIONS \ X(or, Or) \ X(and, And) \ X(xor, Xor) \ X(shl, Shl) \ X(rshl, RShl) \ X(shr, Shr) \ X(rshr, RShr) \ X(add, Add) \ X(sub, Sub) \ X(rsub, RSub) \ X(mul, Mul) \ X(imul, IMul) namespace vc5::tools { using namespace vc5; class Builder { public: Builder(uint8_t* data) : m_data(data) { } void nop(); void hlt(); void jmp_reg(Reg op1); void jmp_imm(uint16_t op1); void jnz_reg(Reg op1, Reg op2); void jnz_imm(Reg op1, uint16_t op2); void mov_reg(Reg dst, Reg src); void mov_imm(Reg dst, uint16_t imm); void ldw_reg(Reg dst, Reg addr, uint16_t offset); void ldw_imm(Reg dst, uint16_t addr); void stw_reg(Reg dst, uint16_t offset, Reg op2); void stw_imm(uint16_t dst, Reg op2); void ldb_reg(Reg dst, Reg addr, uint16_t offset); void ldb_imm(Reg dst, uint16_t addr); void stb_reg(Reg dst, uint16_t offset, Reg op2); void stb_imm(uint16_t dst, Reg op2); void cmp_reg(Reg op1, Reg op2); void cmp_imm(Reg op1, uint16_t op2); #define X(NAME, OP) \ void NAME##_reg(Reg dst, Reg op1, Reg op2); \ void NAME##_imm(Reg dst, Reg op1, uint16_t op2); BINARY_INSTRUCTIONS #undef X void call_reg(Reg op1); void call_imm(uint16_t op1); void ret(); void reti(); void lvcd_reg(Reg op1); void lvcd_imm(uint16_t op1); void lkbd_reg(Reg op1); void lkbd_imm(uint16_t op1); void dskr(Reg dst, Reg op1); void dskw(Reg dst, Reg op1); uint16_t ip() const { return m_ip & 0xffff; } void set_ip(uint16_t ip) { m_ip = ip; } void push(uint16_t v) { m_data[m_ip] = v >> 8; m_data[m_ip + 1] = v & 0xff; m_ip += 2; } void push_byte(uint8_t v) { m_data[m_ip] = v; m_ip += 1; } void align_word() { if (m_ip & 1) { m_ip += 1; } } private: void binary_reg(Reg dst, Reg op1, Reg op2, Op op); void binary_imm(Reg dst, Reg op1, uint16_t op2, Op op); uint8_t* m_data; size_t m_ip = 0; }; } #ifndef DEFINE_BINARY_INSTRUCTIONS #undef BINARY_INSTRUCTIONS #endif