fixed serious ioctl parameter conversion issue - exported type size and align functions
[qemu] / thunk.h
1 /*
2  *  Generic thunking code to convert data between host and target CPU
3  * 
4  *  Copyright (c) 2003 Fabrice Bellard
5  *
6  * This library is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU Lesser General Public
8  * License as published by the Free Software Foundation; either
9  * version 2 of the License, or (at your option) any later version.
10  *
11  * This library is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14  * Lesser General Public License for more details.
15  *
16  * You should have received a copy of the GNU Lesser General Public
17  * License along with this library; if not, write to the Free Software
18  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
19  */
20 #ifndef THUNK_H
21 #define THUNK_H
22
23 #include <inttypes.h>
24 #include "config.h"
25
26 #ifdef HAVE_BYTESWAP_H
27 #include <byteswap.h>
28 #else
29
30 #define bswap_16(x) \
31 ({ \
32         uint16_t __x = (x); \
33         ((uint16_t)( \
34                 (((uint16_t)(__x) & (uint16_t)0x00ffU) << 8) | \
35                 (((uint16_t)(__x) & (uint16_t)0xff00U) >> 8) )); \
36 })
37
38 #define bswap_32(x) \
39 ({ \
40         uint32_t __x = (x); \
41         ((uint32_t)( \
42                 (((uint32_t)(__x) & (uint32_t)0x000000ffUL) << 24) | \
43                 (((uint32_t)(__x) & (uint32_t)0x0000ff00UL) <<  8) | \
44                 (((uint32_t)(__x) & (uint32_t)0x00ff0000UL) >>  8) | \
45                 (((uint32_t)(__x) & (uint32_t)0xff000000UL) >> 24) )); \
46 })
47
48 #define bswap_64(x) \
49 ({ \
50         uint64_t __x = (x); \
51         ((uint64_t)( \
52                 (uint64_t)(((uint64_t)(__x) & (uint64_t)0x00000000000000ffULL) << 56) | \
53                 (uint64_t)(((uint64_t)(__x) & (uint64_t)0x000000000000ff00ULL) << 40) | \
54                 (uint64_t)(((uint64_t)(__x) & (uint64_t)0x0000000000ff0000ULL) << 24) | \
55                 (uint64_t)(((uint64_t)(__x) & (uint64_t)0x00000000ff000000ULL) <<  8) | \
56                 (uint64_t)(((uint64_t)(__x) & (uint64_t)0x000000ff00000000ULL) >>  8) | \
57                 (uint64_t)(((uint64_t)(__x) & (uint64_t)0x0000ff0000000000ULL) >> 24) | \
58                 (uint64_t)(((uint64_t)(__x) & (uint64_t)0x00ff000000000000ULL) >> 40) | \
59                 (uint64_t)(((uint64_t)(__x) & (uint64_t)0xff00000000000000ULL) >> 56) )); \
60 })
61
62 #endif
63
64 #if defined(WORDS_BIGENDIAN) != defined(TARGET_WORDS_BIGENDIAN)
65 #define BSWAP_NEEDED
66 #endif
67
68 /* XXX: autoconf */
69 #define TARGET_LONG_BITS 32
70
71 #if defined(__alpha__) || defined (__ia64__)
72 #define HOST_LONG_BITS 64
73 #else
74 #define HOST_LONG_BITS 32
75 #endif
76
77 #define TARGET_LONG_SIZE (TARGET_LONG_BITS / 8)
78 #define HOST_LONG_SIZE (HOST_LONG_BITS / 8)
79
80 static inline uint16_t bswap16(uint16_t x)
81 {
82     return bswap_16(x);
83 }
84
85 static inline uint32_t bswap32(uint32_t x) 
86 {
87     return bswap_32(x);
88 }
89
90 static inline uint64_t bswap64(uint64_t x) 
91 {
92     return bswap_64(x);
93 }
94
95 static inline void bswap16s(uint16_t *s)
96 {
97     *s = bswap16(*s);
98 }
99
100 static inline void bswap32s(uint32_t *s)
101 {
102     *s = bswap32(*s);
103 }
104
105 static inline void bswap64s(uint64_t *s)
106 {
107     *s = bswap64(*s);
108 }
109
110 #ifdef BSWAP_NEEDED
111
112 static inline uint16_t tswap16(uint16_t s)
113 {
114     return bswap16(s);
115 }
116
117 static inline uint32_t tswap32(uint32_t s)
118 {
119     return bswap32(s);
120 }
121
122 static inline uint64_t tswap64(uint64_t s)
123 {
124     return bswap64(s);
125 }
126
127 static inline void tswap16s(uint16_t *s)
128 {
129     *s = bswap16(*s);
130 }
131
132 static inline void tswap32s(uint32_t *s)
133 {
134     *s = bswap32(*s);
135 }
136
137 static inline void tswap64s(uint64_t *s)
138 {
139     *s = bswap64(*s);
140 }
141
142 #else
143
144 static inline uint16_t tswap16(uint16_t s)
145 {
146     return s;
147 }
148
149 static inline uint32_t tswap32(uint32_t s)
150 {
151     return s;
152 }
153
154 static inline uint64_t tswap64(uint64_t s)
155 {
156     return s;
157 }
158
159 static inline void tswap16s(uint16_t *s)
160 {
161 }
162
163 static inline void tswap32s(uint32_t *s)
164 {
165 }
166
167 static inline void tswap64s(uint64_t *s)
168 {
169 }
170
171 #endif
172
173 #if TARGET_LONG_SIZE == 4
174 #define tswapl(s) tswap32(s)
175 #define tswapls(s) tswap32s((uint32_t *)(s))
176 #else
177 #define tswapl(s) tswap64(s)
178 #define tswapls(s) tswap64s((uint64_t *)(s))
179 #endif
180
181 #if TARGET_LONG_SIZE == 4
182 typedef int32_t target_long;
183 typedef uint32_t target_ulong;
184 #elif TARGET_LONG_SIZE == 8
185 typedef int64_t target_long;
186 typedef uint64_t target_ulong;
187 #else
188 #error TARGET_LONG_SIZE undefined
189 #endif
190
191 /* types enums definitions */
192
193 typedef enum argtype {
194     TYPE_NULL,
195     TYPE_CHAR,
196     TYPE_SHORT,
197     TYPE_INT,
198     TYPE_LONG,
199     TYPE_ULONG,
200     TYPE_PTRVOID, /* pointer on unknown data */
201     TYPE_LONGLONG,
202     TYPE_ULONGLONG,
203     TYPE_PTR,
204     TYPE_ARRAY,
205     TYPE_STRUCT,
206 } argtype;
207
208 #define MK_PTR(type) TYPE_PTR, type
209 #define MK_ARRAY(type, size) TYPE_ARRAY, size, type
210 #define MK_STRUCT(id) TYPE_STRUCT, id
211
212 #define THUNK_TARGET 0
213 #define THUNK_HOST   1
214
215 typedef struct {
216     /* standard struct handling */
217     const argtype *field_types;
218     int nb_fields;
219     int *field_offsets[2];
220     /* special handling */
221     void (*convert[2])(void *dst, const void *src);
222     int size[2];
223     int align[2];
224     const char *name;
225 } StructEntry;
226
227 /* Translation table for bitmasks... */
228 typedef struct bitmask_transtbl {
229         unsigned int    x86_mask;
230         unsigned int    x86_bits;
231         unsigned int    alpha_mask;
232         unsigned int    alpha_bits;
233 } bitmask_transtbl;
234
235 void thunk_register_struct(int id, const char *name, const argtype *types);
236 void thunk_register_struct_direct(int id, const char *name, StructEntry *se1);
237 const argtype *thunk_convert(void *dst, const void *src, 
238                              const argtype *type_ptr, int to_host);
239
240 extern StructEntry struct_entries[];
241
242 static inline int thunk_type_size(const argtype *type_ptr, int is_host)
243 {
244     int type, size;
245     const StructEntry *se;
246
247     type = *type_ptr;
248     switch(type) {
249     case TYPE_CHAR:
250         return 1;
251     case TYPE_SHORT:
252         return 2;
253     case TYPE_INT:
254         return 4;
255     case TYPE_LONGLONG:
256     case TYPE_ULONGLONG:
257         return 8;
258     case TYPE_LONG:
259     case TYPE_ULONG:
260     case TYPE_PTRVOID:
261     case TYPE_PTR:
262         if (is_host) {
263             return HOST_LONG_SIZE;
264         } else {
265             return TARGET_LONG_SIZE;
266         }
267         break;
268     case TYPE_ARRAY:
269         size = type_ptr[1];
270         return size * thunk_type_size(type_ptr + 2, is_host);
271     case TYPE_STRUCT:
272         se = struct_entries + type_ptr[1];
273         return se->size[is_host];
274     default:
275         return -1;
276     }
277 }
278
279 static inline int thunk_type_align(const argtype *type_ptr, int is_host)
280 {
281     int type;
282     const StructEntry *se;
283
284     type = *type_ptr;
285     switch(type) {
286     case TYPE_CHAR:
287         return 1;
288     case TYPE_SHORT:
289         return 2;
290     case TYPE_INT:
291         return 4;
292     case TYPE_LONGLONG:
293     case TYPE_ULONGLONG:
294         return 8;
295     case TYPE_LONG:
296     case TYPE_ULONG:
297     case TYPE_PTRVOID:
298     case TYPE_PTR:
299         if (is_host) {
300             return HOST_LONG_SIZE;
301         } else {
302             return TARGET_LONG_SIZE;
303         }
304         break;
305     case TYPE_ARRAY:
306         return thunk_type_align(type_ptr + 2, is_host);
307     case TYPE_STRUCT:
308         se = struct_entries + type_ptr[1];
309         return se->align[is_host];
310     default:
311         return -1;
312     }
313 }
314
315 unsigned int target_to_host_bitmask(unsigned int x86_mask, 
316                                     bitmask_transtbl * trans_tbl);
317 unsigned int host_to_target_bitmask(unsigned int alpha_mask, 
318                                     bitmask_transtbl * trans_tbl);
319
320 #endif