OpenASIP 2.2
Loading...
Searching...
No Matches
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
38#include "SafePointer.hh"
39#include "ReferenceKey.hh"
40#include "Section.hh"
41#include "SectionElement.hh"
42#include "MoveElement.hh"
43#include "ImmediateElement.hh"
45#include "CodeSection.hh"
46#include "BinaryStream.hh"
47
48namespace TPEF {
49
50using std::list;
51using ReferenceManager::SafePointer;
52using ReferenceManager::FileOffsetKey;
53using ReferenceManager::SectionKey;
54using ReferenceManager::SectionOffsetKey;
55
56const TPEFCodeSectionWriter TPEFCodeSectionWriter::instance_;
58
59/**
60 * Constructor.
61 *
62 * Registers itself to SectionWriter.
63 */
67
68/**
69 * Destructor.
70 */
73
74/**
75 * Returns the type of section that this writer writes.
76 *
77 * @return The type of section that this writer writes.
78 */
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 */
90void
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 */
144void
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 */
199void
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()) {
215 fieldTypes |= TPEFHeaders::MVS_RF;
216 break;
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()) {
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()) {
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 */
303void
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 */
350void
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 */
371void
372TPEFCodeSectionWriter::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
#define assert(condition)
const Byte BYTE_BITWIDTH
Definition BaseType.hh:136
unsigned char Byte
Definition BaseType.hh:116
void writeByte(Byte byte)
void writeHalfWord(HalfWord halfword)
unsigned int writePosition()
TPEFHeaders::TPEFVersion TPEFVersion() const
Byte destinationIndex() const
Byte destinationUnit() const
unsigned int length() const
Byte byte(unsigned int index) const
Byte byte(Byte index) 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.
static void addObjectReference(SectionIndexKey key, const SafePointable *obj)
static SectionKey sectionKeyFor(const SafePointable *obj)
static bool isReferenced(const SafePointable *object)
static void setSize(const SafePointable *obj, Word size)
static void registerSectionWriter(const SectionWriter *sWriter)
@ ST_CODE
Text section.
Definition Section.hh:79
SectionElement * element(Word index) const
Word elementCount() const
virtual void writeId(BinaryStream &stream, HalfWord id) const
void writeAttributeField(BinaryStream &stream, SectionElement *elem, bool isEnd) const
virtual Section::SectionType type() const
void writeAnnotations(BinaryStream &stream, SectionElement *elem) const
static const Byte IMMEDIATE_VALUE_MAX_BYTES
Maximum number of bytes that single immediate can contain.
void writeDataField(BinaryStream &stream, SectionElement *elem) const
virtual void actualWriteData(BinaryStream &stream, const Section *sect) const
virtual void writeInfo(BinaryStream &stream, const Section *sect) const
static const TPEFCodeSectionWriter instance_
Unique instance of class.
@ IA_END
Is end of instruction.
@ IA_MGUARD
Is conditional move or unconditional move.
@ IA_TYPE
Instruction type: move (0), immediate (1).
@ IA_ANNOTE
Contains annotation.
@ IA_EMPTY
Empty instruction.
@ IE_GUARD_INV_MASK
Guard inverted (1) means inverted.
@ MVG_RF
Guard is RF.
@ MVD_UNIT
Destination is FU.
@ MVS_IMM
Source is immediate.
@ MVD_RF
Destination is RF.
@ MVS_UNIT
Source is FU.
@ MVG_UNIT
Guard is FU.
@ MVS_RF
Source is RF.
@ TPEF_V1
Initial TPEF version.
@ IANNOTE_SIZE
Size of payload of annotation.
@ IANNOTE_CONTINUATION
If there is more annotations.
HalfWord SectionId
Type for storing binary file section ids.
Word SectionOffset
Type for storing offsets relative to a given base offset value.
Word FileOffset
Type for storing absolute file offsets.