OpenASIP  2.0
ImmediateElement.icc
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 ImmediateElement.icc
26  *
27  * Inline definitions of ImmediateElement class.
28  *
29  * @author Jussi Nykänen 2003 (nykanen-no.spam-cs.tut.fi)
30  * @author Mikael Lepistö 18.12.2003 (tmlepist-no.spam-cs.tut.fi)
31  * @note reviewed 21 October 2003 by rl, ml, jn, pj
32  *
33  * @note rating: yellow
34  */
35 
36 #include "Conversion.hh"
37 
38 namespace TPEF {
39 
40 /**
41  * Returns true if immediate is inline encoded.
42  *
43  * @return True immediate is inline encoded.
44  */
45 inline bool
46 ImmediateElement::isInline() const {
47  return (destinationUnit_ == 0);
48 }
49 
50 /**
51  * Adds byte to the immediate.
52  *
53  * @param aByte Byte stored to immediate.
54  */
55 inline void
56 ImmediateElement::addByte(Byte aByte) {
57  value_.push_back(aByte);
58 }
59 
60 /**
61  * Sets value of one byte of element.
62  *
63  * @param index Index of byte to set.
64  * @param aValue Value to set.
65  * @exception OutOfRange Thrown if index is too big.
66  */
67 inline void
68 ImmediateElement::setByte(unsigned int index, Byte aValue) {
69  if (index >= length()) {
70  throw OutOfRange(__FILE__, __LINE__, "ImmediateElement::setByte()");
71  }
72  value_[index] = aValue;
73 }
74 
75 /**
76  * Returns value of one byte in immediate.
77  *
78  * @param index Index of byte to get.
79  * @return Value of immediate.
80  * @exception OutOfRange If index is out of bounds.
81  */
82 inline Byte
83 ImmediateElement::byte(unsigned int index) const {
84  if (index >= length()) {
85  throw OutOfRange(__FILE__, __LINE__, "ImmediateElement::byte()");
86  }
87  return value_[index];
88 }
89 
90 /**
91  * Sets value of one word to immediate element.
92  *
93  * Clears old value and writes a word to element.
94  *
95  * If immediate is longer that written value, more significant bytes
96  * will be zeroed. See setWord(index, aValue) if you want to set
97  * word to any position of immediate without modifying other bytes
98  * stored inside.
99  *
100  * @param aValue Value to set.
101  */
102 inline void
103 ImmediateElement::setWord(Word aValue) {
104 
105  // remove old value
106  value_.clear();
107 
108  // check how many bytes are needed
109  Word tempValue = aValue;
110 
111  for (unsigned int i = 0; i < sizeof(aValue); i++) {
112  if (tempValue > 0) {
113  addByte(0);
114  }
115  tempValue = tempValue >> BYTE_BITWIDTH;
116  }
117 
118  for (unsigned int i = 1; i <= length(); i++) {
119  setByte(length() - i, static_cast<Byte>(aValue));
120  aValue = aValue >> BYTE_BITWIDTH;
121  }
122 }
123 
124 /**
125  * Sets value of long word to immediate element.
126  *
127  * Clears old value and writes a word to element.
128  *
129  * If immediate is longer that written value, more significant bytes
130  * will be zeroed. See setWord(index, aValue) if you want to set
131  * word to any position of immediate without modifying other bytes
132  * stored inside.
133  *
134  * @param aValue Value to set.
135  */
136 inline void
137 ImmediateElement::setULongWord(LongWord aValue) {
138 
139  // remove old value
140  value_.clear();
141 
142  // check how many bytes are needed
143  LongWord tempValue = aValue;
144 
145  for (unsigned int i = 0; i < sizeof(aValue); i++) {
146  if (tempValue > 0) {
147  addByte(0);
148  }
149  tempValue = tempValue >> BYTE_BITWIDTH;
150  }
151 
152  for (unsigned int i = 1; i <= length(); i++) {
153  setByte(length() - i, static_cast<Byte>(aValue));
154  aValue = aValue >> BYTE_BITWIDTH;
155  }
156 }
157 
158 /**
159  * Sets value of one word to immediate element.
160  *
161  * Clears old value and writes a signed word to element.
162  *
163  * If immediate is longer that written value, more significant bytes
164  * will be zeroed. See setWord(index, aValue) if you want to set
165  * word to any position of immediate without modifying other bytes
166  * stored inside.
167  *
168  * @param aValue Value to set.
169  */
170 inline void
171 ImmediateElement::setSignedWord(SignedWord sValue) {
172 
173  Word aValue = sValue;
174  // remove old value
175  value_.clear();
176 
177  // check how many bytes are needed
178  Word tempValue = aValue;
179 
180  bool negative = sValue < 0;
181  int neededBytes = 1;
182  for (unsigned int i = sizeof(aValue) ; i > 1; i--) {
183  int upBits = tempValue >> 24;
184  if ((negative && upBits != 255) ||
185  (!negative && upBits != 0)) {
186  neededBytes = i;
187  break;
188  } else {
189  tempValue <<= BYTE_BITWIDTH;
190  }
191 
192  }
193 
194  for (int i = 0; i < neededBytes; i++) {
195  addByte(0);
196  }
197 
198  for (unsigned int i = 1; i <= length(); i++) {
199  setByte(length() - i, static_cast<Byte>(aValue));
200  aValue = aValue >> BYTE_BITWIDTH;
201  }
202 
203  // if we have a negative sub-sized number but upper bit not set 1
204  // add a byte full of sign-bit ones.
205  if (negative && length() < 4 && (!((byte(0) & 128) == 128))) {
206  value_.insert(value_.begin(), 255); // big endian crap
207  }
208  // if we have a positive sub-sized number but upper bit is set 1,
209  // add a byte full of zeroes.
210  if (!negative && length() < 4 && (((byte(0) & 128) == 128))) {
211  value_.insert(value_.begin(), 0); // big endian crap
212  }
213 }
214 
215 
216 /**
217  * Sets value of one word to immediate element.
218  *
219  * Clears old value and writes a signed word to element.
220  *
221  * If immediate is longer that written value, more significant bytes
222  * will be zeroed. See setWord(index, aValue) if you want to set
223  * word to any position of immediate without modifying other bytes
224  * stored inside.
225  *
226  * @param aValue Value to set.
227  */
228 inline void
229 ImmediateElement::setSignedLong(SLongWord sValue) {
230 
231  LongWord aValue = sValue;
232  // remove old value
233  value_.clear();
234 
235  // check how many bytes are needed
236  LongWord tempValue = aValue;
237 
238  bool negative = sValue < 0;
239  int neededBytes = 1;
240  for (unsigned int i = sizeof(aValue) ; i > 1; i--) {
241  int upBits = tempValue >> 56;
242  if ((negative && upBits != 255) ||
243  (!negative && upBits != 0)) {
244  neededBytes = i;
245  break;
246  } else {
247  tempValue <<= BYTE_BITWIDTH;
248  }
249 
250  }
251 
252  for (int i = 0; i < neededBytes; i++) {
253  addByte(0);
254  }
255 
256  for (unsigned int i = 1; i <= length(); i++) {
257  setByte(length() - i, static_cast<Byte>(aValue));
258  aValue = aValue >> BYTE_BITWIDTH;
259  }
260 
261  // if we have a negative sub-sized number but upper bit not set 1
262  // add a byte full of sign-bit ones.
263  if (negative && length() < 8 && (!((byte(0) & 128) == 128))) {
264  value_.insert(value_.begin(), 255); // big endian crap
265  }
266  // if we have a positive sub-sized number but upper bit is set 1,
267  // add a byte full of zeroes.
268  if (!negative && length() < 8 && (((byte(0) & 128) == 128))) {
269  value_.insert(value_.begin(), 0); // big endian crap
270  }
271 }
272 
273 
274 
275 /**
276  * Returns value of element as a word.
277  *
278  * If you want to get word from given index of immediate see
279  * word(index). Empty immediates are read as zero value.
280  *
281  * @return Value of immediate.
282  * @exception OutOfRange Value is too big to return as a word.
283  */
284 inline Word
285 ImmediateElement::word() const {
286  Word retValue = 0;
287 
288  // convert bytes to word
289  for (unsigned int i = 0; i < length(); i++) {
290  retValue =
291  ((retValue << BYTE_BITWIDTH) |
292  static_cast<Byte>(value_[i]));
293 
294  if (retValue != 0 &&
295  length() - i > sizeof(retValue)) {
296 
297  throw OutOfRange(
298  __FILE__, __LINE__, "ImmediateElement::word()",
299  "Value to return is longer than value to return.");
300  }
301  }
302 
303  return retValue;
304 }
305 
306 /**
307  * Returns value of element as a word.
308  *
309  * If you want to get word from given index of immediate see
310  * word(index). Empty immediates are read as zero value.
311  *
312  * @return Value of immediate.
313  * @exception OutOfRange Value is too big to return as a word.
314  */
315 inline LongWord
316 ImmediateElement::longWord() const {
317 
318  LongWord retValue = 0;
319 
320  // convert bytes to word
321  for (unsigned int i = 0; i < length(); i++) {
322  retValue =
323  ((retValue << BYTE_BITWIDTH) |
324  static_cast<Byte>(value_[i]));
325 
326  if (retValue != 0 &&
327  length() - i > sizeof(retValue)) {
328 
329  throw OutOfRange(
330  __FILE__, __LINE__, "ImmediateElement::word()",
331  "Value to return is longer than value to return.");
332  }
333  }
334 
335  return retValue;
336 }
337 
338 /**
339  * Returns value of element as a signed word.
340  *
341  * If you want to get word from given index of immediate see
342  * word(index). Empty immediates are read as zero value.
343  *
344  * @return Value of immediate.
345  * @exception OutOfRange Value is too big to return as a signed word.
346  */
347 inline SignedWord
348 ImmediateElement::signedWord() const {
349 
350  Word retValue = 0;
351 
352  // convert bytes to word
353  for (unsigned int i = 0; i < length(); i++) {
354  retValue =
355  ((retValue << BYTE_BITWIDTH) |
356  static_cast<Byte>(value_[i]));
357 
358  if (retValue != 0 &&
359  length() - i > sizeof(retValue)) {
360 
361  throw OutOfRange(
362  __FILE__, __LINE__, "ImmediateElement::word()",
363  "Value to return is longer than value to return.");
364  }
365  }
366 
367  // If the most upper bit is true, but length < sizeof(word),
368  // this is a signed value, which need to be manually sign-extended.
369  unsigned int byteMask = ((1 << BYTE_BITWIDTH)-1);
370  if ((retValue >> (BYTE_BITWIDTH * length() -1) & 1) &&
371  length() < sizeof(SignedWord)) {
372  for (unsigned int i = length(); i < sizeof(SignedWord); i++) {
373  retValue |= (byteMask << (BYTE_BITWIDTH*i));
374  }
375  }
376  return static_cast<SignedWord>(retValue);
377 }
378 
379 /**
380  * Returns value of element as a signed word.
381  *
382  * If you want to get word from given index of immediate see
383  * word(index). Empty immediates are read as zero value.
384  *
385  * @return Value of immediate.
386  * @exception OutOfRange Value is too big to return as a signed word.
387  */
388 inline SLongWord
389 ImmediateElement::sLongWord() const {
390 
391  SLongWord retValue = 0;
392 
393  // convert bytes to word
394  for (unsigned int i = 0; i < length(); i++) {
395  retValue =
396  ((retValue << BYTE_BITWIDTH) |
397  static_cast<Byte>(value_[i]));
398 
399  if (retValue != 0 &&
400  length() - i > sizeof(retValue)) {
401 
402  throw OutOfRange(
403  __FILE__, __LINE__, "ImmediateElement::word()",
404  "Value to return is longer than value to return.");
405  }
406  }
407 
408  // If the most upper bit is true, but length < sizeof(word),
409  // this is a signed value, which need to be manually sign-extended.
410  unsigned long byteMask = ((1 << BYTE_BITWIDTH)-1);
411  if ((retValue >> (BYTE_BITWIDTH * length() -1) & 1) &&
412  length() < sizeof(SLongWord)) {
413  for (unsigned int i = length(); i < sizeof(SLongWord); i++) {
414  retValue |= (byteMask << (BYTE_BITWIDTH*i));
415  }
416  }
417  return static_cast<SLongWord>(retValue);
418 }
419 
420 
421 /**
422  * Returns the number of bytes taken by the immediate value.
423  *
424  * @return Length of immediate in bytes.
425  */
426 inline unsigned int
427 ImmediateElement::length() const {
428  return value_.size();
429 }
430 
431 /**
432  * Returns destination unit.
433  *
434  * Unit 0x00 means that immediate is inline encoded. For inline immediates
435  * index is unique identifier and source field of move element should match
436  * to that. So destinationIndex and destinationUnit should be same that
437  * are in move element, which uses ImmediateElement.
438  *
439  * @return Destination unit.
440  */
441 inline Byte
442 ImmediateElement::destinationUnit() const {
443  return destinationUnit_;
444 }
445 
446 /**
447  * Sets destination unit.
448  *
449  * See destinationUnit().
450  *
451  * @param aDestinationUnit Destination identifier.
452  */
453 inline void
454 ImmediateElement::setDestinationUnit(Byte aDestinationUnit) {
455  destinationUnit_ = aDestinationUnit;
456 }
457 
458 /**
459  * Returns destination index.
460  *
461  * See destinationUnit().
462  *
463  * @return Destination index.
464  */
465 inline Byte
466 ImmediateElement::destinationIndex() const {
467  return destinationIndex_;
468 }
469 
470 /**
471  * Sets destination index.
472  *
473  * See destinationUnit().
474  *
475  * @param aDestinationIndex Destination index.
476  */
477 inline void
478 ImmediateElement::setDestinationIndex(Byte aDestinationIndex) {
479  destinationIndex_ = aDestinationIndex;
480 }
481 
482 }