OSDN Git Service

2005-01-26 Thiemo Seufer <seufer@csv.ica.uni-stuttgart.de>
[pf3gnuchains/pf3gnuchains3x.git] / sid / include / sidtypes.h
1 // sidtypes.h - Different data types and automatic conversions between
2 // them (for example, big and little endian integrals).  -*- C++ -*-
3
4 // Copyright (C) 1999, 2000 Red Hat.
5 // This file is part of SID and is licensed under the GPL.
6 // See the file COPYING.SID for conditions for redistribution.
7
8 #ifndef SIDTYPES_H
9 #define SIDTYPES_H
10
11 #include <iostream>
12 #include <iomanip>
13 #include <cassert>
14
15 // In order to make the sid core header files host-independent,
16 // host-specific (autoconf-generated) headers are not #included here.
17 // Instead, we use a handful of compiler-provided macros to determine
18 // some key platform parameters.
19
20 #if defined(__NetBSD__)
21 # include <machine/endian.h>
22 # if BYTE_ORDER == LITTLE_ENDIAN
23 #  define HOST_BIG_ENDIAN false
24 # else
25 #  define HOST_BIG_ENDIAN true
26 # endif
27 #else
28 # if defined(__i386__) || defined(__x86_64__) || defined(__alpha__) || (defined(__mips__) && defined(_MIPSEL))
29 #  define HOST_BIG_ENDIAN false
30 # elif defined(__sparc__) || defined(__powerpc__) || (defined(__mips__) && defined(_MIPSEB))
31 #  define HOST_BIG_ENDIAN true
32 # else
33 #  error "Unknown host platform"
34 # endif
35 #endif
36
37
38 namespace sid {
39   // XXX: Define these conditionally.
40   typedef unsigned char host_int_1;
41   typedef unsigned short host_int_2;
42   typedef unsigned int host_int_4;
43   typedef unsigned long long host_int_8;
44   typedef signed char signed_host_int_1;
45   typedef signed short signed_host_int_2;
46   typedef signed int signed_host_int_4;
47   typedef signed long long signed_host_int_8;
48
49
50
51   
52   // The following bytereverse functions are used to convert between
53   // big-endian and little-endian integers.
54
55   inline host_int_1
56   bytereverse(host_int_1 value)
57   {
58     return value;
59   }
60
61   inline host_int_2
62   bytereverse(host_int_2 value)
63   {
64     // This is a 386 instruction.
65 #if defined(__GNUC__) && (defined(__i386__) || defined (__x86_64__))
66     __asm__("xchgb %b0,%h0" : "=q" (value) :  "0" (value));
67 #else
68       value = ( ((value & 0xff00U) >> 8) 
69               | ((value & 0x00ffU) << 8));
70 #endif
71     return value;
72   }
73
74   inline host_int_4
75   bytereverse(host_int_4 value)
76   {
77 #if defined(__GNUC__) && (defined(__i486__) || defined(__i586__) || defined(__i686__) || defined (__x86_64__))
78     // This is a 486+ instruction
79       __asm__ ("bswap %0" : "=r" (value) : "0" (value));
80 #else
81       value = ( ((value & 0xff000000UL) >> 24)
82               | ((value & 0x00ff0000UL) >> 8)
83               | ((value & 0x0000ff00UL) << 8)
84               | ((value & 0x000000ffUL) << 24));
85 #endif
86     return value;
87   }
88
89   inline host_int_8
90   bytereverse(host_int_8 value)
91   {
92 #if defined (__GNUC__) && defined (__x86_64__)
93     // This is an x86_64 instruction.
94     __asm__ ("bswap %0" : "=r" (value) : "0" (value));
95 #else
96     host_int_4 upper = (value & 0xffffffff00000000ULL) >> 32;
97     host_int_4 lower = (value & 0x00000000ffffffffULL);
98     upper = bytereverse(upper);
99     lower = bytereverse(lower);
100     value = ((host_int_8)lower) << 32 | (host_int_8)upper;
101 #endif
102     return value;
103   }
104
105
106   // A bi-endian integer class.
107   // 
108   // Each instance represents an integer quanitity, with an additional
109   // tag that describes how that value should be stored in simulated
110   // memory.
111   //
112   // The template class any_int<> should not be used directly.
113   // Rather, use one of the typedef'd classes:
114   // big_int_1, big_int_2, big_int_4, big_int_8
115   // little_int_1, little_int_2, little_int_4, or little_int_8
116
117   template <typename IntType, bool IsBig>
118   class any_int
119   {
120   public:
121     // Utility related types
122     typedef IntType value_type;
123     typedef any_int<IntType,HOST_BIG_ENDIAN> host_int_type;
124     typedef any_int<host_int_1,IsBig> size_1_type;
125     typedef any_int<host_int_2,IsBig> size_2_type;
126     typedef any_int<host_int_4,IsBig> size_4_type;
127     typedef any_int<host_int_8,IsBig> size_8_type;
128
129
130     // Return the natural integer value represented by this object.
131     // This value is the same, whether this class represents a big or
132     // little endian value.
133     IntType integer_value() const { return _integer_value; }
134     operator IntType () const { return _integer_value; }
135     
136     // Return the simulated memory image of this value.  This may be
137     // a byte-reversed copy of integer_value().
138     IntType target_memory_value() const
139       {
140         if (IsBig == HOST_BIG_ENDIAN)
141           return this->_integer_value;
142         else
143           return bytereverse (_integer_value);
144       }
145
146     // Set the simulated memory image of this value.  It may be
147     // byte-reversed.
148     void set_target_memory_value(IntType v)
149       {
150         if (IsBig == HOST_BIG_ENDIAN)
151           this->_integer_value = v;
152         else
153           this->_integer_value = bytereverse(v);
154       }
155
156
157
158     // The default constructor constructs an object with value 0. 
159     any_int(): _integer_value (0) {}
160
161     // Construct from a big_int type.
162     // Copies the integer_value.  Regardless of types, the value is
163     // NOT byte-reversed by this call.
164     // v is the big_int value to construct the new object from. 
165     any_int(const any_int<IntType,true>& v): _integer_value (v.integer_value()) {}
166  
167     // Construct from a little_int type.
168     // Copies the integer_value.  Regardless of types, the value is
169     // NOT byte-reversed by this call.
170     // v is the little_int value to construct the new object from.
171     any_int(const any_int<IntType,false>& v): _integer_value (v.integer_value()) {}
172
173     // Construct from a integer type.
174     // The new object's integer_value() method will return `v'.
175     // v is the integer value to construct the new object from. 
176     any_int(IntType v): _integer_value(v) {}
177
178
179     // Assign from a little_int type.
180     // Copies the integer_value.  Regardless of types, the value is
181     // NOT byte-reversed by this call.
182     // v is the little_int value to be assigned from.
183     any_int<IntType,IsBig>& operator = (const any_int<IntType,false>& v)
184       {
185         _integer_value = v.integer_value();
186         return *this;
187       }
188
189     // Assign from a big_int type.
190     // Copies the integer_value.  Regardless of types, the value is 
191     // NOT byte-reversed by this call.
192     // v is the little_int value to be assigned from.
193     any_int<IntType,IsBig>& operator = (const any_int<IntType,true>& v)
194       {
195         _integer_value = v.integer_value();
196         return *this;
197       }
198     
199     // Assign from a integer type.
200     // The new object's integer_value() method will return `v'.
201     // v is the integer value to construct the new object from. 
202     any_int<IntType,IsBig>& operator = (IntType v) {
203       _integer_value = v;
204       return *this;
205     }
206
207     // These functions access the stored value as if it was a byte array.
208
209     // Write byte at offset ix in target memory image.
210     // ix is the index of the byte in the in-memory image.
211     // byte is the value to write.
212     void write_byte(unsigned ix, host_int_1 byte)
213       {
214         assert (0 <= ix && ix < sizeof(IntType));
215         char* value_ptr = reinterpret_cast<char*>(&this->_integer_value);
216         if (IsBig != HOST_BIG_ENDIAN) {
217           value_ptr[(sizeof(IntType)-1)-ix] = byte;
218         } else {
219           value_ptr[ix] = byte;
220         }
221       }
222
223     // Read byte at offset ix from the target memory image.
224     // ix is the index of the byte in the in-memory image.
225     // Returns the value of the byte.
226     host_int_1 read_byte(unsigned ix) const
227       {
228         assert (0 <= ix && ix < sizeof(IntType));
229         const char* value_ptr = reinterpret_cast<const char*>(&this->_integer_value);
230         if (IsBig != HOST_BIG_ENDIAN) {
231           return value_ptr[(sizeof(IntType)-1)-ix];
232         } else {
233           return value_ptr[ix];
234         }
235       }
236
237   private:
238     IntType _integer_value;
239   };
240
241
242 // ----------------------------------------------------------------------------
243
244
245   // Stream any_int using current stream flags
246   template <typename IntType, bool IsBig>
247   inline std::ostream&
248   operator << (std::ostream& o, const any_int<IntType,IsBig>& v)
249   {
250     host_int_8 value;
251     value = v; 
252     o << value;
253     return o;
254   }
255
256
257   // Destream any_int using current stream flags
258   template <typename IntType, bool IsBig>
259   inline std::istream&
260   operator >> (std::istream& i, any_int<IntType,IsBig>& v)
261   {
262     host_int_8 value;
263     i >> value;
264     v = (IntType) value;
265     // XXX: range check?
266     return i;
267   }
268
269
270
271 // ----------------------------------------------------------------------------
272
273
274   // A series of big-endian quantities: 1-8 bytes.
275   typedef any_int<host_int_1,true> big_int_1;
276   typedef any_int<host_int_2,true> big_int_2;
277   typedef any_int<host_int_4,true> big_int_4;
278   typedef any_int<host_int_8,true> big_int_8;
279   
280
281   // A series of little-endian quantities: 1-8 bytes.
282   typedef any_int<host_int_1,false> little_int_1;
283   typedef any_int<host_int_2,false> little_int_2;
284   typedef any_int<host_int_4,false> little_int_4;
285   typedef any_int<host_int_8,false> little_int_8;
286 }
287
288 #endif // SIDTYPES_H