OpenASIP  2.0
TPEFDisassembler.cc
Go to the documentation of this file.
1 /*
2  Copyright (c) 2002-2009 Tampere University.
3 
4  This file is part of TTA-Based Codesign Environment (TCE).
5 
6  Permission is hereby granted, free of charge, to any person obtaining a
7  copy of this software and associated documentation files (the "Software"),
8  to deal in the Software without restriction, including without limitation
9  the rights to use, copy, modify, merge, publish, distribute, sublicense,
10  and/or sell copies of the Software, and to permit persons to whom the
11  Software is furnished to do so, subject to the following conditions:
12 
13  The above copyright notice and this permission notice shall be included in
14  all copies or substantial portions of the Software.
15 
16  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17  IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
19  THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20  LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
21  FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
22  DEALINGS IN THE SOFTWARE.
23  */
24 /**
25  * @file TPEFDisassembler.cc
26  *
27  * Implementation of TPEFDisassembler class.
28  *
29  * @author Mikael Lepistö 2005 (tmlepist-no.spam-cs.tut.fi)
30  * @note rating: red
31  */
32 
33 #include <map>
34 
35 #include "TPEFDisassembler.hh"
36 #include "Binary.hh"
37 #include "CodeSection.hh"
38 
40 #include "DisassemblyImmediate.hh"
41 #include "DisassemblyMove.hh"
44 #include "DisassemblyFPRegister.hh"
45 #include "DisassemblyOperand.hh"
46 #include "DisassemblyGuard.hh"
47 #include "DisassemblyFUPort.hh"
49 #include "DisassemblyRegister.hh"
53 #include "DisassemblyNOP.hh"
54 #include "DisassemblyFUOperand.hh"
55 #include "MoveElement.hh"
56 #include "ImmediateElement.hh"
57 
58 #include "ResourceElement.hh"
59 #include "ResourceSection.hh"
60 #include "StringSection.hh"
61 #include "SimValue.hh"
62 
63 using namespace TPEF;
64 
65 /**
66  * Constructor.
67  *
68  * @param aTpef TPEF hierarchy whose code sections are disassembled.
69  */
71  tpef_(&aTpef) {
72 }
73 
74 /**
75  * Destructor.
76  */
78 }
79 
80 /**
81  * Creates dynamically allocated disassembler instruction.
82  *
83  * @param instructionIndex Number of instruction to return.
84  * @return Dynamically allocated disassembler instruction.
85  */
87 TPEFDisassembler::createInstruction(Word instructionIndex) const {
88 
89  CodeSection *theCodeSection =
90  dynamic_cast<CodeSection*>(tpef_->section(Section::ST_CODE,0));
91 
92  assert(theCodeSection != NULL);
93 
94  if (instructionStartCache_.empty()) {
95  initCache();
96  }
97 
98  Word currIndex = instructionStartCache_[instructionIndex];
99 
100  InstructionElement *currElement =
101  dynamic_cast<InstructionElement*>(
102  theCodeSection->element(currIndex));
103 
104  DisassemblyInstruction *newInstruction = new DisassemblyInstruction();
105 
106  // scan all elements in first pass, because we want to have also
107  // immediates when we build instructions
108  ImmediateMap immediates;
109  std::vector<MoveElement*> moves;
110 
111  do {
112  if (currElement->isMove()) {
113  MoveElement *move = dynamic_cast<MoveElement*>(currElement);
114  assert (move != NULL);
115  moves.push_back(move);
116 
117  } else if (currElement->isImmediate()) {
118  ImmediateElement *imm =
119  dynamic_cast<ImmediateElement*>(currElement);
120 
121  assert (imm != NULL);
122 
123  if (imm->isInline()) {
125  immKey(imm->destinationUnit(), imm->destinationIndex());
126 
127  immediates[immKey] = imm;
128 
129  } else {
130  // this is long immediate
131  DisassemblyElement* dest =
132  createDisassemblyElement(MoveElement::MF_IMM,
133  imm->destinationUnit(),
134  imm->destinationIndex(),
135  immediates);
136 
137  SimValue immValue(64);
138  immValue = imm->longWord();
139 
140  // do not know if unit is signed or not without adf
141  DisassemblyImmediateAssignment* immAssign =
142  new DisassemblyImmediateAssignment(immValue, false, dest);
143 
144  // add annotationes for the move
145  for (Word j = 0; j < imm->annotationCount(); j++) {
146  InstructionAnnotation& ann = *(imm->annotation(j));
147  immAssign->addAnnotation(
148  new DisassemblyAnnotation(ann.id(), ann.payload()));
149  }
150 
151  newInstruction->addLongImmediate(immAssign);
152  }
153 
154  } else {
155  assert(false);
156  }
157 
158  currIndex++;
159 
160  // if we reached end of section
161  if (currIndex == theCodeSection->elementCount()) {
162  break;
163  }
164 
165  currElement = dynamic_cast<InstructionElement*>(
166  theCodeSection->element(currIndex));
167 
168  } while (!currElement->begin());
169 
170  // find out how many busses tpef have.
171  ResourceSection* resources = dynamic_cast<ResourceSection*>(
172  tpef_->section(Section::ST_MR, 0));
173 
174  assert(resources != NULL);
175 
176  std::vector<DisassemblyInstructionSlot*> organizedInstr;
177 
178  for (Word i = 0; i < resources->elementCount(); i++) {
179  ResourceElement* resource =
180  dynamic_cast<ResourceElement*>(resources->element(i));
181 
182  if (resource->type() == ResourceElement::MRT_BUS &&
183  resource->id() != ResourceElement::UNIVERSAL_BUS) {
184 
185  organizedInstr.push_back(NULL);
186  }
187  }
188 
189  for (unsigned int i = 0; i < moves.size(); i++) {
190  MoveElement *currMove = moves[i];
191 
192  if (!currMove->isEmpty()) {
193  DisassemblyElement *source =
195  currMove->sourceUnit(),
196  currMove->sourceIndex(),
197  immediates);
198 
199  DisassemblyElement *destination =
201  currMove->destinationUnit(),
202  currMove->destinationIndex(),
203  immediates);
204 
205  DisassemblyGuard *guard = NULL;
206 
207  if (currMove->isGuarded()) {
208  DisassemblyElement *guardElement =
210  currMove->guardUnit(),
211  currMove->guardIndex(),
212  immediates);
213 
214  guard = new DisassemblyGuard(
215  guardElement, currMove->isGuardInverted());
216  }
217 
218  DisassemblyMove *newMove =
219  new DisassemblyMove(source, destination, guard);
220 
221  // add annotationes for the move
222  for (Word j = 0; j < currMove->annotationCount(); j++) {
223  InstructionAnnotation& ann = *(currMove->annotation(j));
224  newMove->addAnnotation(
225  new DisassemblyAnnotation(ann.id(), ann.payload()));
226  }
227 
228  // add unassigned moves to end of instruction
229  if (currMove->bus() > 0) {
230  organizedInstr[currMove->bus() - 1] = newMove;
231  } else {
232  organizedInstr.push_back(newMove);
233  }
234  } else {
235  // empty move element. NOP?
236  // add annotationes for the move
237  for (Word j = 0; j < currMove->annotationCount(); j++) {
238  InstructionAnnotation& ann = *(currMove->annotation(j));
239  newInstruction->addAnnotation(
240  new DisassemblyAnnotation(ann.id(), ann.payload()));
241  }
242  }
243  }
244 
245  // create all moves and add them to disassembler instruction
246  for (Word i = 0; i < organizedInstr.size(); i++) {
247 
248  if (organizedInstr[i] != NULL) {
249  newInstruction->addMove(organizedInstr[i]);
250 
251  } else {
252  DisassemblyNOP *newNOP = new DisassemblyNOP();
253  newInstruction->addMove(newNOP);
254  }
255  }
256 
257  return newInstruction;
258 }
259 
260 /**
261  * Address of first instruction.
262  *
263  * @return Address of first instruction.
264  */
265 Word
267  CodeSection *theCodeSection =
268  dynamic_cast<CodeSection*>(tpef_->section(Section::ST_CODE,0));
269 
270  assert(theCodeSection != NULL);
271  return theCodeSection->startingAddress();
272 }
273 
274 /**
275  * Number of instructions available in first code section of TPEF.
276  *
277  * @return Number of instruction available.
278  */
279 Word
281  if (instructionStartCache_.empty()) {
282  initCache();
283  }
284  return instructionStartCache_.size();
285 }
286 
287 /**
288  * Clears internal cache of instruction start indexes in TPEF
289  * code section.
290  *
291  * If you modify order or begin flags of instruction elements in TPEF,
292  * chache should be cleared, because instruction start indexes might be
293  * changed.
294  */
295 void
297  instructionStartCache_.clear();
298 }
299 
300 /**
301  * Initilises instruction start indexes in code section to vector.
302  *
303  * After cache init we have vector of all instruction start indexes of the
304  * section.
305  */
306 void
308  CodeSection *theCodeSection =
309  dynamic_cast<CodeSection*>(tpef_->section(Section::ST_CODE,0));
310 
311  assert(theCodeSection != NULL);
312 
313  for (Word i = 0; i < theCodeSection->elementCount(); i++) {
314  if (dynamic_cast<InstructionElement*>(
315  theCodeSection->element(i))->begin()) {
316  // if i is begin of instruction push it to instruction start vector
317  instructionStartCache_.push_back(i);
318  }
319  }
320 }
321 
322 /**
323  * Creates DisassemblyElement out of given paramters.
324  *
325  * Finds needed strings and stuff from TPEF hierarchy.
326  *
327  * @param type Type of elemet to create.
328  * @param unit Unit id of referred resource.
329  * @param index Index part of referred resource.
330  * @param immediateMap All immediate values found in instruction.
331  * @return Dynamically allocated fully contructed DisassemblerElement.
332  */
335  MoveElement::FieldType type, Word unit, Word index,
336  ImmediateMap &immediateMap) const {
337 
338  ResourceSection *resources =
339  dynamic_cast<ResourceSection*>(tpef_->section(Section::ST_MR,0));
340 
341  assert(resources != NULL);
342 
343  StringSection *strings =
344  dynamic_cast<StringSection*>(resources->link());
345 
346  switch (type) {
347 
348  case MoveElement::MF_RF: {
349  if (unit & ResourceElement::UNIVERSAL_RF_MASK) {
350  switch (unit) {
351  case ResourceElement::INT_RF:
352  return new DisassemblyIntRegister(index);
353  case ResourceElement::BOOL_RF:
354  // only one boolean register for now
355  assert(index == 0);
356  return new DisassemblyBoolRegister();
357  case ResourceElement::FP_RF:
358  return new DisassemblyFPRegister(index);
359  default:
360  // Error: not universal unit
361  assert(false);
362  }
363  } else {
364  // real resources from real machines
365  ResourceElement &rfUnit =
366  resources->findResource(ResourceElement::MRT_RF,unit);
367 
368  std::string rfName = strings->chunk2String(rfUnit.name());
369 
370  return new DisassemblyRegister(rfName, index);
371  }
372 
373  } break;
374 
375  case MoveElement::MF_IMM: {
376  ImmediateKey immKey(unit, index);
377 
378  if (MapTools::containsKey(immediateMap, immKey)) {
379 
380  ImmediateElement *imm =
381  MapTools::valueForKey<ImmediateElement*>(immediateMap, immKey);
382 
383  assert(imm->isInline());
384 
385  SimValue immValue(64);
386  immValue = imm->sLongWord();
387  return new DisassemblyImmediate(immValue, false);
388 
389  } else {
390  // register reference to immediate register.
391 
392  // get that immediate unit
393  ResourceElement &immUnit =
394  resources->findResource(ResourceElement::MRT_IMM, unit);
395 
396  std::string immUnitName = strings->chunk2String(immUnit.name());
397 
398  return new DisassemblyImmediateRegister(immUnitName, index);
399  }
400 
401  } break;
402 
403  case MoveElement::MF_UNIT: {
404 
405  if (unit == ResourceElement::UNIVERSAL_FU) {
406 
407  // TODO refactor
408 
409  if (resources->hasResource(
410  ResourceElement::MRT_OP, index)) {
411 
412  ResourceElement resource =
413  resources->findResource(
414  ResourceElement::MRT_OP, index);
415 
416  std::string opString =
417  strings->chunk2String(resource.name());
418 
419  std::string::size_type dotIndex = opString.rfind('.');
420  std::string opName = opString.substr(0,dotIndex);
421 
422  // move dotIndex to start of regnumber part of operation
423  dotIndex++;
424 
425  std::string opIndexStr = opString.substr(
426  dotIndex, opString.length() - dotIndex);
427 
428  Word opIndex = Conversion::toInt(opIndexStr);
429 
430  return new DisassemblyOperand(opName, opIndex);
431 
432  } else if (resources->hasResource(
433  ResourceElement::MRT_SR, index)) {
434 
435  ResourceElement &resource =
436  resources->findResource(
437  ResourceElement::MRT_SR, index);
438 
439  std::string regName = strings->chunk2String(resource.name());
440 
441  if (regName == ResourceElement::RETURN_ADDRESS_NAME) {
443 
444  } else {
445  abortWithError("Unknown special register");
446  }
447 
448  } else {
450  "Can't find universal operand or special register "
451  "resource by index:" + Conversion::toString(index));
452  }
453 
454  } else {
455  // terminal types fuName.portName or fuName.opName.index
456  // not universal FU, which has no fuName field
457 
458  // get FU name
459  ResourceElement &fuResource =
460  resources->findResource(ResourceElement::MRT_UNIT, unit);
461 
462  std::string fuName = strings->chunk2String(fuResource.name());
463 
464  // TODO refactor
465  if (resources->hasResource(
466  ResourceElement::MRT_PORT, index)) {
467 
468  ResourceElement &fuPort =
469  resources->findResource(ResourceElement::MRT_PORT, index);
470 
471  std::string fuPortName =
472  strings->chunk2String(fuPort.name());
473 
474  return new DisassemblyFUPort(fuName, fuPortName);
475 
476  } else if (resources->hasResource(
477  ResourceElement::MRT_OP, index)) {
478 
479  ResourceElement &fuOperationOperand =
480  resources->findResource(ResourceElement::MRT_OP, index);
481 
482  std::string operandString =
483  strings->chunk2String(fuOperationOperand.name());
484 
485  std::string::size_type dotPos = operandString.rfind(".");
486 
487  assert(dotPos != std::string::npos);
488 
489  std::string opName = operandString.substr(0, dotPos);
490 
491  std::string operandIndexString =
492  operandString.substr(
493  dotPos+1, operandString.length() - dotPos - 1);
494 
495  Word operandIndex =
496  Conversion::toUnsignedInt(operandIndexString);
497 
498  return new DisassemblyFUOperand(fuName, opName, operandIndex);
499 
500  } else if (resources->hasResource(
501  ResourceElement::MRT_SR, index)) {
502 
503  ResourceElement &fuSpecialRegister =
504  resources->findResource(ResourceElement::MRT_SR, index);
505 
506  std::string srName =
507  strings->chunk2String(fuSpecialRegister.name());
508 
509  return new DisassemblyFUPort(fuName, srName);
510 
511  } else {
513  "Can't find real port, operation or special register by "
514  "index: " + Conversion::toString(index));
515  }
516  }
517 
518  } break;
519 
520  default:
521  abortWithError("Unknown type: " + Conversion::toString((int)type));
522  }
523 
524  assert(false);
525  return NULL;
526 }
TPEF::CodeSection::element
virtual InstructionElement * element(Word index) const
Definition: CodeSection.cc:88
TPEF::ResourceSection::hasResource
bool hasResource(ResourceElement::ResourceType aType, HalfWord anId) const
Definition: ResourceSection.cc:120
TPEF::InstructionElement::isMove
bool isMove() const
TPEF::ResourceSection
Definition: ResourceSection.hh:47
TPEF::MoveElement::isGuarded
bool isGuarded() const
DisassemblyInstruction::addAnnotation
void addAnnotation(DisassemblyAnnotation *annotation)
Definition: DisassemblyInstruction.cc:175
TPEFDisassembler::initCache
void initCache() const
Definition: TPEFDisassembler.cc:307
TPEF::ImmediateElement::sLongWord
SignedLongWord sLongWord() const
TPEF::ImmediateElement::destinationIndex
Byte destinationIndex() const
DisassemblyGuard.hh
TPEF::ResourceElement::id
HalfWord id() const
TPEF::InstructionElement
Definition: InstructionElement.hh:77
TPEF::Binary
Definition: Binary.hh:49
TPEFDisassembler::TPEFDisassembler
TPEFDisassembler(const TPEF::Binary &aTpef)
Definition: TPEFDisassembler.cc:70
TPEF::ResourceElement::type
ResourceType type() const
DisassemblyImmediateRegister
Definition: DisassemblyImmediateRegister.hh:43
TPEF::MoveElement::FieldType
FieldType
Definition: MoveElement.hh:52
DisassemblyElement
Definition: DisassemblyElement.hh:41
TPEF::ResourceElement
Definition: ResourceElement.hh:47
TPEFDisassembler::instructionStartCache_
std::vector< Word > instructionStartCache_
Cache of starting elements of instructions.
Definition: TPEFDisassembler.hh:86
TPEF::InstructionElement::annotation
InstructionAnnotation * annotation(Word index) const
DisassemblyImmediateRegister.hh
TPEF::ImmediateElement
Definition: ImmediateElement.hh:49
TPEF::Binary::section
Section * section(Word index) const
TPEF::StringSection::chunk2String
std::string chunk2String(const Chunk *chunk) const
Definition: StringSection.cc:72
TPEF::InstructionElement::isImmediate
bool isImmediate() const
DisassemblyReturnAddressRegister
Definition: DisassemblyReturnAddressRegister.hh:43
TPEF::MoveElement::sourceIndex
HalfWord sourceIndex() const
TPEF::ResourceSection::findResource
ResourceElement & findResource(ResourceElement::ResourceType aType, HalfWord anId) const
Definition: ResourceSection.cc:91
TPEF::MoveElement::isGuardInverted
bool isGuardInverted() const
DisassemblyImmediateAssignment
Definition: DisassemblyImmediateAssignment.hh:46
StringSection.hh
ResourceSection.hh
TPEFDisassembler::ImmediateMap
std::map< ImmediateKey, TPEF::ImmediateElement * > ImmediateMap
Definition: TPEFDisassembler.hh:73
ImmediateElement.hh
Conversion::toString
static std::string toString(const T &source)
DisassemblyFPRegister.hh
TPEF::MoveElement::bus
HalfWord bus() const
TPEF::ImmediateElement::longWord
LongWord longWord() const
TPEF::StringSection
Definition: StringSection.hh:48
SimValue
Definition: SimValue.hh:96
TPEFDisassembler::tpef_
const TPEF::Binary * tpef_
Binary where data for disassembler is retrieved.
Definition: TPEFDisassembler.hh:83
TPEF::InstructionAnnotation::payload
const std::vector< Byte > & payload() const
TPEF::ResourceElement::name
Chunk * name() const
TPEFDisassembler::clearCache
void clearCache() const
Definition: TPEFDisassembler.cc:296
TPEF::Section::link
Section * link() const
TPEFDisassembler::instructionCount
virtual Word instructionCount() const
Definition: TPEFDisassembler.cc:280
TPEF::Section::element
SectionElement * element(Word index) const
assert
#define assert(condition)
Definition: Application.hh:86
DisassemblyMove.hh
DisassemblyInstructionSlot::addAnnotation
void addAnnotation(DisassemblyAnnotation *annotation)
Definition: DisassemblyInstructionSlot.cc:70
DisassemblyMove
Definition: DisassemblyMove.hh:44
abortWithError
#define abortWithError(message)
Definition: Application.hh:72
DisassemblyInstruction.hh
TPEF::MoveElement::sourceUnit
HalfWord sourceUnit() const
TPEF::MoveElement::guardIndex
HalfWord guardIndex() const
TPEFDisassembler::ImmediateKey
std::pair< Word, Word > ImmediateKey
Definition: TPEFDisassembler.hh:72
ResourceElement.hh
DisassemblyAnnotation
Definition: DisassemblyAnnotation.hh:44
DisassemblyGuard
Definition: DisassemblyGuard.hh:41
DisassemblyNOP.hh
TPEF::MoveElement
Definition: MoveElement.hh:47
TPEFDisassembler::createDisassemblyElement
DisassemblyElement * createDisassemblyElement(TPEF::MoveElement::FieldType type, Word unit, Word index, ImmediateMap &immediateMap) const
Definition: TPEFDisassembler.cc:334
TPEF::InstructionElement::annotationCount
Word annotationCount() const
TPEFDisassembler::createInstruction
virtual DisassemblyInstruction * createInstruction(Word instructionIndex) const
Definition: TPEFDisassembler.cc:87
TPEF::InstructionAnnotation::id
Word id() const
TPEF::InstructionElement::begin
bool begin() const
DisassemblyBoolRegister.hh
DisassemblyOperand.hh
DisassemblyImmediate
Definition: DisassemblyImmediate.hh:42
TPEF::MoveElement::destinationIndex
HalfWord destinationIndex() const
TPEF::MoveElement::destinationType
FieldType destinationType() const
DisassemblyFUOperand.hh
TPEF::CodeSection
Definition: CodeSection.hh:44
DisassemblyFPRegister
Definition: DisassemblyFPRegister.hh:42
DisassemblyImmediateAssignment.hh
TPEF::MoveElement::destinationUnit
HalfWord destinationUnit() const
DisassemblyInstruction::addMove
void addMove(DisassemblyInstructionSlot *move)
Definition: DisassemblyInstruction.cc:58
DisassemblyIntRegister.hh
Conversion::toUnsignedInt
static unsigned int toUnsignedInt(const T &source)
DisassemblyBoolRegister
Definition: DisassemblyBoolRegister.hh:42
DisassemblyReturnAddressRegister.hh
MapTools::containsKey
static bool containsKey(const MapType &aMap, const KeyType &aKey)
DisassemblyRegister.hh
TPEF::MoveElement::guardType
FieldType guardType() const
DisassemblyIntRegister
Definition: DisassemblyIntRegister.hh:42
SimValue.hh
TPEFDisassembler::startAddress
virtual Word startAddress() const
Definition: TPEFDisassembler.cc:266
TPEF::InstructionAnnotation
Definition: InstructionElement.hh:49
TPEFDisassembler::~TPEFDisassembler
virtual ~TPEFDisassembler()
Definition: TPEFDisassembler.cc:77
TPEF::MoveElement::isEmpty
bool isEmpty() const
DisassemblyOperand
Definition: DisassemblyOperand.hh:43
DisassemblyFUPort
Definition: DisassemblyFUPort.hh:41
DisassemblyRegister
Definition: DisassemblyRegister.hh:51
TPEF::ImmediateElement::destinationUnit
Byte destinationUnit() const
DisassemblyFUOpcodePort.hh
TPEF::MoveElement::sourceType
FieldType sourceType() const
Conversion::toInt
static int toInt(const T &source)
DisassemblyImmediate.hh
DisassemblyInstruction::addLongImmediate
void addLongImmediate(DisassemblyImmediateAssignment *longImm)
Definition: DisassemblyInstruction.cc:96
DisassemblyNOP
Definition: DisassemblyNOP.hh:41
MoveElement.hh
TPEF::ImmediateElement::isInline
bool isInline() const
TPEF::Section::startingAddress
AddressImage startingAddress() const
CodeSection.hh
TPEF::MoveElement::guardUnit
HalfWord guardUnit() const
DisassemblyFUPort.hh
DisassemblyFUOperand
Definition: DisassemblyFUOperand.hh:42
DisassemblyInstruction
Definition: DisassemblyInstruction.hh:46
TPEF::Section::elementCount
Word elementCount() const
TPEF
Definition: Assembler.hh:43
Binary.hh
TPEFDisassembler.hh