OpenASIP  2.0
Instruction.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 Instruction.cc
26  *
27  * Implementation of Instruction class.
28  *
29  * @author Ari Metsähalme 2005 (ari.metsahalme-no.spam-tut.fi)
30  * @author Pekka Jääskeläinen 2016
31  * @note rating: red
32  */
33 
34 #include <boost/format.hpp>
35 
36 #include "Instruction.hh"
37 #include "NullInstruction.hh"
38 #include "Procedure.hh"
39 #include "ContainerTools.hh"
40 #include "Move.hh"
41 #include "Immediate.hh"
42 #include "Terminal.hh"
43 #include "TerminalImmediate.hh"
45 #include "NullProcedure.hh"
46 #include "POMDisassembler.hh"
47 #include "Conversion.hh"
48 #include "Bus.hh"
49 
50 #include "MathTools.hh"
51 
52 namespace TTAProgram {
53 
54 /////////////////////////////////////////////////////////////////////////////
55 // Instruction
56 /////////////////////////////////////////////////////////////////////////////
57 
58 /**
59  * The constructor.
60  *
61  * The default size of an instruction is 1 MAU.
62  */
64  const TTAMachine::InstructionTemplate& instructionTemplate) :
65  parent_(NULL), insTemplate_(&instructionTemplate),
66  positionInProcedure_((InstructionAddress)-1),
67  finalAddress_((InstructionAddress)-1),
68  size_(1), hasRegisterAccesses_(false), hasConditionalRegisterAccesses_(false) {
69 }
70 
71 /**
72  * Constructor.
73  *
74  * Alternative constructor that takes the instruction size as a parameter.
75  *
76  * @param size The size of the instruction in MAU's.
77  */
79  int size,
80  const TTAMachine::InstructionTemplate& instructionTemplate) :
81  parent_(NULL), insTemplate_(&instructionTemplate),
82  positionInProcedure_((InstructionAddress)-1),
83  finalAddress_((InstructionAddress)-1),
84  size_(size), hasRegisterAccesses_(false), hasConditionalRegisterAccesses_(false) {
85  assert(size == 1 &&
86  "Instructions sizes other than 1 not supported in POM at the "
87  "moment.");
88 }
89 
90 /**
91  * The destructor.
92  */
94  for (auto i : moves_) {
95  i->setParent(NullInstruction::instance());
96  }
97  moves_.clear();
98  immediates_.clear();
99 }
100 
101 /**
102  * Return the parent that contains the instruction.
103  *
104  * @return The parent that contains the instruction.
105  * @exception IllegalRegistration If the instruction is not registered
106  * anywhere.
107  */
110  if (parent_ != NULL) {
111  return *parent_;
112  } else {
113  throw IllegalRegistration(__FILE__, __LINE__, __func__,
114  "Instruction is not registered.");
115  }
116 }
117 
118 /**
119  * Sets the parent procedure of the instruction.
120  *
121  * @param proc The new parent procedure.
122  */
123 void
125  parent_ = &proc;
126 }
127 
128 /**
129  * Tells whether the instruction belongs to a procedure.
130  *
131  * @return True if the instruction belongs to a procedure (it is registered),
132  * false otherwise.
133  */
134 bool
136  return (parent_ != NULL && parent_ != &NullProcedure::instance());
137 }
138 
139 /**
140  * Adds a move to the instruction.
141  *
142  * The ownership of the move will be passed to the instruction.
143  *
144  * @param move The move to add.
145  */
146 void
147 Instruction::addMove(std::shared_ptr<Move> move) {
149  throw ObjectAlreadyExists(__FILE__, __LINE__, __func__,
150  "Move is already added.");
151  } else {
152  if (move->source().isGPR() || move->destination().isGPR()) {
153  hasRegisterAccesses_ = true;
154  if (!move->isUnconditional())
156  }
157  moves_.push_back(move);
158  move->setParent(*this);
159  }
160 #if 0
162  if (insTemplate_->usesSlot(move->bus().name())) {
163  assert(false &&
164  "Instruction template already uses the move's slot");
165  }
166  }
167 #endif
168 }
169 
170 /**
171  * Returns the number of moves contained in this instruction.
172  *
173  * @return The number of moves contained in this instruction.
174  */
175 int
177  return moves_.size();
178 }
179 
180 /**
181  * Return the move at the given index in this instruction.
182  *
183  * The order of moves is arbitrary, no assumption should be made by
184  * clients. Anyways, order of moves in instruction does not change between
185  * calls to this method.
186  *
187  * @param i The index of the move.
188  * @return The move at the given index in this instruction.
189  * @exception OutOfRange if the given index is negative or greater than
190  * the number of moves in the instruction.
191  */
192 Move&
193 Instruction::move(int i) const {
194  if (i < 0 || static_cast<unsigned int>(i) >= moves_.size()) {
195  throw OutOfRange(__FILE__, __LINE__, __func__,
196  "No move in instruction for given index: " +
198  } else {
199  return *moves_.at(i);
200  }
201 }
202 
203 /**
204  * Return the move at the given index in this instruction.
205  *
206  * The order of moves is arbitrary, no assumption should be made by
207  * clients. Anyways, order of moves in instruction does not change between
208  * calls to this method.
209  *
210  * @param i The index of the move.
211  * @return The move at the given index in this instruction.
212  * @exception OutOfRange if the given index is negative or greater than
213  * the number of moves in the instruction.
214  */
215 std::shared_ptr<Move>
216 Instruction::movePtr(int i) const {
217  if (i < 0 || static_cast<unsigned int>(i) >= moves_.size()) {
218  throw OutOfRange(__FILE__, __LINE__, __func__,
219  "No move in instruction for given index: " +
221  } else {
222  return moves_.at(i);
223  }
224 }
225 
226 /**
227  * Adds an immediate to the instruction.
228  *
229  * The ownership of the immediate will be passed to the instruction.
230  *
231  * @param imm The immediate to add.
232  */
233 void
234 Instruction::addImmediate(std::shared_ptr<Immediate> imm) {
236  throw ObjectAlreadyExists(__FILE__, __LINE__, __func__,
237  "Immediate is already added.");
238  } else {
239  immediates_.push_back(imm);
240  imm->setParent(this);
241  }
242 
243 #if 0
245  int requiredWidth = std::min(
246  MathTools::requiredBits(imm->value().value().unsignedValue()),
247  imm->value().value().width());
248 
249  if (requiredWidth >
250  insTemplate_->supportedWidth(imm->destination().immediateUnit())) {
251  assert(false &&
252  "The immediate is wider than the instruction template can "
253  "transport.");
254  }
255  }
256 #endif
257 }
258 
259 /**
260  * Returns the number of immediate registers written by the
261  * instruction template of this instruction.
262  *
263  * @return The number of immediate registers written by the
264  * instruction template of this instruction.
265  */
266 int
268  return immediates_.size();
269 }
270 
271 /**
272  * Return the immediate write action at the given index in this
273  * instruction.
274  *
275  * The order of immediates is arbitrary, no assumption should be made
276  * by clients.
277  *
278  * @param i The index of the immediate.
279  * @return The immediate write action at the given index in this
280  * instruction.
281  * @exception OutOfRange if the index is negative or greater than the
282  * number of immediates in the instruction.
283  */
284 Immediate&
286  if (i < 0 || static_cast<unsigned int>(i) >= immediates_.size()) {
287  throw OutOfRange(__FILE__, __LINE__, __func__,
288  "No immediate in instruction with index: " +
290  } else {
291  return *immediates_.at(i);
292  }
293 }
294 
295 /**
296  * Return the immediate write action at the given index in this
297  * instruction.
298  *
299  * The order of immediates is arbitrary, no assumption should be made
300  * by clients.
301  *
302  * @param i The index of the immediate.
303  * @return The immediate write action at the given index in this
304  * instruction.
305  * @exception OutOfRange if the index is negative or greater than the
306  * number of immediates in the instruction.
307  */
308 std::shared_ptr<Immediate>
310  if (i < 0 || static_cast<unsigned int>(i) >= immediates_.size()) {
311  throw OutOfRange(__FILE__, __LINE__, __func__,
312  "No immediate in instruction with index: " +
314  } else {
315  return immediates_[i];
316  }
317 }
318 
319 /**
320  * Returns the address of the instruction.
321  *
322  * @return The address of the instruction.
323  * @exception IllegalRegistration if the instruction does not belong
324  * to a procedure.
325  */
326 Address
328  if (finalAddress_ != (InstructionAddress)-1) {
329  Address address(finalAddress_, parent().startAddress().space());
330  return address;
331  }
332 
333  if (!isInProcedure()) {
334  TCEString msg = "Instruction is not registered in a procedure: ";
335  msg += POMDisassembler::disassemble(*this);
336  throw IllegalRegistration(
337  __FILE__, __LINE__, __func__,
338  msg);
339  }
340  // speed up by caching the Instruction's position in the Procedure
343  (InstructionAddress)parent().instructionCount() &&
344  &parent().instructionAtIndex(positionInProcedure_) == this) {
345  // the instruction has not moved in the Procedure, we
346  // can compute its address in constant time
347  // cannot cache the Address itself because the Procedure might
348  // have moved
350  parent().startAddress().location() + positionInProcedure_,
351  parent().startAddress().space());
352  return address;
353  } else {
354  Address address = parent().address(*this);
357  return address;
358  }
359 }
360 
361 /**
362  * Returns the size of the instruction in MAU's.
363  */
364 short
366  return size_;
367 }
368 
369 /**
370  * Make a complete copy of the instruction.
371  *
372  * The copy is identical, except that it is not registered to the
373  * procedure of the original instruction (and therefore, any address
374  * it refers to is not meaningful).
375  *
376  * @return A complete copy of the instruction.
377  */
380  Instruction* newIns = new Instruction(size_, *insTemplate_);
381  for (int i = 0; i < moveCount(); i++) {
382  newIns->addMove(move(i).copy());
383  }
384  for (int i = 0; i < immediateCount(); i++) {
385  newIns->addImmediate(immediate(i).copy());
386  }
389  newIns->copyAnnotationsFrom(*this);
390  return newIns;
391 }
392 
393 /**
394  * Returns true in case this Instruction contains moves that access registers.
395  *
396  * This method can be used to optimize register utilization analysis.
397  */
398 bool
400  return hasRegisterAccesses_;
401 }
402 
403 /**
404  * Returns true in case this Instruction contains moves that access registers
405  * and are conditional.
406  *
407  * This method can be used to optimize register utilization analysis.
408  *
409  * @return True in case at least one conditional move accesses registers.
410  */
411 bool
414 }
415 
416 /**
417  * Returns whether this instruction contains moves that are jumps.
418  *
419  * @return True in case at least one move in this instruction is a jump.
420  */
421 bool
423 
424  for (int i = 0; i < moveCount(); i++ ) {
425  if (move(i).isJump()) {
426  return true;
427  }
428  }
429  return false;
430 }
431 
432 /**
433  * Returns whether this instruction contains moves that are calls.
434  *
435  * @return True in case at least one move in this instruction is a call.
436  */
437 bool
439 
440  for (int i = 0; i < moveCount(); i++ ) {
441  if (move(i).isCall()) {
442  return true;
443  }
444  }
445  return false;
446 }
447 
448 /**
449  * Returns whether this instruction contains a procedure return move.
450  */
451 bool
453 
454  for (int i = 0; i < moveCount(); i++ ) {
455  if (move(i).isReturn()) {
456  return true;
457  }
458  }
459  return false;
460 }
461 
462 
463 /**
464  * Returns whether this instruction contains moves that affect the
465  * control flow (branches or calls).
466  *
467  * @return True in case at least one move in this instruction is a control
468  * flow move.
469  */
470 bool
472  for (int i = 0; i < moveCount(); i++) {
473  if (move(i).isControlFlowMove()) {
474  return true;
475  }
476  }
477  return false;
478 }
479 
480 
481 
482 /**
483  * Sets instruction template.
484  *
485  * @param insTemp Instruction template for the instruction.
486  */
487 void
489  const TTAMachine::InstructionTemplate& insTemp) {
490  insTemplate_= &insTemp;
491 
492 #if 0
493  for (int i = 0; i < moveCount(); i++) {
494  if (insTemplate_->usesSlot(move(i).bus().name())) {
495  assert(false && "Instruction template conflicts with the "
496  "instruction's slot layout: Both the new template and a move "
497  "uses same slot.");
498  }
499  }
500 
501  for (int i = 0; i < immediateCount(); i++) {
502  int requiredWidth = std::min(
504  immediate(i).value().value().unsignedValue()),
505  immediate(i).value().value().width());
506  if (requiredWidth >
508  immediate(i).destination().immediateUnit())) {
509  assert(false && "The instruction has an long immediate "
510  "not supported by the new instruction template.");
511  }
512  }
513 #endif
514 }
515 
516 
517 /**
518  * Returns the instruction template of instruction.
519  *
520  * @return The instruction template of instruction.
521  */
524  return *insTemplate_;
525 }
526 
527 /**
528  * Remove move from instruction.
529  *
530  * Move may become deleted if last smart pointer to it gets removed.
531  *
532  * @param move Move to remove.
533  * @exception IllegalRegistration If move doesn't belong to instruction.
534  */
535 void
537  if (&move.parent() != this) {
538  throw IllegalRegistration(__FILE__, __LINE__);
539  }
540 
542  for (MoveList::iterator iter = moves_.begin();
543  iter != moves_.end(); iter++) {
544  if ((iter->get()) == &move) {
545  moves_.erase(iter);
546  break;
547  }
548  }
549 }
550 
551 /**
552  * Remove immediate from instruction.
553  *
554  * Immediate may get deleted if use-count of smart pointer goes to zero.
555  *
556  * @param immediate Immediate to remove.
557  * @exception IllegalRegistration If immediate doesn't belong to instruction.
558  */
559 void
561  for (ImmList::iterator iter = immediates_.begin();
562  iter != immediates_.end(); iter++) {
563  if ((*iter).get() == &imm) {
564  imm.setParent(nullptr);
565  immediates_.erase(iter);
566  return;
567  }
568  }
569  throw IllegalRegistration(__FILE__, __LINE__);
570 }
571 
572 /**
573  * Returns the disassembly of the instruction.
574  */
575 std::string
577  return POMDisassembler::disassemble(*this);
578 }
579 
580 }
TTAProgram::Move::copy
std::shared_ptr< Move > copy() const
Definition: Move.cc:413
TTAProgram
Definition: Estimator.hh:65
TTAProgram::Instruction::removeMove
void removeMove(Move &move)
Definition: Instruction.cc:536
TTAProgram::Instruction::addMove
void addMove(std::shared_ptr< Move > move)
Definition: Instruction.cc:147
InstructionAddress
UInt32 InstructionAddress
Definition: BaseType.hh:175
TTAProgram::Instruction::finalAddress_
InstructionAddress finalAddress_
In case the final instruction address is known (due to program not modified anymore),...
Definition: Instruction.hh:149
NullProcedure.hh
TTAMachine::Component::name
virtual TCEString name() const
Definition: MachinePart.cc:125
TTAProgram::Instruction::move
Move & move(int i) const
Definition: Instruction.cc:193
TTAProgram::Address
Definition: Address.hh:51
TTAProgram::Immediate::setParent
void setParent(Instruction *ins)
Definition: Immediate.hh:68
TTAProgram::Move::isReturn
bool isReturn() const
Definition: Move.cc:259
TTAProgram::Instruction::hasConditionalRegisterAccesses
bool hasConditionalRegisterAccesses() const
Definition: Instruction.cc:412
TTAProgram::Instruction
Definition: Instruction.hh:57
TTAProgram::Move::isUnconditional
bool isUnconditional() const
Definition: Move.cc:154
OutOfRange
Definition: Exception.hh:320
Procedure.hh
TTAProgram::NullProcedure::instance
static NullProcedure & instance()
Definition: NullProcedure.cc:68
TTAProgram::Move::destination
Terminal & destination() const
Definition: Move.cc:323
TTAProgram::Instruction::removeImmediate
void removeImmediate(Immediate &imm)
Definition: Instruction.cc:560
TTAProgram::Instruction::toString
std::string toString() const
Definition: Instruction.cc:576
TTAProgram::Move::bus
const TTAMachine::Bus & bus() const
Definition: Move.cc:373
TTAProgram::CodeSnippet::startAddress
virtual Address startAddress() const
Definition: CodeSnippet.cc:780
Terminal.hh
TTAProgram::AnnotatedInstructionElement::copyAnnotationsFrom
void copyAnnotationsFrom(const AnnotatedInstructionElement &other)
Definition: AnnotatedInstructionElement.cc:193
TTAProgram::Immediate::copy
std::shared_ptr< Immediate > copy() const
Definition: Immediate.cc:131
TTAProgram::Instruction::immediates_
ImmList immediates_
Immediates contained in this instruction.
Definition: Instruction.hh:137
TTAProgram::Instruction::hasCall
bool hasCall() const
Definition: Instruction.cc:438
Conversion::toString
static std::string toString(const T &source)
TTAProgram::Move::setParent
void setParent(Instruction &ins)
Definition: Move.cc:130
POMDisassembler.hh
TTAMachine::InstructionTemplate
Definition: InstructionTemplate.hh:49
assert
#define assert(condition)
Definition: Application.hh:86
TTAProgram::Instruction::hasRegisterAccesses_
bool hasRegisterAccesses_
Set to true in case this instruction has moves that access registers.
Definition: Instruction.hh:154
TTAProgram::Instruction::insTemplate_
const TTAMachine::InstructionTemplate * insTemplate_
Instruction template that is used for this instruction.
Definition: Instruction.hh:142
TTAProgram::Immediate
Definition: Immediate.hh:54
TTAProgram::Move::isControlFlowMove
bool isControlFlowMove() const
Definition: Move.cc:233
TTAProgram::Move::isCall
bool isCall() const
Definition: Move.cc:190
Instruction.hh
Conversion.hh
TTAProgram::Instruction::copy
Instruction * copy() const
Definition: Instruction.cc:379
NullInstruction.hh
TTAProgram::Instruction::~Instruction
~Instruction()
Definition: Instruction.cc:93
__func__
#define __func__
Definition: Application.hh:67
TTAProgram::Instruction::parent
CodeSnippet & parent() const
Definition: Instruction.cc:109
TTAProgram::Instruction::size_
short size_
Size of instruction in MAU's.
Definition: Instruction.hh:152
TTAProgram::Terminal::isGPR
virtual bool isGPR() const
Definition: Terminal.cc:107
NullInstructionTemplate.hh
MathTools::requiredBits
static int requiredBits(unsigned long int number)
TTAMachine::InstructionTemplate::supportedWidth
virtual int supportedWidth() const
Definition: InstructionTemplate.cc:427
TTAProgram::Address::location
InstructionAddress location() const
TTAProgram::Move
Definition: Move.hh:55
TTAProgram::NullInstruction::instance
static NullInstruction & instance()
Definition: NullInstruction.cc:66
Bus.hh
TTAProgram::Instruction::immediatePtr
std::shared_ptr< Immediate > immediatePtr(int i) const
Definition: Instruction.cc:309
TTAProgram::Instruction::immediate
Immediate & immediate(int i) const
Definition: Instruction.cc:285
TTAProgram::Instruction::hasRegisterAccesses
bool hasRegisterAccesses() const
Definition: Instruction.cc:399
TTAProgram::CodeSnippet
Definition: CodeSnippet.hh:59
IllegalRegistration
Definition: Exception.hh:532
TTAProgram::Instruction::hasJump
bool hasJump() const
Definition: Instruction.cc:422
TTAProgram::Instruction::instructionTemplate
const TTAMachine::InstructionTemplate & instructionTemplate() const
Definition: Instruction.cc:523
TTAProgram::Instruction::hasReturn
bool hasReturn() const
Definition: Instruction.cc:452
TTAProgram::Instruction::setParent
void setParent(CodeSnippet &proc)
Definition: Instruction.cc:124
TTAProgram::Instruction::isInProcedure
bool isInProcedure() const
Definition: Instruction.cc:135
TTAProgram::Instruction::positionInProcedure_
InstructionAddress positionInProcedure_
Cache the instruction's index in the its procedure for faster address().
Definition: Instruction.hh:145
TTAProgram::CodeSnippet::address
virtual Address address(const Instruction &ins) const
Definition: CodeSnippet.cc:163
POMDisassembler::disassemble
static std::string disassemble(const TTAProgram::Move &move)
Definition: POMDisassembler.cc:629
TTAMachine::NullInstructionTemplate::instance
static NullInstructionTemplate & instance()
Definition: NullInstructionTemplate.cc:62
TTAProgram::Instruction::moves_
MoveList moves_
Moves contained in this instruction.
Definition: Instruction.hh:135
TTAProgram::Move::parent
Instruction & parent() const
Definition: Move.cc:115
TerminalImmediate.hh
Immediate.hh
false
find Finds info of the inner loops in the false
Definition: InnerLoopFinder.cc:81
ObjectAlreadyExists
Definition: Exception.hh:1002
TTAProgram::Instruction::hasConditionalRegisterAccesses_
bool hasConditionalRegisterAccesses_
Set to true in case this instruction has moves that access registers and are conditional.
Definition: Instruction.hh:157
TCEString
Definition: TCEString.hh:53
TTAProgram::Instruction::size
short size() const
Definition: Instruction.cc:365
TTAProgram::Instruction::immediateCount
int immediateCount() const
Definition: Instruction.cc:267
TTAProgram::Instruction::setInstructionTemplate
void setInstructionTemplate(const TTAMachine::InstructionTemplate &insTemp)
Definition: Instruction.cc:488
TTAProgram::Move::source
Terminal & source() const
Definition: Move.cc:302
ContainerTools::containsValue
static bool containsValue(const ContainerType &aContainer, const ElementType &aKey)
TTAProgram::Instruction::hasControlFlowMove
bool hasControlFlowMove() const
Definition: Instruction.cc:471
MathTools.hh
TTAProgram::Move::isJump
bool isJump() const
Definition: Move.cc:164
TTAProgram::Instruction::movePtr
std::shared_ptr< Move > movePtr(int i) const
Definition: Instruction.cc:216
Move.hh
TTAProgram::Instruction::parent_
CodeSnippet * parent_
Parent procedure.
Definition: Instruction.hh:139
TTAProgram::Instruction::moveCount
int moveCount() const
Definition: Instruction.cc:176
TTAMachine::InstructionTemplate::usesSlot
virtual bool usesSlot(const std::string &slotName) const
Definition: InstructionTemplate.cc:265
TTAProgram::Instruction::address
Address address() const
Definition: Instruction.cc:327
TTAProgram::Instruction::addImmediate
void addImmediate(std::shared_ptr< Immediate > imm)
Definition: Instruction.cc:234
ContainerTools.hh
TTAProgram::Instruction::Instruction
Instruction(const TTAMachine::InstructionTemplate &instructionTemplate=TTAMachine::NullInstructionTemplate::instance())
Definition: Instruction.cc:63