OpenASIP 2.2
Loading...
Searching...
No Matches
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
41#include "DisassemblyMove.hh"
45#include "DisassemblyOperand.hh"
46#include "DisassemblyGuard.hh"
47#include "DisassemblyFUPort.hh"
53#include "DisassemblyNOP.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
63using 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 */
79
80/**
81 * Creates dynamically allocated disassembler instruction.
82 *
83 * @param instructionIndex Number of instruction to return.
84 * @return Dynamically allocated disassembler instruction.
85 */
87TPEFDisassembler::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 =
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
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*>(
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 */
265Word
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 */
279Word
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 */
295void
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 */
306void
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: {
350 switch (unit) {
352 return new DisassemblyIntRegister(index);
354 // only one boolean register for now
355 assert(index == 0);
356 return new DisassemblyBoolRegister();
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
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(
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(
438
439 std::string regName = strings->chunk2String(resource.name());
440
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(
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}
#define abortWithError(message)
#define assert(condition)
static std::string toString(const T &source)
static int toInt(const T &source)
static unsigned int toUnsignedInt(const T &source)
void addAnnotation(DisassemblyAnnotation *annotation)
void addAnnotation(DisassemblyAnnotation *annotation)
void addLongImmediate(DisassemblyImmediateAssignment *longImm)
void addMove(DisassemblyInstructionSlot *move)
static KeyType keyForValue(const MapType &aMap, const ValueType &aValue)
static bool containsKey(const MapType &aMap, const KeyType &aKey)
virtual Word startAddress() const
virtual DisassemblyInstruction * createInstruction(Word instructionIndex) const
DisassemblyElement * createDisassemblyElement(TPEF::MoveElement::FieldType type, Word unit, Word index, ImmediateMap &immediateMap) const
void clearCache() const
TPEFDisassembler(const TPEF::Binary &aTpef)
std::pair< Word, Word > ImmediateKey
std::vector< Word > instructionStartCache_
Cache of starting elements of instructions.
const TPEF::Binary * tpef_
Binary where data for disassembler is retrieved.
virtual ~TPEFDisassembler()
std::map< ImmediateKey, TPEF::ImmediateElement * > ImmediateMap
virtual Word instructionCount() const
Section * section(Word index) const
virtual InstructionElement * element(Word index) const
LongWord longWord() const
SignedLongWord sLongWord() const
Byte destinationIndex() const
Byte destinationUnit() const
const std::vector< Byte > & payload() const
Word annotationCount() const
InstructionAnnotation * annotation(Word index) const
bool isGuarded() const
FieldType destinationType() const
HalfWord destinationIndex() const
HalfWord destinationUnit() const
bool isEmpty() const
HalfWord bus() const
HalfWord guardUnit() const
HalfWord sourceUnit() const
FieldType guardType() const
HalfWord guardIndex() const
bool isGuardInverted() const
HalfWord sourceIndex() const
FieldType sourceType() const
@ MF_RF
Register file.
@ MF_IMM
Immediate.
@ MF_UNIT
Function unit.
ResourceType type() const
static const std::string RETURN_ADDRESS_NAME
Reserved string of return address special register.
HalfWord id() const
@ MRT_BUS
Transport bus.
@ MRT_IMM
Immediate unit.
@ MRT_SR
Special register.
@ MRT_UNIT
Function unit.
@ MRT_PORT
Function unit port.
@ MRT_OP
Operation operand or function unit register.
@ UNIVERSAL_BUS
Universal bus.
@ UNIVERSAL_FU
Universal function unit.
@ INT_RF
Universal integer register file.
@ UNIVERSAL_RF_MASK
Bit to check if registerfile is real or universal.
@ BOOL_RF
Universal boolean register file.
@ FP_RF
Universal floating point register file.
Chunk * name() const
ResourceElement & findResource(ResourceElement::ResourceType aType, HalfWord anId) const
bool hasResource(ResourceElement::ResourceType aType, HalfWord anId) const
AddressImage startingAddress() const
Section * link() const
@ ST_CODE
Text section.
Definition Section.hh:79
@ ST_MR
Machine resources section.
Definition Section.hh:78
SectionElement * element(Word index) const
Word elementCount() const
std::string chunk2String(const Chunk *chunk) const