]> git.proxmox.com Git - qemu.git/blob - thunk.h
fixed serious ioctl parameter conversion issue - exported type size and align functions
[qemu.git] / 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