OpenASIP 2.2
Loading...
Searching...
No Matches
POMDisassembler.cc
Go to the documentation of this file.
1/*
2 Copyright (c) 2002-2016 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 POMDisassembler.cc
26 *
27 * Implementation of POMDisassembler class.
28 *
29 * @author Veli-Pekka J��skel�inen 2005 (vjaaskel-no.spam-cs.tut.fi)
30 * @author Pekka J��skel�inen 2008,2016 (pjaaskel-no.spam-cs.tut.fi)
31 * @note rating: red
32 */
33
34#include <string>
35#include <sstream>
36#include <boost/format.hpp>
37
38#include "POMDisassembler.hh"
39#include "Application.hh"
40#include "StringTools.hh"
41
42#include "Instruction.hh"
43#include "NullInstruction.hh"
44#include "Port.hh"
45#include "FUPort.hh"
46#include "TerminalFUPort.hh"
47#include "TerminalImmediate.hh"
49#include "Procedure.hh"
50#include "Operation.hh"
51#include "GlobalScope.hh"
52#include "CodeLabel.hh"
53#include "UniversalMachine.hh"
55#include "ControlUnit.hh"
57#include "Guard.hh"
58#include "Machine.hh"
59#include "TCEString.hh"
61#include "Move.hh"
62#include "Instruction.hh"
63#include "Program.hh"
64#include "Procedure.hh"
65#include "Immediate.hh"
66#include "MoveGuard.hh"
67#include "HWOperation.hh"
68#include "Conversion.hh"
69#include "DataMemory.hh"
70#include "DataDefinition.hh"
71#include "NullProgram.hh"
72
73#include "DisassemblyMove.hh"
75#include "DisassemblyFUPort.hh"
82#include "DisassemblyOperand.hh"
86#include "DisassemblyLabel.hh"
87#include "DisassemblyNOP.hh"
90
91using std::string;
92using std::endl;
93
94using namespace TTAMachine;
95using namespace TTAProgram;
96
97/**
98 * A constructor for disassembling whole programs.
99 *
100 * @param program Program to disassemble.
101 * @param printAddresses True in case instruction addresses should be printed at
102 * the end of instruction lines as comments.
103 */
105 program_(program), printAddresses_(printAddresses) {
106}
107
108/**
109 * A constructor for disassembling pieces of a program which might not
110 * be attached to a Program object.
111 *
112 * @param printAddresses True in case instruction addresses should be printed at
113 * the end of instruction lines as comments.
114 */
116 program_(NullProgram::instance()), printAddresses_(printAddresses) {
117}
118
119
120/**
121 * The destructor.
122 */
125
126
127/**
128 * Returns disassembly of an instruction at the given index.
129 *
130 * The client is responsible for destroying the instruction
131 * object.
132 *
133 * @param index Index of the instruction to disassemble.
134 * @return Disassembly of the instruction at given index.
135 */
138
139 const Instruction& instruction = program_.instructionAt(index);
140 return createInstruction(program_, instruction);
141}
142
143
144/**
145 * Returns disassembly of an instruction at the given index.
146 *
147 * The client is responsible for destroying the instruction
148 * object.
149 *
150 * @param program Parent program of the instruction.
151 * @param index Index of the instruction to disassemble.
152 * @return Disassembly of the instruction at given index.
153 */
156 const Program& program, const Instruction& instruction) {
157
159
160 const Machine::BusNavigator& navigator =
161 program.targetProcessor().busNavigator();
162
163 // The instruction disassembly is created by one bus at a time.
164 for (int i = 0; i < navigator.count(); i++) {
165
166 Bus* bus = navigator.item(i);
167 string busName = bus->name();
168 bool isUsed = false;
169
170 // Check for move.
171 for (int i = 0; i < instruction.moveCount(); i++) {
172 if (&instruction.move(i).bus() == bus) {
173 disassembly->addMove(createMove(instruction.move(i)));
174 isUsed = true;
175 }
176 }
177
178 if (!isUsed) {
179 disassembly->addMove(new DisassemblyNOP);
180 }
181 }
182
183 // Add disassembly of long immediates in immediate slots.
184 for (int i = 0; i < instruction.immediateCount(); i++) {
185 disassembly->addLongImmediate(
186 createImmediateAssignment(instruction.immediate(i)));
187 }
188
189 return disassembly;
190}
191
192
193/**
194 * Creates disassembly of a move.
195 *
196 * @param move Move to disassemble.
197 * @return Disassembly of the move.
198 */
201
202 // Disassemble move terminals.
203 DisassemblyElement* destinationDis = createTerminal(move.destination());
204 DisassemblyElement* sourceDis = NULL;
205
206 if (move.source().isImmediate()) {
207
208 // Special case: if the move source is an inline immediate, and
209 // the move destination is call/jump operand, the inline immediate
210 // is disassembled as label if possible.
211 if (isCallOrJump(move.destination()) &&
212 move.isInInstruction() && move.parent().isInProcedure() &&
213 move.parent().parent().isInProgram() &&
215 move.parent().parent().parent(),
216 move.source().value().uLongWordValue()) > 0) {
217
218 LongWord immediate = move.source().value().uLongWordValue();
219 std::string codelabel = label(
220 move.parent().parent().parent(), immediate, 0);
221 sourceDis = new DisassemblyLabel(codelabel);
222 } else {
223 sourceDis =
225 move.source(), move.bus().signExtends());
226 }
227 } else {
228 sourceDis = createTerminal(move.source());
229 }
230
231 DisassemblyMove* disassembly = NULL;
232 if (!move.isUnconditional()) {
233 DisassemblyGuard* guardDis = createGuard(move.guard());
234 disassembly = new DisassemblyMove(sourceDis, destinationDis, guardDis);
235 } else {
236 disassembly = new DisassemblyMove(sourceDis, destinationDis);
237 }
238 return disassembly;
239}
240
241
242/**
243 * Creates disassembly of an immediate assignment.
244 */
247 DisassemblyElement* destination = createTerminal(immediate.destination());
248 SimValue value = immediate.value().value();
249 bool signExt = immediate.destination().immediateUnit().signExtends();
250 return new DisassemblyImmediateAssignment(value, signExt, destination);
251}
252
253
254/**
255 * Creates disassembly of a move terminal.
256 *
257 * Determines the terminal type, an uses appropriate function to create
258 * disassembly of the terminal.
259 *
260 * @param terminal Move terminal to disassemble.
261 * @return Disassembly of the move terminal.
262 * @exception WrongSubclass The terminal type was unknown.
263 */
266 assert (
267 !terminal.isImmediate() &&
268 "Should handle immediate as a special case due to depending on "
269 "extension mode!");
270
271 if (terminal.isFUPort()) {
272 return createFUPort(terminal);
273 }
274
275 if (terminal.isGPR()) {
276 return createRegister(terminal);
277 }
278
279 if (terminal.isImmediateRegister()) {
280 return createImmediateRegister(terminal);
281 }
282
283 // Unkown terminal type.
284 throw WrongSubclass(__FILE__, __LINE__, __func__,
285 "Unknown terminal type.");
286}
287
288/**
289 * Creates disassembly of an immediate value.
290 *
291 * @param terminal Immediate value to disassemble.
292 * @param signExtend If the immediate should be considered signed or unsigned.
293 * @return Disassembly of the immediate value.
294 */
297 const Terminal& terminal, bool signExtend) {
299 dynamic_cast<const TTAProgram::TerminalProgramOperation*>(&terminal)) {
300 if (!tpo->isAddressKnown())
301 return new DisassemblyImmediate(NullSimValue::instance(), false);
302 }
303 try {
304 return new DisassemblyImmediate(
305 terminal.value(), signExtend);
306 } catch (Exception& e) {
307 return new DisassemblyImmediate(
308 NullSimValue::instance(), signExtend);
309 }
310}
311
312
313/**
314 * Creates disassembly of a function unit port.
315 *
316 * @param terminal Function unit terminal to disassemble.
317 * @return Disassembly of the function unit terminal.
318 */
321 const FunctionUnit* fu = &terminal.functionUnit();
322
323 const TTAProgram::TerminalFUPort& fuTerm =
324 dynamic_cast<const TerminalFUPort&>(terminal);
325
326 if (dynamic_cast<const UniversalFunctionUnit*>(fu) != NULL ||
327 (fu->machine()->isUniversalMachine() &&
328 dynamic_cast<const ControlUnit*>(fu) != NULL)) {
329
330 // The terminal is a UniversalFunctionUnit operation or
331 // a universal machine control unit operation.
332 if (&fuTerm.hintOperation() != &NullOperation::instance()) {
333 string operation = fuTerm.hintOperation().name();
334 HWOperation* hwOperation = fu->operation(operation);
335 FUPort* port = fu->operationPort(fuTerm.port().name());
336 int operand = hwOperation->io(*port);
337 return new DisassemblyOperand(
338 fuTerm.hintOperation().name(), operand);
339 }
340 return new DisassemblyControlUnitPort(fuTerm.port().name());
341 }
342
343 // if terminal contains any information about operation
344 if (fuTerm.isOpcodeSetting()) {
345 // check if that osal operation was found
346 if (&fuTerm.operation() == &NullOperation::instance()) {
347 throw InstanceNotFound(__FILE__, __LINE__, __func__,
348 (boost::format(
349 "Osal operation for operation code name '%s' was not found.")
350 % fuTerm.hwOperation()->name()).str());
351 }
352 // The terminal is an opcode setting port of an operation or.
353 // has additional info about opcode that terminal is bound.
354 return new DisassemblyFUOpcodePort(
355 fu->name(), fuTerm.port().name(), fuTerm.operation().name());
356 }
357
358 // The terminal is a generic function unit port.
359 return new DisassemblyFUPort(fu->name(), terminal.port().name());
360}
361
362/**
363 * Creates disassembly of a register.
364 *
365 * @param terminal Register to disassemble.
366 * @return Disassembly of the register.
367 * @exception WrongSubclass The terminal was not register.
368 */
371 const RegisterFile* rf = &terminal.registerFile();
372
373 if (rf == NULL) {
374 throw WrongSubclass(__FILE__, __LINE__, __func__,
375 "Not register terminal.");
376 }
377
379 dynamic_cast<const UniversalMachine*>(rf->machine());
380
381 if (machine != NULL) {
382
383 if (rf == &machine->booleanRegisterFile()) {
384 // universal bool register
385 return new DisassemblyBoolRegister();
386 }
387
388
389 // The register is a UnboundedRegisterFile register of a universal
390 // machine.
391 const UnboundedRegisterFile* universalRF =
392 dynamic_cast<const UnboundedRegisterFile*>(rf);
393
394 if (universalRF == &machine->integerRegisterFile()) {
395 // universal int register
396 return new DisassemblyIntRegister(terminal.index());
397 }
398
399 if (universalRF == &machine->doubleRegisterFile()) {
400 // universal floating point register
401 return new DisassemblyFPRegister(terminal.index());
402 }
403
404 // Unknown universal machine register type.
405 throw WrongSubclass(
406 __FILE__, __LINE__, __func__,
407 "Unknown universal machine register type.");
408 }
409
410 return new DisassemblyRegister(rf->name(), terminal.index());
411}
412
413/**
414 * Creates disassembly of an immediate register.
415 *
416 * @param terminal Immediate register to disassemble.
417 * @return Disassembly of the immediate register.
418 */
421 string immediateUnit = terminal.immediateUnit().name();
422 unsigned int index = terminal.index();
423 return new DisassemblyImmediateRegister(immediateUnit, index);
424}
425
426
427/**
428 * Creates disassembly of a move guard.
429 *
430 * @param guard Move guard to disassemble.
431 * @return Disassembly of the move guard.
432 */
435
436 const Guard* guard = &moveGuard.guard();
437
438 DisassemblyElement* guarded = NULL;
439
440 // Check if the guarded element is a fu port.
441 const PortGuard* portGuard = dynamic_cast<const PortGuard*>(guard);
442 if (portGuard != NULL) {
443 string fuName = portGuard->port()->parentUnit()->name();
444 string portName = portGuard->port()->name();
445 guarded = new DisassemblyFUPort(fuName, portName);
446 }
447
448 // Check if the guarded element is a register.
449 const RegisterGuard* registerGuard =
450 dynamic_cast<const RegisterGuard*>(guard);
451 if (registerGuard != NULL) {
452
453 // Check if the register file is bool rf of a universal machine.
454 const RegisterFile* rf = registerGuard->registerFile();
456 dynamic_cast<const UniversalMachine*>(rf->machine());
457
458 if (machine != NULL && rf == &machine->booleanRegisterFile()) {
459 return new DisassemblySequentialGuard(moveGuard.isInverted());
460 } else {
461 string rfName = registerGuard->registerFile()->name();
462 int index = registerGuard->registerIndex();
463 guarded = new DisassemblyRegister(rfName, index);
464 }
465 }
466
467 // Check if the guard is unconditional.
468 if (moveGuard.isUnconditional()) {
469 // TODO: Disassemble unconditional guards.
470 assert(false);
471 }
472
473
474 return new DisassemblyGuard(guarded, moveGuard.isInverted());
475}
476
477/**
478 * Returns start address of the program.
479 *
480 * @return Start address of the program.
481 */
482Word
484 unsigned int address = program_.startAddress().location();
485 return address;
486}
487
488
489/**
490 * Returns number of instructions in the program.
491 *
492 * @return Instruction count.
493 */
494Word
496 Word count = 0;
497 unsigned procedureCount = program_.procedureCount();
498 for (unsigned i = 0; i < procedureCount; i++) {
499 const Procedure& procedure = program_.procedure(i);
500 count = count + procedure.instructionCount();
501 }
502 return count;
503}
504
505/**
506 * Returns number of labels at the given address.
507 *
508 * @param address Instruction address.
509 * @return Instruction label count.
510 */
511int
512POMDisassembler::labelCount(Word address) const {
513 return labelCount(program_, address);
514}
515
516/**
517 * Returns number of labels at the given address.
518 *
519 * @param address Instruction address.
520 * @return Instruction label count.
521 */
522int
524
525 Address iaddr(address, program.startAddress().space());
526 const GlobalScope& scope = program.globalScopeConst();
527 unsigned labelCount = scope.globalCodeLabelCount(iaddr);
528
529 if (labelCount > 0) {
530 return labelCount;
531 }
532
533 for (int i = 0; i < program.procedureCount(); i++) {
534 if (program.procedure(i).startAddress().location() == address) {
535 return 1;
536 }
537 }
538
539 return 0;
540}
541
542/**
543 * Returns instruction label with the given index.
544 *
545 * @param address Instruction address.
546 * @return Instruction label with the given index and address.
547 * @exception OutOfRange The address or index is out of range.
548 */
549std::string
550POMDisassembler::label(Word address, int index) const {
551 return label(program_, address, index);
552}
553
554/**
555 * Returns instruction label with the given index.
556 *
557 * @param address Instruction address.
558 * @param program Program to search label for.
559 * @return Instruction label with the given index and address.
560 * @exception OutOfRange The address or index is out of range.
561 */
562std::string
564 const TTAProgram::Program& program, Word address, int index) {
565 if (index == 0 && labelCount(program, address) == 1) {
566 for (int i = 0; i < program.procedureCount(); i++) {
567 if (program.procedure(i).startAddress().location() == address) {
568 return program.procedure(i).name();
569 }
570 }
571 }
572
573 if (index > labelCount(program, address)) {
574 throw OutOfRange(
575 __FILE__, __LINE__, __func__, "No label in requested index: " +
576 Conversion::toString(index));
577 }
578
579 Address iaddr(address, program.startAddress().space());
580
581 const CodeLabel& label =
582 program.globalScopeConst().globalCodeLabel(iaddr, index);
583
584 return label.name();
585}
586
587/**
588 * Checks if the terminal is a control unit jump or call operand.
589 *
590 * @param terminal Terminal to check.
591 * @return True, if the terminal is a control unit jump or call operand,
592 * false otherwise.
593 */
594bool
596
597 if (!terminal.isFUPort()) {
598 return false;
599 }
600
601 const FunctionUnit* fu = &terminal.functionUnit();
602
603 if (dynamic_cast<const ControlUnit*>(fu) == NULL) {
604 return false;
605 }
606
607 if (!terminal.isOpcodeSetting()) {
608 return false;
609 }
610
611 string operationName =
613
614 if (operationName == "call" || operationName == "jump") {
615 return true;
616 }
617
618 return false;
619}
620
621
622/**
623 * Static helper function to create disassembly string from a move.
624 *
625 * @param move Move to disassemble.
626 * @return Disassembly of the instruction.
627 */
628std::string
630
631 // special handling for calls: find out the procedure name to make
632 // the disassembly a bit more readable
633 if (move.isCall()) {
634 if (move.source().isInstructionAddress()) {
635
636 DisassemblyMove* dMove = createMove(move);
637 std::string disasm = "";
638 disasm = dMove->toString();
639
640 Procedure* proc = NULL;
641 try {
642 proc = dynamic_cast<TTAProgram::Procedure*>(
644 } catch (...) {
645 // proc stays NULL if something goes wrong.
646 }
647
648 std::string procName =
649 proc != NULL ? proc->name() : "unknown_proc";
650 return (boost::format("%s -> %s.call.1")
651 % procName
652 % move.destination().functionUnit().name()).str();
653 }
654
655 if (move.source().isCodeSymbolReference()) {
656 return (boost::format("%s -> %s.call.1")
657 % move.source().toString()
658 % move.destination().functionUnit().name()).str();
659 }
660 } else if (move.isJump() && move.source().isCodeSymbolReference()) {
661 // A jump to a procedure, converted from a call.
662 return (boost::format("%s -> %s.jump.1")
663 % move.source().toString()
664 % move.destination().functionUnit().name()).str();
665 }
666
667 DisassemblyMove* dMove = createMove(move);
668 std::string disasm = "";
669 disasm = dMove->toString();
670 delete dMove;
671 return disasm;
672}
673
676 const TTAProgram::Instruction& instruction, int addr) {
677 return POMDisassembler::disassemble(instruction, printAddresses_, addr);
678}
679
680/**
681 * Static helper function to create disassembly string from an instruction.
682 *
683 * @param instruction Instruction to disassemble.
684 * @param printAddresses Print the instruction's index as comment.
685 * @return Disassembly of the instruction.
686 */
687std::string
689 const TTAProgram::Instruction& instruction, bool printAddresses, int addr) {
690
691 std::string disasm = "";
692 if (!instruction.isInProcedure() ||
693 !instruction.parent().isInProgram()) {
694
695 // a "free instruction" that is not connected to any program
696 // traverse the moves instead of the buses
697
699 // The instruction disassembly is created by one move at a time.
700 for (int i = 0; i < instruction.moveCount(); i++) {
701
702 const Move& move = instruction.move(i);
703 const Bus* bus = &move.bus();
704 string busName = move.bus().name();
705 bool isUsed = false;
706
707 // Check for long immediate.
708 for (int i = 0; i < instruction.immediateCount(); i++) {
709 if (&instruction.instructionTemplate() !=
711 instruction.instructionTemplate().usesSlot(busName)) {
712 dInstruction->addMove(
713 createImmediateAssignment(instruction.immediate(i)));
714 isUsed = true;
715 }
716 }
717
718 // Check for move.
719 for (int i = 0; i < instruction.moveCount(); i++) {
720 if (&instruction.move(i).bus() == bus) {
721 dInstruction->addMove(createMove(instruction.move(i)));
722 isUsed = true;
723 }
724 }
725
726 if (!isUsed) {
727 dInstruction->addMove(new DisassemblyNOP);
728 }
729 }
730
731 // Add disassembly of long immediates in immediate slots.
732 for (int i = 0; i < instruction.immediateCount(); i++) {
733 dInstruction->addLongImmediate(
734 createImmediateAssignment(instruction.immediate(i)));
735 }
736
737 disasm = dInstruction->toString() + " # 'free instruction'";
738 delete dInstruction;
739 dInstruction = NULL;
740 } else {
741
742 const Program& program = instruction.parent().parent();
743 DisassemblyInstruction* dInstruction =
744 createInstruction(program, instruction);
745
746 disasm = dInstruction->toString();
747 delete dInstruction;
748 dInstruction = NULL;
749
750 // check for partially scheduled code, that is, moves that refer to
751 // the unversal machine even though the target machine is not
752 // a universal machine
753 const TTAMachine::Machine* mach =
754 dynamic_cast<UniversalMachine*>(&program.targetProcessor());
755
756 if (mach == NULL) {
757 // we have either mixed code or parallel code, let's check if this
758 // instruction has a move scheduled to universal machine's bus,
759 // in which case it's mixed code and the sequential move did not
760 // get printed with createInstruction()
761 for (int i = 0; i < instruction.moveCount(); ++i) {
762 const TTAProgram::Move& m = instruction.move(i);
763 if (dynamic_cast<UniversalMachine*>(m.bus().machine()) != NULL) {
764 // found unscheduled move, add it only as a comment to the
765 // disassembly to make the output compilable with TCEAssembler
766 disasm += "\t# unscheduled: ";
767 disasm += POMDisassembler::disassemble(m);
768 }
769 }
770 } else {
771 // a sequential program
772 }
773
774 if (printAddresses) {
775 disasm +=
776 "\t# @" +
778 addr != -1 ? addr : instruction.address().location());
779 }
780 }
781 // to display source filename and line number
782 // check for source code filename, we just use the file filename,
783 // assume the all the move belong the same file
784 TCEString fileNameStr = "";
785 for (int i = 0; i < instruction.moveCount(); ++i) {
786 const TTAProgram::Move& m = instruction.move(i);
787 if (m.hasSourceFileName()) {
788 fileNameStr += m.sourceFileName();
789 break;
790 }
791 }
792
793 if (fileNameStr != "")
794 disasm += "\t# file: " + fileNameStr;
795
796 // check for soure code line number info
797 TCEString lineNumberStr = "";
798 for (int i = 0; i < instruction.moveCount(); ++i) {
799 const TTAProgram::Move& m = instruction.move(i);
800 if (m.hasSourceLineNumber()) {
801 if (lineNumberStr != "") {
802 lineNumberStr += ", ";
803 }
804 lineNumberStr +=
806 }
807 }
808
809 if (lineNumberStr != "")
810 disasm += "\t# slines: " + lineNumberStr;
811
812 return disasm;
813}
814
815/**
816 * Static helper function to create a disassembly string from a program.
817 *
818 * @param program Program to disassemble.
819 * @param printAddresses Print the instruction addresses as comment.
820 * @return Disassembly of the program in a string.
821 * @exception Exception Can leak exceptions if the traversed program is
822 * malformed, etc.
823 * @deprecated Use obj.disassembleProcedures() instead.
824 */
825std::string
827 const TTAProgram::Program& program, bool printAddresses) {
828 POMDisassembler disasm(program, printAddresses);
829 return disasm.disassembleProcedures();
830}
831
834 TCEString output;
835 output << ":procedure " << proc.name() << ";";
836 return output;
837}
838
841 const TTAProgram::Procedure& proc, int instrIndex) const {
842
843 std::stringstream stringStream;
844 InstructionAddress addr = proc.startAddress().location() + instrIndex;
845 const int lc = POMDisassembler::labelCount(proc.parent(), addr);
846 for (int labelIndex = 0; labelIndex < lc; ++labelIndex) {
847 stringStream
849 proc.parent(), addr, labelIndex))
850 << std::endl;
851 }
852 return stringStream.str();
853}
854
857 return labelStr + ":";
858}
859
862
863 std::stringstream stringStream;
864
865 const TTAProgram::Instruction* currentInstruction = NULL;
866 stringStream << procedureDescription(proc) << std::endl;
867
868 for (int instrIndex = 0, iCount = proc.instructionCount();
869 instrIndex < iCount; ++instrIndex) {
870 currentInstruction = &proc.instructionAtIndex(instrIndex);
871
872 stringStream << destinationLabels(proc, instrIndex);
873
874 InstructionAddress addr = proc.startAddress().location() + instrIndex;
875
876 // Do not print "implicit instructions" of OTAs.
877 if (currentInstruction->size() > 0) {
878 stringStream << "\t" <<
879 disassembleInstruction(*currentInstruction, addr) << std::endl;
880 }
881 }
882 return stringStream.str();
883}
884
887
888 std::stringstream stringStream;
889
890 for (int procIndex = 0; procIndex < program_.procedureCount();
891 ++procIndex) {
892 const Procedure& proc = program_.procedureAtIndex(procIndex);
893 stringStream << disassembleProcedure(proc);
894 }
895 return stringStream.str();
896}
897
898/**
899 * Static helper function to create a disassembly string from a whole program
900 * including section markers and data memory initializations.
901 *
902 * @param program Program to disassemble.
903 * @param printAddresses If the instruction addresses should be printed.
904 * @return Disassembly of the program in a string.
905 * @exception Exception Can leak exceptions if the traversed program is
906 * malformed, etc.
907 * @deprecated Use obj.disassembleProgram() instead.
908 */
911 const TTAProgram::Program& program, bool printAddresses) {
912 POMDisassembler disasm(program, printAddresses);
913 return disasm.disassembleProgram();
914}
915
918 TCEString output;
919 output << "CODE " << startAddress << " ;";
920 return output;
921}
922
925 const TTAMachine::AddressSpace& aSpace, Word location) {
926 TCEString output;
927 output << "DATA " << aSpace.name() << " "
928 << location << " ;";
929 return output;
930}
931
934 const TTAProgram::DataDefinition& def) {
935
936 std::ostringstream output;
937 output << "DA " << std::dec << def.size();
938 if (def.isInitialized()) {
939 for (int mau = 0; mau < def.size(); mau++) {
940 output << endl << "1:0x" << std::hex << def.MAU(mau);
941 }
942 }
943 output << " ;" << endl;
944 return output.str();
945}
946
947/**
948 * Create a disassembly string from the whole program
949 * including module headers, section markers and data memory initializations.
950 *
951 * @return Disassembly of the program in a string.
952 * @exception Exception Can leak exceptions if the traversed program is
953 * malformed, etc.
954 */
957
958 std::stringstream output;
959 Word first = startAddress();
960
961 output << codeSectionDescription(first) << endl << endl;
962 output << disassembleProcedures() << endl << endl;
963
964 // Write data memory initializations.
965 for (int i = 0; i < program_.dataMemoryCount(); i++) {
966
968 const TTAMachine::AddressSpace& aSpace = mem.addressSpace();
969
970 if (mem.dataDefinitionCount() == 0) continue;
971
972 output << dataSectionDescription(
973 aSpace, mem.dataDefinition(0).startAddress().location()) << endl;
974
975 // Definitions are put in a map to order them.
976 // TODO: the indexing API of DataMemory could be used for this?
977 // TODO: does this handle "holes" correctly or assume fully
978 // "connected regions" always?
979 // TODO: this does not handle UDATA at all!
980 std::map<Word, const TTAProgram::DataDefinition*> definitions;
981 for (int d = 0; d < mem.dataDefinitionCount(); d++) {
982 const TTAProgram::DataDefinition& def = mem.dataDefinition(d);
983 definitions[def.startAddress().location()] = &def;
984 }
985
986 std::map<Word, const TTAProgram::DataDefinition*>::iterator iter =
987 definitions.begin();
988
989 for (; iter != definitions.end(); iter++) {
990 const TTAProgram::DataDefinition* def = (*iter).second;
991 output << dataDefDescription(*def) << endl;
992 }
993 }
994 output << endl;
995
996 return output.str();
997}
998
999
1000/**
1001 * Static helper function to create a disassembly string from a procedure.
1002 *
1003 * @param proc Procedure to disassemble.
1004 * @param printAddresses Print the instruction addresses as comment.
1005 * @return Disassembly of the procedure in a string.
1006 * @exception Exception Can leak exceptions if the traversed program is
1007 * malformed, etc.
1008 * @deprecated Use obj.disassembleProcedure(proc) instead.
1009 */
1010std::string
1012 const TTAProgram::Procedure& proc, bool printAddresses) {
1013 POMDisassembler disasm(printAddresses);
1014 return disasm.disassembleProcedure(proc);
1015}
1016
1017/**
1018 * A factor for building a correct type of disassembler for the
1019 * target.
1020 */
1023 const TTAMachine::Machine& /*mach*/,
1025 return new POMDisassembler(program);
1026}
1027
1028
1031 return TCEString("\t# @") << instr.address().location();
1032}
#define __func__
#define assert(condition)
unsigned long LongWord
Definition BaseType.hh:49
UInt32 InstructionAddress
Definition BaseType.hh:175
TTAMachine::Machine * machine
the architecture definition of the estimated processor
find Finds info of the inner loops in the program
static std::string toString(const T &source)
void addLongImmediate(DisassemblyImmediateAssignment *longImm)
void addMove(DisassemblyInstructionSlot *move)
virtual std::string toString() const
static NullOperation & instance()
static SimValue & instance()
Definition SimValue.cc:1642
virtual TCEString name() const
Definition Operation.cc:93
static DisassemblyImmediate * createInlineImmediate(const TTAProgram::Terminal &terminal, bool signExtend)
POMDisassembler(bool indices=false)
virtual TCEString procedureDescription(const TTAProgram::Procedure &proc)
int labelCount(Word address) const
static DisassemblyImmediateRegister * createImmediateRegister(const TTAProgram::Terminal &terminal)
static POMDisassembler * disassembler(const TTAMachine::Machine &mach, const TTAProgram::Program &program)
virtual TCEString disassembleInstruction(const TTAProgram::Instruction &instruction, int addr=-1)
"Template methods" that can be overridden in the derived assemblers.
static bool isCallOrJump(const TTAProgram::Terminal &terminal)
static std::string disassemble(const TTAProgram::Move &move)
static DisassemblyElement * createRegister(const TTAProgram::Terminal &terminal)
static TCEString disassembleFully(const TTAProgram::Program &program, bool indices=false)
virtual TCEString disassembleProgram()
virtual DisassemblyInstruction * createInstruction(Word instructionIndex) const
static DisassemblyElement * createTerminal(const TTAProgram::Terminal &terminal)
virtual Word instructionCount() const
static DisassemblyElement * createFUPort(const TTAProgram::Terminal &terminal)
static DisassemblyMove * createMove(const TTAProgram::Move &move)
virtual ~POMDisassembler()
virtual TCEString dataDefDescription(const TTAProgram::DataDefinition &def)
virtual TCEString disassembleProcedure(const TTAProgram::Procedure &proc)
bool printAddresses_
True if instruction indices (addresses) should be printed at the end of lines.
virtual Word startAddress() const
virtual TCEString labelPositionDescription(TCEString labelStr) const
virtual TCEString printAddress(const TTAProgram::Instruction &instr) const
static DisassemblyImmediateAssignment * createImmediateAssignment(const TTAProgram::Immediate &immediate)
virtual TCEString destinationLabels(const TTAProgram::Procedure &proc, int instrIndex) const
virtual TCEString disassembleProcedures()
virtual TCEString dataSectionDescription(const TTAMachine::AddressSpace &aSpace, Word location)
std::string label(Word address, int index) const
const TTAProgram::Program & program_
Program object model to disassemble.
virtual TCEString codeSectionDescription(Word startAddress)
static DisassemblyGuard * createGuard(const TTAProgram::MoveGuard &guard)
ULongWord uLongWordValue() const
Definition SimValue.cc:1027
static std::string stringToLower(const std::string &source)
FunctionUnit * parentUnit() const
Definition BaseFUPort.cc:96
bool signExtends() const
Definition Bus.cc:171
virtual Machine * machine() const
virtual TCEString name() const
virtual HWOperation * operation(const std::string &name) const
virtual FUPort * operationPort(const std::string &name) const
int io(const FUPort &port) const
const std::string & name() const
virtual bool usesSlot(const std::string &slotName) const
ComponentType * item(int index) const
virtual bool isUniversalMachine() const
Definition Machine.cc:127
static NullInstructionTemplate & instance()
FUPort * port() const
virtual std::string name() const
Definition Port.cc:141
const RegisterFile * registerFile() const
InstructionAddress location() const
virtual bool isInProgram() const
virtual int instructionCount() const
virtual Program & parent() const
virtual Address startAddress() const
virtual Instruction & instructionAtIndex(int index) const
virtual Address startAddress() const
virtual bool isInitialized() const
virtual MinimumAddressableUnit MAU(int index) const
DataDefinition & dataDefinition(Address address) const
Definition DataMemory.cc:79
int dataDefinitionCount() const
const TTAMachine::AddressSpace & addressSpace() const
int globalCodeLabelCount(Address address) const
TerminalImmediate & value() const
Definition Immediate.cc:103
const Terminal & destination() const
Definition Immediate.cc:92
Move & move(int i) const
Address address() const
Immediate & immediate(int i) const
CodeSnippet & parent() const
const TTAMachine::InstructionTemplate & instructionTemplate() const
std::string name() const
Definition Label.cc:74
bool isInverted() const
Definition MoveGuard.cc:76
bool isUnconditional() const
Definition MoveGuard.cc:65
const TTAMachine::Guard & guard() const
Definition MoveGuard.cc:86
MoveGuard & guard() const
Definition Move.cc:345
bool hasSourceLineNumber() const
Definition Move.cc:445
bool isUnconditional() const
Definition Move.cc:154
Instruction & parent() const
Definition Move.cc:115
Terminal & source() const
Definition Move.cc:302
int sourceLineNumber() const
Definition Move.cc:459
bool hasSourceFileName() const
Definition Move.cc:478
bool isJump() const
Definition Move.cc:164
bool isInInstruction() const
Definition Move.cc:144
bool isCall() const
Definition Move.cc:190
Terminal & destination() const
Definition Move.cc:323
std::string sourceFileName() const
Definition Move.cc:488
const TTAMachine::Bus & bus() const
Definition Move.cc:373
TCEString name() const
Definition Procedure.hh:66
Procedure & procedure(int index) const
Definition Program.cc:622
const Procedure & procedureAtIndex(int index) const
Definition Program.cc:508
Address startAddress() const
Definition Program.cc:286
DataMemory & dataMemory(int index) const
Definition Program.cc:967
Instruction & instructionAt(InstructionAddress address) const
Definition Program.cc:374
int procedureCount() const
Definition Program.cc:610
int dataMemoryCount() const
Definition Program.cc:942
virtual Operation & hintOperation() const
virtual Operation & operation() const
virtual const TTAMachine::Port & port() const
virtual bool isOpcodeSetting() const
virtual const TTAMachine::HWOperation * hwOperation() const
virtual SimValue value() const
virtual SimValue value() const
Definition Terminal.cc:178
virtual bool isCodeSymbolReference() const
Definition Terminal.cc:154
virtual const TTAMachine::FunctionUnit & functionUnit() const
Definition Terminal.cc:251
virtual int index() const
Definition Terminal.cc:274
virtual bool isOpcodeSetting() const
Definition Terminal.cc:285
virtual Operation & operation() const
Definition Terminal.cc:319
virtual const InstructionReference & instructionReference() const
Definition Terminal.cc:188
virtual bool isGPR() const
Definition Terminal.cc:107
virtual bool isInstructionAddress() const
Definition Terminal.cc:87
virtual bool isImmediateRegister() const
Definition Terminal.cc:97
virtual TCEString toString() const =0
virtual const TTAMachine::Port & port() const
Definition Terminal.cc:378
virtual bool isImmediate() const
Definition Terminal.cc:63
virtual const TTAMachine::ImmediateUnit & immediateUnit() const
Definition Terminal.cc:240
virtual const TTAMachine::RegisterFile & registerFile() const
Definition Terminal.cc:225
virtual bool isFUPort() const
Definition Terminal.cc:118