diff --git a/ast.cpp b/ast.cpp index 331687b..b66c579 100644 --- a/ast.cpp +++ b/ast.cpp @@ -155,7 +155,7 @@ void ast_printer_t::visit(const op::control_word_t * control_word) const { os << "(control_word "; for (const auto& op : control_word->ops) { - reinterpret_cast(op)->accept(this); + dynamic_cast(op)->accept(this); os << ' '; } os << ')'; diff --git a/dsp-notes.ods b/dsp-notes.ods index 5cbd3a9..ea8087a 100644 Binary files a/dsp-notes.ods and b/dsp-notes.ods differ diff --git a/error.hpp b/error.hpp index 3777e72..1dc436c 100644 --- a/error.hpp +++ b/error.hpp @@ -17,7 +17,7 @@ static inline void report(const int line, const int col, const std::string where had_error = true; } -static inline void error(const int line, const int col, std::string message) +static inline void error(const int line, const int col, std::string message) { report(line, col, "", message); } diff --git a/parser.cpp b/parser.cpp index f55cd17..f86157a 100644 --- a/parser.cpp +++ b/parser.cpp @@ -204,33 +204,14 @@ static op::xy_src_t xy_src(const token_t& token) using namespace dsp::op; switch (token.type) { - case _mc0: return xy_src_t::mc0; - case _mc1: return xy_src_t::mc1; - case _mc2: return xy_src_t::mc2; - case _mc3: return xy_src_t::mc3; case _m0: return xy_src_t::m0; case _m1: return xy_src_t::m1; case _m2: return xy_src_t::m2; case _m3: return xy_src_t::m3; - default: assert(false); __builtin_unreachable(); - } -} - -static op::d1_src_t d1_src(const token_t& token) -{ - using namespace dsp::op; - - switch (token.type) { - case _mc0: return d1_src_t::mc0; - case _mc1: return d1_src_t::mc1; - case _mc2: return d1_src_t::mc2; - case _mc3: return d1_src_t::mc3; - case _m0: return d1_src_t::m0; - case _m1: return d1_src_t::m1; - case _m2: return d1_src_t::m2; - case _m3: return d1_src_t::m3; - case _alh: return d1_src_t::alh; - case _all: return d1_src_t::all; + case _mc0: return xy_src_t::mc0; + case _mc1: return xy_src_t::mc1; + case _mc2: return xy_src_t::mc2; + case _mc3: return xy_src_t::mc3; default: assert(false); __builtin_unreachable(); } } @@ -239,7 +220,11 @@ std::optional parser_t::d1_dest() { using namespace dsp::op; - if (match(_rx)) return {d1_dest_t::rx}; + if (match(_mc0)) return {d1_dest_t::mc0}; + else if (match(_mc1)) return {d1_dest_t::mc1}; + else if (match(_mc2)) return {d1_dest_t::mc2}; + else if (match(_mc3)) return {d1_dest_t::mc3}; + else if (match(_rx)) return {d1_dest_t::rx}; else if (match(_pl)) return {d1_dest_t::pl}; else if (match(_ra0)) return {d1_dest_t::ra0}; else if (match(_wa0)) return {d1_dest_t::wa0}; @@ -252,6 +237,25 @@ std::optional parser_t::d1_dest() else return {}; } +static op::d1_src_t d1_src(const token_t& token) +{ + using namespace dsp::op; + + switch (token.type) { + case _m0: return d1_src_t::m0; + case _m1: return d1_src_t::m1; + case _m2: return d1_src_t::m2; + case _m3: return d1_src_t::m3; + case _mc0: return d1_src_t::mc0; + case _mc1: return d1_src_t::mc1; + case _mc2: return d1_src_t::mc2; + case _mc3: return d1_src_t::mc3; + case _all: return d1_src_t::all; + case _alh: return d1_src_t::alh; + default: assert(false); __builtin_unreachable(); + } +} + std::optional parser_t::xyd1_bus() { if (match(_mov)) { @@ -293,10 +297,25 @@ std::optional parser_t::xyd1_bus() std::optional parser_t::op() { std::vector ops; + std::vector tokens; + + auto emplace_op = [&](const token_t& token, const op::op_t * a) { + for (std::vector::size_type i = 0; i < ops.size(); i++) { + const op::op_t * b = ops[i]; + if ((a->mask() & b->mask() & ~(0b11 << 30)) != 0) { + dsp::error(*tokens[i], "conflict"); + throw error(token, "conflict"); + } + } + tokens.emplace_back(&token); + ops.emplace_back(a); + }; + while (true) { // fixme: check for emplacement here - if (auto stmt_o = alu() ) ops.emplace_back(*stmt_o); - else if (auto stmt_o = xyd1_bus()) ops.emplace_back(*stmt_o); + const token_t& token = peek(); + if (auto op_o = alu() ) emplace_op(token, *op_o); + else if (auto op_o = xyd1_bus()) emplace_op(token, *op_o); else break; } if (ops.size() != 0) diff --git a/stmt.hpp b/stmt.hpp index 5ce7c2c..bc326d7 100644 --- a/stmt.hpp +++ b/stmt.hpp @@ -2,6 +2,7 @@ #include #include +#include #include "stmt_enum.hpp" #include "expr.hpp" @@ -45,8 +46,14 @@ using uimm_t = imm_t; namespace op { +static uint32_t op_mask(uint32_t mask) { return (0b11 << 30) | mask; } +static uint32_t op_code(uint32_t code) { return (0b00 << 30) | code; } + struct op_t { + virtual uint32_t mask() const = 0; + virtual uint32_t code() const = 0; + virtual uint32_t bits() const = 0; }; struct alu_t : op_t, stmt_accept_t @@ -55,19 +62,64 @@ struct alu_t : op_t, stmt_accept_t : type(type) {} const alu_type_t type; + + uint32_t mask() const { return op_mask(0b1111 << 26); } + uint32_t code() const { return op_code(0b0000 << 26); } + uint32_t bits() const + { + switch (type) { + case alu_type_t::andl: return 0b0001 << 26; + case alu_type_t::orl: return 0b0010 << 26; + case alu_type_t::xorl: return 0b0011 << 26; + case alu_type_t::add: return 0b0100 << 26; + case alu_type_t::sub: return 0b0101 << 26; + case alu_type_t::ad2: return 0b0110 << 26; + case alu_type_t::sr: return 0b1000 << 26; + case alu_type_t::rr: return 0b1001 << 26; + case alu_type_t::sl: return 0b1010 << 26; + case alu_type_t::rl: return 0b1011 << 26; + case alu_type_t::rl8: return 0b1111 << 26; + default: __builtin_unreachable(); + } + } }; +static uint32_t xy_src_bits(xy_src_t src, int shift) +{ + using enum xy_src_t; + + switch (src) { + case m0: return 0b000 << shift; + case m1: return 0b001 << shift; + case m2: return 0b010 << shift; + case m3: return 0b011 << shift; + case mc0: return 0b100 << shift; + case mc1: return 0b101 << shift; + case mc2: return 0b110 << shift; + case mc3: return 0b111 << shift; + default: __builtin_unreachable(); + } +} + struct mov_ram_x_t : op_t, stmt_accept_t { mov_ram_x_t(xy_src_t src) : src(src) {} const xy_src_t src; + + uint32_t mask() const { return op_mask(0b100'111 << 20); } + uint32_t code() const { return op_code(0b100'000 << 20); } + uint32_t bits() const { return xy_src_bits(src, 20); } }; struct mov_mul_p_t : op_t, stmt_accept_t { mov_mul_p_t() {} + + uint32_t mask() const { return op_mask(0b011'000 << 20); } + uint32_t code() const { return op_code(0b010'000 << 20); } + uint32_t bits() const { return 0; } }; struct mov_ram_p_t : op_t, stmt_accept_t @@ -76,6 +128,10 @@ struct mov_ram_p_t : op_t, stmt_accept_t : src(src) {} const xy_src_t src; + + uint32_t mask() const { return op_mask(0b011'111 << 20); } + uint32_t code() const { return op_code(0b011'000 << 20); } + uint32_t bits() const { return xy_src_bits(src, 20); } }; struct mov_ram_y_t : op_t, stmt_accept_t @@ -84,16 +140,28 @@ struct mov_ram_y_t : op_t, stmt_accept_t : src(src) {} const xy_src_t src; + + uint32_t mask() const { return op_mask(0b100'111 << 14); } + uint32_t code() const { return op_code(0b100'000 << 14); } + uint32_t bits() const { return xy_src_bits(src, 14); } }; struct clr_a_t : op_t, stmt_accept_t { clr_a_t() {} + + uint32_t mask() const { return op_mask(0b011'000 << 14); } + uint32_t code() const { return op_code(0b001'000 << 14); } + uint32_t bits() const { return 0; } }; struct mov_alu_a_t : op_t, stmt_accept_t { mov_alu_a_t() {} + + uint32_t mask() const { return op_mask(0b011'000 << 14); } + uint32_t code() const { return op_code(0b010'000 << 14); } + uint32_t bits() const { return 0; } }; struct mov_ram_a_t : op_t, stmt_accept_t @@ -102,8 +170,54 @@ struct mov_ram_a_t : op_t, stmt_accept_t : src(src) {} const xy_src_t src; + + uint32_t mask() const { return op_mask(0b011'111 << 14); } + uint32_t code() const { return op_code(0b011'000 << 14); } + uint32_t bits() const { return xy_src_bits(src, 14); } }; +static uint32_t d1_dest_bits(d1_dest_t dest) +{ + using enum d1_dest_t; + + switch (dest) { + case mc0: return 0b0000 << 8; + case mc1: return 0b0001 << 8; + case mc2: return 0b0010 << 8; + case mc3: return 0b0011 << 8; + case rx: return 0b0100 << 8; + case pl: return 0b0101 << 8; + case ra0: return 0b0110 << 8; + case wa0: return 0b0111 << 8; + case lop: return 0b1010 << 8; + case top: return 0b1011 << 8; + case ct0: return 0b1100 << 8; + case ct1: return 0b1101 << 8; + case ct2: return 0b1110 << 8; + case ct3: return 0b1111 << 8; + default: __builtin_unreachable(); + } +} + +static uint32_t d1_src_bits(d1_src_t src) +{ + using enum d1_src_t; + + switch (src) { + case m0: return 0b0000 << 0; + case m1: return 0b0001 << 0; + case m2: return 0b0010 << 0; + case m3: return 0b0011 << 0; + case mc0: return 0b0100 << 0; + case mc1: return 0b0101 << 0; + case mc2: return 0b0110 << 0; + case mc3: return 0b0111 << 0; + case all: return 0b1001 << 0; + case alh: return 0b1010 << 0; + default: __builtin_unreachable(); + } +} + struct mov_imm_d1_t : op_t, stmt_accept_t { mov_imm_d1_t(simm_t<8> imm, d1_dest_t dest) @@ -111,6 +225,10 @@ struct mov_imm_d1_t : op_t, stmt_accept_t const simm_t<8> imm; const d1_dest_t dest; + + uint32_t mask() const { return op_mask(0b11'1111'1111'1111 << 0 ); } + uint32_t code() const { return op_code(0b01'0000'0000'0000 << 14); } + uint32_t bits() const { return d1_dest_bits(dest); } }; struct mov_ram_d1_t : op_t, stmt_accept_t @@ -120,25 +238,78 @@ struct mov_ram_d1_t : op_t, stmt_accept_t const d1_src_t src; const d1_dest_t dest; + + uint32_t mask() const { return op_mask(0b11'1111'0000'1111 << 0 ); } + uint32_t code() const { return op_code(0b11'0000'0000'0000 << 14); } + uint32_t bits() const { return d1_dest_bits(dest) | d1_src_bits(src); } }; struct control_word_t : stmt_accept_t { - control_word_t(std::vector ops) - : ops(ops) {} + control_word_t(std::vector ops) + : ops(ops) + { + if (ops.size() == 0) throw std::runtime_error("zero-length ops"); + } const std::vector ops; + + uint32_t mask() const { return 0xffff'ffff; } + uint32_t code() const { return 0; } + uint32_t bits() const { return 0; } }; } // op namespace load { +static uint32_t dest_bits(dest_t dest) +{ + using enum dest_t; + + switch (dest) { + case mc0: return 0b0000 << 26; + case mc1: return 0b0001 << 26; + case mc2: return 0b0010 << 26; + case mc3: return 0b0011 << 26; + case rx: return 0b0100 << 26; + case pl: return 0b0101 << 26; + case ra0: return 0b0110 << 26; + case wa0: return 0b0111 << 26; + case lop: return 0b1010 << 26; + case pc: return 0b1100 << 26; + default: __builtin_unreachable(); + } +} + +static uint32_t cond_bits(cond_t cond) +{ + using enum cond_t; + + switch (cond) { + case z: return 0b1'0'0001 << 19; + case nz: return 0b0'0'0001 << 19; + case s: return 0b1'0'0010 << 19; + case ns: return 0b0'0'0010 << 19; + case c: return 0b1'0'0100 << 19; + case nc: return 0b0'0'0100 << 19; + case t0: return 0b1'0'1000 << 19; + case nt0: return 0b0'0'1000 << 19; + case zs: return 0b1'0'0011 << 19; + case nzs: return 0b0'0'0011 << 19; + default: __builtin_unreachable(); + } +} + struct mvi_t : stmt_accept_t { mvi_t(uimm_t<25> imm, dest_t dest) : imm(imm), dest(dest) {} + uint32_t mask() const { return 0xffff'ffff; } + uint32_t code() const { return 0b10'0000'0 << 25; } + uint32_t bits() const { return dest_bits(dest); } + const uimm_t<25> imm; const dest_t dest; }; @@ -151,22 +322,85 @@ struct mvi_cond_t : stmt_accept_t const uimm_t<19> imm; const dest_t dest; const cond_t cond; + + uint32_t mask() const { return 0xffff'ffff; } + uint32_t code() const { return 0b10'0000'1 << 25; } + uint32_t bits() const { return dest_bits(dest) + | cond_bits(cond); + } }; } // load namespace dma { -struct src_d0_imm_t : stmt_accept_t +static uint32_t add_mode_bits(add_mode_t add) { - src_d0_imm_t(bool hold, add_mode_t add, src_t src, uimm_t<8> imm) - : hold(hold), add(add), src(src), imm(imm) {} + using enum add_mode_t; - const bool hold; - const add_mode_t add; - const src_t src; - const uimm_t<8> imm; -}; + switch (add) { + case _0 : return 0b000 << 15; + case _1 : return 0b001 << 15; + case _2 : return 0b010 << 15; + case _4 : return 0b011 << 15; + case _8 : return 0b100 << 15; + case _16: return 0b101 << 15; + case _32: return 0b110 << 15; + case _64: return 0b111 << 15; + default: __builtin_unreachable(); + } +} + +static uint32_t hold_bits(bool hold) +{ + return hold ? (1 << 14) + : (0 << 14) + ; +} + +static uint32_t src_bits(src_t src) +{ + using enum src_t; + + switch (src) { + case m0 : return 0b000 << 8; + case m1 : return 0b001 << 8; + case m2 : return 0b010 << 8; + case m3 : return 0b011 << 8; + default: __builtin_unreachable(); + } +} + +static uint32_t dst_bits(dst_t dst) +{ + using enum dst_t; + + switch (dst) { + case m0 : return 0b000 << 8; + case m1 : return 0b001 << 8; + case m2 : return 0b010 << 8; + case m3 : return 0b011 << 8; + case prg: return 0b100 << 8; + default: __builtin_unreachable(); + } +} + +static uint32_t length_ram_bits(length_ram_t ram) +{ + using enum length_ram_t; + + switch (ram) { + case m0 : return 0b000 << 0; + case m1 : return 0b001 << 0; + case m2 : return 0b010 << 0; + case m3 : return 0b011 << 0; + case mc0: return 0b100 << 0; + case mc1: return 0b101 << 0; + case mc2: return 0b110 << 0; + case mc3: return 0b111 << 0; + default: __builtin_unreachable(); + } +} struct d0_dst_imm_t : stmt_accept_t { @@ -177,6 +411,50 @@ struct d0_dst_imm_t : stmt_accept_t const add_mode_t add; const dst_t dst; const uimm_t<8> imm; + + uint32_t mask() const { return 0xffff'ffff; } + uint32_t code() const { return 0b1100 << 28 | 0b00 << 12; } + uint32_t bits() const { return add_mode_bits(add) + | hold_bits(hold) + | dst_bits(dst); + } +}; + +struct src_d0_imm_t : stmt_accept_t +{ + src_d0_imm_t(bool hold, add_mode_t add, src_t src, uimm_t<8> imm) + : hold(hold), add(add), src(src), imm(imm) {} + + const bool hold; + const add_mode_t add; + const src_t src; + const uimm_t<8> imm; + + uint32_t mask() const { return 0xffff'ffff; } + uint32_t code() const { return 0b1100 << 28 | 0b01 << 12; } + uint32_t bits() const { return add_mode_bits(add) + | hold_bits(hold) + | src_bits(src); + } +}; + +struct d0_dst_ram_t : stmt_accept_t +{ + d0_dst_ram_t(bool hold, add_mode_t add, dst_t dst, length_ram_t ram) + : hold(hold), add(add), dst(dst), ram(ram) {} + + const bool hold; + const add_mode_t add; + const dst_t dst; + const length_ram_t ram; + + uint32_t mask() const { return 0xffff'ffff; } + uint32_t code() const { return 0b1100 << 28 | 0b10 << 12; } + uint32_t bits() const { return add_mode_bits(add) + | hold_bits(hold) + | dst_bits(dst) + | length_ram_bits(ram); + } }; struct src_d0_ram_t : stmt_accept_t @@ -189,17 +467,14 @@ struct src_d0_ram_t : stmt_accept_t const add_mode_t add; const src_t src; const length_ram_t ram; -}; -struct d0_dst_ram_t : stmt_accept_t -{ - d0_dst_ram_t(bool hold, add_mode_t add, dst_t dst, length_ram_t ram) - : hold(hold), add(add), dst(dst), ram(ram) {} - - const bool hold; - const add_mode_t add; - const dst_t dst; - const length_ram_t ram; + uint32_t mask() const { return 0xffff'ffff; } + uint32_t code() const { return 0b1100 << 28 | 0b11 << 12; } + uint32_t bits() const { return add_mode_bits(add) + | hold_bits(hold) + | src_bits(src) + | length_ram_bits(ram); + } }; } // dma @@ -207,12 +482,35 @@ struct d0_dst_ram_t : stmt_accept_t namespace jump { +static uint32_t cond_bits(cond_t cond) +{ + using enum cond_t; + + switch (cond) { + case z : return 0b100'001 << 19; + case nz : return 0b000'001 << 19; + case s : return 0b100'010 << 19; + case ns : return 0b000'010 << 19; + case c : return 0b100'100 << 19; + case nc : return 0b000'100 << 19; + case t0 : return 0b101'000 << 19; + case nt0: return 0b001'000 << 19; + case zs : return 0b100'011 << 19; + case nzs: return 0b000'011 << 19; + default: __builtin_unreachable(); + } +} + struct jmp_t : stmt_accept_t { jmp_t(uimm_t<8> imm) : imm(imm) {} const uimm_t<8> imm; + + uint32_t mask() const { return 0xffff'ffff; } + uint32_t code() const { return 0b1101'00'0 << 25; } + uint32_t bits() const { return 0; } }; struct jmp_cond_t : stmt_accept_t @@ -222,6 +520,10 @@ struct jmp_cond_t : stmt_accept_t const cond_t cond; const uimm_t<8> imm; + + uint32_t mask() const { return 0xffff'ffff; } + uint32_t code() const { return 0b1101'00'1 << 25; } + uint32_t bits() const { return cond_bits(cond); } }; } // jump @@ -230,10 +532,16 @@ namespace loop { struct btm_t : stmt_accept_t { + uint32_t mask() const { return 0xffff'ffff; } + uint32_t code() const { return 0b1110'0 << 27; } + uint32_t bits() const { return 0; } }; struct lps_t : stmt_accept_t { + uint32_t mask() const { return 0xffff'ffff; } + uint32_t code() const { return 0b1110'1 << 27; } + uint32_t bits() const { return 0; } }; } // loop @@ -242,10 +550,16 @@ namespace end { struct end_t : stmt_accept_t { + uint32_t mask() const { return 0xffff'ffff; } + uint32_t code() const { return 0b1111'0 << 27; } + uint32_t bits() const { return 0; } }; struct endi_t : stmt_accept_t { + uint32_t mask() const { return 0xffff'ffff; } + uint32_t code() const { return 0b1111'1 << 27; } + uint32_t bits() const { return 0; } }; } // end @@ -254,6 +568,9 @@ namespace nop { struct nop_t : stmt_accept_t { + uint32_t mask() const { return 0xffff'ffff; } + uint32_t code() const { return 0x0000'0000; } + uint32_t bits() const { return 0; } }; } diff --git a/stmt_enum.hpp b/stmt_enum.hpp index 6a00b9f..a7ff3e8 100644 --- a/stmt_enum.hpp +++ b/stmt_enum.hpp @@ -19,11 +19,12 @@ enum struct alu_type_t : int { }; enum struct xy_src_t { + m0 , m1 , m2 , m3 , mc0, mc1, mc2, mc3, - m0 , m1 , m2 , m3, }; enum struct d1_dest_t { + mc0, mc1, mc2, mc3, rx , pl , ra0, wa0, lop, top, @@ -31,9 +32,9 @@ enum struct d1_dest_t { }; enum struct d1_src_t { - mc0, mc1, mc2, mc3, m0 , m1 , m2 , m3 , - alh, all, + mc0, mc1, mc2, mc3, + all, alh, }; } @@ -89,9 +90,9 @@ enum struct length_ram_t { namespace jump { enum struct cond_t { - z , nz, - s , ns, - c , nc, + z , nz , + s , ns , + c , nc , t0, nt0, zs, nzs, }; diff --git a/visitable.hpp b/visitable.hpp index 95aac25..d1001ae 100644 --- a/visitable.hpp +++ b/visitable.hpp @@ -31,10 +31,10 @@ struct mvi_cond_t; } namespace dma { -struct src_d0_imm_t; struct d0_dst_imm_t; -struct src_d0_ram_t; +struct src_d0_imm_t; struct d0_dst_ram_t; +struct src_d0_ram_t; } namespace jump { diff --git a/visitor.hpp b/visitor.hpp index 199a3ee..ddc8a7b 100644 --- a/visitor.hpp +++ b/visitor.hpp @@ -14,7 +14,7 @@ struct visitor_t virtual T visit(const literal_t * expr) const = 0; virtual T visit(const unary_t * expr) const = 0; - virtual T visit(const op::alu_t * stmt) const = 0; + virtual T visit(const op::alu_t * alu) const = 0; virtual T visit(const op::mov_ram_x_t * mov_ram_x) const = 0; virtual T visit(const op::mov_mul_p_t * mov_mul_p) const = 0; virtual T visit(const op::mov_ram_p_t * mov_ram_p) const = 0; @@ -22,8 +22,8 @@ struct visitor_t virtual T visit(const op::clr_a_t * clr_a) const = 0; virtual T visit(const op::mov_alu_a_t * mov_alu_a) const = 0; virtual T visit(const op::mov_ram_a_t * mov_ram_a) const = 0; - virtual T visit(const op::mov_imm_d1_t * mov_imm_) const = 0; - virtual T visit(const op::mov_ram_d1_t * mov_ram_) const = 0; + virtual T visit(const op::mov_imm_d1_t * mov_imm_d1) const = 0; + virtual T visit(const op::mov_ram_d1_t * mov_ram_d1) const = 0; virtual T visit(const op::control_word_t * control_word) const = 0; virtual T visit(const load::mvi_t * mvi) const = 0;