mirror of
https://github.com/RIOT-OS/RIOT.git
synced 2024-12-29 04:50:03 +01:00
194 lines
8.0 KiB
Diff
194 lines
8.0 KiB
Diff
From dad62fc48815744036f754f25554aaa27053cdfc Mon Sep 17 00:00:00 2001
|
|
From: =?UTF-8?q?Fabian=20H=C3=BC=C3=9Fler?= <fabian.huessler@st.ovgu.de>
|
|
Date: Wed, 16 Feb 2022 23:06:53 +0100
|
|
Subject: [PATCH] tools/pioasm: add output format for RIOT-OS
|
|
|
|
---
|
|
tools/pioasm/CMakeLists.txt | 1 +
|
|
tools/pioasm/riot_output.cpp | 161 +++++++++++++++++++++++++++++++++++
|
|
2 files changed, 162 insertions(+)
|
|
create mode 100644 tools/pioasm/riot_output.cpp
|
|
|
|
diff --git a/tools/pioasm/CMakeLists.txt b/tools/pioasm/CMakeLists.txt
|
|
index df80530..16041c2 100644
|
|
--- a/tools/pioasm/CMakeLists.txt
|
|
+++ b/tools/pioasm/CMakeLists.txt
|
|
@@ -24,6 +24,7 @@ target_sources(pioasm PRIVATE c_sdk_output.cpp)
|
|
target_sources(pioasm PRIVATE python_output.cpp)
|
|
target_sources(pioasm PRIVATE hex_output.cpp)
|
|
target_sources(pioasm PRIVATE ada_output.cpp)
|
|
+target_sources(pioasm PRIVATE riot_output.cpp)
|
|
target_sources(pioasm PRIVATE ${PIOASM_EXTRA_SOURCE_FILES})
|
|
|
|
if ((CMAKE_CXX_COMPILER_ID STREQUAL "GNU") AND
|
|
diff --git a/tools/pioasm/riot_output.cpp b/tools/pioasm/riot_output.cpp
|
|
new file mode 100644
|
|
index 0000000..d4d828e
|
|
--- /dev/null
|
|
+++ b/tools/pioasm/riot_output.cpp
|
|
@@ -0,0 +1,161 @@
|
|
+/*
|
|
+ * Copyright (C) 2022 Otto-von-Guericke-Universität Magdeburg
|
|
+ *
|
|
+ * This file is subject to the terms and conditions of the GNU Lesser
|
|
+ * General Public License v2.1. See the file LICENSE in the top level
|
|
+ * directory for more details.
|
|
+ */
|
|
+
|
|
+#include <algorithm>
|
|
+#include <iostream>
|
|
+#include <cinttypes>
|
|
+#include "output_format.h"
|
|
+#include "pio_disassembler.h"
|
|
+
|
|
+struct riot_output : public output_format {
|
|
+ struct factory {
|
|
+ factory() {
|
|
+ output_format::add(new riot_output());
|
|
+ }
|
|
+ };
|
|
+
|
|
+ riot_output() : output_format("RIOT") {}
|
|
+
|
|
+ std::string get_description() override
|
|
+ {
|
|
+ return "C header suitable for use with RIOT-OS";
|
|
+ }
|
|
+
|
|
+ void output_symbols(FILE *out, std::string prefix, const std::vector<compiled_source::symbol> &symbols)
|
|
+ {
|
|
+ int count = 0;
|
|
+ for (const auto &s : symbols) {
|
|
+ if (!s.is_label) {
|
|
+ fprintf(out, "#define %s%s %d\n", prefix.c_str(), s.name.c_str(), s.value);
|
|
+ count++;
|
|
+ }
|
|
+ }
|
|
+ fprintf(out, count ? "\n" : "");
|
|
+ count = 0;
|
|
+ for (const auto &s : symbols) {
|
|
+ if (s.is_label) {
|
|
+ fprintf(out, "#define %sLABEL_%s %d\n", prefix.c_str(), s.name.c_str(), s.value);
|
|
+ count++;
|
|
+ }
|
|
+ }
|
|
+ fprintf(out, count ? "\n" : "");
|
|
+ }
|
|
+
|
|
+ int output(std::string destination, std::vector<std::string> output_options,
|
|
+ const compiled_source &source) override
|
|
+ {
|
|
+ for (const auto &program : source.programs) {
|
|
+ for(const auto &p : program.lang_opts) {
|
|
+ if (p.first.size() >= name.size() && p.first.compare(0, name.size(), name) == 0) {
|
|
+ std::cerr << "warning: " << name << " does not support output options; " << p.first << " lang_opt ignored.\n";
|
|
+ }
|
|
+ }
|
|
+ }
|
|
+ FILE *out = open_single_output(destination);
|
|
+ if (!out) {
|
|
+ return 1;
|
|
+ }
|
|
+ std::string fname = destination.substr(destination.find_last_of("/\\") + 1);
|
|
+ fname = fname.substr(0, std::max(fname.find_first_of("."), (std::size_t)0));
|
|
+ std::transform(fname.begin(), fname.end(), fname.begin(), ::toupper);
|
|
+ fprintf(out, "#ifndef PIO_%s_H\n", fname.c_str());
|
|
+ fprintf(out, "#define PIO_%s_H\n", fname.c_str());
|
|
+ fprintf(out, "\n"
|
|
+ "#include <stdbool.h>\n"
|
|
+ "#include \"periph/pio.h\"\n");
|
|
+ fprintf(out, "\n"
|
|
+ "#ifdef __cplusplus\n"
|
|
+ "extern \"C\" {\n"
|
|
+ "#endif\n");
|
|
+ fprintf(out, "\n");
|
|
+ output_symbols(out, "", source.global_symbols);
|
|
+
|
|
+ for (const auto &program : source.programs) {
|
|
+ std::string prefix = "PIO_" + program.name + "_";
|
|
+ std::transform(prefix.begin(), prefix.end(), prefix.begin(), ::toupper);
|
|
+ fprintf(out, "/* %s */\n", program.name.c_str());
|
|
+ fprintf(out, "#define %sSIDESET_COUNT %d\n", prefix.c_str(),
|
|
+ program.sideset_bits_including_opt.is_specified()
|
|
+ ? program.sideset_bits_including_opt.value - !!program.sideset_opt : 0);
|
|
+ fprintf(out, "#define %sSIDESET_OPTIONAL %s\n", prefix.c_str(), program.sideset_opt ? "true" : "false");
|
|
+ fprintf(out, "#define %sSIDESET_PINDIRS %s\n", prefix.c_str(), program.sideset_pindirs ? "true" : "false");
|
|
+ fprintf(out, "#define %sWRAP_BOTTOM %d\n", prefix.c_str(), program.wrap_target);
|
|
+ fprintf(out, "#define %sWRAP_TOP %d\n", prefix.c_str(), program.wrap);
|
|
+ fprintf(out, "\n");
|
|
+ output_symbols(out, prefix, program.symbols);
|
|
+ fprintf(out, "#define %sPROGRAM { \\\n", prefix.c_str());
|
|
+ for (int i = 0; i < (int)program.instructions.size(); i++) {
|
|
+ const auto &inst = program.instructions[i];
|
|
+ const char comma = i == (int)program.instructions.size() -1 ? ' ' : ',';
|
|
+ const std::string disasm = disassemble(inst,
|
|
+ program.sideset_bits_including_opt.get(),
|
|
+ program.sideset_opt);
|
|
+ if (i == program.wrap_target) {
|
|
+ fprintf(out, " /* .wrap_target */ \\\n");
|
|
+ }
|
|
+ fprintf(out, " 0x%04x%c /* %2d: %s */ \\\n", inst, comma, i, disasm.c_str());
|
|
+ if (i == program.wrap) {
|
|
+ fprintf(out, " /* .wrap */ \\\n");
|
|
+ }
|
|
+ }
|
|
+ fprintf(out, "}\n");
|
|
+ fprintf(out, "#define %sPROGRAM_LENGTH %d\n", prefix.c_str(), program.instructions.size());
|
|
+ fprintf(out, "#ifndef %sLABEL_entry_point\n"
|
|
+ "#define %sLABEL_entry_point 0\n"
|
|
+ "#endif\n",
|
|
+ prefix.c_str(), prefix.c_str());
|
|
+ fprintf(out, "#define %sPROGRAM_CONF { \\\n"
|
|
+ " %sLABEL_entry_point, \\\n"
|
|
+ " %sWRAP_BOTTOM, \\\n"
|
|
+ " %sWRAP_TOP, \\\n"
|
|
+ " %sSIDESET_COUNT, \\\n"
|
|
+ " %sSIDESET_OPTIONAL, \\\n"
|
|
+ " %sSIDESET_PINDIRS \\\n"
|
|
+ "}\n",
|
|
+ prefix.c_str(), prefix.c_str(), prefix.c_str(), prefix.c_str(),
|
|
+ prefix.c_str(), prefix.c_str(), prefix.c_str()
|
|
+ );
|
|
+
|
|
+ /* generate functions */
|
|
+ fprintf(out, "\n");
|
|
+ fprintf(out, "static inline pio_program_t pio_%s_create_program(void)\n"
|
|
+ "{\n"
|
|
+ " pio_program_t pro = {\n"
|
|
+ " .instr_numof = %sPROGRAM_LENGTH,\n"
|
|
+ " .location = PIO_PROGRAM_NOT_LOADED\n"
|
|
+ " };\n"
|
|
+ " return pro;\n"
|
|
+ "}\n",
|
|
+ program.name.c_str(),
|
|
+ prefix.c_str());
|
|
+
|
|
+ /* todo maybe have some code blocks inside or outside here? */
|
|
+ for(const auto& o : program.code_blocks) {
|
|
+ fprintf(out, "\n");
|
|
+ if (o.first == name) {
|
|
+ for(const auto &contents : o.second) {
|
|
+ fprintf(out, "%s", contents.c_str());
|
|
+ fprintf(out, "\n");
|
|
+ }
|
|
+ }
|
|
+ }
|
|
+ }
|
|
+
|
|
+ fprintf(out, "#ifdef __cplusplus\n"
|
|
+ "}\n"
|
|
+ "#endif\n");
|
|
+ fprintf(out, "#endif /* PIO_%s_H */\n", fname.c_str());
|
|
+
|
|
+ if (out != stdout) {
|
|
+ fclose(out);
|
|
+ }
|
|
+ return 0;
|
|
+ }
|
|
+};
|
|
+
|
|
+static riot_output::factory creator;
|
|
--
|
|
2.35.1
|
|
|