ETISS 0.8.0
Extendable Translating Instruction Set Simulator (version 0.8.0)
All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Modules Pages
Instruction.h
Go to the documentation of this file.
1
59#ifndef ETISS_INCLUDE_INSTRUCTION_H_
60#define ETISS_INCLUDE_INSTRUCTION_H_
61
62#include "etiss/Misc.h"
63
64#include "etiss/CodePart.h"
65
66#include <climits>
67#include <cstring>
68#include <iomanip>
69#include <sstream>
70#include <stdexcept>
71#include <string>
72#include <boost/dynamic_bitset.hpp>
73
74namespace etiss
75{
76
77namespace instr
78{
79
80typedef uint32_t I;
81
82class Instruction;
88
92class Buffer {
93public:
94 I* d_;
95 unsigned intcount_;
96public:
97 Buffer(): d_(nullptr), intcount_(0) {}
98 Buffer(const Buffer& o) : d_(new I[o.intcount_]), intcount_(o.intcount_){
99 *this = o;
100 }
102 o.d_ = nullptr;
103 }
104 Buffer(unsigned intcount) : d_(new I[intcount]), intcount_(intcount) {
105 for (unsigned i = 0; i < intcount_; i++) d_[i] = 0;
106 }
107 Buffer(unsigned intcount, I val) : Buffer(intcount) {
108 *d_ = val;
109 }
111 clear();
112 }
113
115 if (o.intcount_ != intcount_)
116 throw std::runtime_error("operator= called with incompatible bit array");
117 for (unsigned i = 0; i < intcount_; i++)
118 d_[i] = o.d_[i];
119 return *this;
120 }
121
123 clear();
124 intcount_ = o.intcount_;
125 d_ = o.d_;
126 o.d_ = nullptr;
127 return *this;
128 }
129
130 void clear(){
131 if(d_) delete[] d_;
132 }
138 char *internalBuffer();
142 unsigned internalBufferSize();
143
144 I data(){return *d_;}
149 void recoverFromEndianness(unsigned alignment, endian_t endianness);
150};
151
155typedef std::set<Instruction*> Node;
156
160class BitArray : public boost::dynamic_bitset<>
161{
162private:
163 typedef boost::dynamic_bitset<> super;
164public:
165 using super::dynamic_bitset;
166 BitArray(const super& a) : super(a){} // hack for parent's explicit constructors
167
171 unsigned byteCount() const;
175 unsigned intCount() const;
179 void set_value(size_type width, unsigned long value);
180 void set_value(unsigned long value);
184 BitArray get_range(size_type end, size_type start) const;
188 void set_range(unsigned long val, size_type end, size_type start);
195 static std::vector<BitArray> permutate(const BitArray& input, std::vector<size_type> indexes);
199 std::string to_string() const;
200};
201
208{
209public:
211private:
212 BitArray::size_type startpos;
213 BitArray::size_type endpos;
214public:
219 BitArrayRange(unsigned endindex_included, unsigned startindex_included);
220
225 I read(const BitArray& ba);
229 void write(BitArray &ba, I val);
233 BitArray::size_type start();
238 BitArray::size_type end();
239};
240
272{
273 public:
276 template <typename T, typename = typename std::enable_if<std::is_integral<T>::value, T>::type>
283 OPCode(unsigned width, const T code, const T mask) : code_(width, code & mask), mask_(width, mask)
284 {
285#if DEBUG
286 if ((code & mask) != code)
287 {
288 etiss::log(etiss::WARNING, "etiss::instr::OPCode constructed with mismatched code and mask");
289 }
290 if (width != 16 && width != 32 && width != 64 && width != 128 && width != 256)
291 {
292 etiss::log(etiss::VERBOSE, std::string("OPCode with unusual width: ") + toString(width) +
293 "[width must be given in bits and is usually 16,32,64,128,256 bits long]");
294 }
295#endif
296 }
297
301 OPCode(const BitArray &code, const BitArray &mask);
302
306 OPCode(const OPCode &cpy);
307
312 bool operator<(const OPCode &o) const;
313 inline bool operator==(const OPCode &o) const { return !((*this < o) || (o < *this)); }
314 inline bool operator!=(const OPCode &o) const { return !((*this) == o); }
315};
316
320struct less
321{
322 bool operator()(const OPCode *const &o1, const OPCode *const &o2) const;
323};
324
337{
338
339 public:
341
342 inline InstructionContext()
343 {
344 }
345
348 unsigned instr_width_;
355 unsigned &ufield(std::string name);
356 template <typename T>
362 uint64_t &ufield(const T &plugin, std::string name)
363 {
364 return lufields_[&plugin][name];
365 }
368
369 public:
371 // common fields
373
374 private:
375 std::map<std::string, unsigned> ufields_;
377 std::map<void *, std::map<std::string, uint64_t>>
379};
380
393{
394 private:
395 std::list<std::tuple<std::function<bool(BitArray &, etiss::CodeSet &, InstructionContext &)>, uint32_t,
396 std::set<uint32_t>>> callbacks_;
398 std::set<uint32_t> groups_;
399 std::function<std::string(BitArray &, Instruction &)> printer_;
400 public:
402
403 enum class BUILTINGROUP : uint32_t {
404 CPUTIMEUPDATE = 1 << 0
406 };
407
408 const BitArray::size_type width;
410 const std::string name_;
411
412 static std::string printASMSimple(BitArray &ba, Instruction &instr);
413
414 Instruction(const OPCode &opc, const std::string &name);
415 template <typename T, typename = typename std::enable_if<std::is_integral<T>::value, T>::type>
416 Instruction(unsigned width, const T code, const T mask, const std::string &name)
417 : builtinGroups_(0), printer_(printASMSimple), width(width), opc_(OPCode(width, code, mask)), name_(name)
418 {
419 }
420 virtual std::string print(std::string indent, I pos, unsigned pfillwidth, bool printunused = false);
421 bool addCallback(std::function<bool(BitArray &, etiss::CodeSet &, InstructionContext &)> callback,
422 uint32_t builtinGroups, const std::set<uint32_t> &groups = std::set<uint32_t>());
423 bool translate(BitArray &, CodeSet &cs, InstructionContext &context);
425 std::set<uint32_t> &presentGroups();
426 std::string printASM(BitArray &);
427 void setASMPrinter(std::function<std::string(BitArray &, Instruction &)> printer);
428 inline std::string toString() const { return name_; }
429};
430
442{
443 public:
445
446 VariableInstructionSet &parent_;
447 const std::string name_;
448 const unsigned width_;
449 const unsigned chunk_size;
450 InstructionSet(VariableInstructionSet &parent, unsigned width, const std::string &name, unsigned c_size=4);
452
453 Instruction *get(const OPCode &key);
454 Instruction &open(const OPCode &key, const std::string &name);
455 Instruction *create(const OPCode &key, const std::string &name);
456
457 template <typename T>
458 Instruction &open(T code, T val, const std::string &name)
459 {
460 return open(OPCode(width_, code, val), name);
461 }
462
463 bool compile();
464 bool compile(Node* node, BitArray code, Instruction* instr);
465
468
469 std::string print(std::string prefix, bool printunused = false);
470
472
473 void foreach (std::function<void(Instruction &)> func);
474
475 size_t size();
476
477 inline std::string toString() const { return name_; }
478
479 private:
480 std::map<const OPCode *, Instruction *, etiss::instr::less> instrmap_;
481
482 Node** root_; // holds the entry of the bucket tree in decoding and compilition algorithm
483
485};
486
500{
501 private:
502 std::map<unsigned, InstructionSet *> ismap_;
503
504 public:
506 unsigned width_;
507 const std::string archname_;
509
510 public:
512
515 bool compile();
516
517 InstructionSet *get(unsigned width);
518 InstructionSet *create(unsigned width, const std::string &name = std::string());
519 InstructionSet &open(unsigned width, const std::string &name = std::string());
520 inline InstructionSet *getMain() { return get(width_); }
521 inline InstructionSet *createMain(const std::string &name = std::string()) { return create(width_); }
522 inline InstructionSet &openMain(const std::string &name = std::string()) { return open(width_); }
523
524 template <typename T>
525 Instruction &open(unsigned bits, T code, T mask, const char *name)
526 {
527#if DEBUG
528 unsigned bytes = bits >> 3;
529 if (bytes * 8 != bits)
530 {
531 etiss_log(ERROR, "Invalid bit count");
532 throw std::runtime_error();
533 }
534#endif
535 return open(bits).open<T>(bits, code, mask, std::string(name));
536 }
537
538 void foreach (std::function<void(InstructionSet &)> func);
539
540 std::string print(std::string prefix = std::string());
541};
542
562{
563 private:
564 std::map<uint32_t, std::string> modetostring_;
565 std::map<std::string, uint32_t> stringtomode_;
566 std::map<uint32_t, VariableInstructionSet *> vismap_;
567 std::map<VariableInstructionSet *, uint32_t> invvismap_;
568
569 public:
570 const std::string archname_;
571
572 public:
574
575 ModedInstructionSet(const std::string &name);
577
579 VariableInstructionSet *create(uint32_t mode, unsigned width, const std::string &name = std::string());
583 VariableInstructionSet &open(uint32_t mode, unsigned width, const std::string &name = std::string());
584
585 template <typename T>
586 Instruction &open(uint32_t mode, unsigned width, unsigned bits, T code, T mask, const char *instrname)
587 {
588 return open(mode, width).open<T>(bits, code, mask, instrname);
589 }
590
592 inline uint32_t getMode(VariableInstructionSet &vis) { return getMode(&vis); }
593
594 void foreach (std::function<void(VariableInstructionSet &)> call);
595
596 bool compile();
597
598 std::string print(std::string prefix = std::string());
599};
600
605{
606 private:
607 std::set<InstructionClass *> classes_;
608 template <typename... T>
609 void add(InstructionClass &klass, T &... args)
610 {
611 classes_.insert(&klass);
612 add(args...);
613 }
614 inline void add() {}
615
616 public:
618
619 const std::string name_; // e.g. ARMv6-M
620 template <typename... T>
621 inline InstructionCollection(const std::string &name, InstructionClass &class1, T &... otherclasses) : name_(name)
622 {
623 add(class1, otherclasses...);
624 }
625 inline void foreach (std::function<void(InstructionClass &)> call)
626 {
627 for (auto iter = classes_.begin(); iter != classes_.end(); iter++)
628 {
629 call(**iter);
630 }
631 }
632 void addTo(ModedInstructionSet &set, bool &ok);
633};
638{
639 private:
640 std::set<InstructionGroup *> groups_;
641 template <typename... T>
642 void add(InstructionGroup &group, T &... args)
643 {
644 groups_.insert(&group);
645 add(args...);
646 }
647 inline void add() {}
648
649 public:
650 const unsigned mode_; // e.g. 0 for ARM 1 for thumb
651 const std::string name_; // e.g. ARM
652 const unsigned width_; // most common read width (fastest)
653 public:
655
656 template <typename... T>
657 InstructionClass(unsigned mode, const std::string &name, unsigned width, InstructionGroup &group1,
660 {
662 }
663 inline void foreach (std::function<void(InstructionGroup &)> call)
664 {
665 for (auto iter = groups_.begin(); iter != groups_.end(); iter++)
666 {
667 call(**iter);
668 }
669 }
670 void addTo(VariableInstructionSet &set, bool &ok);
671};
672
677{
679
680 private:
681 std::set<InstructionDefinition *> defs_;
682
683 public:
684 const std::string name_; // e.g. thumb / thumb-2
685 const unsigned width_; // e.g. 16/32 bits
686 public:
688
689 inline InstructionGroup(const std::string &name, unsigned width)
690 : name_(name), width_(width)
691 {
692 }
693 inline void foreach (std::function<void(InstructionDefinition &)> call)
694 {
695 for (auto iter = defs_.begin(); iter != defs_.end(); iter++)
696 {
697 call(**iter);
698 }
699 }
700 void addTo(InstructionSet &set, bool &ok);
701 inline std::string toString() const { return name_; }
702};
703
708{
709 public:
711 const std::string name_;
714 const std::function<std::string(BitArray &, Instruction &)> ASMprinter_;
716
717 public:
719
720 template <typename T>
721 InstructionDefinition(InstructionGroup &ig, const std::string &name, T code, T mask,
723 uint32_t builtinGroups, std::function<std::string(BitArray &, Instruction &)> ASMprinter)
724 : group_(ig)
726 , opc_(ig.width_, code, mask)
730 {
731 if (!callback)
732 {
733 etiss_log(
735 (std::string(
736 "Instruction defined without a function callback: ") +
737 name));
738 return;
739 }
740 group_.defs_.insert(this);
741 }
743 {
744 // group_.defs_.erase(this); // removed since InstructionDefinition should not be deleted during execution
745 }
746 void addTo(Instruction &set, bool &ok);
747 inline std::string toString() const { return group_.name_ + ":" + name_; }
748};
749
750#if __cplusplus >= 201103L
751uint32_t operator"" _i32(const char *s);
752#endif
753
754uint32_t parse_i32(const char *s);
755
756template <typename T_>
791typename std::enable_if<std::is_integral<T_>::value, typename std::make_unsigned<T_>::type>::type parse_i(
792 const char *s, bool *good = 0)
793{
794 if (good)
795 *good = true;
796 typedef typename std::make_unsigned<T_>::type U;
797 unsigned shifted = 0;
798 unsigned pos = 0;
799 int mode = 0;
800 U tmp = 0;
801 U ret = 0;
802 U mask = 0;
803 do
804 {
805 switch (mode)
806 {
807 case 0:
808 if (s[pos] >= '0' && s[pos] <= '9')
809 {
810 tmp = tmp * 10 + s[pos] - '0';
811 }
812 else if (s[pos] == 'x' || s[pos] == 'x')
813 {
814 mask = 0;
815 ret = ret << tmp;
816 shifted += tmp;
817 for (unsigned i = 0; i < tmp; i++)
818 mask = (mask << 1) | 1;
819 tmp = 0;
820 mode = 1;
821 }
822 else if (s[pos] == ' ' || s[pos] == '\t')
823 {
824 // ignore spaces
825 // TODO only ignore leading spaces
826 }
827 else
828 {
829 if (good)
830 *good = false;
831 etiss::log(etiss::ERROR, std::string("Failed to parse literal ") + s);
832 return (U)(T_)-1;
833 }
834 break;
835 case 1:
836 if (s[pos] >= '0' && s[pos] <= '9')
837 {
838 tmp = tmp * 16 + s[pos] - '0';
839 }
840 else if (s[pos] >= 'a' && s[pos] <= 'f')
841 {
842 tmp = tmp * 16 + s[pos] + 10 - 'a';
843 }
844 else if (s[pos] >= 'A' && s[pos] <= 'F')
845 {
846 tmp = tmp * 16 + s[pos] + 10 - 'A';
847 }
848 else if (s[pos] == ' ' || s[pos] == '\t' || s[pos] == 0)
849 {
850 // complain if hex is shorter than bit length?
851 ret = ret | (tmp & mask);
852 tmp = 0;
853 mode = 0;
854 }
855 else
856 {
857 if (good)
858 *good = false;
859 etiss::log(etiss::ERROR, std::string("Failed to parse literal ") + s);
860 return (U)(T_)-1;
861 }
862 }
863 } while (s[pos++] != 0);
864
865 if (shifted != 32)
866 {
867 if (good)
868 *good = false;
869 etiss::log(etiss::ERROR, std::string("Failed to parse literal due to invalid length: ") + s);
870 // return (U)(T_)-1; return the parsed value anyway
871 }
872
873 return ret;
874}
875
876} // namespace instr
877
878} // namespace etiss
879#endif
classes to hold code and additional information used for optimization of instruction translations
general configuration and logging
#define etiss_del_como(CLASS)
Definition Misc.h:94
#define etiss_log(LEVEL, MSG)
Definition Misc.h:83
__device__ __2f16 float bool s
static __inline__ uint32_t
Definition arm_cde.h:25
static __inline__ uint64_t
Definition arm_cde.h:31
A set of CodeParts.
Definition CodePart.h:437
Marker interface for toString() support.
Definition Misc.h:137
Reading through it will only return bits within the range.
BitArray::size_type end()
lowest bit of the range (included).
BitArray::size_type start()
highest bit of the range (included)
etiss_del_como(BitArrayRange) private BitArray::size_type endpos
void write(BitArray &ba, I val)
write the bit from the passed value starting at the lsb to the range.
I read(const BitArray &ba)
reads bits from the range to the return value starting at the lsb.
stores a bit vector
static std::vector< BitArray > permutate(const BitArray &input, std::vector< size_type > indexes)
permutates the given input at the specified indexes.
void set_value(size_type width, unsigned long value)
change the value the object is holding
BitArray get_range(size_type end, size_type start) const
get the interval [end, start]
BitArray(const super &a)
unsigned byteCount() const
std::string to_string() const
string representation of the BitArray
unsigned intCount() const
boost::dynamic_bitset super
void set_range(unsigned long val, size_type end, size_type start)
set the value to the interval [end, start]
Buffer for reading data from memory while instructions are being fetched.
Definition Instruction.h:92
Buffer(unsigned intcount)
Buffer(const Buffer &o)
Definition Instruction.h:98
unsigned internalBufferSize()
Buffer(unsigned intcount, I val)
char * internalBuffer()
get the internal buffer
Buffer & operator=(Buffer &&o)
void recoverFromEndianness(unsigned alignment, endian_t endianness)
changes byte positions as needed to resove endiannes incompabilities after using the internal buffer ...
Buffer & operator=(const Buffer &o)
maps to VariableInstructionSet
void addTo(VariableInstructionSet &set, bool &ok)
void add(InstructionGroup &group, T &... args)
const std::string unsigned InstructionGroup T & othergroups
etiss_del_como(InstructionClass) template< typename... T > InstructionClass(unsigned mode
std::set< InstructionGroup * > groups_
const std::string unsigned width
const std::string unsigned InstructionGroup & group1
maps to ModedInstructionSet
void add(InstructionClass &klass, T &... args)
void addTo(ModedInstructionSet &set, bool &ok)
std::set< InstructionClass * > classes_
etiss_del_como(InstructionCollection) const std InstructionCollection(const std::string &name, InstructionClass &class1, T &... otherclasses)
this class contains parameters that persist in between instruction lookpus/translation within a trans...
std::map< std::string, unsigned > ufields_
additional fields that can be used by any plugin/architecture.
uint64_t current_local_address_
address within the current block
bool is_not_default_width_
if true the this instruction is not as long as the width of the variable instruction set
bool force_block_end_
if true then the block ends after the current instruction.
unsigned & ufield(std::string name)
std::map< void *, std::map< std::string, uint64_t > > lufields_
additonal fields that are local (private) to a plugin/architecture.
bool instr_width_fully_evaluated_
if true the length_updater_ function will be called again after instr_width_ bits are available
uint64_t & ufield(const T &plugin, std::string name)
returns a persistent field
uint64_t current_address_
start address of current instruction
etiss_del_como(InstructionContext) inline InstructionContext()
instruction context is initialized by etiss::Translation class
bool force_append_next_instr_
if true then the block will continue with the next instruction and cannot be terminated
const std::string T T std::function< bool(BitArray &, etiss::CodeSet &, InstructionContext &)> uint32_t builtinGroups
void addTo(Instruction &set, bool &ok)
const std::string T T std::function< bool(BitArray &, etiss::CodeSet &, InstructionContext &)> callback
const std::function< bool(BitArray &, etiss::CodeSet &, InstructionContext &)> callback_
const std::string T T std::function< bool(BitArray &, etiss::CodeSet &, InstructionContext &)> uint32_t std::function< std::string(BitArray &, Instruction &)> ASMprinter
const std::function< std::string(BitArray &, Instruction &)> ASMprinter_
etiss_del_como(InstructionDefinition) template< typename T > InstructionDefinition(InstructionGroup &ig
maps to InstructionSet
std::string toString() const
etiss_del_como(InstructionGroup) inline InstructionGroup(const std
void addTo(InstructionSet &set, bool &ok)
std::set< InstructionDefinition * > defs_
holds etiss::instr::Instruction instances and handles automatic instruction tree creation.
etiss_del_como(InstructionSet) VariableInstructionSet &parent_
std::map< const OPCode *, Instruction *, etiss::instr::less > instrmap_
Instruction * get(const OPCode &key)
std::string print(std::string prefix, bool printunused=false)
Instruction * resolve(BitArray &instr)
Instruction * resolve(Node *node, BitArray &instr)
bool compile(Node *node, BitArray code, Instruction *instr)
std::string toString() const
Instruction * create(const OPCode &key, const std::string &name)
Instruction & open(const OPCode &key, const std::string &name)
Instruction & open(T code, T val, const std::string &name)
holds information and translation callbacks for an instruction.
bool addCallback(std::function< bool(BitArray &, etiss::CodeSet &, InstructionContext &)> callback, uint32_t builtinGroups, const std::set< uint32_t > &groups=std::set< uint32_t >())
std::set< uint32_t > & presentGroups()
bool translate(BitArray &, CodeSet &cs, InstructionContext &context)
uint32_t & presentBuiltinGroups()
void setASMPrinter(std::function< std::string(BitArray &, Instruction &)> printer)
Instruction(unsigned width, const T code, const T mask, const std::string &name)
const std::string name_
std::function< std::string(BitArray &, Instruction &)> printer_
static std::string printASMSimple(BitArray &ba, Instruction &instr)
virtual std::string print(std::string indent, I pos, unsigned pfillwidth, bool printunused=false)
std::string printASM(BitArray &)
std::set< uint32_t > groups_
std::list< std::tuple< std::function< bool(BitArray &, etiss::CodeSet &, InstructionContext &)>, uint32_t, std::set< uint32_t > > > callbacks_
etiss_del_como(Instruction) enum class BUILTINGROUP const BitArray::size_type width
std::string toString() const
holds etiss::instr::VariableInstructionSet instances for different modes.
std::string print(std::string prefix=std::string())
uint32_t getMode(VariableInstructionSet &vis)
etiss_del_como(ModedInstructionSet) ModedInstructionSet(const std ~ModedInstructionSet()
std::map< uint32_t, std::string > modetostring_
VariableInstructionSet * create(uint32_t mode, unsigned width, const std::string &name=std::string())
std::map< VariableInstructionSet *, uint32_t > invvismap_
VariableInstructionSet & open(uint32_t mode, unsigned width, const std::string &name=std::string())
Instruction & open(uint32_t mode, unsigned width, unsigned bits, T code, T mask, const char *instrname)
uint32_t getMode(VariableInstructionSet *vis)
std::map< std::string, uint32_t > stringtomode_
VariableInstructionSet * get(uint32_t mode)
std::map< uint32_t, VariableInstructionSet * > vismap_
defines the relevant bits and their value to identify an instruction.
bool operator!=(const OPCode &o) const
OPCode(unsigned width, const T code, const T mask)
ctor that uses integral values for mask and code
const BitArray code_
bool operator==(const OPCode &o) const
bool operator<(const OPCode &o) const
comparison operator for map/sets.
const BitArray mask_
holds etiss::instr::InstructionSet instances with different bit widths.
InstructionSet & open(unsigned width, const std::string &name=std::string())
std::string print(std::string prefix=std::string())
InstructionSet * get(unsigned width)
InstructionSet & openMain(const std::string &name=std::string())
std::map< unsigned, InstructionSet * > ismap_
Instruction & open(unsigned bits, T code, T mask, const char *name)
unsigned const std::string & archname
InstructionSet * create(unsigned width, const std::string &name=std::string())
etiss_del_como(VariableInstructionSet) VariableInstructionSet(ModedInstructionSet &
std::function< void(VariableInstructionSet &, InstructionContext &, BitArray &)> length_updater_
InstructionSet * createMain(const std::string &name=std::string())
std::set< Instruction * > Node
Holding unique instruction sets code chunks after permutation.
std::enable_if< std::is_integral< T_ >::value, typenamestd::make_unsigned< T_ >::type >::type parse_i(const char *s, bool *good=0)
this parser basically allows to write as a string hexadecimal values which will be appended as if it ...
BitArray::size_type size_type
uint32_t I
Definition Instruction.h:80
uint32_t parse_i32(const char *s)
Page Table Entry (PTE) defines the composition of Page Frame Number (PFN) and relavant flags.
Definition Benchmark.h:53
std::string toString(const T &val)
conversion of type T to std::string.
Definition Misc.h:174
endian_t
Enumeration type for the endianness.
Definition Misc.h:525
@ VERBOSE
Definition Misc.h:130
@ WARNING
Definition Misc.h:128
@ ERROR
Definition Misc.h:127
@ FATALERROR
Definition Misc.h:126
void log(Verbosity level, std::string msg)
write log message at the given level.
Definition Misc.cpp:125
STL namespace.
#define bool
Definition stdbool.h:15
calls operator< of the objects.
bool operator()(const OPCode *const &o1, const OPCode *const &o2) const