stmt_ins: refactor
The overall intent is to make writing a decompiler require less code duplication. "bits.hpp" and "stmt_enum.hpp" are replaced with "stmt_ins.hpp" which is generated directly from dsp-notes.csv.
This commit is contained in:
parent
2d047c6c54
commit
ddf46ce8fd
3
.gitignore
vendored
3
.gitignore
vendored
@ -7,4 +7,5 @@ scu-dsp-asm.*
|
||||
*.d
|
||||
test/*.s
|
||||
test/*.txt
|
||||
*.bin
|
||||
*.bin
|
||||
__pycache__
|
2
Makefile
2
Makefile
@ -3,7 +3,7 @@ CXXFLAGS = -Og -g -Wall -Wextra -Werror -Wfatal-errors -Wno-c99-designator -std=
|
||||
LDFLAGS =
|
||||
|
||||
TARGET ?=
|
||||
CXX = $(TARGET)g++
|
||||
CXX = $(TARGET)clang++
|
||||
|
||||
SRC = main.cpp
|
||||
SRC += lexer.cpp
|
||||
|
@ -89,9 +89,59 @@ uint32_t emitter_t::visit(const unary_t * unary) const
|
||||
|
||||
// instructions
|
||||
|
||||
uint32_t emitter_t::visit(const op::alu_t * alu) const
|
||||
uint32_t emitter_t::visit(const op::andl_t * andl) const
|
||||
{
|
||||
return alu->code() | alu->bits();
|
||||
return andl->code() | andl->bits();
|
||||
}
|
||||
|
||||
uint32_t emitter_t::visit(const op::orl_t * orl) const
|
||||
{
|
||||
return orl->code() | orl->bits();
|
||||
}
|
||||
|
||||
uint32_t emitter_t::visit(const op::xorl_t * xorl) const
|
||||
{
|
||||
return xorl->code() | xorl->bits();
|
||||
}
|
||||
|
||||
uint32_t emitter_t::visit(const op::add_t * add) const
|
||||
{
|
||||
return add->code() | add->bits();
|
||||
}
|
||||
|
||||
uint32_t emitter_t::visit(const op::sub_t * sub) const
|
||||
{
|
||||
return sub->code() | sub->bits();
|
||||
}
|
||||
|
||||
uint32_t emitter_t::visit(const op::ad2_t * ad2) const
|
||||
{
|
||||
return ad2->code() | ad2->bits();
|
||||
}
|
||||
|
||||
uint32_t emitter_t::visit(const op::sr_t * sr) const
|
||||
{
|
||||
return sr->code() | sr->bits();
|
||||
}
|
||||
|
||||
uint32_t emitter_t::visit(const op::rr_t * rr) const
|
||||
{
|
||||
return rr->code() | rr->bits();
|
||||
}
|
||||
|
||||
uint32_t emitter_t::visit(const op::sl_t * sl) const
|
||||
{
|
||||
return sl->code() | sl->bits();
|
||||
}
|
||||
|
||||
uint32_t emitter_t::visit(const op::rl_t * rl) const
|
||||
{
|
||||
return rl->code() | rl->bits();
|
||||
}
|
||||
|
||||
uint32_t emitter_t::visit(const op::rl8_t * rl8) const
|
||||
{
|
||||
return rl8->code() | rl8->bits();
|
||||
}
|
||||
|
||||
uint32_t emitter_t::visit(const op::mov_ram_x_t * mov_ram_x) const
|
||||
@ -146,7 +196,9 @@ uint32_t emitter_t::visit(const op::mov_ram_d1_t * mov_ram_d1) const
|
||||
uint32_t emitter_t::visit(const op::control_word_t * control_word) const
|
||||
{
|
||||
uint32_t word = control_word->code() | control_word->bits();
|
||||
for (auto& op : control_word->ops) { word |= dynamic_cast<const stmt_t *>(op)->accept(this); }
|
||||
for (const auto& op : control_word->ops) {
|
||||
word |= std::visit([*this](auto&& arg) -> uint32_t { return (arg).accept(this); }, op);
|
||||
}
|
||||
return word;
|
||||
}
|
||||
|
||||
|
@ -7,6 +7,8 @@
|
||||
#include "visitor.hpp"
|
||||
#include "expr.hpp"
|
||||
#include "stmt.hpp"
|
||||
#include "stmt_ins.hpp"
|
||||
#include "control_word.hpp"
|
||||
#include "ast.hpp"
|
||||
|
||||
namespace dsp {
|
||||
@ -33,7 +35,18 @@ struct emitter_t : visitor_t<uint32_t>
|
||||
uint32_t visit(const literal_t * literal) const;
|
||||
uint32_t visit(const unary_t * unary) const;
|
||||
|
||||
uint32_t visit(const op::alu_t * alu) const;
|
||||
uint32_t visit(const op::andl_t * andl) const;
|
||||
uint32_t visit(const op::orl_t * orl) const;
|
||||
uint32_t visit(const op::xorl_t * xorl) const;
|
||||
uint32_t visit(const op::add_t * add) const;
|
||||
uint32_t visit(const op::sub_t * sub) const;
|
||||
uint32_t visit(const op::ad2_t * ad2) const;
|
||||
uint32_t visit(const op::sr_t * sr) const;
|
||||
uint32_t visit(const op::rr_t * rr) const;
|
||||
uint32_t visit(const op::sl_t * sl) const;
|
||||
uint32_t visit(const op::rl_t * rl) const;
|
||||
uint32_t visit(const op::rl8_t * rl8) const;
|
||||
|
||||
uint32_t visit(const op::mov_ram_x_t * mov_ram_x) const;
|
||||
uint32_t visit(const op::mov_mul_p_t * mov_mul_p) const;
|
||||
uint32_t visit(const op::mov_ram_p_t * mov_ram_p) const;
|
||||
|
108
ast_printer.cpp
108
ast_printer.cpp
@ -1,5 +1,6 @@
|
||||
#include "ast_printer.hpp"
|
||||
#include "stmt_string.hpp"
|
||||
#include "control_word.hpp"
|
||||
|
||||
namespace dsp {
|
||||
|
||||
@ -96,14 +97,75 @@ void printer_t::parenthesize(const std::string_view s, const expr_t * a, const e
|
||||
|
||||
// instructions
|
||||
|
||||
void printer_t::visit(const op::alu_t * alu) const
|
||||
void printer_t::visit(const op::andl_t * andl) const
|
||||
{
|
||||
parenthesize(op::alu_type_string[static_cast<int>(alu->type)]);
|
||||
(void)andl;
|
||||
parenthesize("andl");
|
||||
}
|
||||
|
||||
void printer_t::visit(const op::orl_t * orl) const
|
||||
{
|
||||
(void)orl;
|
||||
parenthesize("orl");
|
||||
}
|
||||
|
||||
void printer_t::visit(const op::xorl_t * xorl) const
|
||||
{
|
||||
(void)xorl;
|
||||
parenthesize("xorl");
|
||||
}
|
||||
|
||||
void printer_t::visit(const op::add_t * add) const
|
||||
{
|
||||
(void)add;
|
||||
parenthesize("add");
|
||||
}
|
||||
|
||||
void printer_t::visit(const op::sub_t * sub) const
|
||||
{
|
||||
(void)sub;
|
||||
parenthesize("sub");
|
||||
}
|
||||
|
||||
void printer_t::visit(const op::ad2_t * ad2) const
|
||||
{
|
||||
(void)ad2;
|
||||
parenthesize("ad2");
|
||||
}
|
||||
|
||||
void printer_t::visit(const op::sr_t * sr) const
|
||||
{
|
||||
(void)sr;
|
||||
parenthesize("sr");
|
||||
}
|
||||
|
||||
void printer_t::visit(const op::rr_t * rr) const
|
||||
{
|
||||
(void)rr;
|
||||
parenthesize("rr");
|
||||
}
|
||||
|
||||
void printer_t::visit(const op::sl_t * sl) const
|
||||
{
|
||||
(void)sl;
|
||||
parenthesize("sl");
|
||||
}
|
||||
|
||||
void printer_t::visit(const op::rl_t * rl) const
|
||||
{
|
||||
(void)rl;
|
||||
parenthesize("rl");
|
||||
}
|
||||
|
||||
void printer_t::visit(const op::rl8_t * rl8) const
|
||||
{
|
||||
(void)rl8;
|
||||
parenthesize("rl8");
|
||||
}
|
||||
|
||||
void printer_t::visit(const op::mov_ram_x_t * mov_ram_x) const
|
||||
{
|
||||
parenthesize("mov", op::xy_src_string[static_cast<int>(mov_ram_x->src)], "x");
|
||||
parenthesize("mov", op::x_src_string[static_cast<int>(mov_ram_x->src.value)], "x");
|
||||
}
|
||||
|
||||
void printer_t::visit(const op::mov_mul_p_t * mov_mul_p) const
|
||||
@ -114,12 +176,12 @@ void printer_t::visit(const op::mov_mul_p_t * mov_mul_p) const
|
||||
|
||||
void printer_t::visit(const op::mov_ram_p_t * mov_ram_p) const
|
||||
{
|
||||
parenthesize("mov", op::xy_src_string[static_cast<int>(mov_ram_p->src)], "p");
|
||||
parenthesize("mov", op::x_src_string[static_cast<int>(mov_ram_p->src.value)], "p");
|
||||
}
|
||||
|
||||
void printer_t::visit(const op::mov_ram_y_t * mov_ram_y) const
|
||||
{
|
||||
parenthesize("mov", op::xy_src_string[static_cast<int>(mov_ram_y->src)], "y");
|
||||
parenthesize("mov", op::y_src_string[static_cast<int>(mov_ram_y->src.value)], "y");
|
||||
}
|
||||
|
||||
void printer_t::visit(const op::clr_a_t * clr_a) const
|
||||
@ -136,28 +198,28 @@ void printer_t::visit(const op::mov_alu_a_t * mov_alu_a) const
|
||||
|
||||
void printer_t::visit(const op::mov_ram_a_t * mov_ram_a) const
|
||||
{
|
||||
parenthesize("mov", op::xy_src_string[static_cast<int>(mov_ram_a->src)], "a");
|
||||
parenthesize("mov", op::y_src_string[static_cast<int>(mov_ram_a->src.value)], "a");
|
||||
}
|
||||
|
||||
void printer_t::visit(const op::mov_imm_d1_t * mov_imm_d1) const
|
||||
{
|
||||
parenthesize("mov",
|
||||
mov_imm_d1->imm.expr,
|
||||
op::d1_dest_string[static_cast<int>(mov_imm_d1->dest)]);
|
||||
op::d1_dst_string[static_cast<int>(mov_imm_d1->dst.value)]);
|
||||
}
|
||||
|
||||
void printer_t::visit(const op::mov_ram_d1_t * mov_ram_d1) const
|
||||
{
|
||||
parenthesize("mov",
|
||||
op::d1_src_string[static_cast<int>(mov_ram_d1->src)],
|
||||
op::d1_dest_string[static_cast<int>(mov_ram_d1->dest)]);
|
||||
op::d1_src_string[static_cast<int>(mov_ram_d1->src.value)],
|
||||
op::d1_dst_string[static_cast<int>(mov_ram_d1->dst.value)]);
|
||||
}
|
||||
|
||||
void printer_t::visit(const op::control_word_t * control_word) const
|
||||
{
|
||||
os << "(control_word ";
|
||||
for (const auto& op : control_word->ops) {
|
||||
dynamic_cast<const stmt_t *>(op)->accept(this);
|
||||
std::visit([*this](auto&& arg){ (arg).accept(this); }, op);
|
||||
os << ' ';
|
||||
}
|
||||
os << ')';
|
||||
@ -165,27 +227,27 @@ void printer_t::visit(const op::control_word_t * control_word) const
|
||||
|
||||
void printer_t::visit(const load::mvi_t * mvi) const
|
||||
{
|
||||
parenthesize("mvi", mvi->imm.expr, load::dest_string[static_cast<int>(mvi->dest)]);
|
||||
parenthesize("mvi", mvi->imm.expr, load::dst_string[static_cast<int>(mvi->dst.value)]);
|
||||
}
|
||||
|
||||
void printer_t::visit(const load::mvi_cond_t * mvi_cond) const
|
||||
{
|
||||
parenthesize("mvi",
|
||||
mvi_cond->imm.expr,
|
||||
load::dest_string[static_cast<int>(mvi_cond->dest)],
|
||||
load::cond_string[static_cast<int>(mvi_cond->cond)]);
|
||||
load::dst_string[static_cast<int>(mvi_cond->dst.value)],
|
||||
load::cond_string[static_cast<int>(mvi_cond->cond.value)]);
|
||||
}
|
||||
|
||||
static std::string dma_hold_add(bool hold, dma::add_mode_t add)
|
||||
static std::string dma_hold_add(dma::hold_t hold, dma::add_t add)
|
||||
{
|
||||
return dma::hold_mode_string[static_cast<int>(hold)]
|
||||
+ dma::add_mode_string[static_cast<int>(add)];
|
||||
return dma::hold_mode_string[static_cast<int>(hold.value)]
|
||||
+ dma::add_mode_string[static_cast<int>(add.value)];
|
||||
}
|
||||
|
||||
void printer_t::visit(const dma::src_d0_imm_t * src_d0_imm) const
|
||||
{
|
||||
parenthesize(dma_hold_add(src_d0_imm->hold, src_d0_imm->add),
|
||||
dma::src_string[static_cast<int>(src_d0_imm->src)],
|
||||
dma::src_string[static_cast<int>(src_d0_imm->src.value)],
|
||||
"d0",
|
||||
src_d0_imm->imm.expr);
|
||||
}
|
||||
@ -194,24 +256,24 @@ void printer_t::visit(const dma::d0_dst_imm_t * d0_dst_imm) const
|
||||
{
|
||||
parenthesize(dma_hold_add(d0_dst_imm->hold, d0_dst_imm->add),
|
||||
"d0",
|
||||
dma::dst_string[static_cast<int>(d0_dst_imm->dst)],
|
||||
dma::dst_string[static_cast<int>(d0_dst_imm->dst.value)],
|
||||
d0_dst_imm->imm.expr);
|
||||
}
|
||||
|
||||
void printer_t::visit(const dma::src_d0_ram_t * src_d0_ram) const
|
||||
{
|
||||
parenthesize(dma_hold_add(src_d0_ram->hold, src_d0_ram->add),
|
||||
dma::src_string[static_cast<int>(src_d0_ram->src)],
|
||||
dma::src_string[static_cast<int>(src_d0_ram->src.value)],
|
||||
"d0",
|
||||
dma::length_ram_string[static_cast<int>(src_d0_ram->ram)]);
|
||||
dma::length_ram_string[static_cast<int>(src_d0_ram->ram.value)]);
|
||||
}
|
||||
|
||||
void printer_t::visit(const dma::d0_dst_ram_t * d0_dst_ram) const
|
||||
{
|
||||
parenthesize(dma_hold_add(d0_dst_ram->hold, d0_dst_ram->add),
|
||||
"d0",
|
||||
dma::dst_string[static_cast<int>(d0_dst_ram->dst)],
|
||||
dma::length_ram_string[static_cast<int>(d0_dst_ram->ram)]);
|
||||
dma::dst_string[static_cast<int>(d0_dst_ram->dst.value)],
|
||||
dma::length_ram_string[static_cast<int>(d0_dst_ram->ram.value)]);
|
||||
}
|
||||
|
||||
void printer_t::visit(const jump::jmp_t * jmp) const
|
||||
@ -222,7 +284,7 @@ void printer_t::visit(const jump::jmp_t * jmp) const
|
||||
void printer_t::visit(const jump::jmp_cond_t * jmp_cond) const
|
||||
{
|
||||
parenthesize("jmp",
|
||||
jump::cond_string[static_cast<int>(jmp_cond->cond)],
|
||||
jump::cond_string[static_cast<int>(jmp_cond->cond.value)],
|
||||
jmp_cond->imm.expr);
|
||||
}
|
||||
|
||||
|
@ -7,6 +7,7 @@
|
||||
#include "expr.hpp"
|
||||
#include "num.hpp"
|
||||
#include "stmt.hpp"
|
||||
#include "stmt_ins.hpp"
|
||||
|
||||
namespace dsp {
|
||||
|
||||
@ -25,7 +26,18 @@ struct printer_t : visitor_t<void>
|
||||
void visit(const literal_t * literal) const;
|
||||
void visit(const unary_t * unary) const;
|
||||
|
||||
void visit(const op::alu_t * alu) const;
|
||||
void visit(const op::andl_t * andl) const;
|
||||
void visit(const op::orl_t * orl) const;
|
||||
void visit(const op::xorl_t * xorl) const;
|
||||
void visit(const op::add_t * add) const;
|
||||
void visit(const op::sub_t * sub) const;
|
||||
void visit(const op::ad2_t * ad2) const;
|
||||
void visit(const op::sr_t * sr) const;
|
||||
void visit(const op::rr_t * rr) const;
|
||||
void visit(const op::sl_t * sl) const;
|
||||
void visit(const op::rl_t * rl) const;
|
||||
void visit(const op::rl8_t * rl8) const;
|
||||
|
||||
void visit(const op::mov_ram_x_t * mov_ram_x) const;
|
||||
void visit(const op::mov_mul_p_t * mov_mul_p) const;
|
||||
void visit(const op::mov_ram_p_t * mov_ram_p) const;
|
||||
|
@ -33,9 +33,59 @@ void resolver_t::visit(const unary_t * unary) const
|
||||
|
||||
// instructions
|
||||
|
||||
void resolver_t::visit(const op::alu_t * alu) const
|
||||
void resolver_t::visit(const op::andl_t * andl) const
|
||||
{
|
||||
(void)alu;
|
||||
(void)andl;
|
||||
}
|
||||
|
||||
void resolver_t::visit(const op::orl_t * orl) const
|
||||
{
|
||||
(void)orl;
|
||||
}
|
||||
|
||||
void resolver_t::visit(const op::xorl_t * xorl) const
|
||||
{
|
||||
(void)xorl;
|
||||
}
|
||||
|
||||
void resolver_t::visit(const op::add_t * add) const
|
||||
{
|
||||
(void)add;
|
||||
}
|
||||
|
||||
void resolver_t::visit(const op::sub_t * sub) const
|
||||
{
|
||||
(void)sub;
|
||||
}
|
||||
|
||||
void resolver_t::visit(const op::ad2_t * ad2) const
|
||||
{
|
||||
(void)ad2;
|
||||
}
|
||||
|
||||
void resolver_t::visit(const op::sr_t * sr) const
|
||||
{
|
||||
(void)sr;
|
||||
}
|
||||
|
||||
void resolver_t::visit(const op::rr_t * rr) const
|
||||
{
|
||||
(void)rr;
|
||||
}
|
||||
|
||||
void resolver_t::visit(const op::sl_t * sl) const
|
||||
{
|
||||
(void)sl;
|
||||
}
|
||||
|
||||
void resolver_t::visit(const op::rl_t * rl) const
|
||||
{
|
||||
(void)rl;
|
||||
}
|
||||
|
||||
void resolver_t::visit(const op::rl8_t * rl8) const
|
||||
{
|
||||
(void)rl8;
|
||||
}
|
||||
|
||||
void resolver_t::visit(const op::mov_ram_x_t * mov_ram_x) const
|
||||
|
@ -37,7 +37,18 @@ struct resolver_t : visitor_t<void>
|
||||
void visit(const literal_t * literal) const;
|
||||
void visit(const unary_t * unary) const;
|
||||
|
||||
void visit(const op::alu_t * alu) const;
|
||||
void visit(const op::andl_t * andl) const;
|
||||
void visit(const op::orl_t * orl) const;
|
||||
void visit(const op::xorl_t * xorl) const;
|
||||
void visit(const op::add_t * add) const;
|
||||
void visit(const op::sub_t * sub) const;
|
||||
void visit(const op::ad2_t * ad2) const;
|
||||
void visit(const op::sr_t * sr) const;
|
||||
void visit(const op::rr_t * rr) const;
|
||||
void visit(const op::sl_t * sl) const;
|
||||
void visit(const op::rl_t * rl) const;
|
||||
void visit(const op::rl8_t * rl8) const;
|
||||
|
||||
void visit(const op::mov_ram_x_t * mov_ram_x) const;
|
||||
void visit(const op::mov_mul_p_t * mov_mul_p) const;
|
||||
void visit(const op::mov_ram_p_t * mov_ram_p) const;
|
||||
|
222
bits.hpp
222
bits.hpp
@ -1,222 +0,0 @@
|
||||
namespace dsp {
|
||||
|
||||
namespace op {
|
||||
|
||||
static uint32_t alu_bits(alu_type_t type)
|
||||
{
|
||||
using enum alu_type_t;
|
||||
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();
|
||||
}
|
||||
}
|
||||
|
||||
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();
|
||||
}
|
||||
}
|
||||
|
||||
} // 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();
|
||||
}
|
||||
}
|
||||
|
||||
} // load
|
||||
|
||||
namespace dma {
|
||||
|
||||
static uint32_t add_mode_bits(add_mode_t add)
|
||||
{
|
||||
using enum add_mode_t;
|
||||
|
||||
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 mc0: return 0b000 << 8;
|
||||
case mc1: return 0b001 << 8;
|
||||
case mc2: return 0b010 << 8;
|
||||
case mc3: return 0b011 << 8;
|
||||
default: __builtin_unreachable();
|
||||
}
|
||||
}
|
||||
|
||||
static uint32_t dst_bits(dst_t dst)
|
||||
{
|
||||
using enum dst_t;
|
||||
|
||||
switch (dst) {
|
||||
case mc0: return 0b000 << 8;
|
||||
case mc1: return 0b001 << 8;
|
||||
case mc2: return 0b010 << 8;
|
||||
case mc3: 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();
|
||||
}
|
||||
}
|
||||
|
||||
} // dma
|
||||
|
||||
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();
|
||||
}
|
||||
}
|
||||
|
||||
} // jump
|
||||
|
||||
} // dsp
|
84
control_word.hpp
Normal file
84
control_word.hpp
Normal file
@ -0,0 +1,84 @@
|
||||
#pragma once
|
||||
|
||||
#include <cstdint>
|
||||
#include <variant>
|
||||
#include <vector>
|
||||
#include <utility>
|
||||
|
||||
#include "stmt_base.hpp"
|
||||
#include "stmt_ins.hpp"
|
||||
|
||||
namespace dsp {
|
||||
|
||||
namespace op {
|
||||
using op_t = std::variant<andl_t,
|
||||
orl_t,
|
||||
xorl_t,
|
||||
add_t,
|
||||
sub_t,
|
||||
ad2_t,
|
||||
sr_t,
|
||||
rr_t,
|
||||
sl_t,
|
||||
rl_t,
|
||||
rl8_t,
|
||||
mov_ram_x_t,
|
||||
mov_mul_p_t,
|
||||
mov_ram_p_t,
|
||||
mov_ram_y_t,
|
||||
clr_a_t,
|
||||
mov_alu_a_t,
|
||||
mov_ram_a_t,
|
||||
mov_imm_d1_t,
|
||||
mov_ram_d1_t>;
|
||||
|
||||
struct control_word_t : stmt_accept_t<control_word_t>
|
||||
{
|
||||
control_word_t(std::vector<op_t> ops)
|
||||
: ops(ops)
|
||||
{
|
||||
}
|
||||
|
||||
std::vector<op_t> build_ops(uint32_t code)
|
||||
{
|
||||
std::vector<op_t> ops;
|
||||
if (andl_t::pred(code)) ops.emplace_back(op_t{std::in_place_type<andl_t>, code});
|
||||
else if (orl_t::pred(code)) ops.emplace_back(op_t{std::in_place_type<orl_t>, code});
|
||||
else if (xorl_t::pred(code)) ops.emplace_back(op_t{std::in_place_type<xorl_t>, code});
|
||||
else if (add_t::pred(code)) ops.emplace_back(op_t{std::in_place_type<add_t>, code});
|
||||
else if (sub_t::pred(code)) ops.emplace_back(op_t{std::in_place_type<sub_t>, code});
|
||||
else if (ad2_t::pred(code)) ops.emplace_back(op_t{std::in_place_type<ad2_t>, code});
|
||||
else if (sr_t::pred(code)) ops.emplace_back(op_t{std::in_place_type<sr_t>, code});
|
||||
else if (rr_t::pred(code)) ops.emplace_back(op_t{std::in_place_type<rr_t>, code});
|
||||
else if (sl_t::pred(code)) ops.emplace_back(op_t{std::in_place_type<sl_t>, code});
|
||||
else if (rl_t::pred(code)) ops.emplace_back(op_t{std::in_place_type<rl_t>, code});
|
||||
else if (rl8_t::pred(code)) ops.emplace_back(op_t{std::in_place_type<rl8_t>, code});
|
||||
else if (mov_ram_x_t::pred(code)) ops.emplace_back(op_t{std::in_place_type<mov_ram_x_t>, code});
|
||||
else if (mov_mul_p_t::pred(code)) ops.emplace_back(op_t{std::in_place_type<mov_mul_p_t>, code});
|
||||
else if (mov_ram_p_t::pred(code)) ops.emplace_back(op_t{std::in_place_type<mov_ram_p_t>, code});
|
||||
else if (mov_ram_y_t::pred(code)) ops.emplace_back(op_t{std::in_place_type<mov_ram_y_t>, code});
|
||||
else if (clr_a_t::pred(code)) ops.emplace_back(op_t{std::in_place_type<clr_a_t>, code});
|
||||
else if (mov_alu_a_t::pred(code)) ops.emplace_back(op_t{std::in_place_type<mov_alu_a_t>, code});
|
||||
else if (mov_ram_a_t::pred(code)) ops.emplace_back(op_t{std::in_place_type<mov_ram_a_t>, code});
|
||||
else if (mov_imm_d1_t::pred(code)) ops.emplace_back(op_t{std::in_place_type<mov_imm_d1_t>, code});
|
||||
else if (mov_ram_d1_t::pred(code)) ops.emplace_back(op_t{std::in_place_type<mov_ram_d1_t>, code});
|
||||
else {
|
||||
std::cerr << "invalid control word code: " << (code) << std::endl;
|
||||
throw std::runtime_error("invalid control word code");
|
||||
}
|
||||
return ops;
|
||||
}
|
||||
|
||||
control_word_t(uint32_t code)
|
||||
: ops(build_ops(code)) {}
|
||||
|
||||
const std::vector<op_t> ops;
|
||||
|
||||
uint32_t mask() const { return 0b11 << 30; }
|
||||
uint32_t code() const { return 0b00 << 30; }
|
||||
uint32_t bits() const { return 0; }
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
}
|
158
dsp-notes.csv
Normal file
158
dsp-notes.csv
Normal file
@ -0,0 +1,158 @@
|
||||
,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,
|
||||
,,,31,30,29,28,27,26,25,24,23,22,21,20,19,18,17,16,15,14,13,12,11,10,9,8,7,6,5,4,3,2,1,0,
|
||||
"OP",,,0,0,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,
|
||||
,"ALU",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,
|
||||
,,"struct andl",,,0,0,0,1,,,,,,,,,,,,,,,,,,,,,,,,,,,1
|
||||
,,"struct orl",,,0,0,1,0,,,,,,,,,,,,,,,,,,,,,,,,,,,2
|
||||
,,"struct xorl",,,0,0,1,1,,,,,,,,,,,,,,,,,,,,,,,,,,,3
|
||||
,,"struct add",,,0,1,0,0,,,,,,,,,,,,,,,,,,,,,,,,,,,4
|
||||
,,"struct sub",,,0,1,0,1,,,,,,,,,,,,,,,,,,,,,,,,,,,5
|
||||
,,"struct ad2",,,0,1,1,0,,,,,,,,,,,,,,,,,,,,,,,,,,,6
|
||||
,,"struct sr",,,1,0,0,0,,,,,,,,,,,,,,,,,,,,,,,,,,,8
|
||||
,,"struct rr",,,1,0,0,1,,,,,,,,,,,,,,,,,,,,,,,,,,,9
|
||||
,,"struct sl",,,1,0,1,0,,,,,,,,,,,,,,,,,,,,,,,,,,,10
|
||||
,,"struct rl",,,1,0,1,1,,,,,,,,,,,,,,,,,,,,,,,,,,,11
|
||||
,,"struct rl8",,,1,1,1,1,,,,,,,,,,,,,,,,,,,,,,,,,,,15
|
||||
,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,
|
||||
,"X-bus","enum x_src",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,
|
||||
,,"m0",,,,,,,,,,0,0,0,,,,,,,,,,,,,,,,,,,,,
|
||||
,,"m1",,,,,,,,,,0,0,1,,,,,,,,,,,,,,,,,,,,,
|
||||
,,"m2",,,,,,,,,,0,1,0,,,,,,,,,,,,,,,,,,,,,
|
||||
,,"m3",,,,,,,,,,0,1,1,,,,,,,,,,,,,,,,,,,,,
|
||||
,,"mc0",,,,,,,,,,1,0,0,,,,,,,,,,,,,,,,,,,,,
|
||||
,,"mc1",,,,,,,,,,1,0,1,,,,,,,,,,,,,,,,,,,,,
|
||||
,,"mc2",,,,,,,,,,1,1,0,,,,,,,,,,,,,,,,,,,,,
|
||||
,,"mc3",,,,,,,,,,1,1,1,,,,,,,,,,,,,,,,,,,,,
|
||||
,,"struct mov_ram_x",,,,,,,1,,,"x_src",,,,,,,,,,,,,,,,,,,,,,,
|
||||
,,"struct mov_mul_p",,,,,,,,1,0,,,,,,,,,,,,,,,,,,,,,,,,
|
||||
,,"struct mov_ram_p",,,,,,,,1,1,"x_src",,,,,,,,,,,,,,,,,,,,,,,
|
||||
,"Y-bus","enum y_src",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,
|
||||
,,"m0",,,,,,,,,,,,,,,,0,0,0,,,,,,,,,,,,,,,
|
||||
,,"m1",,,,,,,,,,,,,,,,0,0,1,,,,,,,,,,,,,,,
|
||||
,,"m2",,,,,,,,,,,,,,,,0,1,0,,,,,,,,,,,,,,,
|
||||
,,"m3",,,,,,,,,,,,,,,,0,1,1,,,,,,,,,,,,,,,
|
||||
,,"mc0",,,,,,,,,,,,,,,,1,0,0,,,,,,,,,,,,,,,
|
||||
,,"mc1",,,,,,,,,,,,,,,,1,0,1,,,,,,,,,,,,,,,
|
||||
,,"mc2",,,,,,,,,,,,,,,,1,1,0,,,,,,,,,,,,,,,
|
||||
,,"mc3",,,,,,,,,,,,,,,,1,1,1,,,,,,,,,,,,,,,
|
||||
,,"struct mov_ram_y",,,,,,,,,,,,,1,,,"y_src",,,,,,,,,,,,,,,,,
|
||||
,,"struct clr_a",,,,,,,,,,,,,,0,1,,,,,,,,,,,,,,,,,,
|
||||
,,"struct mov_alu_a",,,,,,,,,,,,,,1,0,,,,,,,,,,,,,,,,,,
|
||||
,,"struct mov_ram_a",,,,,,,,,,,,,,1,1,"y_src",,,,,,,,,,,,,,,,,
|
||||
,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,
|
||||
,,,31,30,29,28,27,26,25,24,23,22,21,20,19,18,17,16,15,14,13,12,11,10,9,8,7,6,5,4,3,2,1,0,
|
||||
,"D1-bus","enum d1_src",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,
|
||||
,,"m0",,,,,,,,,,,,,,,,,,,,,,,,,,,,,0,0,0,0,0
|
||||
,,"m1",,,,,,,,,,,,,,,,,,,,,,,,,,,,,0,0,0,1,1
|
||||
,,"m2",,,,,,,,,,,,,,,,,,,,,,,,,,,,,0,0,1,0,2
|
||||
,,"m3",,,,,,,,,,,,,,,,,,,,,,,,,,,,,0,0,1,1,3
|
||||
,,"mc0",,,,,,,,,,,,,,,,,,,,,,,,,,,,,0,1,0,0,4
|
||||
,,"mc1",,,,,,,,,,,,,,,,,,,,,,,,,,,,,0,1,0,1,5
|
||||
,,"mc2",,,,,,,,,,,,,,,,,,,,,,,,,,,,,0,1,1,0,6
|
||||
,,"mc3",,,,,,,,,,,,,,,,,,,,,,,,,,,,,0,1,1,1,7
|
||||
,,"all",,,,,,,,,,,,,,,,,,,,,,,,,,,,,1,0,0,1,9
|
||||
,,"alh",,,,,,,,,,,,,,,,,,,,,,,,,,,,,1,0,1,0,10
|
||||
,,"enum d1_dst",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,
|
||||
,,"mc0",,,,,,,,,,,,,,,,,,,,,0,0,0,0,,,,,,,,,0
|
||||
,,"mc1",,,,,,,,,,,,,,,,,,,,,0,0,0,1,,,,,,,,,1
|
||||
,,"mc2",,,,,,,,,,,,,,,,,,,,,0,0,1,0,,,,,,,,,2
|
||||
,,"mc3",,,,,,,,,,,,,,,,,,,,,0,0,1,1,,,,,,,,,3
|
||||
,,"rx",,,,,,,,,,,,,,,,,,,,,0,1,0,0,,,,,,,,,4
|
||||
,,"pl",,,,,,,,,,,,,,,,,,,,,0,1,0,1,,,,,,,,,5
|
||||
,,"ra0",,,,,,,,,,,,,,,,,,,,,0,1,1,0,,,,,,,,,6
|
||||
,,"wa0",,,,,,,,,,,,,,,,,,,,,0,1,1,1,,,,,,,,,7
|
||||
,,"lop",,,,,,,,,,,,,,,,,,,,,1,0,1,0,,,,,,,,,10
|
||||
,,"top",,,,,,,,,,,,,,,,,,,,,1,0,1,1,,,,,,,,,11
|
||||
,,"ct0",,,,,,,,,,,,,,,,,,,,,1,1,0,0,,,,,,,,,12
|
||||
,,"ct1",,,,,,,,,,,,,,,,,,,,,1,1,0,1,,,,,,,,,13
|
||||
,,"ct2",,,,,,,,,,,,,,,,,,,,,1,1,1,0,,,,,,,,,14
|
||||
,,"ct3",,,,,,,,,,,,,,,,,,,,,1,1,1,1,,,,,,,,,15
|
||||
,,"struct mov_imm_d1",,,,,,,,,,,,,,,,,,,0,1,"d1_dst",,,,"imm",,,,,,,,
|
||||
,,"struct mov_ram_d1",,,,,,,,,,,,,,,,,,,1,1,"d1_dst",,,,,,,,"d1_src",,,,
|
||||
,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,
|
||||
,,,31,30,29,28,27,26,25,24,23,22,21,20,19,18,17,16,15,14,13,12,11,10,9,8,7,6,5,4,3,2,1,0,
|
||||
"LOAD",,"struct mvi",1,0,"dst",,,,0,"imm",,,,,,,,,,,,,,,,,,,,,,,,,
|
||||
,"conditional","struct mvi_cond",1,0,"dst",,,,1,"cond",,,,,,"imm",,,,,,,,,,,,,,,,,,,
|
||||
,,"enum cond",,,,,,,,"N",,"T0","C","S","Z",,,,,,,,,,,,,,,,,,,,
|
||||
,,"z",,,,,,,,1,0,0,0,0,1,,,,,,,,,,,,,,,,,,,,
|
||||
,,"nz",,,,,,,,0,0,0,0,0,1,,,,,,,,,,,,,,,,,,,,
|
||||
,,"s",,,,,,,,1,0,0,0,1,0,,,,,,,,,,,,,,,,,,,,
|
||||
,,"ns",,,,,,,,0,0,0,0,1,0,,,,,,,,,,,,,,,,,,,,
|
||||
,,"c",,,,,,,,1,0,0,1,0,0,,,,,,,,,,,,,,,,,,,,
|
||||
,,"nc",,,,,,,,0,0,0,1,0,0,,,,,,,,,,,,,,,,,,,,
|
||||
,,"t0",,,,,,,,1,0,1,0,0,0,,,,,,,,,,,,,,,,,,,,
|
||||
,,"nt0",,,,,,,,0,0,1,0,0,0,,,,,,,,,,,,,,,,,,,,
|
||||
,,"zs",,,,,,,,1,0,0,0,1,1,,,,,,,,,,,,,,,,,,,,
|
||||
,,"nzs",,,,,,,,0,0,0,0,1,1,,,,,,,,,,,,,,,,,,,,
|
||||
,,"enum dst",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,
|
||||
,,"mc0",,,0,0,0,0,,,,,,,,,,,,,,,,,,,,,,,,,,,0
|
||||
,,"mc1",,,0,0,0,1,,,,,,,,,,,,,,,,,,,,,,,,,,,1
|
||||
,,"mc2",,,0,0,1,0,,,,,,,,,,,,,,,,,,,,,,,,,,,2
|
||||
,,"mc3",,,0,0,1,1,,,,,,,,,,,,,,,,,,,,,,,,,,,3
|
||||
,,"rx",,,0,1,0,0,,,,,,,,,,,,,,,,,,,,,,,,,,,4
|
||||
,,"pl",,,0,1,0,1,,,,,,,,,,,,,,,,,,,,,,,,,,,5
|
||||
,,"ra0",,,0,1,1,0,,,,,,,,,,,,,,,,,,,,,,,,,,,6
|
||||
,,"wa0",,,0,1,1,1,,,,,,,,,,,,,,,,,,,,,,,,,,,7
|
||||
,,"lop",,,1,0,1,0,,,,,,,,,,,,,,,,,,,,,,,,,,,10
|
||||
,,"pc",,,1,1,0,0,,,,,,,,,,,,,,,,,,,,,,,,,,,12
|
||||
,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,
|
||||
,,,31,30,29,28,27,26,25,24,23,22,21,20,19,18,17,16,15,14,13,12,11,10,9,8,7,6,5,4,3,2,1,0,
|
||||
"DMA",,,,,,,,,,,,,,,,,,,,"H","L","D",,,,,,,,,,,,,
|
||||
,"imm","struct d0_dst_imm",1,1,0,0,,,,,,,,,,,"add",,,"hold",0,0,,"dst",,,"imm",,,,,,,,
|
||||
,,"struct src_d0_imm",1,1,0,0,,,,,,,,,,,"add",,,"hold",0,1,,"src",,,"imm",,,,,,,,
|
||||
,"ram","struct d0_dst_ram",1,1,0,0,,,,,,,,,,,"add",,,"hold",1,0,,"dst",,,,,,,,"ram",,,
|
||||
,,"struct src_d0_ram",1,1,0,0,,,,,,,,,,,"add",,,"hold",1,1,,"src",,,,,,,,"ram",,,
|
||||
,,"enum ram",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,
|
||||
,,"m0",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,0,0,0,0
|
||||
,,"m1",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,0,0,1,1
|
||||
,,"m2",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,0,1,0,2
|
||||
,,"m3",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,0,1,1,3
|
||||
,,"mc0",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,1,0,0,4
|
||||
,,"mc1",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,1,0,1,5
|
||||
,,"mc2",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,1,1,0,6
|
||||
,,"mc3",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,1,1,1,7
|
||||
,,"enum src",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,
|
||||
,,"mc0",,,,,,,,,,,,,,,,,,,,,,0,0,0,,,,,,,,,
|
||||
,,"mc1",,,,,,,,,,,,,,,,,,,,,,0,0,1,,,,,,,,,
|
||||
,,"mc2",,,,,,,,,,,,,,,,,,,,,,0,1,0,,,,,,,,,
|
||||
,,"mc3",,,,,,,,,,,,,,,,,,,,,,0,1,1,,,,,,,,,
|
||||
,,"enum dst",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,
|
||||
,,"mc0",,,,,,,,,,,,,,,,,,,,,,0,0,0,,,,,,,,,
|
||||
,,"mc1",,,,,,,,,,,,,,,,,,,,,,0,0,1,,,,,,,,,
|
||||
,,"mc2",,,,,,,,,,,,,,,,,,,,,,0,1,0,,,,,,,,,
|
||||
,,"mc3",,,,,,,,,,,,,,,,,,,,,,0,1,1,,,,,,,,,
|
||||
,,"prg",,,,,,,,,,,,,,,,,,,,,,1,0,0,,,,,,,,,
|
||||
,,"enum hold",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,
|
||||
,,"_false",,,,,,,,,,,,,,,,,,0,,,,,,,,,,,,,,,
|
||||
,,"_true",,,,,,,,,,,,,,,,,,1,,,,,,,,,,,,,,,
|
||||
,,"enum add",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,
|
||||
,,"_0",,,,,,,,,,,,,,,0,0,0,,,,,,,,,,,,,,,,0
|
||||
,,"_1",,,,,,,,,,,,,,,0,0,1,,,,,,,,,,,,,,,,1
|
||||
,,"_2",,,,,,,,,,,,,,,0,1,0,,,,,,,,,,,,,,,,2
|
||||
,,"_4",,,,,,,,,,,,,,,0,1,1,,,,,,,,,,,,,,,,3
|
||||
,,"_8",,,,,,,,,,,,,,,1,0,0,,,,,,,,,,,,,,,,4
|
||||
,,"_16",,,,,,,,,,,,,,,1,0,1,,,,,,,,,,,,,,,,5
|
||||
,,"_32",,,,,,,,,,,,,,,1,1,0,,,,,,,,,,,,,,,,6
|
||||
,,"_64",,,,,,,,,,,,,,,1,1,1,,,,,,,,,,,,,,,,7
|
||||
,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,
|
||||
,,,31,30,29,28,27,26,25,24,23,22,21,20,19,18,17,16,15,14,13,12,11,10,9,8,7,6,5,4,3,2,1,0,
|
||||
"JUMP",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,
|
||||
,,"struct jmp",1,1,0,1,,,0,"imm",,,,,,,,,,,,,,,,,,,,,,,,,
|
||||
,"conditional","struct jmp_cond",1,1,0,1,,,1,"cond",,,,,,"imm",,,,,,,,,,,,,,,,,,,
|
||||
,,"enum cond",,,,,,,"F","N",,"T0","C","S","Z",,,,,,,,,,,,,,,,,,,,
|
||||
,,"z",,,,,,,,1,0,0,0,0,1,,,,,,,,,,,,,,,,,,,,
|
||||
,,"nz",,,,,,,,0,0,0,0,0,1,,,,,,,,,,,,,,,,,,,,
|
||||
,,"s",,,,,,,,1,0,0,0,1,0,,,,,,,,,,,,,,,,,,,,
|
||||
,,"ns",,,,,,,,0,0,0,0,1,0,,,,,,,,,,,,,,,,,,,,
|
||||
,,"c",,,,,,,,1,0,0,1,0,0,,,,,,,,,,,,,,,,,,,,
|
||||
,,"nc",,,,,,,,0,0,0,1,0,0,,,,,,,,,,,,,,,,,,,,
|
||||
,,"t0",,,,,,,,1,0,1,0,0,0,,,,,,,,,,,,,,,,,,,,
|
||||
,,"nt0",,,,,,,,0,0,1,0,0,0,,,,,,,,,,,,,,,,,,,,
|
||||
,,"zs",,,,,,,,1,0,0,0,1,1,,,,,,,,,,,,,,,,,,,,
|
||||
,,"nzs",,,,,,,,0,0,0,0,1,1,,,,,,,,,,,,,,,,,,,,
|
||||
,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,
|
||||
"LOOP",,"struct btm",1,1,1,0,0,,,,,,,,,,,,,,,,,,,,,,,,,,,,
|
||||
,,"struct lps",1,1,1,0,1,,,,,,,,,,,,,,,,,,,,,,,,,,,,
|
||||
,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,
|
||||
"END",,"struct end",1,1,1,1,0,,,,,,,,,,,,,,,,,,,,,,,,,,,,
|
||||
,,"struct endi",1,1,1,1,1,,,,,,,,,,,,,,,,,,,,,,,,,,,,
|
|
BIN
dsp-notes.ods
BIN
dsp-notes.ods
Binary file not shown.
@ -17,6 +17,12 @@ static inline void report(const int line, const int col, const std::string where
|
||||
had_error = true;
|
||||
}
|
||||
|
||||
static inline void error(std::string message, const int value)
|
||||
{
|
||||
std::cerr << "error " << message << ": " << value << std::endl;
|
||||
had_error = true;
|
||||
}
|
||||
|
||||
static inline void error(const int line, const int col, std::string message)
|
||||
{
|
||||
report(line, col, "", message);
|
||||
|
24
gen/generate.py
Normal file
24
gen/generate.py
Normal file
@ -0,0 +1,24 @@
|
||||
import io
|
||||
|
||||
def _render(out, lines):
|
||||
indent = " "
|
||||
level = 0
|
||||
for l in lines:
|
||||
if l and (l[0] == "}" or l[0] == ")"):
|
||||
level -= 2
|
||||
assert level >= 0, out.getvalue()
|
||||
|
||||
out.write(indent * level + l + "\n")
|
||||
|
||||
if l and (l[-1] == "{" or l[-1] == "("):
|
||||
level += 2
|
||||
|
||||
if level == 0 and l and l[-1] == ";":
|
||||
out.write("\n")
|
||||
return out
|
||||
|
||||
def renderer():
|
||||
out = io.StringIO()
|
||||
def render(lines):
|
||||
return _render(out, lines)
|
||||
return render, out
|
241
gen/generate_notes.py
Normal file
241
gen/generate_notes.py
Normal file
@ -0,0 +1,241 @@
|
||||
import sys
|
||||
from generate import renderer
|
||||
from parse_notes import parse, read, X, Bits, Enum, Struct, Namespace
|
||||
|
||||
def bits_mask_literal(bits, start, end) -> str:
|
||||
b_str = lambda b: '1' if b is not X else '0'
|
||||
s = ''.join(map(b_str, reversed(bits[start:end])))
|
||||
return s
|
||||
|
||||
def bits_literal(bits, start, end) -> str:
|
||||
b_str = lambda b: str(b) if b is not X else '0'
|
||||
s = ''.join(map(b_str, reversed(bits[start:end])))
|
||||
return s
|
||||
|
||||
def bits_start_end(bits):
|
||||
start = 0
|
||||
while bits[start] is X:
|
||||
start += 1
|
||||
|
||||
ix = start + 1
|
||||
end = ix
|
||||
while ix < 32:
|
||||
if bits[ix] is not X:
|
||||
end = ix + 1
|
||||
ix += 1
|
||||
|
||||
return start, end
|
||||
|
||||
def bits_to_shift(bits) -> str:
|
||||
start, end = bits_start_end(bits)
|
||||
literal = bits_literal(bits, start, end)
|
||||
return f"0b{literal} << {start}"
|
||||
|
||||
def bits_to_mask(bits) -> str:
|
||||
start, end = bits_start_end(bits)
|
||||
mask = bits_mask_literal(bits, start, end)
|
||||
return f"0b{mask} << {start}"
|
||||
|
||||
def enum_consts_to_value(namespace_name, enum_name, consts):
|
||||
yield "static constexpr value_t to_value(uint32_t code)"
|
||||
yield "{"
|
||||
yield "using enum value_t;"
|
||||
yield ""
|
||||
yield "switch (code & mask()) {"
|
||||
for const in consts:
|
||||
shift = bits_to_shift(const.bits)
|
||||
yield f"case {shift}: return {const.name};"
|
||||
yield "default:"
|
||||
yield f' std::cerr << "invalid {namespace_name} {enum_name} code: " << (code & mask()) << std::endl;'
|
||||
yield ' throw std::runtime_error("invalid code");'
|
||||
yield "}"
|
||||
yield "}"
|
||||
|
||||
def enum_consts_bits(consts):
|
||||
yield "uint32_t bits() const"
|
||||
yield "{"
|
||||
yield "using enum value_t;"
|
||||
yield ""
|
||||
yield "switch (value) {"
|
||||
for const in consts:
|
||||
shift = bits_to_shift(const.bits)
|
||||
yield f"case {const.name}: return {shift};"
|
||||
yield "default: __builtin_unreachable();"
|
||||
yield "}"
|
||||
yield "}"
|
||||
|
||||
def enum_value_t(consts):
|
||||
yield "enum value_t {"
|
||||
for const in consts:
|
||||
yield f"{const.name},"
|
||||
yield "};"
|
||||
|
||||
def enum_struct(namespace, enum):
|
||||
yield f"struct {enum.name}_t {{"
|
||||
yield from enum_value_t(enum.consts)
|
||||
yield ""
|
||||
yield "const value_t value;"
|
||||
yield ""
|
||||
yield f"constexpr {enum.name}_t(value_t value)"
|
||||
yield " : value(value) {}"
|
||||
yield ""
|
||||
yield f"constexpr {enum.name}_t(uint32_t code)"
|
||||
yield " : value(to_value(code)) {}"
|
||||
yield ""
|
||||
mask = bits_to_mask(enum.consts[0].bits)
|
||||
yield f"static constexpr uint32_t mask() {{ return {mask}; }}"
|
||||
yield ""
|
||||
yield from enum_consts_to_value(namespace.name, enum.name, enum.consts)
|
||||
yield ""
|
||||
yield from enum_consts_bits(enum.consts)
|
||||
yield "};"
|
||||
|
||||
def has_imm(struct):
|
||||
return 'imm' in {name for _i, name in struct.fields}
|
||||
|
||||
def imm_length(struct):
|
||||
imm_length, = [i for i, name in struct.fields if name == 'imm']
|
||||
return imm_length + 1
|
||||
|
||||
def f_name(name):
|
||||
return name.split('_', maxsplit=1)[-1]
|
||||
|
||||
def struct_struct(namespace, struct):
|
||||
if has_imm(struct):
|
||||
length = imm_length(struct)
|
||||
yield f"struct {struct.name}_t : stmt_accept_t<{struct.name}_t>, ins_imm_t<{struct.name}_t, {length}>"
|
||||
yield "{"
|
||||
yield f"using imm_type = uimm_t<{length}>;"
|
||||
else:
|
||||
yield f"struct {struct.name}_t : stmt_accept_t<{struct.name}_t>, ins_t<{struct.name}_t>"
|
||||
yield "{"
|
||||
yield ""
|
||||
|
||||
|
||||
field_decls = [f"{name}_t {f_name(name)}" for _, name in struct.fields if name != 'imm']
|
||||
field_inits = [f"{f_name(name)}({f_name(name)})" for _, name in struct.fields if name != 'imm']
|
||||
if has_imm(struct):
|
||||
field_decls.insert(0, "imm_type imm")
|
||||
field_inits.insert(0, "ins_imm_t(imm)")
|
||||
field_inits = ", ".join(field_inits)
|
||||
field_decls = ", ".join(field_decls)
|
||||
yield f"{struct.name}_t({field_decls})"
|
||||
if field_inits.strip():
|
||||
yield f" : {field_inits} {{}}"
|
||||
else:
|
||||
yield "{}"
|
||||
yield ""
|
||||
yield f"{struct.name}_t(uint32_t code)"
|
||||
code_inits = [f"{f_name(name)}(code)" for _, name in struct.fields if name != 'imm']
|
||||
if has_imm(struct):
|
||||
code_inits.insert(0, "ins_imm_t(code)")
|
||||
code_inits = ", ".join(code_inits)
|
||||
if code_inits.strip():
|
||||
yield f" : {code_inits} {{ (void)code; }}"
|
||||
else:
|
||||
yield "{ (void)code; }"
|
||||
yield ""
|
||||
|
||||
for _, name in struct.fields:
|
||||
if name == 'imm':
|
||||
pass
|
||||
else:
|
||||
yield f"const {name}_t {f_name(name)};"
|
||||
yield ""
|
||||
|
||||
start, end = bits_start_end(struct.bits)
|
||||
mask_literal = bits_mask_literal(struct.bits, start, end)
|
||||
literal = bits_literal(struct.bits, start, end)
|
||||
|
||||
yield f"static uint32_t mask() {{ return 0b{mask_literal} << {start}; }}"
|
||||
yield f"static uint32_t code() {{ return 0b{literal} << {start}; }}"
|
||||
bits_return = " | ".join(f"{f_name(name)}.bits()" for _, name in struct.fields if name != 'imm')
|
||||
if not bits_return.strip():
|
||||
bits_return = "0"
|
||||
yield f"uint32_t bits() const {{ return {bits_return}; }}"
|
||||
|
||||
yield "};"
|
||||
|
||||
def sort_events(events):
|
||||
enums = []
|
||||
structs = []
|
||||
namespace = None
|
||||
def do_yield():
|
||||
nonlocal enums, structs, namespace
|
||||
|
||||
yield namespace
|
||||
#yield from sorted(enums, key=lambda e: e.name)
|
||||
yield from enums
|
||||
assert structs, structs
|
||||
yield from structs
|
||||
#yield from sorted(structs, key=lambda e: e.name)
|
||||
|
||||
for event in events:
|
||||
if type(event) is Namespace:
|
||||
if namespace is not None:
|
||||
yield from do_yield()
|
||||
else:
|
||||
assert not enums
|
||||
assert not structs
|
||||
namespace = event
|
||||
enums = []
|
||||
structs = []
|
||||
elif type(event) is Enum:
|
||||
assert namespace is not None
|
||||
enums.append(event)
|
||||
elif type(event) is Struct:
|
||||
assert namespace is not None
|
||||
structs.append(event)
|
||||
else:
|
||||
assert False
|
||||
assert namespace is not None
|
||||
yield from do_yield()
|
||||
|
||||
def generate_header_namespaces(events):
|
||||
namespace = None
|
||||
yield "namespace dsp {"
|
||||
for event in events:
|
||||
if type(event) is Namespace:
|
||||
if namespace is not None:
|
||||
yield ""
|
||||
yield f"}} // {namespace.name}"
|
||||
yield ""
|
||||
yield f"namespace {event.name} {{"
|
||||
yield ""
|
||||
namespace = event
|
||||
elif type(event) is Enum:
|
||||
yield from enum_struct(namespace, event)
|
||||
yield ""
|
||||
elif type(event) is Struct:
|
||||
yield from struct_struct(namespace, event)
|
||||
yield ""
|
||||
else:
|
||||
assert False
|
||||
assert namespace is not None
|
||||
yield f"}} // namespace {namespace.name}"
|
||||
yield ""
|
||||
yield "} // namespace dsp"
|
||||
|
||||
def generate_includes():
|
||||
yield "#pragma once"
|
||||
yield ""
|
||||
yield "#include <cstdint>"
|
||||
yield "#include <iostream>"
|
||||
yield ""
|
||||
yield '#include "imm.hpp"'
|
||||
yield '#include "ins.hpp"'
|
||||
yield '#include "stmt_base.hpp"'
|
||||
yield ""
|
||||
|
||||
def generate_header():
|
||||
events = list(sort_events(parse(read(sys.argv[1]))))
|
||||
render, out = renderer()
|
||||
render(generate_includes())
|
||||
render(generate_header_namespaces(events))
|
||||
return out
|
||||
|
||||
print(generate_header().getvalue())
|
||||
|
||||
#consts=[Const(name='z', bits=xxxxxxx100001xxxxxxxxxxxxxxxxxxx),
|
||||
|
||||
b = Bits(bits=[X,X,1,1,0,0,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X,X])
|
128
gen/parse_notes.py
Normal file
128
gen/parse_notes.py
Normal file
@ -0,0 +1,128 @@
|
||||
import csv
|
||||
import sys
|
||||
from dataclasses import dataclass
|
||||
from typing import Union
|
||||
|
||||
class _X:
|
||||
def __repr__(self):
|
||||
return 'x'
|
||||
|
||||
X = _X()
|
||||
|
||||
bit = Union[int, _X]
|
||||
|
||||
@dataclass
|
||||
class Bits:
|
||||
bits: tuple[bit, bit, bit, bit, bit, bit, bit, bit,
|
||||
bit, bit, bit, bit, bit, bit, bit, bit,
|
||||
bit, bit, bit, bit, bit, bit, bit, bit,
|
||||
bit, bit, bit, bit, bit, bit, bit, bit]
|
||||
|
||||
def __repr__(self):
|
||||
return ''.join(repr(i) for i in self.bits)
|
||||
|
||||
def __getitem__(self, key):
|
||||
return list(reversed(self.bits))[key]
|
||||
|
||||
@dataclass
|
||||
class Const:
|
||||
name: str
|
||||
bits: Bits
|
||||
|
||||
@dataclass
|
||||
class Enum:
|
||||
name: str
|
||||
consts: list[Const]
|
||||
|
||||
@dataclass
|
||||
class Struct:
|
||||
name: str
|
||||
bits: Bits
|
||||
fields: list[tuple[int, str]]
|
||||
|
||||
@dataclass
|
||||
class Namespace:
|
||||
name: str
|
||||
|
||||
def read(path):
|
||||
with open(path, newline='') as f:
|
||||
reader = csv.reader(f, delimiter=',', quotechar='"')
|
||||
return list(reader)
|
||||
|
||||
label_col = 2
|
||||
bits_col = 3
|
||||
|
||||
def parse_struct(rows, ix):
|
||||
return None, ix + 1
|
||||
|
||||
def validate_consts(consts):
|
||||
by_index = set([
|
||||
frozenset([ix for ix, bit in enumerate(const.bits) if bit is not X])
|
||||
for const in consts
|
||||
])
|
||||
assert len(by_index) == 1
|
||||
|
||||
def get_bits(row):
|
||||
return [
|
||||
int(i) if i in {"0", "1"} else X
|
||||
for i in row[bits_col:bits_col+32]
|
||||
]
|
||||
|
||||
def get_nonbits(row):
|
||||
return [
|
||||
(31-ix, i)
|
||||
for ix, i in enumerate(row[bits_col:bits_col+32])
|
||||
if i and i not in {"0", "1"}
|
||||
]
|
||||
|
||||
def get_name(row, key):
|
||||
label0 = row[label_col]
|
||||
assert label0.startswith(f'{key} '), label0
|
||||
_, name = label0.split(' ', maxsplit=1)
|
||||
return name
|
||||
|
||||
def parse_enum(rows, ix):
|
||||
enum_name = get_name(rows[ix], "enum")
|
||||
ix += 1
|
||||
consts = []
|
||||
|
||||
while ix < len(rows):
|
||||
label = rows[ix][label_col]
|
||||
if not label or ' ' in label:
|
||||
validate_consts(consts)
|
||||
return Enum(enum_name, consts), ix
|
||||
else:
|
||||
const_name = label
|
||||
bits = get_bits(rows[ix])
|
||||
assert len(bits) == 32
|
||||
consts.append(Const(const_name, Bits(bits)))
|
||||
ix += 1
|
||||
|
||||
def parse_struct(rows, ix):
|
||||
struct_name = get_name(rows[ix], "struct")
|
||||
bits = get_bits(rows[ix])
|
||||
fields = get_nonbits(rows[ix])
|
||||
ix += 1
|
||||
|
||||
struct = Struct(struct_name, Bits(bits), fields)
|
||||
return struct, ix
|
||||
|
||||
def parse(rows):
|
||||
ix = 0
|
||||
while ix < len(rows):
|
||||
if rows[ix][0].strip():
|
||||
yield Namespace(rows[ix][0].lower())
|
||||
|
||||
label = rows[ix][label_col]
|
||||
if label.startswith('struct'):
|
||||
ret, ix = parse_struct(rows, ix)
|
||||
yield ret
|
||||
elif label.startswith('enum' ):
|
||||
ret, ix = parse_enum(rows, ix)
|
||||
yield ret
|
||||
else:
|
||||
ix += 1
|
||||
|
||||
#events = list(parse(read(sys.argv[1])))
|
||||
#from pprint import pprint
|
||||
#pprint(events)
|
187
gen/template.cpp
Normal file
187
gen/template.cpp
Normal file
@ -0,0 +1,187 @@
|
||||
#include <cstdint>
|
||||
|
||||
#include "imm.hpp"
|
||||
#include "stmt_base.hpp"
|
||||
|
||||
namespace dsp {
|
||||
|
||||
template <typename T>
|
||||
struct ins_t
|
||||
{
|
||||
virtual uint32_t bits() const;
|
||||
|
||||
uint32_t render() const
|
||||
{
|
||||
return T::code() | bits();
|
||||
}
|
||||
|
||||
constexpr bool pred(uint32_t ins) const
|
||||
{
|
||||
return (ins & T::mask()) == T::code();
|
||||
}
|
||||
};
|
||||
|
||||
template <typename T, int N>
|
||||
struct ins_imm_t : ins_t<T>
|
||||
{
|
||||
ins_imm_t(uimm_t<N> imm)
|
||||
: imm(imm) {}
|
||||
|
||||
const uimm_t<N> imm;
|
||||
|
||||
uint32_t render(visitor_t<uint32_t> * visitor)
|
||||
{
|
||||
num_t value = imm.normalize(imm.expr->accept(visitor));
|
||||
if (imm.in_range(value))
|
||||
return render() | value;
|
||||
else
|
||||
throw imm_out_of_range(imm, value);
|
||||
}
|
||||
};
|
||||
|
||||
namespace load {
|
||||
|
||||
struct dest_t {
|
||||
enum value_t {
|
||||
mc0, mc1, mc2, mc3,
|
||||
rx , pl ,
|
||||
ra0, wa0,
|
||||
lop, pc ,
|
||||
};
|
||||
|
||||
const value_t value;
|
||||
|
||||
constexpr dest_t(value_t value)
|
||||
: value(value) {}
|
||||
|
||||
constexpr dest_t(uint32_t code)
|
||||
: value(to_value(code)) { }
|
||||
|
||||
static constexpr uint32_t mask() { return 0b1111 << 26; }
|
||||
|
||||
static constexpr value_t to_value(uint32_t code)
|
||||
{
|
||||
using enum value_t;
|
||||
|
||||
switch (code & mask()) {
|
||||
case 0b0000 << 26: return mc0;
|
||||
case 0b0001 << 26: return mc1;
|
||||
case 0b0010 << 26: return mc2;
|
||||
case 0b0011 << 26: return mc3;
|
||||
case 0b0100 << 26: return rx;
|
||||
case 0b0101 << 26: return pl;
|
||||
case 0b0110 << 26: return ra0;
|
||||
case 0b0111 << 26: return wa0;
|
||||
case 0b1010 << 26: return lop;
|
||||
case 0b1100 << 26: return pc;
|
||||
default:
|
||||
std::cerr << "invalid load dest code: " << (code & mask()) << std::endl;
|
||||
throw std::runtime_error("invalid code");
|
||||
}
|
||||
}
|
||||
|
||||
uint32_t bits() const
|
||||
{
|
||||
using enum value_t;
|
||||
|
||||
switch (value) {
|
||||
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();
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
struct cond_t {
|
||||
enum value_t {
|
||||
z , nz ,
|
||||
s , ns ,
|
||||
c , nc ,
|
||||
t0, nt0,
|
||||
zs, nzs,
|
||||
};
|
||||
|
||||
const value_t value;
|
||||
|
||||
constexpr cond_t(value_t value)
|
||||
: value(value) {}
|
||||
|
||||
constexpr cond_t(uint32_t code)
|
||||
: value(to_value(code)) { }
|
||||
|
||||
static constexpr uint32_t mask() { return 0b1'0'1111 << 19; }
|
||||
|
||||
static constexpr value_t to_value(uint32_t code)
|
||||
{
|
||||
using enum value_t;
|
||||
|
||||
switch (code & mask()) {
|
||||
case 0b1'0'0001 << 19: return z;
|
||||
case 0b0'0'0001 << 19: return nz;
|
||||
case 0b1'0'0010 << 19: return s;
|
||||
case 0b0'0'0010 << 19: return ns;
|
||||
case 0b1'0'0100 << 19: return c;
|
||||
case 0b0'0'0100 << 19: return nc;
|
||||
case 0b1'0'1000 << 19: return t0;
|
||||
case 0b0'0'1000 << 19: return nt0;
|
||||
case 0b1'0'0011 << 19: return zs;
|
||||
case 0b0'0'0011 << 19: return nzs;
|
||||
default:
|
||||
std::cerr << "invalid load cond code: " << (code & mask()) << std::endl;
|
||||
throw std::runtime_error("invalid code");
|
||||
}
|
||||
}
|
||||
|
||||
uint32_t bits() const
|
||||
{
|
||||
using enum value_t;
|
||||
|
||||
switch (value) {
|
||||
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_cond_t : stmt_accept_t<mvi_cond_t>, ins_imm_t<mvi_cond_t, 19>
|
||||
{
|
||||
using imm_type = uimm_t<19>;
|
||||
|
||||
mvi_cond_t(dest_t dest, cond_t cond, imm_type imm)
|
||||
: dest(dest), cond(cond), ins_imm_t(imm)
|
||||
{ }
|
||||
|
||||
mvi_cond_t(uint32_t code)
|
||||
: dest(code), cond(code), ins_imm_t(code)
|
||||
{ }
|
||||
|
||||
const dest_t dest;
|
||||
const cond_t cond;
|
||||
|
||||
static uint32_t mask() { return 0b11'0000'1 << 25; }
|
||||
static uint32_t code() { return 0b10'0000'1 << 25; }
|
||||
uint32_t bits() const { return dest.bits()
|
||||
| cond.bits();
|
||||
}
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
}
|
47
imm.hpp
Normal file
47
imm.hpp
Normal file
@ -0,0 +1,47 @@
|
||||
#pragma once
|
||||
|
||||
#include "expr.hpp"
|
||||
|
||||
namespace dsp {
|
||||
|
||||
static const token_t null_token;
|
||||
|
||||
template <bool S, int N>
|
||||
struct imm_t {
|
||||
imm_t(const token_t& token, const expr_t * expr)
|
||||
: token(token), expr(expr) {}
|
||||
|
||||
imm_t(const uint32_t code)
|
||||
: token(null_token), expr(new literal_t(code & mask)) {}
|
||||
|
||||
const token_t& token;
|
||||
const expr_t * expr;
|
||||
|
||||
static constexpr bool sign = S;
|
||||
static constexpr int bits = N;
|
||||
static constexpr num_t max = (1L << (bits - static_cast<num_t>(sign))) - 1;
|
||||
static constexpr num_t min = sign ? -(max + 1) : 0;
|
||||
static constexpr num_t mask = (1L << bits) - 1;
|
||||
|
||||
num_t normalize(num_t value) const
|
||||
{
|
||||
if (!S && value > 2147483648) { // fixme: hack
|
||||
return value & max;
|
||||
} else {
|
||||
return value;
|
||||
}
|
||||
}
|
||||
|
||||
bool in_range(num_t value) const
|
||||
{
|
||||
return value <= max && value >= min;
|
||||
}
|
||||
};
|
||||
|
||||
template <int N>
|
||||
using simm_t = imm_t<true, N>;
|
||||
|
||||
template <int N>
|
||||
using uimm_t = imm_t<false, N>;
|
||||
|
||||
}
|
45
ins.hpp
Normal file
45
ins.hpp
Normal file
@ -0,0 +1,45 @@
|
||||
#pragma once
|
||||
|
||||
#include <cstdint>
|
||||
|
||||
#include "imm.hpp"
|
||||
|
||||
namespace dsp {
|
||||
|
||||
template <typename T>
|
||||
struct ins_t
|
||||
{
|
||||
/*
|
||||
virtual uint32_t bits() const;
|
||||
|
||||
uint32_t render() const
|
||||
{
|
||||
return T::code() | bits();
|
||||
}
|
||||
*/
|
||||
|
||||
static bool pred(uint32_t ins)
|
||||
{
|
||||
return (ins & T::mask()) == T::code();
|
||||
}
|
||||
};
|
||||
|
||||
template <typename T, int N>
|
||||
struct ins_imm_t : ins_t<T>
|
||||
{
|
||||
ins_imm_t(uimm_t<N> imm)
|
||||
: imm(imm) {}
|
||||
|
||||
const uimm_t<N> imm;
|
||||
|
||||
uint32_t render(visitor_t<uint32_t> * visitor)
|
||||
{
|
||||
num_t value = imm.normalize(imm.expr->accept(visitor));
|
||||
if (imm.in_range(value))
|
||||
return render() | value;
|
||||
else
|
||||
throw imm_out_of_range(imm, value);
|
||||
}
|
||||
};
|
||||
|
||||
}
|
215
parser.cpp
215
parser.cpp
@ -173,21 +173,22 @@ void parser_t::synchronize()
|
||||
}
|
||||
*/
|
||||
|
||||
std::optional<op::op_t *> parser_t::alu()
|
||||
std::optional<op::op_t> parser_t::alu()
|
||||
{
|
||||
using namespace dsp::op;
|
||||
|
||||
if (match(_and)) return {new alu_t(alu_type_t::andl)};
|
||||
else if (match(_or )) return {new alu_t(alu_type_t::orl)};
|
||||
else if (match(_xor)) return {new alu_t(alu_type_t::xorl)};
|
||||
else if (match(_add)) return {new alu_t(alu_type_t::add)};
|
||||
else if (match(_sub)) return {new alu_t(alu_type_t::sub)};
|
||||
else if (match(_ad2)) return {new alu_t(alu_type_t::ad2)};
|
||||
else if (match(_sr )) return {new alu_t(alu_type_t::sr)};
|
||||
else if (match(_rr )) return {new alu_t(alu_type_t::rr)};
|
||||
else if (match(_sl )) return {new alu_t(alu_type_t::sl)};
|
||||
else if (match(_rl )) return {new alu_t(alu_type_t::rl)};
|
||||
else if (match(_rl8)) return {new alu_t(alu_type_t::rl8)};
|
||||
|
||||
if (match(_and)) return {op_t{std::in_place_type<andl_t>}};
|
||||
else if (match(_or )) return {op_t{std::in_place_type<orl_t>}};
|
||||
else if (match(_xor)) return {op_t{std::in_place_type<xorl_t>}};
|
||||
else if (match(_add)) return {op_t{std::in_place_type<add_t>}};
|
||||
else if (match(_sub)) return {op_t{std::in_place_type<sub_t>}};
|
||||
else if (match(_ad2)) return {op_t{std::in_place_type<ad2_t>}};
|
||||
else if (match(_sr )) return {op_t{std::in_place_type<sr_t>}};
|
||||
else if (match(_rr )) return {op_t{std::in_place_type<rr_t>}};
|
||||
else if (match(_sl )) return {op_t{std::in_place_type<sl_t>}};
|
||||
else if (match(_rl )) return {op_t{std::in_place_type<rl_t>}};
|
||||
else if (match(_rl8)) return {op_t{std::in_place_type<rl8_t>}};
|
||||
else return {};
|
||||
}
|
||||
|
||||
@ -199,41 +200,58 @@ bool parser_t::xyd1_src()
|
||||
return mc || m || al;
|
||||
}
|
||||
|
||||
static op::xy_src_t xy_src(const token_t& token)
|
||||
static op::x_src_t x_src(const token_t& token)
|
||||
{
|
||||
using namespace dsp::op;
|
||||
|
||||
switch (token.type) {
|
||||
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;
|
||||
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 x_src_t::m0;
|
||||
case _m1: return x_src_t::m1;
|
||||
case _m2: return x_src_t::m2;
|
||||
case _m3: return x_src_t::m3;
|
||||
case _mc0: return x_src_t::mc0;
|
||||
case _mc1: return x_src_t::mc1;
|
||||
case _mc2: return x_src_t::mc2;
|
||||
case _mc3: return x_src_t::mc3;
|
||||
default: assert(false); __builtin_unreachable();
|
||||
}
|
||||
}
|
||||
|
||||
std::optional<op::d1_dest_t> parser_t::d1_dest()
|
||||
static op::y_src_t y_src(const token_t& token)
|
||||
{
|
||||
using namespace dsp::op;
|
||||
|
||||
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};
|
||||
else if (match(_lop)) return {d1_dest_t::lop};
|
||||
else if (match(_top)) return {d1_dest_t::top};
|
||||
else if (match(_ct0)) return {d1_dest_t::ct0};
|
||||
else if (match(_ct1)) return {d1_dest_t::ct1};
|
||||
else if (match(_ct2)) return {d1_dest_t::ct2};
|
||||
else if (match(_ct3)) return {d1_dest_t::ct3};
|
||||
switch (token.type) {
|
||||
case _m0: return y_src_t::m0;
|
||||
case _m1: return y_src_t::m1;
|
||||
case _m2: return y_src_t::m2;
|
||||
case _m3: return y_src_t::m3;
|
||||
case _mc0: return y_src_t::mc0;
|
||||
case _mc1: return y_src_t::mc1;
|
||||
case _mc2: return y_src_t::mc2;
|
||||
case _mc3: return y_src_t::mc3;
|
||||
default: assert(false); __builtin_unreachable();
|
||||
}
|
||||
}
|
||||
|
||||
std::optional<op::d1_dst_t> parser_t::d1_dst()
|
||||
{
|
||||
using namespace dsp::op;
|
||||
|
||||
if (match(_mc0)) return {d1_dst_t::mc0};
|
||||
else if (match(_mc1)) return {d1_dst_t::mc1};
|
||||
else if (match(_mc2)) return {d1_dst_t::mc2};
|
||||
else if (match(_mc3)) return {d1_dst_t::mc3};
|
||||
else if (match(_rx)) return {d1_dst_t::rx};
|
||||
else if (match(_pl)) return {d1_dst_t::pl};
|
||||
else if (match(_ra0)) return {d1_dst_t::ra0};
|
||||
else if (match(_wa0)) return {d1_dst_t::wa0};
|
||||
else if (match(_lop)) return {d1_dst_t::lop};
|
||||
else if (match(_top)) return {d1_dst_t::top};
|
||||
else if (match(_ct0)) return {d1_dst_t::ct0};
|
||||
else if (match(_ct1)) return {d1_dst_t::ct1};
|
||||
else if (match(_ct2)) return {d1_dst_t::ct2};
|
||||
else if (match(_ct3)) return {d1_dst_t::ct3};
|
||||
else return {};
|
||||
}
|
||||
|
||||
@ -256,55 +274,60 @@ static op::d1_src_t d1_src(const token_t& token)
|
||||
}
|
||||
}
|
||||
|
||||
std::optional<op::op_t *> parser_t::xyd1_bus()
|
||||
std::optional<op::op_t> parser_t::xyd1_bus()
|
||||
{
|
||||
if (match(_mov)) {
|
||||
if (match(_alu)) {
|
||||
consume(comma, "expected `,` after `mov alu`");
|
||||
consume(_a, "expected `a` after `mov alu,`");
|
||||
return {new op::mov_alu_a_t()};
|
||||
return {op::mov_alu_a_t()};
|
||||
} else if (match(_mul)) {
|
||||
consume(comma, "expected ',' after `mov mul`");
|
||||
consume(_p, "expected 'p' after `mov mul,`");
|
||||
return {new op::mov_mul_p_t()};
|
||||
return {op::mov_mul_p_t()};
|
||||
} else if (xyd1_src()) {
|
||||
const token_t& src_token = previous();
|
||||
consume(comma, "expected `,` after mov src operand");
|
||||
// this is starting to feel a bit ugly...
|
||||
bool d1 = src_token.type == _alh || src_token.type == _alh;
|
||||
if (!d1 && match(_y)) return {new op::mov_ram_y_t(xy_src(src_token))};
|
||||
else if (!d1 && match(_a)) return {new op::mov_ram_a_t(xy_src(src_token))};
|
||||
else if (!d1 && match(_x)) return {new op::mov_ram_x_t(xy_src(src_token))};
|
||||
else if (!d1 && match(_p)) return {new op::mov_ram_p_t(xy_src(src_token))};
|
||||
else if (auto dest_o = d1_dest()) return {new op::mov_ram_d1_t(d1_src(src_token), *dest_o)};
|
||||
if (!d1 && match(_y)) return {op::mov_ram_y_t(y_src(src_token))};
|
||||
else if (!d1 && match(_a)) return {op::mov_ram_a_t(y_src(src_token))};
|
||||
else if (!d1 && match(_x)) return {op::mov_ram_x_t(x_src(src_token))};
|
||||
else if (!d1 && match(_p)) return {op::mov_ram_p_t(x_src(src_token))};
|
||||
else if (auto dst_o = d1_dst()) return {op::mov_ram_d1_t(*dst_o, d1_src(src_token))};
|
||||
else
|
||||
throw error(peek(), "expected x-bus, y-bus, or d-bus destination operand");
|
||||
} else {
|
||||
uimm_t<8> imm = uimm_t<8>(peek(), immediate());
|
||||
consume(comma, "expected `,`");
|
||||
if (auto dest_o = d1_dest())
|
||||
return {new op::mov_imm_d1_t(imm, *dest_o)};
|
||||
if (auto dst_o = d1_dst())
|
||||
return {op::mov_imm_d1_t(imm, *dst_o)};
|
||||
else
|
||||
throw error(peek(), "expected d1 destination operand");
|
||||
}
|
||||
} else if (match(_clr)) {
|
||||
consume(_a, "expected `a` after `clr`");
|
||||
return {new op::clr_a_t()};
|
||||
return {op::clr_a_t()};
|
||||
} else {
|
||||
return {};
|
||||
}
|
||||
}
|
||||
|
||||
static uint32_t op_mask(const op::op_t& op)
|
||||
{
|
||||
return std::visit([](auto&& arg) -> uint32_t { return arg.mask(); }, op);
|
||||
}
|
||||
|
||||
std::optional<stmt_t *> parser_t::op()
|
||||
{
|
||||
bool saw_nop = false;
|
||||
std::vector<const op::op_t *> ops;
|
||||
std::vector<op::op_t> ops;
|
||||
std::vector<const token_t *> tokens;
|
||||
|
||||
auto emplace_op = [&](const token_t& token, const op::op_t * a) {
|
||||
for (std::vector<const op::op_t *>::size_type i = 0; i < ops.size(); i++) {
|
||||
const op::op_t * b = ops[i];
|
||||
if ((a->mask() & b->mask() & ~(0b11 << 30)) != 0) {
|
||||
auto emplace_op = [&](const token_t& token, const op::op_t& a) {
|
||||
for (decltype(ops)::size_type i = 0; i < ops.size(); i++) {
|
||||
const op::op_t& b = ops[i];
|
||||
if ((op_mask(a) & op_mask(b)) != 0) {
|
||||
dsp::error(*tokens[i], "conflict");
|
||||
throw error(token, "conflict");
|
||||
}
|
||||
@ -319,7 +342,7 @@ std::optional<stmt_t *> parser_t::op()
|
||||
if (match(_nop)) saw_nop = 1;
|
||||
else if (auto op_o = alu() ) emplace_op(token, *op_o);
|
||||
else if (auto op_o = xyd1_bus()) emplace_op(token, *op_o);
|
||||
else break;
|
||||
else break;
|
||||
}
|
||||
if (ops.size() != 0 || saw_nop)
|
||||
return {new op::control_word_t(ops)};
|
||||
@ -327,20 +350,20 @@ std::optional<stmt_t *> parser_t::op()
|
||||
return {};
|
||||
}
|
||||
|
||||
load::dest_t parser_t::load_dest()
|
||||
load::dst_t parser_t::load_dst()
|
||||
{
|
||||
using namespace dsp::load;
|
||||
|
||||
if (match(_mc0)) return dest_t::mc0;
|
||||
else if (match(_mc1)) return dest_t::mc1;
|
||||
else if (match(_mc2)) return dest_t::mc2;
|
||||
else if (match(_mc3)) return dest_t::mc3;
|
||||
else if (match(_rx)) return dest_t::rx;
|
||||
else if (match(_pl)) return dest_t::pl;
|
||||
else if (match(_ra0)) return dest_t::ra0;
|
||||
else if (match(_wa0)) return dest_t::wa0;
|
||||
else if (match(_lop)) return dest_t::lop;
|
||||
else if (match(_pc)) return dest_t::pc;
|
||||
if (match(_mc0)) return dst_t::mc0;
|
||||
else if (match(_mc1)) return dst_t::mc1;
|
||||
else if (match(_mc2)) return dst_t::mc2;
|
||||
else if (match(_mc3)) return dst_t::mc3;
|
||||
else if (match(_rx)) return dst_t::rx;
|
||||
else if (match(_pl)) return dst_t::pl;
|
||||
else if (match(_ra0)) return dst_t::ra0;
|
||||
else if (match(_wa0)) return dst_t::wa0;
|
||||
else if (match(_lop)) return dst_t::lop;
|
||||
else if (match(_pc)) return dst_t::pc;
|
||||
else
|
||||
throw error(peek(), "expected mvi destination");
|
||||
}
|
||||
@ -371,14 +394,14 @@ std::optional<stmt_t *> parser_t::load()
|
||||
const token_t& expr_token = peek();
|
||||
expr_t * expr = immediate();
|
||||
consume(comma, "expected `,`");
|
||||
load::dest_t dest = parser_t::load_dest();
|
||||
load::dst_t dst = parser_t::load_dst();
|
||||
if (match(comma)) {
|
||||
load::cond_t cond = load_cond();
|
||||
uimm_t<19> imm = uimm_t<19>(expr_token, expr);
|
||||
return {new load::mvi_cond_t(imm, dest, cond)};
|
||||
return {new load::mvi_cond_t(imm, dst, cond)};
|
||||
} else {
|
||||
uimm_t<25> imm = uimm_t<25>(expr_token, expr);
|
||||
return {new load::mvi_t(imm, dest)};
|
||||
return {new load::mvi_t(imm, dst)};
|
||||
}
|
||||
} else
|
||||
return {};
|
||||
@ -434,29 +457,29 @@ static bool dma_hold_p(const token_t& token)
|
||||
}
|
||||
}
|
||||
|
||||
static dma::add_mode_t dma_add(const token_t& token)
|
||||
static dma::add_t dma_add(const token_t& token)
|
||||
{
|
||||
using namespace dsp::dma;
|
||||
|
||||
switch (token.type) {
|
||||
case _dma: [[fallthrough]];
|
||||
case _dmah: return add_mode_t::_2;
|
||||
case _dmah: return add_t::_2;
|
||||
case _dma0: [[fallthrough]];
|
||||
case _dmah0: return add_mode_t::_0;
|
||||
case _dmah0: return add_t::_0;
|
||||
case _dma1: [[fallthrough]];
|
||||
case _dmah1: return add_mode_t::_1;
|
||||
case _dmah1: return add_t::_1;
|
||||
case _dma2: [[fallthrough]];
|
||||
case _dmah2: return add_mode_t::_2;
|
||||
case _dmah2: return add_t::_2;
|
||||
case _dma4: [[fallthrough]];
|
||||
case _dmah4: return add_mode_t::_4;
|
||||
case _dmah4: return add_t::_4;
|
||||
case _dma8: [[fallthrough]];
|
||||
case _dmah8: return add_mode_t::_8;
|
||||
case _dmah8: return add_t::_8;
|
||||
case _dma16: [[fallthrough]];
|
||||
case _dmah16: return add_mode_t::_16;
|
||||
case _dmah16: return add_t::_16;
|
||||
case _dma32: [[fallthrough]];
|
||||
case _dmah32: return add_mode_t::_32;
|
||||
case _dmah32: return add_t::_32;
|
||||
case _dma64: [[fallthrough]];
|
||||
case _dmah64: return add_mode_t::_64;
|
||||
case _dmah64: return add_t::_64;
|
||||
default: assert(false);
|
||||
}
|
||||
}
|
||||
@ -486,18 +509,18 @@ dma::dst_t parser_t::dma_dst()
|
||||
}
|
||||
}
|
||||
|
||||
std::optional<dma::length_ram_t> parser_t::dma_length_ram()
|
||||
std::optional<dma::ram_t> parser_t::dma_ram()
|
||||
{
|
||||
using namespace dsp::dma;
|
||||
|
||||
if (match(_m0)) return length_ram_t::m0;
|
||||
else if (match(_m1)) return length_ram_t::m1;
|
||||
else if (match(_m2)) return length_ram_t::m2;
|
||||
else if (match(_m3)) return length_ram_t::m3;
|
||||
else if (match(_mc0)) return length_ram_t::mc0;
|
||||
else if (match(_mc1)) return length_ram_t::mc1;
|
||||
else if (match(_mc2)) return length_ram_t::mc2;
|
||||
else if (match(_mc3)) return length_ram_t::mc3;
|
||||
if (match(_m0)) return ram_t::m0;
|
||||
else if (match(_m1)) return ram_t::m1;
|
||||
else if (match(_m2)) return ram_t::m2;
|
||||
else if (match(_m3)) return ram_t::m3;
|
||||
else if (match(_mc0)) return ram_t::mc0;
|
||||
else if (match(_mc1)) return ram_t::mc1;
|
||||
else if (match(_mc2)) return ram_t::mc2;
|
||||
else if (match(_mc3)) return ram_t::mc3;
|
||||
else return {};
|
||||
}
|
||||
|
||||
@ -506,27 +529,27 @@ std::optional<stmt_t *> parser_t::dma()
|
||||
if (dma_p(peek())) {
|
||||
const token_t& token = advance();
|
||||
bool hold = dma_hold_p(token);
|
||||
dma::add_mode_t add = dma_add(token);
|
||||
dma::add_t add = dma_add(token);
|
||||
if (match(_d0)) {
|
||||
consume(comma, "expected `,`");
|
||||
dma::dst_t dst = dma_dst();
|
||||
consume(comma, "expected `,`");
|
||||
if (auto length_ram_o = dma_length_ram()) {
|
||||
return {new dma::d0_dst_ram_t(hold, add, dst, *length_ram_o)};
|
||||
if (auto ram_o = dma_ram()) {
|
||||
return {new dma::d0_dst_ram_t(add, hold, dst, *ram_o)};
|
||||
} else {
|
||||
uimm_t<8> imm = uimm_t<8>(peek(), immediate());
|
||||
return {new dma::d0_dst_imm_t(hold, add, dst, imm)};
|
||||
return {new dma::d0_dst_imm_t(imm, add, hold, dst)};
|
||||
}
|
||||
} else {
|
||||
dma::src_t src = dma_src();
|
||||
consume(comma, "expected `,`");
|
||||
consume(_d0, "expected `d0`");
|
||||
consume(comma, "expected `,`");
|
||||
if (auto length_ram_o = dma_length_ram()) {
|
||||
return {new dma::src_d0_ram_t(hold, add, src, *length_ram_o)};
|
||||
if (auto ram_o = dma_ram()) {
|
||||
return {new dma::src_d0_ram_t(add, hold, src, *ram_o)};
|
||||
} else {
|
||||
uimm_t<8> imm = uimm_t<8>(peek(), immediate());
|
||||
return {new dma::src_d0_imm_t(hold, add, src, imm)};
|
||||
return {new dma::src_d0_imm_t(imm, add, hold, src)};
|
||||
}
|
||||
}
|
||||
} else
|
||||
@ -555,10 +578,10 @@ std::optional<stmt_t *> parser_t::jump()
|
||||
if (match(_jmp)) {
|
||||
if (auto cond_o = jump_cond()) {
|
||||
consume(comma, "expected `,` after jump condition");
|
||||
uimm_t<8> imm = uimm_t<8>(peek(), immediate());
|
||||
return {new jump::jmp_cond_t(*cond_o, imm)};
|
||||
uimm_t<19> imm = uimm_t<19>(peek(), immediate());
|
||||
return {new jump::jmp_cond_t(imm, *cond_o)};
|
||||
} else {
|
||||
uimm_t<8> imm = uimm_t<8>(peek(), immediate());
|
||||
uimm_t<25> imm = uimm_t<25>(peek(), immediate());
|
||||
return {new jump::jmp_t(imm)};
|
||||
}
|
||||
} else
|
||||
|
12
parser.hpp
12
parser.hpp
@ -6,6 +6,8 @@
|
||||
#include "token.hpp"
|
||||
#include "expr.hpp"
|
||||
#include "stmt.hpp"
|
||||
#include "stmt_ins.hpp"
|
||||
#include "control_word.hpp"
|
||||
|
||||
namespace dsp {
|
||||
|
||||
@ -49,17 +51,17 @@ struct parser_t
|
||||
expr_t * orl();
|
||||
expr_t * primary();
|
||||
|
||||
std::optional<op::op_t *> alu();
|
||||
std::optional<op::op_t> alu();
|
||||
bool xyd1_src();
|
||||
std::optional<op::d1_dest_t> d1_dest();
|
||||
std::optional<op::op_t *> xyd1_bus();
|
||||
std::optional<op::d1_dst_t> d1_dst();
|
||||
std::optional<op::op_t> xyd1_bus();
|
||||
std::optional<stmt_t *> op();
|
||||
load::dest_t load_dest();
|
||||
load::dst_t load_dst();
|
||||
load::cond_t load_cond();
|
||||
std::optional<stmt_t *> load();
|
||||
dma::src_t dma_src();
|
||||
dma::dst_t dma_dst();
|
||||
std::optional<dma::length_ram_t> dma_length_ram();
|
||||
std::optional<dma::ram_t> dma_ram();
|
||||
std::optional<stmt_t *> dma();
|
||||
std::optional<jump::cond_t> jump_cond();
|
||||
std::optional<stmt_t *> jump();
|
||||
|
387
stmt.hpp
387
stmt.hpp
@ -1,393 +1,30 @@
|
||||
#pragma once
|
||||
|
||||
#include <vector>
|
||||
#include <string>
|
||||
#include <cstdint>
|
||||
|
||||
#include "stmt_enum.hpp"
|
||||
#include "expr.hpp"
|
||||
#include "bits.hpp"
|
||||
#include "ins.hpp"
|
||||
#include "stmt_base.hpp"
|
||||
|
||||
namespace dsp {
|
||||
|
||||
struct stmt_t
|
||||
{
|
||||
virtual void accept(visitor_t<void> const * visitor) const = 0;
|
||||
virtual uint32_t accept(visitor_t<uint32_t> const * visitor) const = 0;
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
struct stmt_accept_t : stmt_t {
|
||||
virtual void accept(visitor_t<void> const * visitor) const {
|
||||
return visitor->visit(static_cast<const T*>(this));
|
||||
}
|
||||
|
||||
virtual uint32_t accept(visitor_t<uint32_t> const * visitor) const
|
||||
{
|
||||
return visitor->visit(static_cast<const T*>(this));
|
||||
}
|
||||
};
|
||||
|
||||
template <bool S, int N>
|
||||
struct imm_t {
|
||||
imm_t(const token_t& token, const expr_t * expr)
|
||||
: token(token), expr(expr) {}
|
||||
|
||||
const token_t& token;
|
||||
const expr_t * expr;
|
||||
|
||||
static constexpr bool sign = S;
|
||||
static constexpr int bits = N;
|
||||
static constexpr num_t max = (1L << (bits - static_cast<num_t>(sign))) - 1;
|
||||
static constexpr num_t min = sign ? -(max + 1) : 0;
|
||||
|
||||
num_t normalize(num_t value) const
|
||||
{
|
||||
if (!S && value > 2147483648) { // fixme: hack
|
||||
return value & max;
|
||||
} else {
|
||||
return value;
|
||||
}
|
||||
}
|
||||
|
||||
bool in_range(num_t value) const
|
||||
{
|
||||
return value <= max && value >= min;
|
||||
}
|
||||
};
|
||||
|
||||
template <int N>
|
||||
using simm_t = imm_t<true, N>;
|
||||
|
||||
template <int N>
|
||||
using uimm_t = imm_t<false, N>;
|
||||
|
||||
namespace op {
|
||||
|
||||
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<alu_t>
|
||||
{
|
||||
alu_t(alu_type_t type)
|
||||
: type(type) {}
|
||||
|
||||
const alu_type_t type;
|
||||
|
||||
uint32_t mask() const { return 0b1111 << 26; }
|
||||
uint32_t code() const { return 0b0000 << 26; }
|
||||
uint32_t bits() const { return alu_bits(type); }
|
||||
};
|
||||
|
||||
struct mov_ram_x_t : op_t, stmt_accept_t<mov_ram_x_t>
|
||||
{
|
||||
mov_ram_x_t(xy_src_t src)
|
||||
: src(src) {}
|
||||
|
||||
const xy_src_t src;
|
||||
|
||||
uint32_t mask() const { return 0b100'111 << 20; }
|
||||
uint32_t code() const { return 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>
|
||||
{
|
||||
mov_mul_p_t() {}
|
||||
|
||||
uint32_t mask() const { return 0b011'000 << 20; }
|
||||
uint32_t code() const { return 0b010'000 << 20; }
|
||||
uint32_t bits() const { return 0; }
|
||||
};
|
||||
|
||||
struct mov_ram_p_t : op_t, stmt_accept_t<mov_ram_p_t>
|
||||
{
|
||||
mov_ram_p_t(xy_src_t src)
|
||||
: src(src) {}
|
||||
|
||||
const xy_src_t src;
|
||||
|
||||
uint32_t mask() const { return 0b011'111 << 20; }
|
||||
uint32_t code() const { return 0b011'000 << 20; }
|
||||
uint32_t bits() const { return xy_src_bits(src, 20); }
|
||||
};
|
||||
|
||||
struct mov_ram_y_t : op_t, stmt_accept_t<mov_ram_y_t>
|
||||
{
|
||||
mov_ram_y_t(xy_src_t src)
|
||||
: src(src) {}
|
||||
|
||||
const xy_src_t src;
|
||||
|
||||
uint32_t mask() const { return 0b100'111 << 14; }
|
||||
uint32_t code() const { return 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>
|
||||
{
|
||||
clr_a_t() {}
|
||||
|
||||
uint32_t mask() const { return 0b011'000 << 14; }
|
||||
uint32_t code() const { return 0b001'000 << 14; }
|
||||
uint32_t bits() const { return 0; }
|
||||
};
|
||||
|
||||
struct mov_alu_a_t : op_t, stmt_accept_t<mov_alu_a_t>
|
||||
{
|
||||
mov_alu_a_t() {}
|
||||
|
||||
uint32_t mask() const { return 0b011'000 << 14; }
|
||||
uint32_t code() const { return 0b010'000 << 14; }
|
||||
uint32_t bits() const { return 0; }
|
||||
};
|
||||
|
||||
struct mov_ram_a_t : op_t, stmt_accept_t<mov_ram_a_t>
|
||||
{
|
||||
mov_ram_a_t(xy_src_t src)
|
||||
: src(src) {}
|
||||
|
||||
const xy_src_t src;
|
||||
|
||||
uint32_t mask() const { return 0b011'111 << 14; }
|
||||
uint32_t code() const { return 0b011'000 << 14; }
|
||||
uint32_t bits() const { return xy_src_bits(src, 14); }
|
||||
};
|
||||
|
||||
struct mov_imm_d1_t : op_t, stmt_accept_t<mov_imm_d1_t>
|
||||
{
|
||||
mov_imm_d1_t(uimm_t<8> imm, d1_dest_t dest)
|
||||
: imm(imm), dest(dest) {}
|
||||
|
||||
const uimm_t<8> imm;
|
||||
const d1_dest_t dest;
|
||||
|
||||
uint32_t mask() const { return 0b11'1111'1111'1111 << 0; }
|
||||
uint32_t code() const { return 0b01'0000'0000'0000 << 0; }
|
||||
uint32_t bits() const { return d1_dest_bits(dest); }
|
||||
};
|
||||
|
||||
struct mov_ram_d1_t : op_t, stmt_accept_t<mov_ram_d1_t>
|
||||
{
|
||||
mov_ram_d1_t(d1_src_t src, d1_dest_t dest)
|
||||
: src(src), dest(dest) {}
|
||||
|
||||
const d1_src_t src;
|
||||
const d1_dest_t dest;
|
||||
|
||||
uint32_t mask() const { return 0b11'1111'0000'1111 << 0; }
|
||||
uint32_t code() const { return 0b11'0000'0000'0000 << 0; }
|
||||
uint32_t bits() const { return d1_dest_bits(dest) | d1_src_bits(src); }
|
||||
};
|
||||
|
||||
struct control_word_t : stmt_accept_t<control_word_t>
|
||||
{
|
||||
control_word_t(std::vector<const op::op_t *> ops)
|
||||
: ops(ops)
|
||||
{
|
||||
}
|
||||
|
||||
const std::vector<const op_t *> ops;
|
||||
|
||||
uint32_t mask() const { return 0b11 << 30; }
|
||||
uint32_t code() const { return 0b00 << 30; }
|
||||
uint32_t bits() const { return 0; }
|
||||
};
|
||||
|
||||
} // op
|
||||
|
||||
namespace load {
|
||||
|
||||
struct mvi_t : stmt_accept_t<mvi_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;
|
||||
};
|
||||
|
||||
struct mvi_cond_t : stmt_accept_t<mvi_cond_t>
|
||||
{
|
||||
mvi_cond_t(uimm_t<19> imm, dest_t dest, cond_t cond)
|
||||
: imm(imm), dest(dest), cond(cond) {}
|
||||
|
||||
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 d0_dst_imm_t : stmt_accept_t<d0_dst_imm_t>
|
||||
{
|
||||
d0_dst_imm_t(bool hold, add_mode_t add, dst_t dst, uimm_t<8> imm)
|
||||
: hold(hold), add(add), dst(dst), imm(imm) {}
|
||||
|
||||
const bool hold;
|
||||
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>
|
||||
{
|
||||
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>
|
||||
{
|
||||
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<src_d0_ram_t>
|
||||
{
|
||||
// from src to d0
|
||||
src_d0_ram_t(bool hold, add_mode_t add, src_t src, length_ram_t ram)
|
||||
: hold(hold), add(add), src(src), ram(ram) {}
|
||||
|
||||
const bool hold;
|
||||
const add_mode_t add;
|
||||
const src_t src;
|
||||
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
|
||||
|
||||
namespace jump
|
||||
{
|
||||
|
||||
struct jmp_t : stmt_accept_t<jmp_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<jmp_cond_t>
|
||||
{
|
||||
jmp_cond_t(cond_t cond, uimm_t<8> imm)
|
||||
: cond(cond), imm(imm) {}
|
||||
|
||||
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
|
||||
|
||||
namespace loop {
|
||||
|
||||
struct btm_t : stmt_accept_t<btm_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<lps_t>
|
||||
{
|
||||
uint32_t mask() const { return 0xffff'ffff; }
|
||||
uint32_t code() const { return 0b1110'1 << 27; }
|
||||
uint32_t bits() const { return 0; }
|
||||
};
|
||||
|
||||
} // loop
|
||||
|
||||
namespace end {
|
||||
|
||||
struct end_t : stmt_accept_t<end_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<endi_t>
|
||||
{
|
||||
uint32_t mask() const { return 0xffff'ffff; }
|
||||
uint32_t code() const { return 0b1111'1 << 27; }
|
||||
uint32_t bits() const { return 0; }
|
||||
};
|
||||
|
||||
} // end
|
||||
|
||||
namespace nop {
|
||||
|
||||
struct nop_t : stmt_accept_t<nop_t>
|
||||
struct nop_t : stmt_accept_t<nop_t>, ins_t<nop_t>
|
||||
{
|
||||
nop_t()
|
||||
{}
|
||||
|
||||
nop_t(uint32_t code)
|
||||
{
|
||||
(void)code;
|
||||
}
|
||||
|
||||
uint32_t mask() const { return 0xffff'ffff; }
|
||||
uint32_t code() const { return 0x0000'0000; }
|
||||
uint32_t bits() const { return 0; }
|
||||
};
|
||||
|
||||
}
|
||||
} // namespace nop
|
||||
|
||||
struct assign_t : stmt_accept_t<assign_t>
|
||||
{
|
||||
|
25
stmt_base.hpp
Normal file
25
stmt_base.hpp
Normal file
@ -0,0 +1,25 @@
|
||||
#pragma once
|
||||
|
||||
#include "visitor.hpp"
|
||||
|
||||
namespace dsp {
|
||||
|
||||
struct stmt_t
|
||||
{
|
||||
virtual void accept(visitor_t<void> const * visitor) const = 0;
|
||||
virtual uint32_t accept(visitor_t<uint32_t> const * visitor) const = 0;
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
struct stmt_accept_t : stmt_t {
|
||||
virtual void accept(visitor_t<void> const * visitor) const {
|
||||
return visitor->visit(static_cast<const T*>(this));
|
||||
}
|
||||
|
||||
virtual uint32_t accept(visitor_t<uint32_t> const * visitor) const
|
||||
{
|
||||
return visitor->visit(static_cast<const T*>(this));
|
||||
}
|
||||
};
|
||||
|
||||
}
|
102
stmt_enum.hpp
102
stmt_enum.hpp
@ -1,102 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
namespace dsp {
|
||||
|
||||
namespace op {
|
||||
|
||||
enum struct alu_type_t : int {
|
||||
andl,
|
||||
orl,
|
||||
xorl,
|
||||
add,
|
||||
sub,
|
||||
ad2,
|
||||
sr,
|
||||
rr,
|
||||
sl,
|
||||
rl,
|
||||
rl8,
|
||||
};
|
||||
|
||||
enum struct xy_src_t {
|
||||
m0 , m1 , m2 , m3 ,
|
||||
mc0, mc1, mc2, mc3,
|
||||
};
|
||||
|
||||
enum struct d1_dest_t {
|
||||
mc0, mc1, mc2, mc3,
|
||||
rx , pl ,
|
||||
ra0, wa0,
|
||||
lop, top,
|
||||
ct0, ct1, ct2, ct3,
|
||||
};
|
||||
|
||||
enum struct d1_src_t {
|
||||
m0 , m1 , m2 , m3 ,
|
||||
mc0, mc1, mc2, mc3,
|
||||
all, alh,
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
namespace load {
|
||||
|
||||
enum struct dest_t {
|
||||
mc0, mc1, mc2, mc3,
|
||||
rx , pl ,
|
||||
ra0, wa0,
|
||||
lop, pc ,
|
||||
};
|
||||
|
||||
enum struct cond_t {
|
||||
z , nz ,
|
||||
s , ns ,
|
||||
c , nc ,
|
||||
t0, nt0,
|
||||
zs, nzs,
|
||||
};
|
||||
|
||||
} // load
|
||||
|
||||
namespace dma {
|
||||
|
||||
enum struct add_mode_t {
|
||||
_0 ,
|
||||
_1 ,
|
||||
_2 ,
|
||||
_4 ,
|
||||
_8 ,
|
||||
_16,
|
||||
_32,
|
||||
_64,
|
||||
};
|
||||
|
||||
enum struct src_t {
|
||||
mc0, mc1, mc2, mc3,
|
||||
};
|
||||
|
||||
enum struct dst_t {
|
||||
mc0, mc1, mc2, mc3,
|
||||
prg,
|
||||
};
|
||||
|
||||
enum struct length_ram_t {
|
||||
m0 , m1 , m2 , m3 ,
|
||||
mc0, mc1, mc2, mc3,
|
||||
};
|
||||
|
||||
} // dma
|
||||
|
||||
namespace jump {
|
||||
|
||||
enum struct cond_t {
|
||||
z , nz ,
|
||||
s , ns ,
|
||||
c , nc ,
|
||||
t0, nt0,
|
||||
zs, nzs,
|
||||
};
|
||||
|
||||
} // jump
|
||||
|
||||
}
|
1264
stmt_ins.hpp
Normal file
1264
stmt_ins.hpp
Normal file
File diff suppressed because it is too large
Load Diff
125
stmt_string.cpp
125
stmt_string.cpp
@ -1,5 +1,5 @@
|
||||
#include "stmt_string.hpp"
|
||||
#include "stmt_enum.hpp"
|
||||
#include "stmt_ins.hpp"
|
||||
|
||||
#define i(v) (static_cast<int>(v))
|
||||
|
||||
@ -7,46 +7,43 @@ namespace dsp {
|
||||
|
||||
namespace op {
|
||||
|
||||
const std::string alu_type_string[] = {
|
||||
[i(alu_type_t::andl)] = "andl",
|
||||
[i(alu_type_t::orl )] = "orl",
|
||||
[i(alu_type_t::xorl)] = "xorl",
|
||||
[i(alu_type_t::add )] = "add",
|
||||
[i(alu_type_t::sub )] = "sub",
|
||||
[i(alu_type_t::ad2 )] = "ad2",
|
||||
[i(alu_type_t::sr )] = "sr",
|
||||
[i(alu_type_t::rr )] = "rr",
|
||||
[i(alu_type_t::sl )] = "sl",
|
||||
[i(alu_type_t::rl )] = "rl",
|
||||
[i(alu_type_t::rl8 )] = "rl8",
|
||||
const std::string x_src_string[] = {
|
||||
[i(x_src_t::m0 )] = "m0" ,
|
||||
[i(x_src_t::m1 )] = "m1" ,
|
||||
[i(x_src_t::m2 )] = "m2" ,
|
||||
[i(x_src_t::m3 )] = "m3" ,
|
||||
[i(x_src_t::mc0)] = "mc0",
|
||||
[i(x_src_t::mc1)] = "mc1",
|
||||
[i(x_src_t::mc2)] = "mc2",
|
||||
[i(x_src_t::mc3)] = "mc3",
|
||||
};
|
||||
|
||||
const std::string xy_src_string[] = {
|
||||
[i(xy_src_t::m0 )] = "m0" ,
|
||||
[i(xy_src_t::m1 )] = "m1" ,
|
||||
[i(xy_src_t::m2 )] = "m2" ,
|
||||
[i(xy_src_t::m3 )] = "m3" ,
|
||||
[i(xy_src_t::mc0)] = "mc0",
|
||||
[i(xy_src_t::mc1)] = "mc1",
|
||||
[i(xy_src_t::mc2)] = "mc2",
|
||||
[i(xy_src_t::mc3)] = "mc3",
|
||||
const std::string y_src_string[] = {
|
||||
[i(y_src_t::m0 )] = "m0" ,
|
||||
[i(y_src_t::m1 )] = "m1" ,
|
||||
[i(y_src_t::m2 )] = "m2" ,
|
||||
[i(y_src_t::m3 )] = "m3" ,
|
||||
[i(y_src_t::mc0)] = "mc0",
|
||||
[i(y_src_t::mc1)] = "mc1",
|
||||
[i(y_src_t::mc2)] = "mc2",
|
||||
[i(y_src_t::mc3)] = "mc3",
|
||||
};
|
||||
|
||||
const std::string d1_dest_string[] = {
|
||||
[i(d1_dest_t::mc0)] = "mc0",
|
||||
[i(d1_dest_t::mc1)] = "mc1",
|
||||
[i(d1_dest_t::mc2)] = "mc2",
|
||||
[i(d1_dest_t::mc3)] = "mc3",
|
||||
[i(d1_dest_t::rx )] = "rx" ,
|
||||
[i(d1_dest_t::pl )] = "pl" ,
|
||||
[i(d1_dest_t::ra0)] = "ra0",
|
||||
[i(d1_dest_t::wa0)] = "wa0",
|
||||
[i(d1_dest_t::lop)] = "lop",
|
||||
[i(d1_dest_t::top)] = "top",
|
||||
[i(d1_dest_t::ct0)] = "ct0",
|
||||
[i(d1_dest_t::ct1)] = "ct1",
|
||||
[i(d1_dest_t::ct2)] = "ct2",
|
||||
[i(d1_dest_t::ct3)] = "ct3",
|
||||
const std::string d1_dst_string[] = {
|
||||
[i(d1_dst_t::mc0)] = "mc0",
|
||||
[i(d1_dst_t::mc1)] = "mc1",
|
||||
[i(d1_dst_t::mc2)] = "mc2",
|
||||
[i(d1_dst_t::mc3)] = "mc3",
|
||||
[i(d1_dst_t::rx )] = "rx" ,
|
||||
[i(d1_dst_t::pl )] = "pl" ,
|
||||
[i(d1_dst_t::ra0)] = "ra0",
|
||||
[i(d1_dst_t::wa0)] = "wa0",
|
||||
[i(d1_dst_t::lop)] = "lop",
|
||||
[i(d1_dst_t::top)] = "top",
|
||||
[i(d1_dst_t::ct0)] = "ct0",
|
||||
[i(d1_dst_t::ct1)] = "ct1",
|
||||
[i(d1_dst_t::ct2)] = "ct2",
|
||||
[i(d1_dst_t::ct3)] = "ct3",
|
||||
};
|
||||
|
||||
const std::string d1_src_string[] = {
|
||||
@ -66,17 +63,17 @@ const std::string d1_src_string[] = {
|
||||
|
||||
namespace load {
|
||||
|
||||
const std::string dest_string[] = {
|
||||
[i(dest_t::mc0)] = "mc0",
|
||||
[i(dest_t::mc1)] = "mc1",
|
||||
[i(dest_t::mc2)] = "mc2",
|
||||
[i(dest_t::mc3)] = "mc3",
|
||||
[i(dest_t::rx )] = "rx" ,
|
||||
[i(dest_t::pl )] = "pl" ,
|
||||
[i(dest_t::ra0)] = "ra0",
|
||||
[i(dest_t::wa0)] = "wa0",
|
||||
[i(dest_t::lop)] = "lop",
|
||||
[i(dest_t::pc )] = "pc" ,
|
||||
const std::string dst_string[] = {
|
||||
[i(dst_t::mc0)] = "mc0",
|
||||
[i(dst_t::mc1)] = "mc1",
|
||||
[i(dst_t::mc2)] = "mc2",
|
||||
[i(dst_t::mc3)] = "mc3",
|
||||
[i(dst_t::rx )] = "rx" ,
|
||||
[i(dst_t::pl )] = "pl" ,
|
||||
[i(dst_t::ra0)] = "ra0",
|
||||
[i(dst_t::wa0)] = "wa0",
|
||||
[i(dst_t::lop)] = "lop",
|
||||
[i(dst_t::pc )] = "pc" ,
|
||||
};
|
||||
|
||||
const std::string cond_string[] = {
|
||||
@ -102,14 +99,14 @@ const std::string hold_mode_string[] = {
|
||||
};
|
||||
|
||||
const std::string add_mode_string[] = {
|
||||
[i(add_mode_t::_0 )] = "0" ,
|
||||
[i(add_mode_t::_1 )] = "1" ,
|
||||
[i(add_mode_t::_2 )] = "2" ,
|
||||
[i(add_mode_t::_4 )] = "4" ,
|
||||
[i(add_mode_t::_8 )] = "8" ,
|
||||
[i(add_mode_t::_16)] = "16",
|
||||
[i(add_mode_t::_32)] = "32",
|
||||
[i(add_mode_t::_64)] = "64",
|
||||
[i(add_t::_0 )] = "0" ,
|
||||
[i(add_t::_1 )] = "1" ,
|
||||
[i(add_t::_2 )] = "2" ,
|
||||
[i(add_t::_4 )] = "4" ,
|
||||
[i(add_t::_8 )] = "8" ,
|
||||
[i(add_t::_16)] = "16",
|
||||
[i(add_t::_32)] = "32",
|
||||
[i(add_t::_64)] = "64",
|
||||
};
|
||||
|
||||
const std::string src_string[] = {
|
||||
@ -128,14 +125,14 @@ const std::string dst_string[] = {
|
||||
};
|
||||
|
||||
const std::string length_ram_string[] = {
|
||||
[i(length_ram_t::m0 )] = "m0" ,
|
||||
[i(length_ram_t::m1 )] = "m1" ,
|
||||
[i(length_ram_t::m2 )] = "m2" ,
|
||||
[i(length_ram_t::m3 )] = "m3" ,
|
||||
[i(length_ram_t::mc0)] = "mc0",
|
||||
[i(length_ram_t::mc1)] = "mc1",
|
||||
[i(length_ram_t::mc2)] = "mc2",
|
||||
[i(length_ram_t::mc3)] = "mc3",
|
||||
[i(ram_t::m0 )] = "m0" ,
|
||||
[i(ram_t::m1 )] = "m1" ,
|
||||
[i(ram_t::m2 )] = "m2" ,
|
||||
[i(ram_t::m3 )] = "m3" ,
|
||||
[i(ram_t::mc0)] = "mc0",
|
||||
[i(ram_t::mc1)] = "mc1",
|
||||
[i(ram_t::mc2)] = "mc2",
|
||||
[i(ram_t::mc3)] = "mc3",
|
||||
};
|
||||
|
||||
} // dma
|
||||
|
@ -7,15 +7,16 @@ namespace dsp {
|
||||
namespace op {
|
||||
|
||||
extern const std::string alu_type_string[];
|
||||
extern const std::string xy_src_string[];
|
||||
extern const std::string d1_dest_string[];
|
||||
extern const std::string x_src_string[];
|
||||
extern const std::string y_src_string[];
|
||||
extern const std::string d1_dst_string[];
|
||||
extern const std::string d1_src_string[];
|
||||
|
||||
}
|
||||
|
||||
namespace load {
|
||||
|
||||
extern const std::string dest_string[];
|
||||
extern const std::string dst_string[];
|
||||
extern const std::string cond_string[];
|
||||
|
||||
} // load
|
||||
|
@ -4,12 +4,16 @@ SRC = sample1.asm sample2a.asm sample2b.asm sample3.asm
|
||||
#SRC += cmpnm.asm fbtrans.asm loop_pr.asm udiv.asm
|
||||
EXPECT = $(patsubst %.asm,expect/%.bin,$(SRC))
|
||||
ACTUAL = $(patsubst %.asm,actual/%.bin,$(SRC))
|
||||
EXPECT_TXT = $(patsubst %.bin,%.txt,$(EXPECT))
|
||||
ACTUAL_TXT = $(patsubst %.bin,%.txt,$(ACTUAL))
|
||||
ALL = $(EXPECT) $(ACTUAL)
|
||||
ALL_TXT = $(patsubst %.bin,%.txt,$(ALL))
|
||||
ALL_TXT = $(EXPECT_TXT) $(ACTUAL_TXT)
|
||||
|
||||
all: $(ALL)
|
||||
all-expect: $(EXPECT)
|
||||
all-actual: $(ACTUAL)
|
||||
expect: $(EXPECT)
|
||||
actual: $(ACTUAL)
|
||||
expect-txt: $(EXPECT_TXT)
|
||||
actual-txt: $(ACTUAL_TXT)
|
||||
all-txt: $(ALL_TXT)
|
||||
|
||||
%.s: %.asm
|
||||
@ -35,7 +39,7 @@ expect/%.bin: %.s
|
||||
@mkdir -p $(dir $@)
|
||||
srec_cat -Output $@ -Binary $<
|
||||
|
||||
actual/%.bin: %.asm
|
||||
actual/%.bin: %.asm ../scu-dsp-asm
|
||||
@mkdir -p $(dir $@)
|
||||
../scu-dsp-asm $< $@
|
||||
|
||||
|
@ -64,7 +64,9 @@ struct token_t {
|
||||
const std::string_view lexeme;
|
||||
const literal_t literal;
|
||||
|
||||
token_t() = delete;
|
||||
constexpr token_t()
|
||||
: pos({0, 0}), type(type_t::number), lexeme(""), literal({})
|
||||
{ }
|
||||
|
||||
constexpr token_t(token_pos_t pos, type_t type, const std::string_view lexeme, num_type number)
|
||||
: pos(pos), type(type), lexeme(lexeme), literal(number)
|
||||
|
@ -11,7 +11,18 @@ struct unary_t;
|
||||
|
||||
// instructions
|
||||
namespace op {
|
||||
struct alu_t;
|
||||
struct andl_t;
|
||||
struct orl_t;
|
||||
struct xorl_t;
|
||||
struct add_t;
|
||||
struct sub_t;
|
||||
struct ad2_t;
|
||||
struct sr_t;
|
||||
struct rr_t;
|
||||
struct sl_t;
|
||||
struct rl_t;
|
||||
struct rl8_t;
|
||||
|
||||
struct mov_ram_x_t;
|
||||
struct mov_ram_x_t;
|
||||
struct mov_mul_p_t;
|
||||
@ -22,6 +33,7 @@ struct mov_alu_a_t;
|
||||
struct mov_ram_a_t;
|
||||
struct mov_imm_d1_t;
|
||||
struct mov_ram_d1_t;
|
||||
|
||||
struct control_word_t;
|
||||
}
|
||||
|
||||
|
14
visitor.hpp
14
visitor.hpp
@ -14,7 +14,18 @@ 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 * alu) const = 0;
|
||||
virtual T visit(const op::andl_t * andl) const = 0;
|
||||
virtual T visit(const op::orl_t * orl) const = 0;
|
||||
virtual T visit(const op::xorl_t * xorl) const = 0;
|
||||
virtual T visit(const op::add_t * add) const = 0;
|
||||
virtual T visit(const op::sub_t * sub) const = 0;
|
||||
virtual T visit(const op::ad2_t * ad2) const = 0;
|
||||
virtual T visit(const op::sr_t * sr) const = 0;
|
||||
virtual T visit(const op::rr_t * rr) const = 0;
|
||||
virtual T visit(const op::sl_t * sl) const = 0;
|
||||
virtual T visit(const op::rl_t * rl) const = 0;
|
||||
virtual T visit(const op::rl8_t * rl8) 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;
|
||||
@ -24,6 +35,7 @@ struct visitor_t
|
||||
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_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;
|
||||
|
Loading…
x
Reference in New Issue
Block a user