From 6ee484a771611fad3ccfe26245dd8b8500bfee06 Mon Sep 17 00:00:00 2001 From: Eyck-Alexander Jentzsch Date: Tue, 23 Jul 2024 11:30:33 +0200 Subject: [PATCH] moves instruction decoder into own class --- CMakeLists.txt | 1 + src/vm/instruction_decoder.cpp | 103 +++++++++++++++++++++++++++++++++ src/vm/instruction_decoder.h | 63 ++++++++++++++++++++ 3 files changed, 167 insertions(+) create mode 100644 src/vm/instruction_decoder.cpp create mode 100644 src/vm/instruction_decoder.h diff --git a/CMakeLists.txt b/CMakeLists.txt index 2a46f47..b8dd450 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -20,6 +20,7 @@ set(LIB_SOURCES src/iss/arch/tgc5c.cpp src/vm/interp/vm_tgc5c.cpp src/vm/fp_functions.cpp + src/vm/instruction_decoder.cpp src/iss/semihosting/semihosting.cpp ) diff --git a/src/vm/instruction_decoder.cpp b/src/vm/instruction_decoder.cpp new file mode 100644 index 0000000..b975d81 --- /dev/null +++ b/src/vm/instruction_decoder.cpp @@ -0,0 +1,103 @@ +/******************************************************************************* + * Copyright (C) 2024 MINRES Technologies GmbH + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * 3. Neither the name of the copyright holder nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + * Contributors: + * alex@minres.com - initial implementation + ******************************************************************************/ + +#include +#include +#include +#include +#include +#include +#include +#include + +decoder::decoder(std::vector instr_list) { + for(auto instr : instr_list) { + root.instrs.push_back(instr); + } + populate_decoding_tree(root); +} + +void decoder::populate_decoding_tree(decoding_tree_node& parent) { + // create submask + parent.submask = + std::accumulate(parent.instrs.begin(), parent.instrs.end(), std::numeric_limits::max(), + [](int current_submask, const generic_instruction_descriptor& instr) { return current_submask & instr.mask; }); + // put each instr according to submask&encoding into children + for(auto instr : parent.instrs) { + bool foundMatch = false; + for(auto& child : parent.children) { + // use value as identifying trait + if(child.value == (instr.value & parent.submask)) { + child.instrs.push_back(instr); + foundMatch = true; + } + } + if(!foundMatch) { + decoding_tree_node child = decoding_tree_node(instr.value & parent.submask); + child.instrs.push_back(instr); + parent.children.push_back(child); + } + } + parent.instrs.clear(); + // call populate_decoding_tree for all children + if(parent.children.size() > 1) + for(auto& child : parent.children) { + populate_decoding_tree(child); + } + else { + // sort instrs by value of the mask, so we have the least restrictive mask last + std::sort(parent.children[0].instrs.begin(), parent.children[0].instrs.end(), + [](const generic_instruction_descriptor& instr1, const generic_instruction_descriptor& instr2) { + return instr1.mask > instr2.mask; + }); + } +} +uint32_t decoder::decode_instr(uint32_t word) { return _decode_instr(this->root, word); } +uint32_t decoder::_decode_instr(decoding_tree_node const& node, uint32_t word) { + if(!node.children.size()) { + if(node.instrs.size() == 1) + return node.instrs[0].index; + for(auto instr : node.instrs) { + if((instr.mask & word) == instr.value) + return instr.index; + } + } else { + for(auto child : node.children) { + if(child.value == (node.submask & word)) { + return _decode_instr(child, word); + } + } + } + return std::numeric_limits::max(); +} diff --git a/src/vm/instruction_decoder.h b/src/vm/instruction_decoder.h new file mode 100644 index 0000000..c1e8aac --- /dev/null +++ b/src/vm/instruction_decoder.h @@ -0,0 +1,63 @@ +/******************************************************************************* + * Copyright (C) 2024 MINRES Technologies GmbH + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * 3. Neither the name of the copyright holder nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + * + * Contributors: + * alex@minres.com - initial implementation + ******************************************************************************/ + +#include +#include +#include +#include + +struct generic_instruction_descriptor { + uint32_t value; + uint32_t mask; + uint32_t index; +}; + +struct decoding_tree_node { + std::vector instrs; + std::vector children; + uint32_t submask = std::numeric_limits::max(); + uint32_t value; + decoding_tree_node(uint32_t value) + : value(value) {} +}; +class decoder { +public: + decoder(std::vector instr_list); + uint32_t decode_instr(uint32_t word); + +private: + decoding_tree_node root{decoding_tree_node(std::numeric_limits::max())}; + void populate_decoding_tree(decoding_tree_node& root); + uint32_t _decode_instr(decoding_tree_node const& node, uint32_t word); +}; \ No newline at end of file