use bswap.h
[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 #include "bswap.h"
27
28 #if defined(WORDS_BIGENDIAN) != defined(TARGET_WORDS_BIGENDIAN)
29 #define BSWAP_NEEDED
30 #endif
31
32 /* XXX: autoconf */
33 #define TARGET_LONG_BITS 32
34
35 #define TARGET_LONG_SIZE (TARGET_LONG_BITS / 8)
36
37 #ifdef BSWAP_NEEDED
38
39 static inline uint16_t tswap16(uint16_t s)
40 {
41     return bswap16(s);
42 }
43
44 static inline uint32_t tswap32(uint32_t s)
45 {
46     return bswap32(s);
47 }
48
49 static inline uint64_t tswap64(uint64_t s)
50 {
51     return bswap64(s);
52 }
53
54 static inline void tswap16s(uint16_t *s)
55 {
56     *s = bswap16(*s);
57 }
58
59 static inline void tswap32s(uint32_t *s)
60 {
61     *s = bswap32(*s);
62 }
63
64 static inline void tswap64s(uint64_t *s)
65 {
66     *s = bswap64(*s);
67 }
68
69 #else
70
71 static inline uint16_t tswap16(uint16_t s)
72 {
73     return s;
74 }
75
76 static inline uint32_t tswap32(uint32_t s)
77 {
78     return s;
79 }
80
81 static inline uint64_t tswap64(uint64_t s)
82 {
83     return s;
84 }
85
86 static inline void tswap16s(uint16_t *s)
87 {
88 }
89
90 static inline void tswap32s(uint32_t *s)
91 {
92 }
93
94 static inline void tswap64s(uint64_t *s)
95 {
96 }
97
98 #endif
99
100 #if TARGET_LONG_SIZE == 4
101 #define tswapl(s) tswap32(s)
102 #define tswapls(s) tswap32s((uint32_t *)(s))
103 #else
104 #define tswapl(s) tswap64(s)
105 #define tswapls(s) tswap64s((uint64_t *)(s))
106 #endif
107
108 #if TARGET_LONG_SIZE == 4
109 typedef int32_t target_long;
110 typedef uint32_t target_ulong;
111 #elif TARGET_LONG_SIZE == 8
112 typedef int64_t target_long;
113 typedef uint64_t target_ulong;
114 #else
115 #error TARGET_LONG_SIZE undefined
116 #endif
117
118 /* types enums definitions */
119
120 typedef enum argtype {
121     TYPE_NULL,
122     TYPE_CHAR,
123     TYPE_SHORT,
124     TYPE_INT,
125     TYPE_LONG,
126     TYPE_ULONG,
127     TYPE_PTRVOID, /* pointer on unknown data */
128     TYPE_LONGLONG,
129     TYPE_ULONGLONG,
130     TYPE_PTR,
131     TYPE_ARRAY,
132     TYPE_STRUCT,
133 } argtype;
134
135 #define MK_PTR(type) TYPE_PTR, type
136 #define MK_ARRAY(type, size) TYPE_ARRAY, size, type
137 #define MK_STRUCT(id) TYPE_STRUCT, id
138
139 #define THUNK_TARGET 0
140 #define THUNK_HOST   1
141
142 typedef struct {
143     /* standard struct handling */
144     const argtype *field_types;
145     int nb_fields;
146     int *field_offsets[2];
147     /* special handling */
148     void (*convert[2])(void *dst, const void *src);
149     int size[2];
150     int align[2];
151     const char *name;
152 } StructEntry;
153
154 /* Translation table for bitmasks... */
155 typedef struct bitmask_transtbl {
156         unsigned int    x86_mask;
157         unsigned int    x86_bits;
158         unsigned int    alpha_mask;
159         unsigned int    alpha_bits;
160 } bitmask_transtbl;
161
162 void thunk_register_struct(int id, const char *name, const argtype *types);
163 void thunk_register_struct_direct(int id, const char *name, StructEntry *se1);
164 const argtype *thunk_convert(void *dst, const void *src, 
165                              const argtype *type_ptr, int to_host);
166 #ifndef NO_THUNK_TYPE_SIZE
167
168 extern StructEntry struct_entries[];
169
170 static inline int thunk_type_size(const argtype *type_ptr, int is_host)
171 {
172     int type, size;
173     const StructEntry *se;
174
175     type = *type_ptr;
176     switch(type) {
177     case TYPE_CHAR:
178         return 1;
179     case TYPE_SHORT:
180         return 2;
181     case TYPE_INT:
182         return 4;
183     case TYPE_LONGLONG:
184     case TYPE_ULONGLONG:
185         return 8;
186     case TYPE_LONG:
187     case TYPE_ULONG:
188     case TYPE_PTRVOID:
189     case TYPE_PTR:
190         if (is_host) {
191             return HOST_LONG_SIZE;
192         } else {
193             return TARGET_LONG_SIZE;
194         }
195         break;
196     case TYPE_ARRAY:
197         size = type_ptr[1];
198         return size * thunk_type_size(type_ptr + 2, is_host);
199     case TYPE_STRUCT:
200         se = struct_entries + type_ptr[1];
201         return se->size[is_host];
202     default:
203         return -1;
204     }
205 }
206
207 static inline int thunk_type_align(const argtype *type_ptr, int is_host)
208 {
209     int type;
210     const StructEntry *se;
211
212     type = *type_ptr;
213     switch(type) {
214     case TYPE_CHAR:
215         return 1;
216     case TYPE_SHORT:
217         return 2;
218     case TYPE_INT:
219         return 4;
220     case TYPE_LONGLONG:
221     case TYPE_ULONGLONG:
222         return 8;
223     case TYPE_LONG:
224     case TYPE_ULONG:
225     case TYPE_PTRVOID:
226     case TYPE_PTR:
227         if (is_host) {
228             return HOST_LONG_SIZE;
229         } else {
230             return TARGET_LONG_SIZE;
231         }
232         break;
233     case TYPE_ARRAY:
234         return thunk_type_align(type_ptr + 2, is_host);
235     case TYPE_STRUCT:
236         se = struct_entries + type_ptr[1];
237         return se->align[is_host];
238     default:
239         return -1;
240     }
241 }
242
243 #endif /* NO_THUNK_TYPE_SIZE */
244
245 unsigned int target_to_host_bitmask(unsigned int x86_mask, 
246                                     bitmask_transtbl * trans_tbl);
247 unsigned int host_to_target_bitmask(unsigned int alpha_mask, 
248                                     bitmask_transtbl * trans_tbl);
249
250 #endif