From fb4fadea0cd87cecf2ae97c57ec09e897c2dbc4b Mon Sep 17 00:00:00 2001 From: Markus Gyger <182590275+magy00@users.noreply.github.com> Date: Thu, 22 May 2025 08:53:09 +0700 Subject: [PATCH] pioasm: add target for .wrap, dot symbol, .word as instruction (#2163) --- tools/pioasm/lexer.ll | 2 ++ tools/pioasm/parser.yy | 7 +++++-- tools/pioasm/pio_assembler.cpp | 15 +++++++++++++-- tools/pioasm/pio_types.h | 4 +++- tools/pioasm/test/amethyst.pio | 10 ++++++++++ 5 files changed, 33 insertions(+), 5 deletions(-) diff --git a/tools/pioasm/lexer.ll b/tools/pioasm/lexer.ll index fdf8c7220..2b762026c 100644 --- a/tools/pioasm/lexer.ll +++ b/tools/pioasm/lexer.ll @@ -220,6 +220,8 @@ output_fmt [^%\n]+ {comment} { } +"." return yy::parser::make_DOT(loc); + . { throw yy::parser::syntax_error(loc, "invalid character: " + std::string(yytext)); } %% diff --git a/tools/pioasm/parser.yy b/tools/pioasm/parser.yy index 730bc9205..910a6a9e4 100644 --- a/tools/pioasm/parser.yy +++ b/tools/pioasm/parser.yy @@ -85,6 +85,7 @@ DOT_SET ".set" DOT_OUT ".out" DOT_IN ".in" + DOT "." JMP "jmp" WAIT "wait" @@ -203,8 +204,8 @@ directive: | DOT_OUT value direction autop threshold { pioasm.get_current_program(@1, ".out", true).set_out(@$, $2, $3, $4, $5); } | DOT_SET value { pioasm.get_current_program(@1, ".set", true).set_set_count(@$, $2); } | WRAP_TARGET { pioasm.get_current_program(@1, ".wrap_target").set_wrap_target(@$); } + | WRAP expression { pioasm.get_current_program(@1, ".wrap").set_wrap(@$, $2); } | WRAP { pioasm.get_current_program(@1, ".wrap").set_wrap(@$); } - | WORD value { pioasm.get_current_program(@1, "instruction").add_instruction(std::shared_ptr(new instr_word(@$, $2))); } | LANG_OPT NON_WS NON_WS ASSIGN INT { pioasm.get_current_program(@1, ".lang_opt").add_lang_opt($2, $3, std::to_string($5)); } | LANG_OPT NON_WS NON_WS ASSIGN STRING { pioasm.get_current_program(@1, ".lang_opt").add_lang_opt($2, $3, $5); } | LANG_OPT NON_WS NON_WS ASSIGN NON_WS { pioasm.get_current_program(@1, ".lang_opt").add_lang_opt($2, $3, $5); } @@ -224,6 +225,7 @@ directive: /* value is a more limited top level expression... requiring parenthesis */ %type > value; value: INT { $$ = resolvable_int(@$, $1); } + | DOT { $$ = resolvable_int(@$, pioasm.get_current_program(@1, ".").instructions.size()); } | ID { $$ = std::shared_ptr(new name_ref(@$, $1)); } | LPAREN expression RPAREN { $$ = $2; } @@ -257,7 +259,8 @@ instruction: %type > base_instruction; base_instruction: - NOP { $$ = std::shared_ptr(new instr_nop(@$)); } + WORD value { $$ = std::shared_ptr(new instr_word(@$, $2)); } + | NOP { $$ = std::shared_ptr(new instr_nop(@$)); } | JMP condition comma expression { $$ = std::shared_ptr(new instr_jmp(@$, $2, $4)); } | WAIT value wait_source { $$ = std::shared_ptr(new instr_wait(@$, $2, $3)); } | WAIT wait_source { $$ = std::shared_ptr(new instr_wait(@$, resolvable_int(@$, 1), $2)); } diff --git a/tools/pioasm/pio_assembler.cpp b/tools/pioasm/pio_assembler.cpp index a36854b2c..861d2f5e3 100644 --- a/tools/pioasm/pio_assembler.cpp +++ b/tools/pioasm/pio_assembler.cpp @@ -161,6 +161,17 @@ void program::set_wrap(const yy::location &l) { wrap = resolvable_int(l, instructions.size() - 1); } +void program::set_wrap(const yy::location &l, rvalue target) { + set_wrap(l); + + if (wrap_target) { + std::stringstream msg; + msg << ".wrap_target was already specified at " << wrap_target->location; + throw syntax_error(l, msg.str()); + } + wrap_target = std::move(target); +} + void program::set_wrap_target(const yy::location &l) { if (wrap_target) { std::stringstream msg; @@ -299,12 +310,12 @@ raw_encoding instruction::raw_encode(program& program) { throw syntax_error(location, "internal error"); } -uint instr_word::encode(program &program) { +raw_encoding instr_word::raw_encode(program& program) { uint value = encoding->resolve(program); if (value > 0xffffu) { throw syntax_error(location, ".word value must be a positive 16 bit value"); } - return value; + return {inst_type(0), value >> 5, value & 0x1fu}; } uint instr_mov::get_push_get_index(const program &program, extended_mov index) { diff --git a/tools/pioasm/pio_types.h b/tools/pioasm/pio_types.h index 755eb75a0..56ca64b78 100644 --- a/tools/pioasm/pio_types.h +++ b/tools/pioasm/pio_types.h @@ -321,6 +321,8 @@ struct program : public src_item { void set_wrap(const yy::location &l); + void set_wrap(const yy::location &l, rvalue target); + void set_sideset(const yy::location &l, rvalue _sideset, bool optional, bool pindirs) { sideset = rvalue_loc(_sideset, l); sideset_opt = optional; @@ -486,7 +488,7 @@ struct instr_word : public instruction { instr_word(const yy::location &l, rvalue encoding) : instruction(l), encoding(std::move(encoding)) {} - uint encode(program &program) override; + raw_encoding raw_encode(program &program) override; }; #endif diff --git a/tools/pioasm/test/amethyst.pio b/tools/pioasm/test/amethyst.pio index 6b8160460..cc9bfc692 100644 --- a/tools/pioasm/test/amethyst.pio +++ b/tools/pioasm/test/amethyst.pio @@ -45,6 +45,16 @@ wait gpio 40 .mov_status txfifo < 12 .mov_status irq next set 3 +.program wrap +decrement: + jmp x--, .+1 +skip: + .wrap .+1 +delay: + jmp x--, . +jump: + .word (.-1) [2] + .program python .pio_version 1 wait 0 jmppin