updates templates for decoder in seperate class, adds again generated templates
This commit is contained in:
parent
e3942be776
commit
051dd5e2d3
|
@ -37,6 +37,7 @@
|
||||||
#include <iss/asmjit/vm_base.h>
|
#include <iss/asmjit/vm_base.h>
|
||||||
#include <asmjit/asmjit.h>
|
#include <asmjit/asmjit.h>
|
||||||
#include <util/logging.h>
|
#include <util/logging.h>
|
||||||
|
#include <vm/instruction_decoder.h>
|
||||||
|
|
||||||
#ifndef FMT_HEADER_ONLY
|
#ifndef FMT_HEADER_ONLY
|
||||||
#define FMT_HEADER_ONLY
|
#define FMT_HEADER_ONLY
|
||||||
|
@ -115,20 +116,11 @@ private:
|
||||||
* start opcode definitions
|
* start opcode definitions
|
||||||
****************************************************************************/
|
****************************************************************************/
|
||||||
struct instruction_descriptor {
|
struct instruction_descriptor {
|
||||||
size_t length;
|
uint32_t length;
|
||||||
uint32_t value;
|
uint32_t value;
|
||||||
uint32_t mask;
|
uint32_t mask;
|
||||||
compile_func op;
|
compile_func op;
|
||||||
};
|
};
|
||||||
struct decoding_tree_node{
|
|
||||||
std::vector<instruction_descriptor> instrs;
|
|
||||||
std::vector<decoding_tree_node*> children;
|
|
||||||
uint32_t submask = std::numeric_limits<uint32_t>::max();
|
|
||||||
uint32_t value;
|
|
||||||
decoding_tree_node(uint32_t value) : value(value){}
|
|
||||||
};
|
|
||||||
|
|
||||||
decoding_tree_node* root {nullptr};
|
|
||||||
|
|
||||||
const std::array<instruction_descriptor, ${instructions.size()}> instr_descr = {{
|
const std::array<instruction_descriptor, ${instructions.size()}> instr_descr = {{
|
||||||
/* entries are: size, valid value, valid mask, function ptr */<%instructions.each{instr -> %>
|
/* entries are: size, valid value, valid mask, function ptr */<%instructions.each{instr -> %>
|
||||||
|
@ -136,6 +128,9 @@ private:
|
||||||
{${instr.length}, ${instr.encoding}, ${instr.mask}, &this_class::__${generator.functionName(instr.name)}},<%}%>
|
{${instr.length}, ${instr.encoding}, ${instr.mask}, &this_class::__${generator.functionName(instr.name)}},<%}%>
|
||||||
}};
|
}};
|
||||||
|
|
||||||
|
//needs to be declared after instr_descr
|
||||||
|
decoder instr_decoder;
|
||||||
|
|
||||||
/* instruction definitions */<%instructions.eachWithIndex{instr, idx -> %>
|
/* instruction definitions */<%instructions.eachWithIndex{instr, idx -> %>
|
||||||
/* instruction ${idx}: ${instr.name} */
|
/* instruction ${idx}: ${instr.name} */
|
||||||
continuation_e __${generator.functionName(instr.name)}(virt_addr_t& pc, code_word_t instr, jit_holder& jh){
|
continuation_e __${generator.functionName(instr.name)}(virt_addr_t& pc, code_word_t instr, jit_holder& jh){
|
||||||
|
@ -200,72 +195,22 @@ private:
|
||||||
gen_instr_epilogue(jh);
|
gen_instr_epilogue(jh);
|
||||||
return BRANCH;
|
return BRANCH;
|
||||||
}
|
}
|
||||||
|
|
||||||
//decoding functionality
|
|
||||||
|
|
||||||
void populate_decoding_tree(decoding_tree_node* root){
|
|
||||||
//create submask
|
|
||||||
for(auto instr: root->instrs){
|
|
||||||
root->submask &= instr.mask;
|
|
||||||
}
|
|
||||||
//put each instr according to submask&encoding into children
|
|
||||||
for(auto instr: root->instrs){
|
|
||||||
bool foundMatch = false;
|
|
||||||
for(auto child: root->children){
|
|
||||||
//use value as identifying trait
|
|
||||||
if(child->value == (instr.value&root->submask)){
|
|
||||||
child->instrs.push_back(instr);
|
|
||||||
foundMatch = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if(!foundMatch){
|
|
||||||
decoding_tree_node* child = new decoding_tree_node(instr.value&root->submask);
|
|
||||||
child->instrs.push_back(instr);
|
|
||||||
root->children.push_back(child);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
root->instrs.clear();
|
|
||||||
//call populate_decoding_tree for all children
|
|
||||||
if(root->children.size() >1)
|
|
||||||
for(auto child: root->children){
|
|
||||||
populate_decoding_tree(child);
|
|
||||||
}
|
|
||||||
else{
|
|
||||||
//sort instrs by value of the mask, this works bc we want to have the least restrictive one last
|
|
||||||
std::sort(root->children[0]->instrs.begin(), root->children[0]->instrs.end(), [](const instruction_descriptor& instr1, const instruction_descriptor& instr2) {
|
|
||||||
return instr1.mask > instr2.mask;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
compile_func decode_instr(decoding_tree_node* node, code_word_t word){
|
|
||||||
if(!node->children.size()){
|
|
||||||
if(node->instrs.size() == 1) return node->instrs[0].op;
|
|
||||||
for(auto instr : node->instrs){
|
|
||||||
if((instr.mask&word) == instr.value) return instr.op;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else{
|
|
||||||
for(auto child : node->children){
|
|
||||||
if (child->value == (node->submask&word)){
|
|
||||||
return decode_instr(child, word);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return nullptr;
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
template <typename ARCH> vm_impl<ARCH>::vm_impl() { this(new ARCH()); }
|
template <typename ARCH> vm_impl<ARCH>::vm_impl() { this(new ARCH()); }
|
||||||
|
|
||||||
template <typename ARCH>
|
template <typename ARCH>
|
||||||
vm_impl<ARCH>::vm_impl(ARCH &core, unsigned core_id, unsigned cluster_id)
|
vm_impl<ARCH>::vm_impl(ARCH &core, unsigned core_id, unsigned cluster_id)
|
||||||
: vm_base<ARCH>(core, core_id, cluster_id) {
|
: vm_base<ARCH>(core, core_id, cluster_id)
|
||||||
root = new decoding_tree_node(std::numeric_limits<uint32_t>::max());
|
, instr_decoder([this]() {
|
||||||
for(auto instr: instr_descr){
|
std::vector<generic_instruction_descriptor> g_instr_descr;
|
||||||
root->instrs.push_back(instr);
|
g_instr_descr.reserve(instr_descr.size());
|
||||||
}
|
for (uint32_t i = 0; i < instr_descr.size(); ++i) {
|
||||||
populate_decoding_tree(root);
|
generic_instruction_descriptor new_instr_descr {instr_descr[i].value, instr_descr[i].mask, i};
|
||||||
|
g_instr_descr.push_back(new_instr_descr);
|
||||||
}
|
}
|
||||||
|
return std::move(g_instr_descr);
|
||||||
|
}()) {}
|
||||||
|
|
||||||
template <typename ARCH>
|
template <typename ARCH>
|
||||||
continuation_e vm_impl<ARCH>::gen_single_inst_behavior(virt_addr_t &pc, unsigned int &inst_cnt, jit_holder& jh) {
|
continuation_e vm_impl<ARCH>::gen_single_inst_behavior(virt_addr_t &pc, unsigned int &inst_cnt, jit_holder& jh) {
|
||||||
|
@ -281,7 +226,10 @@ continuation_e vm_impl<ARCH>::gen_single_inst_behavior(virt_addr_t &pc, unsigned
|
||||||
if (instr == 0x0000006f || (instr&0xffff)==0xa001)
|
if (instr == 0x0000006f || (instr&0xffff)==0xa001)
|
||||||
throw simulation_stopped(0); // 'J 0' or 'C.J 0'
|
throw simulation_stopped(0); // 'J 0' or 'C.J 0'
|
||||||
++inst_cnt;
|
++inst_cnt;
|
||||||
auto f = decode_instr(root, instr);
|
uint32_t inst_index = instr_decoder.decode_instr(instr);
|
||||||
|
compile_func f = nullptr;
|
||||||
|
if(inst_index < instr_descr.size())
|
||||||
|
f = instr_descr[inst_index].op;
|
||||||
if (f == nullptr)
|
if (f == nullptr)
|
||||||
f = &this_class::illegal_instruction;
|
f = &this_class::illegal_instruction;
|
||||||
return (this->*f)(pc, instr, jh);
|
return (this->*f)(pc, instr, jh);
|
||||||
|
|
|
@ -36,6 +36,7 @@
|
||||||
#include <iss/iss.h>
|
#include <iss/iss.h>
|
||||||
#include <iss/llvm/vm_base.h>
|
#include <iss/llvm/vm_base.h>
|
||||||
#include <util/logging.h>
|
#include <util/logging.h>
|
||||||
|
#include <vm/instruction_decoder.h>
|
||||||
|
|
||||||
#ifndef FMT_HEADER_ONLY
|
#ifndef FMT_HEADER_ONLY
|
||||||
#define FMT_HEADER_ONLY
|
#define FMT_HEADER_ONLY
|
||||||
|
@ -136,20 +137,11 @@ private:
|
||||||
* start opcode definitions
|
* start opcode definitions
|
||||||
****************************************************************************/
|
****************************************************************************/
|
||||||
struct instruction_descriptor {
|
struct instruction_descriptor {
|
||||||
size_t length;
|
uint32_t length;
|
||||||
uint32_t value;
|
uint32_t value;
|
||||||
uint32_t mask;
|
uint32_t mask;
|
||||||
compile_func op;
|
compile_func op;
|
||||||
};
|
};
|
||||||
struct decoding_tree_node{
|
|
||||||
std::vector<instruction_descriptor> instrs;
|
|
||||||
std::vector<decoding_tree_node*> children;
|
|
||||||
uint32_t submask = std::numeric_limits<uint32_t>::max();
|
|
||||||
uint32_t value;
|
|
||||||
decoding_tree_node(uint32_t value) : value(value){}
|
|
||||||
};
|
|
||||||
|
|
||||||
decoding_tree_node* root {nullptr};
|
|
||||||
|
|
||||||
const std::array<instruction_descriptor, ${instructions.size()}> instr_descr = {{
|
const std::array<instruction_descriptor, ${instructions.size()}> instr_descr = {{
|
||||||
/* entries are: size, valid value, valid mask, function ptr */<%instructions.each{instr -> %>
|
/* entries are: size, valid value, valid mask, function ptr */<%instructions.each{instr -> %>
|
||||||
|
@ -157,6 +149,9 @@ private:
|
||||||
{${instr.length}, ${instr.encoding}, ${instr.mask}, &this_class::__${generator.functionName(instr.name)}},<%}%>
|
{${instr.length}, ${instr.encoding}, ${instr.mask}, &this_class::__${generator.functionName(instr.name)}},<%}%>
|
||||||
}};
|
}};
|
||||||
|
|
||||||
|
//needs to be declared after instr_descr
|
||||||
|
decoder instr_decoder;
|
||||||
|
|
||||||
/* instruction definitions */<%instructions.eachWithIndex{instr, idx -> %>
|
/* instruction definitions */<%instructions.eachWithIndex{instr, idx -> %>
|
||||||
/* instruction ${idx}: ${instr.name} */
|
/* instruction ${idx}: ${instr.name} */
|
||||||
std::tuple<continuation_e, BasicBlock*> __${generator.functionName(instr.name)}(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){
|
std::tuple<continuation_e, BasicBlock*> __${generator.functionName(instr.name)}(virt_addr_t& pc, code_word_t instr, BasicBlock* bb){
|
||||||
|
@ -219,58 +214,6 @@ private:
|
||||||
this->builder.CreateBr(bb);
|
this->builder.CreateBr(bb);
|
||||||
return std::make_tuple(BRANCH, nullptr);
|
return std::make_tuple(BRANCH, nullptr);
|
||||||
}
|
}
|
||||||
//decoding functionality
|
|
||||||
|
|
||||||
void populate_decoding_tree(decoding_tree_node* root){
|
|
||||||
//create submask
|
|
||||||
for(auto instr: root->instrs){
|
|
||||||
root->submask &= instr.mask;
|
|
||||||
}
|
|
||||||
//put each instr according to submask&encoding into children
|
|
||||||
for(auto instr: root->instrs){
|
|
||||||
bool foundMatch = false;
|
|
||||||
for(auto child: root->children){
|
|
||||||
//use value as identifying trait
|
|
||||||
if(child->value == (instr.value&root->submask)){
|
|
||||||
child->instrs.push_back(instr);
|
|
||||||
foundMatch = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if(!foundMatch){
|
|
||||||
decoding_tree_node* child = new decoding_tree_node(instr.value&root->submask);
|
|
||||||
child->instrs.push_back(instr);
|
|
||||||
root->children.push_back(child);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
root->instrs.clear();
|
|
||||||
//call populate_decoding_tree for all children
|
|
||||||
if(root->children.size() >1)
|
|
||||||
for(auto child: root->children){
|
|
||||||
populate_decoding_tree(child);
|
|
||||||
}
|
|
||||||
else{
|
|
||||||
//sort instrs by value of the mask, this works bc we want to have the least restrictive one last
|
|
||||||
std::sort(root->children[0]->instrs.begin(), root->children[0]->instrs.end(), [](const instruction_descriptor& instr1, const instruction_descriptor& instr2) {
|
|
||||||
return instr1.mask > instr2.mask;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
compile_func decode_instr(decoding_tree_node* node, code_word_t word){
|
|
||||||
if(!node->children.size()){
|
|
||||||
if(node->instrs.size() == 1) return node->instrs[0].op;
|
|
||||||
for(auto instr : node->instrs){
|
|
||||||
if((instr.mask&word) == instr.value) return instr.op;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else{
|
|
||||||
for(auto child : node->children){
|
|
||||||
if (child->value == (node->submask&word)){
|
|
||||||
return decode_instr(child, word);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return nullptr;
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
template <typename CODE_WORD> void debug_fn(CODE_WORD instr) {
|
template <typename CODE_WORD> void debug_fn(CODE_WORD instr) {
|
||||||
|
@ -282,13 +225,16 @@ template <typename ARCH> vm_impl<ARCH>::vm_impl() { this(new ARCH()); }
|
||||||
|
|
||||||
template <typename ARCH>
|
template <typename ARCH>
|
||||||
vm_impl<ARCH>::vm_impl(ARCH &core, unsigned core_id, unsigned cluster_id)
|
vm_impl<ARCH>::vm_impl(ARCH &core, unsigned core_id, unsigned cluster_id)
|
||||||
: vm_base<ARCH>(core, core_id, cluster_id) {
|
: vm_base<ARCH>(core, core_id, cluster_id)
|
||||||
root = new decoding_tree_node(std::numeric_limits<uint32_t>::max());
|
, instr_decoder([this]() {
|
||||||
for(auto instr:instr_descr){
|
std::vector<generic_instruction_descriptor> g_instr_descr;
|
||||||
root->instrs.push_back(instr);
|
g_instr_descr.reserve(instr_descr.size());
|
||||||
}
|
for (uint32_t i = 0; i < instr_descr.size(); ++i) {
|
||||||
populate_decoding_tree(root);
|
generic_instruction_descriptor new_instr_descr {instr_descr[i].value, instr_descr[i].mask, i};
|
||||||
|
g_instr_descr.push_back(new_instr_descr);
|
||||||
}
|
}
|
||||||
|
return std::move(g_instr_descr);
|
||||||
|
}()) {}
|
||||||
|
|
||||||
template <typename ARCH>
|
template <typename ARCH>
|
||||||
std::tuple<continuation_e, BasicBlock *>
|
std::tuple<continuation_e, BasicBlock *>
|
||||||
|
@ -315,7 +261,10 @@ vm_impl<ARCH>::gen_single_inst_behavior(virt_addr_t &pc, unsigned int &inst_cnt,
|
||||||
if (instr == 0x0000006f || (instr&0xffff)==0xa001) throw simulation_stopped(0); // 'J 0' or 'C.J 0'
|
if (instr == 0x0000006f || (instr&0xffff)==0xa001) throw simulation_stopped(0); // 'J 0' or 'C.J 0'
|
||||||
// curr pc on stack
|
// curr pc on stack
|
||||||
++inst_cnt;
|
++inst_cnt;
|
||||||
auto f = decode_instr(root, instr);
|
uint32_t inst_index = instr_decoder.decode_instr(instr);
|
||||||
|
compile_func f = nullptr;
|
||||||
|
if(inst_index < instr_descr.size())
|
||||||
|
f = instr_descr[inst_index].op;
|
||||||
if (f == nullptr) {
|
if (f == nullptr) {
|
||||||
f = &this_class::illegal_instruction;
|
f = &this_class::illegal_instruction;
|
||||||
}
|
}
|
||||||
|
|
|
@ -37,6 +37,7 @@
|
||||||
#include <iss/tcc/vm_base.h>
|
#include <iss/tcc/vm_base.h>
|
||||||
#include <util/logging.h>
|
#include <util/logging.h>
|
||||||
#include <sstream>
|
#include <sstream>
|
||||||
|
#include <vm/instruction_decoder.h>
|
||||||
|
|
||||||
#ifndef FMT_HEADER_ONLY
|
#ifndef FMT_HEADER_ONLY
|
||||||
#define FMT_HEADER_ONLY
|
#define FMT_HEADER_ONLY
|
||||||
|
@ -137,20 +138,11 @@ private:
|
||||||
* start opcode definitions
|
* start opcode definitions
|
||||||
****************************************************************************/
|
****************************************************************************/
|
||||||
struct instruction_descriptor {
|
struct instruction_descriptor {
|
||||||
size_t length;
|
uint32_t length;
|
||||||
uint32_t value;
|
uint32_t value;
|
||||||
uint32_t mask;
|
uint32_t mask;
|
||||||
compile_func op;
|
compile_func op;
|
||||||
};
|
};
|
||||||
struct decoding_tree_node{
|
|
||||||
std::vector<instruction_descriptor> instrs;
|
|
||||||
std::vector<decoding_tree_node*> children;
|
|
||||||
uint32_t submask = std::numeric_limits<uint32_t>::max();
|
|
||||||
uint32_t value;
|
|
||||||
decoding_tree_node(uint32_t value) : value(value){}
|
|
||||||
};
|
|
||||||
|
|
||||||
decoding_tree_node* root {nullptr};
|
|
||||||
|
|
||||||
const std::array<instruction_descriptor, ${instructions.size()}> instr_descr = {{
|
const std::array<instruction_descriptor, ${instructions.size()}> instr_descr = {{
|
||||||
/* entries are: size, valid value, valid mask, function ptr */<%instructions.each{instr -> %>
|
/* entries are: size, valid value, valid mask, function ptr */<%instructions.each{instr -> %>
|
||||||
|
@ -158,6 +150,9 @@ private:
|
||||||
{${instr.length}, ${instr.encoding}, ${instr.mask}, &this_class::__${generator.functionName(instr.name)}},<%}%>
|
{${instr.length}, ${instr.encoding}, ${instr.mask}, &this_class::__${generator.functionName(instr.name)}},<%}%>
|
||||||
}};
|
}};
|
||||||
|
|
||||||
|
//needs to be declared after instr_descr
|
||||||
|
decoder instr_decoder;
|
||||||
|
|
||||||
/* instruction definitions */<%instructions.eachWithIndex{instr, idx -> %>
|
/* instruction definitions */<%instructions.eachWithIndex{instr, idx -> %>
|
||||||
/* instruction ${idx}: ${instr.name} */
|
/* instruction ${idx}: ${instr.name} */
|
||||||
compile_ret_t __${generator.functionName(instr.name)}(virt_addr_t& pc, code_word_t instr, tu_builder& tu){
|
compile_ret_t __${generator.functionName(instr.name)}(virt_addr_t& pc, code_word_t instr, tu_builder& tu){
|
||||||
|
@ -198,59 +193,6 @@ private:
|
||||||
vm_impl::gen_trap_check(tu);
|
vm_impl::gen_trap_check(tu);
|
||||||
return BRANCH;
|
return BRANCH;
|
||||||
}
|
}
|
||||||
|
|
||||||
//decoding functionality
|
|
||||||
|
|
||||||
void populate_decoding_tree(decoding_tree_node* root){
|
|
||||||
//create submask
|
|
||||||
for(auto instr: root->instrs){
|
|
||||||
root->submask &= instr.mask;
|
|
||||||
}
|
|
||||||
//put each instr according to submask&encoding into children
|
|
||||||
for(auto instr: root->instrs){
|
|
||||||
bool foundMatch = false;
|
|
||||||
for(auto child: root->children){
|
|
||||||
//use value as identifying trait
|
|
||||||
if(child->value == (instr.value&root->submask)){
|
|
||||||
child->instrs.push_back(instr);
|
|
||||||
foundMatch = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if(!foundMatch){
|
|
||||||
decoding_tree_node* child = new decoding_tree_node(instr.value&root->submask);
|
|
||||||
child->instrs.push_back(instr);
|
|
||||||
root->children.push_back(child);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
root->instrs.clear();
|
|
||||||
//call populate_decoding_tree for all children
|
|
||||||
if(root->children.size() >1)
|
|
||||||
for(auto child: root->children){
|
|
||||||
populate_decoding_tree(child);
|
|
||||||
}
|
|
||||||
else{
|
|
||||||
//sort instrs by value of the mask, this works bc we want to have the least restrictive one last
|
|
||||||
std::sort(root->children[0]->instrs.begin(), root->children[0]->instrs.end(), [](const instruction_descriptor& instr1, const instruction_descriptor& instr2) {
|
|
||||||
return instr1.mask > instr2.mask;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
compile_func decode_instr(decoding_tree_node* node, code_word_t word){
|
|
||||||
if(!node->children.size()){
|
|
||||||
if(node->instrs.size() == 1) return node->instrs[0].op;
|
|
||||||
for(auto instr : node->instrs){
|
|
||||||
if((instr.mask&word) == instr.value) return instr.op;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else{
|
|
||||||
for(auto child : node->children){
|
|
||||||
if (child->value == (node->submask&word)){
|
|
||||||
return decode_instr(child, word);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return nullptr;
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
template <typename CODE_WORD> void debug_fn(CODE_WORD instr) {
|
template <typename CODE_WORD> void debug_fn(CODE_WORD instr) {
|
||||||
|
@ -262,13 +204,16 @@ template <typename ARCH> vm_impl<ARCH>::vm_impl() { this(new ARCH()); }
|
||||||
|
|
||||||
template <typename ARCH>
|
template <typename ARCH>
|
||||||
vm_impl<ARCH>::vm_impl(ARCH &core, unsigned core_id, unsigned cluster_id)
|
vm_impl<ARCH>::vm_impl(ARCH &core, unsigned core_id, unsigned cluster_id)
|
||||||
: vm_base<ARCH>(core, core_id, cluster_id) {
|
: vm_base<ARCH>(core, core_id, cluster_id)
|
||||||
root = new decoding_tree_node(std::numeric_limits<uint32_t>::max());
|
, instr_decoder([this]() {
|
||||||
for(auto instr:instr_descr){
|
std::vector<generic_instruction_descriptor> g_instr_descr;
|
||||||
root->instrs.push_back(instr);
|
g_instr_descr.reserve(instr_descr.size());
|
||||||
}
|
for (uint32_t i = 0; i < instr_descr.size(); ++i) {
|
||||||
populate_decoding_tree(root);
|
generic_instruction_descriptor new_instr_descr {instr_descr[i].value, instr_descr[i].mask, i};
|
||||||
|
g_instr_descr.push_back(new_instr_descr);
|
||||||
}
|
}
|
||||||
|
return std::move(g_instr_descr);
|
||||||
|
}()) {}
|
||||||
|
|
||||||
template <typename ARCH>
|
template <typename ARCH>
|
||||||
std::tuple<continuation_e>
|
std::tuple<continuation_e>
|
||||||
|
@ -293,7 +238,10 @@ vm_impl<ARCH>::gen_single_inst_behavior(virt_addr_t &pc, unsigned int &inst_cnt,
|
||||||
if (instr == 0x0000006f || (instr&0xffff)==0xa001) throw simulation_stopped(0); // 'J 0' or 'C.J 0'
|
if (instr == 0x0000006f || (instr&0xffff)==0xa001) throw simulation_stopped(0); // 'J 0' or 'C.J 0'
|
||||||
// curr pc on stack
|
// curr pc on stack
|
||||||
++inst_cnt;
|
++inst_cnt;
|
||||||
auto f = decode_instr(root, instr);
|
uint32_t inst_index = instr_decoder.decode_instr(instr);
|
||||||
|
compile_func f = nullptr;
|
||||||
|
if(inst_index < instr_descr.size())
|
||||||
|
f = instr_descr[inst_index].op;
|
||||||
if (f == nullptr) {
|
if (f == nullptr) {
|
||||||
f = &this_class::illegal_instruction;
|
f = &this_class::illegal_instruction;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue