| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396 |
- /*
- * Copyright (c) 2020 Raspberry Pi (Trading) Ltd.
- *
- * SPDX-License-Identifier: BSD-3-Clause
- */
- #ifndef _PIO_TYPES_H
- #define _PIO_TYPES_H
- #include <string>
- #include <map>
- #include <set>
- #include <utility>
- #include <vector>
- #include <memory>
- #include "location.h"
- typedef unsigned int uint;
- enum struct inst_type {
- jmp = 0x0,
- wait = 0x1,
- in = 0x2,
- out = 0x3,
- push_pull = 0x4,
- mov = 0x5,
- irq = 0x6,
- set = 0x7,
- };
- /* condition codes */
- enum struct condition {
- al = 0x0,
- xz = 0x1,
- xnz__ = 0x2,
- yz = 0x3,
- ynz__ = 0x4,
- xney = 0x5,
- pin = 0x6,
- osrez = 0x7,
- };
- /* in source / out / set target - not all valid */
- enum struct in_out_set {
- in_out_set_pins = 0x0,
- in_out_set_x = 0x1,
- in_out_set_y = 0x2,
- in_out_null = 0x3,
- in_out_set_pindirs = 0x4,
- in_status = 0x5,
- out_set_pc = 0x5,
- in_out_isr = 0x6,
- in_osr = 0x7,
- out_exec = 0x7,
- };
- enum struct irq {
- set = 0x0,
- set_wait = 0x1,
- clear = 0x2,
- };
- // mov src/dest (not all valid)
- enum struct mov {
- pins = 0x0,
- x = 0x1,
- y = 0x2,
- null = 0x3,
- exec = 0x4,
- pc = 0x5,
- status = 0x5,
- isr = 0x6,
- osr = 0x7,
- };
- enum struct mov_op {
- none = 0x0,
- invert = 0x1,
- bit_reverse = 0x2,
- };
- struct src_item {
- yy::location location;
- src_item() = default;
- explicit src_item(const yy::location &location) : location(location) {}
- };
- struct program;
- struct pio_assembler;
- struct resolvable : public src_item {
- resolvable(const yy::location &l) : src_item(l) {}
- int resolve(const program &program);
- int resolve(pio_assembler *pioasm, const program *program) {
- return resolve(pioasm, program, *this);
- }
- virtual int resolve(pio_assembler *pioasm, const program *program, const resolvable &scope) = 0;
- };
- using rvalue = std::shared_ptr<resolvable>;
- struct wait_source {
- enum type {
- gpio = 0x0,
- pin = 0x1,
- irq = 0x2
- } target;
- rvalue param;
- bool flag;
- wait_source(type target, rvalue param, bool flag = false) : target(target), param(std::move(param)), flag(flag) {}
- };
- struct name_ref : public resolvable {
- std::string name;
- name_ref(const yy::location &l, std::string name) : resolvable(l), name(std::move(name)) {}
- int resolve(pio_assembler *pioasm, const program *program, const resolvable &scope) override;
- };
- struct code_block : public resolvable {
- std::string lang;
- std::string contents;
- code_block(const yy::location &l, std::string lang, std::string contents) : resolvable(l), lang(std::move(lang)),
- contents(std::move(contents)) {}
- int resolve(pio_assembler *pioasm, const program *program, const resolvable &scope) override {
- return 0;
- }
- };
- struct int_value : public resolvable {
- int value;
- int_value(const yy::location &l, int value) : resolvable(l), value(value) {}
- int resolve(pio_assembler *pioasm, const program *program, const resolvable &scope) override {
- return value;
- }
- };
- static inline rvalue resolvable_int(const yy::location &l, int v) {
- return std::shared_ptr<resolvable>(new int_value(l, v));
- }
- struct binary_operation : public resolvable {
- enum op_type {
- add,
- subtract,
- multiply,
- divide,
- and_, // pesky C++
- or_,
- xor_
- };
- op_type op;
- rvalue left, right;
- binary_operation(const yy::location &l, op_type op, rvalue left, rvalue right) :
- resolvable(l), op(op), left(std::move(left)), right(std::move(right)) {}
- int resolve(pio_assembler *pioasm, const program *program, const resolvable &scope) override;
- };
- struct unary_operation : public resolvable {
- enum op_type {
- negate,
- reverse
- };
- op_type op;
- rvalue arg;
- unary_operation(const yy::location &l, op_type op, const rvalue &arg) :
- resolvable(l), op(op), arg(arg) {}
- int resolve(pio_assembler *pioasm, const program *program, const resolvable &scope) override;
- };
- struct symbol : public src_item {
- std::string name;
- rvalue value;
- bool is_public;
- bool is_label;
- int resolve_started;
- symbol(const yy::location &l, std::string name, bool is_extern = false) : src_item(l), name(std::move(name)),
- is_public(is_extern), is_label(false),
- resolve_started(false) {}
- };
- struct raw_encoding {
- enum inst_type type;
- uint arg1;
- uint arg2;
- };
- struct instruction : public src_item {
- rvalue sideset; // possibly null
- rvalue delay;
- instruction(const yy::location &l) : src_item(l) {}
- virtual uint encode(const program &program);
- virtual raw_encoding raw_encode(const program &program);
- };
- struct pio_assembler;
- // rvalue with extra encompassing location
- struct rvalue_loc {
- rvalue value;
- yy::location location;
- rvalue_loc() = default;
- rvalue_loc(const rvalue &v, const yy::location &l) : value(v), location(l) {}
- };
- struct program : public src_item {
- static const int MAX_INSTRUCTIONS = 32;
- pio_assembler *pioasm;
- std::string name;
- rvalue_loc origin;
- rvalue_loc sideset;
- bool sideset_opt;
- bool sideset_pindirs;
- rvalue wrap_target;
- rvalue wrap;
- std::map<std::string, std::shared_ptr<symbol>> symbols;
- std::vector<std::shared_ptr<symbol>> ordered_symbols;
- std::vector<std::shared_ptr<instruction>> instructions;
- std::map<std::string, std::vector<code_block>> code_blocks;
- std::map<std::string, std::vector<std::pair<std::string,std::string>>> lang_opts;
- // post finalization
- int delay_max;
- int sideset_bits_including_opt; // specified side set bits + 1 if we need presence flag
- int sideset_max;
- program(pio_assembler *pioasm, const yy::location &l, std::string name) :
- src_item(l), pioasm(pioasm), name(std::move(name)), sideset_opt(true), sideset_pindirs(false) {}
- void set_origin(const yy::location &l, const rvalue &_origin) {
- origin = rvalue_loc(_origin, l);
- }
- void set_wrap_target(const yy::location &l);
- void set_wrap(const yy::location &l);
- void set_sideset(const yy::location &l, rvalue _sideset, bool optional, bool pindirs) {
- sideset = rvalue_loc(_sideset, l);
- sideset_opt = optional;
- sideset_pindirs = pindirs;
- }
- void add_label(std::shared_ptr<symbol> label) {
- label->value = resolvable_int(label->location, instructions.size());
- add_symbol(label);
- }
- void add_symbol(std::shared_ptr<symbol> symbol);
- void add_instruction(std::shared_ptr<instruction> inst);
- void add_code_block(const code_block &block);
- void add_lang_opt(std::string lang, std::string name, std::string value);
- void finalize();
- };
- struct instr_jmp : public instruction {
- condition cond;
- rvalue target;
- instr_jmp(const yy::location &l, condition c, rvalue target) : instruction(l), cond(c), target(std::move(target)) { }
- raw_encoding raw_encode(const program &program) override;
- };
- struct instr_wait : public instruction {
- rvalue polarity;
- std::shared_ptr<wait_source> source;
- instr_wait(const yy::location &l, rvalue polarity, std::shared_ptr<wait_source> source) : instruction(l), polarity(
- std::move(polarity)), source(std::move(source)) {}
- raw_encoding raw_encode(const program &program) override;
- };
- struct instr_in : public instruction {
- enum in_out_set src;
- rvalue value;
- instr_in(const yy::location &l, const enum in_out_set &src, rvalue value) : instruction(l), src(src),
- value(std::move(value)) {}
- raw_encoding raw_encode(const program &program) override;
- };
- struct instr_out : public instruction {
- enum in_out_set dest;
- rvalue value;
- instr_out(const yy::location &l, const enum in_out_set &dest, rvalue value) : instruction(l), dest(dest),
- value(std::move(value)) {}
- raw_encoding raw_encode(const program &program) override;
- };
- struct instr_set : public instruction {
- enum in_out_set dest;
- rvalue value;
- instr_set(const yy::location &l, const enum in_out_set &dest, rvalue value) : instruction(l), dest(dest),
- value(std::move(value)) {}
- raw_encoding raw_encode(const program &program) override;
- };
- struct instr_push : public instruction {
- bool if_full, blocking;
- instr_push(const yy::location &l, bool if_full, bool blocking) : instruction(l), if_full(if_full),
- blocking(blocking) {}
- raw_encoding raw_encode(const program &program) override {
- uint arg1 = (blocking ? 1u : 0u) | (if_full ? 0x2u : 0);
- return {inst_type::push_pull, arg1, 0};
- }
- };
- struct instr_pull : public instruction {
- bool if_empty, blocking;
- instr_pull(const yy::location &l, bool if_empty, bool blocking) : instruction(l), if_empty(if_empty),
- blocking(blocking) {}
- raw_encoding raw_encode(const program &program) override {
- uint arg1 = (blocking ? 1u : 0u) | (if_empty ? 0x2u : 0) | 0x4u;
- return {inst_type::push_pull, arg1, 0};
- }
- };
- struct instr_mov : public instruction {
- enum mov dest, src;
- mov_op op;
- instr_mov(const yy::location &l, const enum mov &dest, const enum mov &src, const mov_op& op = mov_op::none) :
- instruction(l), dest(dest), src(src), op(op) {}
- raw_encoding raw_encode(const program &program) override {
- return {inst_type::mov, (uint) dest, (uint)src | ((uint)op << 3u)};
- }
- };
- struct instr_irq : public instruction {
- enum irq modifiers;
- rvalue num;
- bool relative;
- instr_irq(const yy::location &l, const enum irq &modifiers, rvalue num, bool relative = false) :
- instruction(l), modifiers(modifiers), num(std::move(num)), relative(relative) {}
- raw_encoding raw_encode(const program &program) override;
- };
- struct instr_nop : public instr_mov {
- instr_nop(const yy::location &l) : instr_mov(l, mov::y, mov::y) {}
- };
- struct instr_word : public instruction {
- rvalue encoding;
- instr_word(const yy::location &l, rvalue encoding) : instruction(l), encoding(std::move(encoding)) {}
- uint encode(const program &program) override;
- };
- #endif
|