ETISS 0.11.2
ExtendableTranslatingInstructionSetSimulator(version0.11.2)
Loading...
Searching...
No Matches
Instruction.cpp
Go to the documentation of this file.
1// SPDX-License-Identifier: BSD-3-Clause
2//
3// This file is part of ETISS. It is licensed under the BSD 3-Clause License; you may not use this file except in
4// compliance with the License. You should have received a copy of the license along with this project. If not, see the
5// LICENSE file.
14#include "etiss/Instruction.h"
15
16#include <sstream>
17#include <cassert>
18#include <cmath>
19#if ETISS_USE_BYTESWAP_H
20#include <byteswap.h>
21#endif
22
23namespace etiss
24{
25
26namespace instr
27{
28
29typedef BitArray::size_type size_type;
30
32{
33 return static_cast<char *>(static_cast<void *>(d_));
34}
36{
37 return intcount_ * sizeof(I);
38}
39
40void Buffer::recoverFromEndianness(unsigned alignment, endian_t endianness)
41{
42 if (intcount_ <= 0)
43 return;
44
45#if ETISS_USE_BYTESWAP_H
46 if (sizeof(I) == alignment)
47 {
48 if (endianness != getEndianness())
49 {
50 if (sizeof(I) == 4)
51 {
52 for (unsigned i = 0; i < intcount_; i++)
53 {
54 d_[i] = __bswap_32(d_[i]);
55 }
56 }
57 else
58 {
59 // TODO
60 etiss::log(etiss::FATALERROR, "bit swap notimplemented for this case", alignment, endianness, sizeof(I),
62 }
63 }
64 }
65 else
66 {
67 etiss::log(etiss::FATALERROR, "bit swap notimplemented for this case", alignment, endianness, sizeof(I),
69 }
70#else
71
72 if (sizeof(I) == alignment)
73 {
74 if (endianness != getEndianness())
75 {
76 for (unsigned i = 0; i < intcount_; i++)
77 {
78 for (unsigned j = 0; j < (sizeof(I) >> 1); j++)
79 {
80 int8_t tmp = ((int8_t *)&(d_[i]))[j];
81 ((int8_t *)&(d_[i]))[j] = ((int8_t *)&(d_[i]))[sizeof(I) - 1 - j];
82 ((int8_t *)&(d_[i]))[sizeof(I) - 1 - j] = tmp;
83 }
84 }
85 }
86 }
87 else
88 {
89 etiss::log(etiss::FATALERROR, "bit swap notimplemented for this case", alignment, endianness, sizeof(I),
91 }
92
93#endif
94}
95
96unsigned BitArray::byteCount() const
97{
98 unsigned mod = size() % (8);
99 unsigned ret = (size() - mod) / (8);
100 if (mod > 0)
101 ret++;
102 return ret;
103}
104unsigned BitArray::intCount() const
105{
106 unsigned mod = size() % (sizeof(I) * 8);
107 unsigned ret = (size() - mod) / (sizeof(I) * 8);
108 if (mod > 0)
109 ret++;
110 return ret;
111}
112
113std::vector<BitArray> BitArray::permutate(const BitArray &input, std::vector<size_type> indexes)
114{
115 std::vector<BitArray> results{ input };
116 int count = 0;
117 for (const auto &i : indexes)
118 {
119 for (int j = 0; j < (1 << count); j++)
120 {
121 results.push_back(results[j]);
122 results[j].flip(i);
123 results.push_back(results[j]);
124 }
125 results.erase(results.begin(), results.begin() + (1 << count));
126 count++;
127 }
128 return results;
129}
130
131void BitArray::set_value(size_type width, unsigned long value)
132{
133 BitArray b(width, value);
134 *this = b;
135}
136
137void BitArray::set_value(unsigned long value)
138{
139 set_value(size(), value);
140}
141
143{
144 // shift the bits and resize it accordingly
145 BitArray ret = *this;
146 ret >>= start;
147 ret.resize(end - start + 1);
148 return ret;
149}
150
151void BitArray::set_range(unsigned long val, size_type end, size_type start)
152{
153 auto len = end - start + 1;
154 BitArray range(len, val);
155 for (size_type i = 0; i < len; ++i)
156 (*this)[i + start] = range[i];
157}
158
159std::string BitArray::to_string() const
160{
161 std::string s;
162 boost::to_string(*this, s);
163 return s;
164}
165
166BitArrayRange::BitArrayRange(unsigned endindex_included, unsigned startindex_included)
167 : startpos(startindex_included), endpos(endindex_included)
168{
169}
170
172{
173 assert(ba.size() >= (endpos - startpos + 1) && "BitArrayRange outside of BitArray");
174 auto range = ba.get_range(endpos, startpos);
175 return range.to_ulong();
176}
177
179{
180 assert(ba.size() >= (endpos - startpos + 1) && "BitArrayRange outside of BitArray");
181 ba.set_range(val, endpos, startpos);
182}
183
184BitArray::size_type BitArrayRange::start()
185{
186 return startpos;
187}
188
189BitArray::size_type BitArrayRange::end()
190{
191 return endpos;
192}
193
194OPCode::OPCode(const BitArray &code, const BitArray &mask) : code_(code & mask), mask_(mask)
195{
196 if (code_.size() != mask_.size())
197 {
198 etiss::log(etiss::ERROR, "etiss::instr::OPCode constructed with code and mask of different widths");
199 throw std::runtime_error("etiss::instr::OPCode constructed with code and mask of different widths");
200 }
201#if DEBUG
202 if (!((code & mask) == code))
203 {
204 etiss::log(etiss::WARNING, "etiss::instr::OPCode constructed with mismatched code and mask");
205 }
206#endif
207}
208
209OPCode::OPCode(const OPCode &cpy) : code_(cpy.code_), mask_(cpy.mask_) {}
210
211bool OPCode::operator<(const OPCode &o) const
212{
213 if (mask_ != o.mask_)
214 return mask_ < o.mask_;
215 if (code_ != o.code_)
216 return code_ < o.code_;
217 return false;
218}
219
220bool less::operator()(const OPCode *const &o1, const OPCode *const &o2) const
221{
222
223 if ((o1 == 0) || (o2 == 0))
224 {
225 if (o2 != 0)
226 return true;
227 etiss_log(FATALERROR, "null pointer passed to etiss::instr::less");
228 return false;
229 }
230
231 return (*o1) < (*o2);
232}
233
234unsigned &InstructionContext::ufield(std::string name)
235{
236 return ufields_[name];
237}
238
239Instruction::Instruction(const OPCode &opc, const std::string &name)
240 : builtinGroups_(0), printer_(printASMSimple), width(opc.code_.size()), opc_(opc), name_(name)
241{
242}
244{
245 std::stringstream ss;
246 ss << instr.name_ << " # 0x" << ba << " [UNKNOWN PARAMETERS]";
247 return ss.str();
248}
249
250std::string Instruction::print(std::string indent, I pos, unsigned pfillwidth, bool printunused)
251{
252 std::stringstream ss;
253 ss.fill('0');
254 ss << indent << "@0x" << std::hex << std::setw(pfillwidth) << pos << std::dec << " Instruction: " << name_ << "\n";
255 return ss.str();
256}
257bool Instruction::addCallback(std::function<bool(BitArray &, etiss::CodeSet &, InstructionContext &)> callback,
258 uint32_t builtinGroups, const std::set<uint32_t> &groups)
259{
260
261 if ((builtinGroups_ & builtinGroups) != 0)
262 {
263 etiss::log(etiss::VERBOSE, "cannot add instruction translation callback due to overlapping builtin group",
264 *this);
265 return false;
266 }
267 for (auto iter = groups.begin(); iter != groups.end(); iter++)
268 {
269 if (groups_.find(*iter) != groups_.end())
270 {
271 etiss::log(etiss::VERBOSE, "cannot add instruction translation callback due to overlapping group", *this);
272 return false;
273 }
274 }
275
276 if (!callback)
277 {
278 etiss::log(etiss::VERBOSE, "empty instruction translation callback", *this);
279 return false;
280 }
281
282 builtinGroups_ |= builtinGroups;
283 for (auto iter = groups.begin(); iter != groups.end(); iter++)
284 {
285 groups_.insert(*iter);
286 }
287
288 callbacks_.push_back(std::tuple<std::function<bool(BitArray &, etiss::CodeSet &, InstructionContext &)>, uint32_t,
289 std::set<uint32_t>>(callback, builtinGroups, groups));
290
291 return true;
292}
294{
295 bool ok = true;
296 for (auto iter = callbacks_.begin(); iter != callbacks_.end(); iter++)
297 {
298 ok = ok & std::get<0>(*iter)(ba, cs, context);
299 }
300 return ok;
301}
302
307std::set<uint32_t> &Instruction::presentGroups()
308{
309 return groups_;
310}
311
313{
314 return printer_(ba, *this);
315}
316
317void Instruction::setASMPrinter(std::function<std::string(BitArray &, Instruction &)> printer)
318{
319 printer_ = printer;
320 if (!printer_)
322}
323
324InstructionSet::InstructionSet(VariableInstructionSet &parent, unsigned width, const std::string &name, unsigned c_size)
325 : parent_(parent), name_(name), width_(width), chunk_size(c_size), root_(nullptr), invalid(width, -1, -1, "INVALID")
326{
327}
328
330{
331 auto iter = instrmap_.begin();
332 // delete instructions
333 while (iter != instrmap_.end())
334 {
335 Instruction *i = iter->second;
336 instrmap_.erase(iter);
337 iter = instrmap_.begin();
338 delete i;
339 }
340 for (unsigned int i = 0; i < width_ / chunk_size; i++)
341 delete[] root_[i];
342 delete root_;
343}
344
346{
347 auto f = instrmap_.find(&key);
348 if (f != instrmap_.end())
349 {
350 return f->second;
351 }
352 return nullptr;
353}
354Instruction &InstructionSet::open(const OPCode &key, const std::string &name)
355{
356 Instruction *ret = get(key);
357 if (ret != nullptr)
358 return *ret;
359 ret = create(key, name);
360#if DEBUG
361 if (ret == nullptr)
362 {
363 etiss_log(FATALERROR, "should not happen");
364 }
365#endif
366 return *ret;
367}
368Instruction *InstructionSet::create(const OPCode &key, const std::string &name)
369{
370 auto f = instrmap_.find(&key);
371 if (f != instrmap_.end())
372 {
373 return nullptr;
374 }
375 Instruction *ret = new Instruction(key, name);
376 if (instrmap_.insert(std::pair<const OPCode *, Instruction *>(&ret->opc_, ret)).second == false)
377 {
378 etiss::log(ERROR, "Failed to add instruction to instrmap_.", name, *this);
379 delete ret;
380 return nullptr;
381 }
382 return ret;
383}
384
386{
387 delete root_; // cleanup
388
389 root_ = new Node *[width_ / chunk_size](); // number of groups = width_ / chunk_size
390
391 bool ok = true;
392
393 std::vector<size_type> indexes;
394 for (const auto &op2instr : instrmap_)
395 { // iterate through all instructions
396 Instruction *inst = op2instr.second; // current instruction to be assigned
397 BitArray code = op2instr.first->code_; // opcode of the current instruction
398 BitArray mask = op2instr.first->mask_; // mask of the opcode
399
400 // iterate through chunks and permutate chunks. then put them into nodes
401 for (size_type i = 0; i < mask.size() / chunk_size; ++i)
402 {
403 auto chunk_bits_code = code.get_range((i + 1) * chunk_size - 1, i * chunk_size); // ith chunk of the opcode
404 auto chunk_bits_mask = mask.get_range((i + 1) * chunk_size - 1, i * chunk_size); // ith chunk of the mask
405
406 indexes.clear();
407 for (size_type j = 0; j < chunk_bits_mask.size(); ++j)
408 if (!chunk_bits_mask[j])
409 indexes.push_back(j); // these indexed should be permutated since
410 // they dont have associated mask bit
411
412 if (!(root_[i])) // not initialized
413 root_[i] = new Node[(int)std::pow(2, chunk_size)]; // each group has 2^(chunksize) nodes
414
415 auto permutated_chunk_codes = BitArray::permutate(chunk_bits_code, indexes); // put permutated codes
416
417 for (const auto &permutated_chunk : permutated_chunk_codes)
418 {
419 auto val = permutated_chunk.to_ulong(); // index of the node based on the value of the chunk
420 root_[i][val].insert(inst); // assign the current instruction to the associated node
421 }
422 }
423 }
424 return ok;
425}
426
428{
429 std::set<Instruction *> results;
430 for (size_type i = 0; i < instr.size() / chunk_size; ++i)
431 { // divide the incoming bitarray into chunks
432 auto chunk_bits_code = instr.get_range((i + 1) * chunk_size - 1, i * chunk_size); // get ith chunk
433
434 auto val = chunk_bits_code.to_ulong(); // the value chunk is evaluated to,
435 // which is also the index of the associated node
436 auto instrs_in_node = root_[i][val]; // val'th node
437
438 if (i == 0)
439 results = instrs_in_node;
440 else
441 { // intersect all the associated nodes, the result will be the decoded instruction
442 std::set<Instruction *> results_o;
443 std::set_intersection(
444 results.begin(), results.end(), // intersect the ith node with the
445 instrs_in_node.begin(), instrs_in_node.end(), // current results
446 std::inserter(results_o, results_o.begin())); // put overlapped instructions to results_o
447 results = results_o; // write the overlapped instructions to results
448 }
449 }
450
451 if (results.empty())
452 return nullptr; // there is no overlapped instruction after the decoding
453 else if (results.size() == 1)
454 return *(results.begin()); // instruction is found succesfully
455 else
456 {
457 // sometimes an instruction can be a subset of another instruction and hence the
458 // algorithm can find multiple instruction. In such cases, it is returning the parent
459 // instruction by simply returning the instrucion whose opcode is the longest,
460 // i.e mask has the most 1-bits.
461 auto longest =
462 std::max_element(results.begin(), results.end(), [](const Instruction *lhs, const Instruction *rhs)
463 { return lhs->opc_.mask_.count() < rhs->opc_.mask_.count(); });
464 return *longest;
465 }
466}
467
468std::string InstructionSet::print(std::string prefix, bool printunused)
469{
470 if (root_ != nullptr)
471 {
472 std::stringstream ss;
473 ss << prefix << name_ << "[" << width_ << "]:\n";
474 return ss.str();
475 }
476 else
477 {
478 return "EMPTY\n";
479 }
480}
481
486
487void InstructionSet::foreach (std::function<void(Instruction &)> func)
488{
489 for (auto iter = instrmap_.begin(); iter != instrmap_.end(); iter++)
490 {
491#if DEBUG
492 if (iter->second != nullptr)
493 {
494#endif
495 func(*iter->second);
496#if DEBUG
497 }
498 else
499 {
500 etiss::log(etiss::ERROR, "InstructionSet::getInvalid found a null pointer");
501 }
502#endif
503 }
504}
505
507{
508 return instrmap_.size();
509}
510
511VariableInstructionSet::VariableInstructionSet(ModedInstructionSet &parent, unsigned width, const std::string &archname)
512 : parent_(parent), width_(width), archname_(archname)
513{
514 length_updater_ = [this](VariableInstructionSet &, InstructionContext &con, BitArray &)
515 {
516 con.is_not_default_width_ = false;
517 con.instr_width_ = width_;
518 };
519}
521{
522 // delete instruction set
523 for (auto iter = ismap_.begin(); iter != ismap_.end(); iter++)
524 {
525 delete iter->second;
526 }
527}
528
530{
531 bool ok = true;
532 for (auto iter = ismap_.begin(); iter != ismap_.end();)
533 {
534 if (iter->second->size() <= 0)
535 {
536 etiss::log(etiss::WARNING, "Removed empty etiss::instr::InstructionSet during compilation.", *iter->second);
537 ismap_.erase(iter++);
538 }
539 else
540 {
541 ok = ok & iter->second->compile();
542 iter++;
543 }
544 }
545 if (ismap_.begin() != ismap_.end())
546 width_ = ismap_.begin()->first;
547 return ok;
548}
549
551{
552 auto f = ismap_.find(width);
553 if (f != ismap_.end())
554 return f->second;
555 return nullptr;
556}
557InstructionSet *VariableInstructionSet::create(unsigned width, const std::string &name)
558{
559 auto f = ismap_.find(width);
560 if (f != ismap_.end())
561 return nullptr;
562 InstructionSet *ret = new InstructionSet(*this, width, name);
563 ismap_[width] = ret;
564 return ret;
565}
566InstructionSet &VariableInstructionSet::open(unsigned width, const std::string &name)
567{
568 InstructionSet *ret = get(width);
569 if (ret != nullptr)
570 {
571 return *ret;
572 }
573 return *create(width, name);
574}
575
576void VariableInstructionSet::foreach (std::function<void(InstructionSet &)> call)
577{
578 for (auto iter = ismap_.begin(); iter != ismap_.end(); iter++)
579 {
580 if (iter->second != nullptr)
581 {
582 call(*(iter->second));
583 }
584 else
585 {
586 etiss_log(ERROR, "invalid pointer in ismap_.");
587 }
588 }
589}
590
591std::string VariableInstructionSet::print(std::string prefix)
592{
593 std::stringstream ss;
594 ss << prefix << archname_ << "[default: " << width_ << "]:\n";
595 foreach ([&ss, &prefix](InstructionSet &is) { ss << is.print(prefix + "\t"); })
596 ;
597 return ss.str();
598}
599
600ModedInstructionSet::ModedInstructionSet(const std::string &name) : archname_(name) {}
602{
603 // delete variable instruction sets
604 for (auto iter = vismap_.begin(); iter != vismap_.end(); ++iter)
605 {
606 delete iter->second;
607 }
608}
610{
611 auto f = vismap_.find(mode);
612 if (f != vismap_.end())
613 return f->second;
614 return nullptr;
615}
616VariableInstructionSet *ModedInstructionSet::create(uint32_t mode, unsigned width, const std::string &name)
617{
618 auto f = vismap_.find(mode);
619 if (f != vismap_.end())
620 {
621#if DEBUG
622 if (f->second->width_ != width)
623 {
624 etiss_log(ERROR, "missmatch width values");
625 }
626#endif
627 return nullptr;
628 }
629 VariableInstructionSet *ret = new VariableInstructionSet(*this, width, name);
630 vismap_[mode] = ret;
631 invvismap_[ret] = mode;
632 return ret;
633}
634VariableInstructionSet &ModedInstructionSet::open(uint32_t mode, unsigned width, const std::string &name)
635{
636 VariableInstructionSet *ret = get(mode);
637 if (ret != nullptr)
638 {
639#if DEBUG
640 if (ret->width_ != width)
641 {
642 etiss_log(ERROR, "missmatch width values");
643 }
644#endif
645 return *ret;
646 }
647 return *create(mode, width, name);
648}
650{
651 auto iter = invvismap_.find(vis);
652 if (iter != invvismap_.end())
653 return iter->second;
655 "variable instruction set mode cannot be found since this moded instruction set is not its parent");
656 return (uint32_t)-1;
657}
658
659void ModedInstructionSet::foreach (std::function<void(VariableInstructionSet &)> call)
660{
661 for (auto iter = vismap_.begin(); iter != vismap_.end(); iter++)
662 {
663 if (iter->second != nullptr)
664 {
665 call(*(iter->second));
666 }
667 else
668 {
669 etiss_log(ERROR, "invalid pointer in vismap_.");
670 }
671 }
672}
673
675{
676 bool ok = true;
677 foreach ([&ok](VariableInstructionSet &vis) { ok = ok & vis.compile(); })
678 ;
679 return ok;
680}
681
682std::string ModedInstructionSet::print(std::string prefix)
683{
684 std::stringstream ss;
685 ss << prefix << archname_ << ":\n";
686 foreach (
687 [&ss, &prefix](VariableInstructionSet &vis)
688 {
689 ss << prefix << "MODE " << vis.parent_.getMode(vis) << ": ";
690 ss << vis.print(prefix + "\t");
691 })
692 ;
693 return ss.str();
694}
695
697{
698 foreach (
699 [&set, &ok](InstructionClass &klass)
700 {
701 VariableInstructionSet &vis = set.open(klass.mode_, klass.width_, klass.name_);
702 klass.addTo(vis, ok);
703 })
704 ;
705}
707{
708 foreach (
709 [&set, &ok](InstructionGroup &group)
710 {
711 InstructionSet &is = set.open(group.width_, group.name_);
712 group.addTo(is, ok);
713 })
714 ;
715}
717{
718 foreach (
719 [&set, &ok](InstructionDefinition &id)
720 {
721 Instruction *instr = set.create(id.opc_, id.name_);
722 if (instr == nullptr)
723 {
724 ok = false;
725 etiss::log(ERROR, "failed to add InstructionDefinition to Instruction set.", id, set);
726 return;
727 }
728 id.addTo(*instr, ok);
729 })
730 ;
731}
733{
734
735 if (!(opc_ == instr.opc_))
736 {
737 etiss::log(etiss::ERROR, "cannot add instruction definition to instruction.", *this, instr);
738 ok = false;
739 return;
740 }
741 etiss::log(VERBOSE, "Added instruction definition to instruction.", *this, instr);
743 if (ASMprinter_)
744 {
746 }
747}
748
749#if __cplusplus >= 201103L
750uint32_t operator"" _i32(const char *s)
751{
752 return parse_i32(s);
753}
754#endif
755uint32_t parse_i32(const char *s)
756{
757 return parse_i<uint32_t>(s);
758}
759
760} // namespace instr
761
762} // namespace etiss
contains container classes to store instruction definitions + translation functions and build a trans...
#define ETISS_SRCLOC
Definition Misc.h:202
#define etiss_log(LEVEL, MSG)
Definition Misc.h:41
__device__ __2f16 b
__device__ __2f16 float bool s
static __inline__ uint32_t
Definition arm_cde.h:25
static __inline__ int8_t
Definition arm_mve.h:311
A set of CodeParts.
Definition CodePart.h:399
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.
BitArrayRange(unsigned endindex_included, unsigned startindex_included)
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]
unsigned byteCount() const
std::string to_string() const
string representation of the BitArray
unsigned intCount() const
void set_range(unsigned long val, size_type end, size_type start)
set the value to the interval [end, start]
unsigned internalBufferSize()
char * internalBuffer()
get the internal buffer
void recoverFromEndianness(unsigned alignment, endian_t endianness)
changes byte positions as needed to resove endiannes incompabilities after using the internal buffer ...
maps to VariableInstructionSet
void addTo(VariableInstructionSet &set, bool &ok)
void addTo(ModedInstructionSet &set, bool &ok)
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.
unsigned & ufield(std::string name)
void addTo(Instruction &set, bool &ok)
const std::function< bool(BitArray &, etiss::CodeSet &, InstructionContext &)> callback_
const std::function< std::string(BitArray &, Instruction &)> ASMprinter_
maps to InstructionSet
void addTo(InstructionSet &set, bool &ok)
holds etiss::instr::Instruction instances and handles automatic instruction tree creation.
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)
void foreach(std::function< void(Instruction &)> func)
Instruction * create(const OPCode &key, const std::string &name)
Instruction & open(const OPCode &key, const std::string &name)
InstructionSet(VariableInstructionSet &parent, unsigned width, const std::string &name, unsigned c_size=4)
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)
const std::string name_
std::function< std::string(BitArray &, Instruction &)> printer_
static std::string printASMSimple(BitArray &ba, Instruction &instr)
Instruction(const OPCode &opc, const std::string &name)
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_
holds etiss::instr::VariableInstructionSet instances for different modes.
std::string print(std::string prefix=std::string())
etiss_del_como(ModedInstructionSet) ModedInstructionSet(const std ~ModedInstructionSet()
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())
uint32_t getMode(VariableInstructionSet *vis)
VariableInstructionSet * get(uint32_t mode)
std::map< uint32_t, VariableInstructionSet * > vismap_
void foreach(std::function< void(VariableInstructionSet &)> call)
defines the relevant bits and their value to identify an instruction.
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
comparison operator for map/sets.
const BitArray mask_
holds etiss::instr::InstructionSet instances with different bit widths.
void foreach(std::function< void(InstructionSet &)> func)
InstructionSet & open(unsigned width, const std::string &name=std::string())
std::string print(std::string prefix=std::string())
InstructionSet * get(unsigned width)
std::map< unsigned, InstructionSet * > ismap_
InstructionSet * create(unsigned width, const std::string &name=std::string())
BitArray::size_type size_type
uint32_t I
Definition Instruction.h:40
std::set< Instruction * > Node
Holding unique instruction sets code chunks after permutation.
uint32_t parse_i32(const char *s)
forwards: include/jit/*
Definition Benchmark.h:17
endian_t
Enumeration type for the endianness.
Definition Misc.h:488
@ VERBOSE
Definition Misc.h:88
@ WARNING
Definition Misc.h:86
@ ERROR
Definition Misc.h:85
@ FATALERROR
Definition Misc.h:84
endian_t getEndianness()
evaluates the endianness of the current build as a constexpr.
Definition Misc.h:505
void log(Verbosity level, std::string msg)
write log message at the given level.
Definition Misc.cpp:94
bool operator()(const OPCode *const &o1, const OPCode *const &o2) const