OpenASIP  2.0
TPEFCodeSectionWriter.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 TPEFCodeSectionWriter.cc
26  *
27  * Definition of TPEFCodeSectionWriter class.
28  *
29  * @author Jussi Nykänen 2003 (nykanen-no.spam-cs.tut.fi)
30  * @author Mikael Lepistö 2003 (tmlepist-no.spam-cs.tut.fi)
31  *
32  * @note rating: yellow
33  */
34 
35 #include <list>
36 
37 #include "TPEFCodeSectionWriter.hh"
38 #include "SafePointer.hh"
39 #include "ReferenceKey.hh"
40 #include "Section.hh"
41 #include "SectionElement.hh"
42 #include "MoveElement.hh"
43 #include "ImmediateElement.hh"
44 #include "SectionSizeReplacer.hh"
45 #include "CodeSection.hh"
46 #include "BinaryStream.hh"
47 
48 namespace TPEF {
49 
50 using std::list;
51 using ReferenceManager::SafePointer;
52 using ReferenceManager::FileOffsetKey;
53 using ReferenceManager::SectionKey;
54 using ReferenceManager::SectionOffsetKey;
55 
56 const TPEFCodeSectionWriter TPEFCodeSectionWriter::instance_;
58 
59 /**
60  * Constructor.
61  *
62  * Registers itself to SectionWriter.
63  */
66 }
67 
68 /**
69  * Destructor.
70  */
72 }
73 
74 /**
75  * Returns the type of section that this writer writes.
76  *
77  * @return The type of section that this writer writes.
78  */
81  return Section::ST_CODE;
82 }
83 
84 /**
85  * Writes the data of the section to stream.
86  *
87  * @param stream The stream to be written to.
88  * @param sect The section to be written.
89  */
90 void
92  BinaryStream& stream,
93  const Section* sect) const {
94 
95  // file offset to data of section
96  FileOffset startOffset = stream.writePosition();
97 
98  SectionOffset sectOffset = 0;
99 
101  SectionId id = sKey.sectionId();
102 
103  for (Word i = 0; i < sect->elementCount(); i++) {
104  InstructionElement *elem =
105  dynamic_cast<InstructionElement*>(sect->element(i));
106 
107  assert(elem != NULL);
108 
109  sectOffset = stream.writePosition() - startOffset;
110 
111  if (SafePointer::isReferenced(elem) || i == 0) {
113  SectionOffsetKey(id, sectOffset), elem);
114  }
115 
116  // check if this is ending move of instruction
117  bool isEnd = false;
118  i++;
119  if (i == sect->elementCount() ||
120  dynamic_cast<InstructionElement*>(sect->element(i))->begin()) {
121 
122  isEnd = true;
123  }
124  i--;
125 
126  writeAttributeField(stream, elem, isEnd);
127  writeDataField(stream, elem);
128  writeAnnotations(stream, elem);
129  }
130 
131  // section body offset
133  FileOffsetKey(startOffset), sect->element(0));
134 
135  SectionSizeReplacer::setSize(sect, stream.writePosition() - startOffset);
136 }
137 
138 /**
139  * Writes the attribute field of either move or immediate.
140  *
141  * @param stream The stream to be written to.
142  * @param elem The element to be written out.
143  */
144 void
146  BinaryStream& stream,
147  SectionElement* elem,
148  bool isEnd) const {
149 
150  Byte attribute = 0;
151 
152  if (dynamic_cast<InstructionElement*>(elem)->isMove()) {
153 
154  MoveElement* move = dynamic_cast<MoveElement*>(elem);
155 
156  if (move->isGuarded()) {
157  attribute = attribute | TPEFHeaders::IA_MGUARD;
158  }
159 
160  if (move->isEmpty()) {
161  attribute = attribute | TPEFHeaders::IA_EMPTY;
162  }
163 
164  } else if (dynamic_cast<InstructionElement*>(elem)->isImmediate()) {
165 
166  ImmediateElement* imm = dynamic_cast<ImmediateElement*>(elem);
167 
168  // immediate type flag
169  attribute = attribute | TPEFHeaders::IA_TYPE;
170 
171  // length of immediate is stored in 4 first bits of byte.
172  Byte immLength = imm->length();
173  Byte immBits = (immLength << (BYTE_BITWIDTH / 2));
174 
175  attribute = attribute | immBits;
176 
177  } else {
178  bool impossibleInstructionElementType = false;
179  assert(impossibleInstructionElementType);
180  }
181 
182  if (dynamic_cast<InstructionElement*>(elem)->annotationCount() > 0) {
183  attribute = attribute | TPEFHeaders::IA_ANNOTE;
184  }
185 
186  if (isEnd) {
187  attribute = attribute | TPEFHeaders::IA_END;
188  }
189 
190  stream.writeByte(attribute);
191 }
192 
193 /**
194  * Writes the data portion of either move or immediate element.
195  *
196  * @param stream The stream to be written to.
197  * @param elem The element to be written.
198  */
199 void
201  BinaryStream& stream,
202  SectionElement* elem) const {
203 
204  if (dynamic_cast<InstructionElement*>(elem)->isMove()) {
205  MoveElement* move = dynamic_cast<MoveElement*>(elem);
206 
207  writeId(stream, move->bus());
208 
209  Byte fieldTypes = 0;
210 
211  if (!move->isEmpty()) {
212 
213  switch(move->sourceType()) {
214  case MoveElement::MF_RF:
215  fieldTypes |= TPEFHeaders::MVS_RF;
216  break;
217  case MoveElement::MF_IMM:
218  fieldTypes |= TPEFHeaders::MVS_IMM;
219  break;
221  fieldTypes |= TPEFHeaders::MVS_UNIT;
222  break;
223  default:
224  std::cerr << "move source type: " << std::hex
225  << (int)move->sourceType() << std::dec << std::endl;
226  assert(false);
227  }
228 
229  switch(move->destinationType()) {
230  case MoveElement::MF_RF:
231  fieldTypes |= TPEFHeaders::MVD_RF;
232  break;
234  fieldTypes |= TPEFHeaders::MVD_UNIT;
235  break;
236  default:
237  std::cerr << "move dest type: "
238  << (int)move->destinationType()
239  << "\tdest unit: "
240  << (int)move->destinationUnit()
241  << "\tindex: "
242  << (int)move->destinationIndex()
243  << std::endl;
244 
245  assert(false);
246  }
247 
248  if (move->isGuarded()) {
249  switch(move->guardType()) {
250  case MoveElement::MF_RF:
251  fieldTypes |= TPEFHeaders::MVG_RF;
252  break;
254  fieldTypes |= TPEFHeaders::MVG_UNIT;
255  break;
256  default:
257  std::cerr << "move guarde type: " << std::hex
258  << (int)move->guardType()
259  << std::dec << std::endl;
260  assert(false);
261  }
262 
263  if (move->isGuardInverted() != 0) {
264  fieldTypes |= TPEFHeaders::IE_GUARD_INV_MASK;
265 
266  }
267  }
268  }
269 
270  stream.writeByte(fieldTypes);
271 
272  writeId(stream, move->sourceUnit());
273  stream.writeHalfWord(move->sourceIndex());
274 
275  writeId(stream, move->destinationUnit());
276  stream.writeHalfWord(move->destinationIndex());
277 
278  writeId(stream, move->guardUnit());
279  stream.writeHalfWord(move->guardIndex());
280 
281  } else {
282  ImmediateElement* imm = dynamic_cast<ImmediateElement*>(elem);
283  Byte dstUnit = imm->destinationUnit();
284  Byte dstIndex = imm->destinationIndex();
285 
286  stream.writeByte(dstUnit);
287  stream.writeByte(dstIndex);
288 
290 
291  for (unsigned int i = 0; i < imm->length(); i++) {
292  stream.writeByte(imm->byte(i));
293  }
294  }
295 }
296 
297 /**
298  * Writes annotations to stream if there are any.
299  *
300  * @param stream Stream to write.
301  * @param elem Element, whose annotations are written.
302  */
303 void
305  BinaryStream& stream,
306  SectionElement* elem) const {
307 
308  InstructionElement *instr = dynamic_cast<InstructionElement*>(elem);
309 
310  for (Word i = 0; i < instr->annotationCount(); i++) {
311 
312  InstructionAnnotation* annotation = instr->annotation(i);
313 
314  Byte sizeAndContinuation =
315  annotation->size() & TPEFHeaders::IANNOTE_SIZE;
316 
317  // if not last annotation
318  if (i != (instr->annotationCount() - 1)) {
319  sizeAndContinuation =
320  sizeAndContinuation | TPEFHeaders::IANNOTE_CONTINUATION;
321  }
322 
323  stream.writeByte(sizeAndContinuation);
324 
325  // write identification code in big endian format
326  // NOTE: should there be function in
327  // BinaryStream to write 3 byte "word"s?
328  stream.writeByte(annotation->id() & 0xff);
329  stream.writeByte((annotation->id() >> (BYTE_BITWIDTH)) & 0xff);
330  stream.writeByte((annotation->id() >> (BYTE_BITWIDTH*2)) & 0xff);
331 
332  // write payload
333  for (Word j = 0; j < annotation->size(); j++) {
334  stream.writeByte(annotation->byte(j));
335  }
336  }
337 }
338 
339 
340 /**
341  * Writes the `info' field of code section header.
342  *
343  * The `info' field of code sections normally contains information related
344  * to instruction size and encoding. The TUT_TTA architecture does not use
345  * this field and ignores its contents.
346  *
347  * @param stream Stream to which the data is written.
348  * @param sect Input section. Unused.
349  */
350 void
352  BinaryStream& stream,
353  const Section*) const {
354 
355  stream.writeHalfWord(0); // unused field
356  stream.writeByte(0); // unused field - must be set to zero!
357  stream.writeByte(0); // padding
358 }
359 
360 
361 /**
362  * Writes Bus, FU or RF id according to TPEF version.
363  *
364  * Original TPEF version 1 supports only less than 256 buses, FUs and RFs.
365  * Version 2 fixes that issue and we need to check the stream version for proper
366  * amount of bytes to write.
367  *
368  * @param stream Stream to which the data is written.
369  * @param sect id of the component.
370  */
371 void
372 TPEFCodeSectionWriter::writeId(BinaryStream& stream, HalfWord id) const {
373 
374  TPEFHeaders::TPEFVersion version = stream.TPEFVersion();
375 
376  if (version == TPEFHeaders::TPEFVersion::TPEF_V1) {
377  stream.writeByte(id);
378  } else {
379  stream.writeHalfWord(id);
380  }
381 }
382 
383 } // namespace TPEF
TPEF::SectionId
HalfWord SectionId
Type for storing binary file section ids.
Definition: TPEFBaseType.hh:43
TPEF::TPEFHeaders::IA_ANNOTE
@ IA_ANNOTE
Contains annotation.
Definition: TPEFHeaders.hh:123
TPEF::BinaryStream::writeHalfWord
void writeHalfWord(HalfWord halfword)
Definition: BinaryStream.cc:336
SectionSizeReplacer.hh
TPEF::TPEFHeaders::IA_MGUARD
@ IA_MGUARD
Is conditional move or unconditional move.
Definition: TPEFHeaders.hh:126
TPEF::TPEFHeaders::IA_END
@ IA_END
Is end of instruction.
Definition: TPEFHeaders.hh:122
TPEF::TPEFHeaders::MVD_RF
@ MVD_RF
Destination is RF.
Definition: TPEFHeaders.hh:141
TPEF::ReferenceManager::SafePointer::isReferenced
static bool isReferenced(const SafePointable *object)
Definition: SafePointer.cc:282
TPEF::MoveElement::isGuarded
bool isGuarded() const
TPEF::ImmediateElement::destinationIndex
Byte destinationIndex() const
TPEF::TPEFHeaders::MVS_RF
@ MVS_RF
Source is RF.
Definition: TPEFHeaders.hh:137
TPEF::TPEFCodeSectionWriter::writeDataField
void writeDataField(BinaryStream &stream, SectionElement *elem) const
Definition: TPEFCodeSectionWriter.cc:200
TPEF::InstructionElement
Definition: InstructionElement.hh:77
TPEF::MoveElement::MF_UNIT
@ MF_UNIT
Function unit.
Definition: MoveElement.hh:56
TPEF::TPEFHeaders::IANNOTE_CONTINUATION
@ IANNOTE_CONTINUATION
If there is more annotations.
Definition: TPEFHeaders.hh:113
TPEF::BinaryStream
Definition: BinaryStream.hh:59
TPEF::TPEFHeaders::IA_TYPE
@ IA_TYPE
Instruction type: move (0), immediate (1).
Definition: TPEFHeaders.hh:121
TPEF::BinaryStream::writePosition
unsigned int writePosition()
Definition: BinaryStream.cc:592
TPEF::MoveElement::MF_IMM
@ MF_IMM
Immediate.
Definition: MoveElement.hh:55
TPEF::InstructionElement::annotation
InstructionAnnotation * annotation(Word index) const
SafePointer.hh
TPEF::ImmediateElement
Definition: ImmediateElement.hh:49
TPEF::InstructionElement::isImmediate
bool isImmediate() const
TPEF::MoveElement::sourceIndex
HalfWord sourceIndex() const
TPEF::ReferenceManager::SectionKey::sectionId
SectionId sectionId() const
TPEF::MoveElement::isGuardInverted
bool isGuardInverted() const
Byte
unsigned char Byte
Definition: BaseType.hh:116
TPEF::TPEFCodeSectionWriter::TPEFCodeSectionWriter
TPEFCodeSectionWriter()
Definition: TPEFCodeSectionWriter.cc:64
TPEF::ReferenceManager::SafePointer::addObjectReference
static void addObjectReference(SectionIndexKey key, const SafePointable *obj)
Definition: SafePointer.cc:306
ImmediateElement.hh
TPEF::MoveElement::bus
HalfWord bus() const
TPEF::Section
Definition: Section.hh:64
TPEF::MoveElement::MF_RF
@ MF_RF
Register file.
Definition: MoveElement.hh:54
TPEF::TPEFCodeSectionWriter::instance_
static const TPEFCodeSectionWriter instance_
Unique instance of class.
Definition: TPEFCodeSectionWriter.hh:78
TPEF::TPEFHeaders::MVS_UNIT
@ MVS_UNIT
Source is FU.
Definition: TPEFHeaders.hh:139
assert
#define assert(condition)
Definition: Application.hh:86
TPEF::Section::element
SectionElement * element(Word index) const
TPEF::TPEFHeaders::TPEFVersion
TPEFVersion
Definition: TPEFHeaders.hh:56
TPEF::TPEFHeaders::MVG_RF
@ MVG_RF
Guard is RF.
Definition: TPEFHeaders.hh:145
TPEF::TPEFHeaders::IANNOTE_SIZE
@ IANNOTE_SIZE
Size of payload of annotation.
Definition: TPEFHeaders.hh:114
TPEF::SectionWriter::registerSectionWriter
static void registerSectionWriter(const SectionWriter *sWriter)
Definition: SectionWriter.cc:148
TPEF::MoveElement::sourceUnit
HalfWord sourceUnit() const
TPEF::MoveElement::guardIndex
HalfWord guardIndex() const
TPEF::ReferenceManager::SafePointer::sectionKeyFor
static SectionKey sectionKeyFor(const SafePointable *obj)
Definition: SafePointer.cc:408
TPEF::MoveElement
Definition: MoveElement.hh:47
TPEF::SectionElement
Definition: SectionElement.hh:44
TPEFCodeSectionWriter.hh
TPEF::TPEFHeaders::IA_EMPTY
@ IA_EMPTY
Empty instruction.
Definition: TPEFHeaders.hh:124
TPEF::FileOffset
Word FileOffset
Type for storing absolute file offsets.
Definition: TPEFBaseType.hh:52
TPEF::TPEFHeaders::MVS_IMM
@ MVS_IMM
Source is immediate.
Definition: TPEFHeaders.hh:138
TPEF::InstructionElement::annotationCount
Word annotationCount() const
TPEF::InstructionAnnotation::id
Word id() const
TPEF::InstructionElement::begin
bool begin() const
TPEF::TPEFCodeSectionWriter::IMMEDIATE_VALUE_MAX_BYTES
static const Byte IMMEDIATE_VALUE_MAX_BYTES
Maximum number of bytes that single immediate can contain.
Definition: TPEFCodeSectionWriter.hh:80
TPEF::MoveElement::destinationIndex
HalfWord destinationIndex() const
TPEF::TPEFHeaders::TPEF_V1
@ TPEF_V1
Initial TPEF version.
Definition: TPEFHeaders.hh:57
TPEF::TPEFHeaders::IE_GUARD_INV_MASK
@ IE_GUARD_INV_MASK
Guard inverted (1) means inverted.
Definition: TPEFHeaders.hh:146
TPEF::TPEFCodeSectionWriter::writeId
virtual void writeId(BinaryStream &stream, HalfWord id) const
Definition: TPEFCodeSectionWriter.cc:372
TPEF::BinaryStream::writeByte
void writeByte(Byte byte)
Definition: BinaryStream.cc:310
TPEF::MoveElement::destinationType
FieldType destinationType() const
TPEF::MoveElement::destinationUnit
HalfWord destinationUnit() const
TPEF::TPEFCodeSectionWriter::type
virtual Section::SectionType type() const
Definition: TPEFCodeSectionWriter.cc:80
TPEF::TPEFHeaders::MVG_UNIT
@ MVG_UNIT
Guard is FU.
Definition: TPEFHeaders.hh:144
TPEF::SectionOffset
Word SectionOffset
Type for storing offsets relative to a given base offset value.
Definition: TPEFBaseType.hh:49
TPEF::ReferenceManager::SectionKey
Definition: ReferenceKey.hh:145
TPEF::ImmediateElement::byte
Byte byte(unsigned int index) const
TPEF::TPEFCodeSectionWriter::writeAttributeField
void writeAttributeField(BinaryStream &stream, SectionElement *elem, bool isEnd) const
Definition: TPEFCodeSectionWriter.cc:145
TPEF::ReferenceManager::FileOffsetKey
Definition: ReferenceKey.hh:121
TPEF::TPEFCodeSectionWriter::~TPEFCodeSectionWriter
virtual ~TPEFCodeSectionWriter()
Definition: TPEFCodeSectionWriter.cc:71
SectionElement.hh
TPEF::TPEFCodeSectionWriter::actualWriteData
virtual void actualWriteData(BinaryStream &stream, const Section *sect) const
Definition: TPEFCodeSectionWriter.cc:91
TPEF::SectionSizeReplacer::setSize
static void setSize(const SafePointable *obj, Word size)
Definition: SectionSizeReplacer.cc:100
TPEF::MoveElement::guardType
FieldType guardType() const
BYTE_BITWIDTH
const Byte BYTE_BITWIDTH
Definition: BaseType.hh:136
TPEF::TPEFHeaders::MVD_UNIT
@ MVD_UNIT
Destination is FU.
Definition: TPEFHeaders.hh:143
Section.hh
TPEF::InstructionAnnotation
Definition: InstructionElement.hh:49
TPEF::MoveElement::isEmpty
bool isEmpty() const
TPEF::TPEFCodeSectionWriter::writeInfo
virtual void writeInfo(BinaryStream &stream, const Section *sect) const
Definition: TPEFCodeSectionWriter.cc:351
TPEF::ReferenceManager::SectionOffsetKey
Definition: ReferenceKey.hh:93
BinaryStream.hh
TPEF::Section::SectionType
SectionType
Definition: Section.hh:69
TPEF::BinaryStream::TPEFVersion
TPEFHeaders::TPEFVersion TPEFVersion() const
Definition: BinaryStream.cc:95
TPEF::ImmediateElement::destinationUnit
Byte destinationUnit() const
TPEF::MoveElement::sourceType
FieldType sourceType() const
TPEF::InstructionAnnotation::size
Byte size() const
TPEF::TPEFCodeSectionWriter::writeAnnotations
void writeAnnotations(BinaryStream &stream, SectionElement *elem) const
Definition: TPEFCodeSectionWriter.cc:304
TPEF::Section::ST_CODE
@ ST_CODE
Text section.
Definition: Section.hh:79
TPEF::ImmediateElement::length
unsigned int length() const
TPEF::InstructionAnnotation::byte
Byte byte(Byte index) const
ReferenceKey.hh
TPEF::TPEFSectionWriter
Definition: TPEFSectionWriter.hh:49
MoveElement.hh
CodeSection.hh
TPEF::MoveElement::guardUnit
HalfWord guardUnit() const
TPEF::Section::elementCount
Word elementCount() const
TPEF
Definition: Assembler.hh:43