xref: /qemu/linux-user/thunk.c (revision 4e111653)
1ff9c1e55SRichard Henderson /*
2ff9c1e55SRichard Henderson  *  Generic thunking code to convert data between host and target CPU
3ff9c1e55SRichard Henderson  *
4ff9c1e55SRichard Henderson  *  Copyright (c) 2003 Fabrice Bellard
5ff9c1e55SRichard Henderson  *
6ff9c1e55SRichard Henderson  * This library is free software; you can redistribute it and/or
7ff9c1e55SRichard Henderson  * modify it under the terms of the GNU Lesser General Public
8ff9c1e55SRichard Henderson  * License as published by the Free Software Foundation; either
9ff9c1e55SRichard Henderson  * version 2.1 of the License, or (at your option) any later version.
10ff9c1e55SRichard Henderson  *
11ff9c1e55SRichard Henderson  * This library is distributed in the hope that it will be useful,
12ff9c1e55SRichard Henderson  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13ff9c1e55SRichard Henderson  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14ff9c1e55SRichard Henderson  * Lesser General Public License for more details.
15ff9c1e55SRichard Henderson  *
16ff9c1e55SRichard Henderson  * You should have received a copy of the GNU Lesser General Public
17ff9c1e55SRichard Henderson  * License along with this library; if not, see <http://www.gnu.org/licenses/>.
18ff9c1e55SRichard Henderson  */
19ff9c1e55SRichard Henderson #include "qemu/osdep.h"
20ff9c1e55SRichard Henderson #include "qemu/log.h"
21ff9c1e55SRichard Henderson 
22ff9c1e55SRichard Henderson #include "qemu.h"
23*4e111653SPhilippe Mathieu-Daudé #include "user/thunk.h"
24ff9c1e55SRichard Henderson 
25ff9c1e55SRichard Henderson //#define DEBUG
26ff9c1e55SRichard Henderson 
27ff9c1e55SRichard Henderson static unsigned int max_struct_entries;
28ff9c1e55SRichard Henderson StructEntry *struct_entries;
29ff9c1e55SRichard Henderson 
30ff9c1e55SRichard Henderson static const argtype *thunk_type_next_ptr(const argtype *type_ptr);
31ff9c1e55SRichard Henderson 
thunk_type_next(const argtype * type_ptr)32ff9c1e55SRichard Henderson static inline const argtype *thunk_type_next(const argtype *type_ptr)
33ff9c1e55SRichard Henderson {
34ff9c1e55SRichard Henderson     int type;
35ff9c1e55SRichard Henderson 
36ff9c1e55SRichard Henderson     type = *type_ptr++;
37ff9c1e55SRichard Henderson     switch(type) {
38ff9c1e55SRichard Henderson     case TYPE_CHAR:
39ff9c1e55SRichard Henderson     case TYPE_SHORT:
40ff9c1e55SRichard Henderson     case TYPE_INT:
41ff9c1e55SRichard Henderson     case TYPE_LONGLONG:
42ff9c1e55SRichard Henderson     case TYPE_ULONGLONG:
43ff9c1e55SRichard Henderson     case TYPE_LONG:
44ff9c1e55SRichard Henderson     case TYPE_ULONG:
45ff9c1e55SRichard Henderson     case TYPE_PTRVOID:
46ff9c1e55SRichard Henderson     case TYPE_OLDDEVT:
47ff9c1e55SRichard Henderson         return type_ptr;
48ff9c1e55SRichard Henderson     case TYPE_PTR:
49ff9c1e55SRichard Henderson         return thunk_type_next_ptr(type_ptr);
50ff9c1e55SRichard Henderson     case TYPE_ARRAY:
51ff9c1e55SRichard Henderson         return thunk_type_next_ptr(type_ptr + 1);
52ff9c1e55SRichard Henderson     case TYPE_STRUCT:
53ff9c1e55SRichard Henderson         return type_ptr + 1;
54ff9c1e55SRichard Henderson     default:
55ff9c1e55SRichard Henderson         return NULL;
56ff9c1e55SRichard Henderson     }
57ff9c1e55SRichard Henderson }
58ff9c1e55SRichard Henderson 
thunk_type_next_ptr(const argtype * type_ptr)59ff9c1e55SRichard Henderson static const argtype *thunk_type_next_ptr(const argtype *type_ptr)
60ff9c1e55SRichard Henderson {
61ff9c1e55SRichard Henderson     return thunk_type_next(type_ptr);
62ff9c1e55SRichard Henderson }
63ff9c1e55SRichard Henderson 
thunk_register_struct(int id,const char * name,const argtype * types)64ff9c1e55SRichard Henderson void thunk_register_struct(int id, const char *name, const argtype *types)
65ff9c1e55SRichard Henderson {
66ff9c1e55SRichard Henderson     const argtype *type_ptr;
67ff9c1e55SRichard Henderson     StructEntry *se;
68ff9c1e55SRichard Henderson     int nb_fields, offset, max_align, align, size, i, j;
69ff9c1e55SRichard Henderson 
70ff9c1e55SRichard Henderson     assert(id < max_struct_entries);
71ff9c1e55SRichard Henderson 
72ff9c1e55SRichard Henderson     /* first we count the number of fields */
73ff9c1e55SRichard Henderson     type_ptr = types;
74ff9c1e55SRichard Henderson     nb_fields = 0;
75ff9c1e55SRichard Henderson     while (*type_ptr != TYPE_NULL) {
76ff9c1e55SRichard Henderson         type_ptr = thunk_type_next(type_ptr);
77ff9c1e55SRichard Henderson         nb_fields++;
78ff9c1e55SRichard Henderson     }
79ff9c1e55SRichard Henderson     assert(nb_fields > 0);
80ff9c1e55SRichard Henderson     se = struct_entries + id;
81ff9c1e55SRichard Henderson     se->field_types = types;
82ff9c1e55SRichard Henderson     se->nb_fields = nb_fields;
83ff9c1e55SRichard Henderson     se->name = name;
84ff9c1e55SRichard Henderson #ifdef DEBUG
85ff9c1e55SRichard Henderson     printf("struct %s: id=%d nb_fields=%d\n",
86ff9c1e55SRichard Henderson            se->name, id, se->nb_fields);
87ff9c1e55SRichard Henderson #endif
88ff9c1e55SRichard Henderson     /* now we can alloc the data */
89ff9c1e55SRichard Henderson 
90ff9c1e55SRichard Henderson     for (i = 0; i < ARRAY_SIZE(se->field_offsets); i++) {
91ff9c1e55SRichard Henderson         offset = 0;
92ff9c1e55SRichard Henderson         max_align = 1;
93ff9c1e55SRichard Henderson         se->field_offsets[i] = g_new(int, nb_fields);
94ff9c1e55SRichard Henderson         type_ptr = se->field_types;
95ff9c1e55SRichard Henderson         for(j = 0;j < nb_fields; j++) {
96ff9c1e55SRichard Henderson             size = thunk_type_size(type_ptr, i);
97ff9c1e55SRichard Henderson             align = thunk_type_align(type_ptr, i);
98ff9c1e55SRichard Henderson             offset = (offset + align - 1) & ~(align - 1);
99ff9c1e55SRichard Henderson             se->field_offsets[i][j] = offset;
100ff9c1e55SRichard Henderson             offset += size;
101ff9c1e55SRichard Henderson             if (align > max_align)
102ff9c1e55SRichard Henderson                 max_align = align;
103ff9c1e55SRichard Henderson             type_ptr = thunk_type_next(type_ptr);
104ff9c1e55SRichard Henderson         }
105ff9c1e55SRichard Henderson         offset = (offset + max_align - 1) & ~(max_align - 1);
106ff9c1e55SRichard Henderson         se->size[i] = offset;
107ff9c1e55SRichard Henderson         se->align[i] = max_align;
108ff9c1e55SRichard Henderson #ifdef DEBUG
109ff9c1e55SRichard Henderson         printf("%s: size=%d align=%d\n",
110ff9c1e55SRichard Henderson                i == THUNK_HOST ? "host" : "target", offset, max_align);
111ff9c1e55SRichard Henderson #endif
112ff9c1e55SRichard Henderson     }
113ff9c1e55SRichard Henderson }
114ff9c1e55SRichard Henderson 
thunk_register_struct_direct(int id,const char * name,const StructEntry * se1)115ff9c1e55SRichard Henderson void thunk_register_struct_direct(int id, const char *name,
116ff9c1e55SRichard Henderson                                   const StructEntry *se1)
117ff9c1e55SRichard Henderson {
118ff9c1e55SRichard Henderson     StructEntry *se;
119ff9c1e55SRichard Henderson 
120ff9c1e55SRichard Henderson     assert(id < max_struct_entries);
121ff9c1e55SRichard Henderson     se = struct_entries + id;
122ff9c1e55SRichard Henderson     *se = *se1;
123ff9c1e55SRichard Henderson     se->name = name;
124ff9c1e55SRichard Henderson }
125ff9c1e55SRichard Henderson 
126ff9c1e55SRichard Henderson 
127ff9c1e55SRichard Henderson /* now we can define the main conversion functions */
thunk_convert(void * dst,const void * src,const argtype * type_ptr,int to_host)128ff9c1e55SRichard Henderson const argtype *thunk_convert(void *dst, const void *src,
129ff9c1e55SRichard Henderson                              const argtype *type_ptr, int to_host)
130ff9c1e55SRichard Henderson {
131ff9c1e55SRichard Henderson     int type;
132ff9c1e55SRichard Henderson 
133ff9c1e55SRichard Henderson     type = *type_ptr++;
134ff9c1e55SRichard Henderson     switch(type) {
135ff9c1e55SRichard Henderson     case TYPE_CHAR:
136ff9c1e55SRichard Henderson         *(uint8_t *)dst = *(uint8_t *)src;
137ff9c1e55SRichard Henderson         break;
138ff9c1e55SRichard Henderson     case TYPE_SHORT:
139ff9c1e55SRichard Henderson         *(uint16_t *)dst = tswap16(*(uint16_t *)src);
140ff9c1e55SRichard Henderson         break;
141ff9c1e55SRichard Henderson     case TYPE_INT:
142ff9c1e55SRichard Henderson         *(uint32_t *)dst = tswap32(*(uint32_t *)src);
143ff9c1e55SRichard Henderson         break;
144ff9c1e55SRichard Henderson     case TYPE_LONGLONG:
145ff9c1e55SRichard Henderson     case TYPE_ULONGLONG:
146ff9c1e55SRichard Henderson         *(uint64_t *)dst = tswap64(*(uint64_t *)src);
147ff9c1e55SRichard Henderson         break;
148ff9c1e55SRichard Henderson #if HOST_LONG_BITS == 32 && TARGET_ABI_BITS == 32
149ff9c1e55SRichard Henderson     case TYPE_LONG:
150ff9c1e55SRichard Henderson     case TYPE_ULONG:
151ff9c1e55SRichard Henderson     case TYPE_PTRVOID:
152ff9c1e55SRichard Henderson         *(uint32_t *)dst = tswap32(*(uint32_t *)src);
153ff9c1e55SRichard Henderson         break;
154ff9c1e55SRichard Henderson #elif HOST_LONG_BITS == 64 && TARGET_ABI_BITS == 32
155ff9c1e55SRichard Henderson     case TYPE_LONG:
156ff9c1e55SRichard Henderson     case TYPE_ULONG:
157ff9c1e55SRichard Henderson     case TYPE_PTRVOID:
158ff9c1e55SRichard Henderson         if (to_host) {
159ff9c1e55SRichard Henderson             if (type == TYPE_LONG) {
160ff9c1e55SRichard Henderson                 /* sign extension */
161ff9c1e55SRichard Henderson                 *(uint64_t *)dst = (int32_t)tswap32(*(uint32_t *)src);
162ff9c1e55SRichard Henderson             } else {
163ff9c1e55SRichard Henderson                 *(uint64_t *)dst = tswap32(*(uint32_t *)src);
164ff9c1e55SRichard Henderson             }
165ff9c1e55SRichard Henderson         } else {
166ff9c1e55SRichard Henderson             *(uint32_t *)dst = tswap32(*(uint64_t *)src & 0xffffffff);
167ff9c1e55SRichard Henderson         }
168ff9c1e55SRichard Henderson         break;
169ff9c1e55SRichard Henderson #elif HOST_LONG_BITS == 64 && TARGET_ABI_BITS == 64
170ff9c1e55SRichard Henderson     case TYPE_LONG:
171ff9c1e55SRichard Henderson     case TYPE_ULONG:
172ff9c1e55SRichard Henderson     case TYPE_PTRVOID:
173ff9c1e55SRichard Henderson         *(uint64_t *)dst = tswap64(*(uint64_t *)src);
174ff9c1e55SRichard Henderson         break;
175ff9c1e55SRichard Henderson #elif HOST_LONG_BITS == 32 && TARGET_ABI_BITS == 64
176ff9c1e55SRichard Henderson     case TYPE_LONG:
177ff9c1e55SRichard Henderson     case TYPE_ULONG:
178ff9c1e55SRichard Henderson     case TYPE_PTRVOID:
179ff9c1e55SRichard Henderson         if (to_host) {
180ff9c1e55SRichard Henderson             *(uint32_t *)dst = tswap64(*(uint64_t *)src);
181ff9c1e55SRichard Henderson         } else {
182ff9c1e55SRichard Henderson             if (type == TYPE_LONG) {
183ff9c1e55SRichard Henderson                 /* sign extension */
184ff9c1e55SRichard Henderson                 *(uint64_t *)dst = tswap64(*(int32_t *)src);
185ff9c1e55SRichard Henderson             } else {
186ff9c1e55SRichard Henderson                 *(uint64_t *)dst = tswap64(*(uint32_t *)src);
187ff9c1e55SRichard Henderson             }
188ff9c1e55SRichard Henderson         }
189ff9c1e55SRichard Henderson         break;
190ff9c1e55SRichard Henderson #else
191ff9c1e55SRichard Henderson #warning unsupported conversion
192ff9c1e55SRichard Henderson #endif
193ff9c1e55SRichard Henderson     case TYPE_OLDDEVT:
194ff9c1e55SRichard Henderson     {
195ff9c1e55SRichard Henderson         uint64_t val = 0;
196ff9c1e55SRichard Henderson         switch (thunk_type_size(type_ptr - 1, !to_host)) {
197ff9c1e55SRichard Henderson         case 2:
198ff9c1e55SRichard Henderson             val = *(uint16_t *)src;
199ff9c1e55SRichard Henderson             break;
200ff9c1e55SRichard Henderson         case 4:
201ff9c1e55SRichard Henderson             val = *(uint32_t *)src;
202ff9c1e55SRichard Henderson             break;
203ff9c1e55SRichard Henderson         case 8:
204ff9c1e55SRichard Henderson             val = *(uint64_t *)src;
205ff9c1e55SRichard Henderson             break;
206ff9c1e55SRichard Henderson         }
207ff9c1e55SRichard Henderson         switch (thunk_type_size(type_ptr - 1, to_host)) {
208ff9c1e55SRichard Henderson         case 2:
209ff9c1e55SRichard Henderson             *(uint16_t *)dst = tswap16(val);
210ff9c1e55SRichard Henderson             break;
211ff9c1e55SRichard Henderson         case 4:
212ff9c1e55SRichard Henderson             *(uint32_t *)dst = tswap32(val);
213ff9c1e55SRichard Henderson             break;
214ff9c1e55SRichard Henderson         case 8:
215ff9c1e55SRichard Henderson             *(uint64_t *)dst = tswap64(val);
216ff9c1e55SRichard Henderson             break;
217ff9c1e55SRichard Henderson         }
218ff9c1e55SRichard Henderson         break;
219ff9c1e55SRichard Henderson     }
220ff9c1e55SRichard Henderson     case TYPE_ARRAY:
221ff9c1e55SRichard Henderson         {
222ff9c1e55SRichard Henderson             int array_length, i, dst_size, src_size;
223ff9c1e55SRichard Henderson             const uint8_t *s;
224ff9c1e55SRichard Henderson             uint8_t  *d;
225ff9c1e55SRichard Henderson 
226ff9c1e55SRichard Henderson             array_length = *type_ptr++;
227ff9c1e55SRichard Henderson             dst_size = thunk_type_size(type_ptr, to_host);
228ff9c1e55SRichard Henderson             src_size = thunk_type_size(type_ptr, 1 - to_host);
229ff9c1e55SRichard Henderson             d = dst;
230ff9c1e55SRichard Henderson             s = src;
231ff9c1e55SRichard Henderson             for(i = 0;i < array_length; i++) {
232ff9c1e55SRichard Henderson                 thunk_convert(d, s, type_ptr, to_host);
233ff9c1e55SRichard Henderson                 d += dst_size;
234ff9c1e55SRichard Henderson                 s += src_size;
235ff9c1e55SRichard Henderson             }
236ff9c1e55SRichard Henderson             type_ptr = thunk_type_next(type_ptr);
237ff9c1e55SRichard Henderson         }
238ff9c1e55SRichard Henderson         break;
239ff9c1e55SRichard Henderson     case TYPE_STRUCT:
240ff9c1e55SRichard Henderson         {
241ff9c1e55SRichard Henderson             int i;
242ff9c1e55SRichard Henderson             const StructEntry *se;
243ff9c1e55SRichard Henderson             const uint8_t *s;
244ff9c1e55SRichard Henderson             uint8_t  *d;
245ff9c1e55SRichard Henderson             const argtype *field_types;
246ff9c1e55SRichard Henderson             const int *dst_offsets, *src_offsets;
247ff9c1e55SRichard Henderson 
248ff9c1e55SRichard Henderson             assert(*type_ptr < max_struct_entries);
249ff9c1e55SRichard Henderson             se = struct_entries + *type_ptr++;
250ff9c1e55SRichard Henderson             if (se->convert[0] != NULL) {
251ff9c1e55SRichard Henderson                 /* specific conversion is needed */
252ff9c1e55SRichard Henderson                 (*se->convert[to_host])(dst, src);
253ff9c1e55SRichard Henderson             } else {
254ff9c1e55SRichard Henderson                 /* standard struct conversion */
255ff9c1e55SRichard Henderson                 field_types = se->field_types;
256ff9c1e55SRichard Henderson                 dst_offsets = se->field_offsets[to_host];
257ff9c1e55SRichard Henderson                 src_offsets = se->field_offsets[1 - to_host];
258ff9c1e55SRichard Henderson                 d = dst;
259ff9c1e55SRichard Henderson                 s = src;
260ff9c1e55SRichard Henderson                 for(i = 0;i < se->nb_fields; i++) {
261ff9c1e55SRichard Henderson                     field_types = thunk_convert(d + dst_offsets[i],
262ff9c1e55SRichard Henderson                                                 s + src_offsets[i],
263ff9c1e55SRichard Henderson                                                 field_types, to_host);
264ff9c1e55SRichard Henderson                 }
265ff9c1e55SRichard Henderson             }
266ff9c1e55SRichard Henderson         }
267ff9c1e55SRichard Henderson         break;
268ff9c1e55SRichard Henderson     default:
269ff9c1e55SRichard Henderson         fprintf(stderr, "Invalid type 0x%x\n", type);
270ff9c1e55SRichard Henderson         break;
271ff9c1e55SRichard Henderson     }
272ff9c1e55SRichard Henderson     return type_ptr;
273ff9c1e55SRichard Henderson }
274ff9c1e55SRichard Henderson 
thunk_print(void * arg,const argtype * type_ptr)275ff9c1e55SRichard Henderson const argtype *thunk_print(void *arg, const argtype *type_ptr)
276ff9c1e55SRichard Henderson {
277ff9c1e55SRichard Henderson     int type;
278ff9c1e55SRichard Henderson 
279ff9c1e55SRichard Henderson     type = *type_ptr++;
280ff9c1e55SRichard Henderson 
281ff9c1e55SRichard Henderson     switch (type) {
282ff9c1e55SRichard Henderson     case TYPE_CHAR:
283ff9c1e55SRichard Henderson         qemu_log("%c", *(uint8_t *)arg);
284ff9c1e55SRichard Henderson         break;
285ff9c1e55SRichard Henderson     case TYPE_SHORT:
286ff9c1e55SRichard Henderson         qemu_log("%" PRId16, tswap16(*(uint16_t *)arg));
287ff9c1e55SRichard Henderson         break;
288ff9c1e55SRichard Henderson     case TYPE_INT:
289ff9c1e55SRichard Henderson         qemu_log("%" PRId32, tswap32(*(uint32_t *)arg));
290ff9c1e55SRichard Henderson         break;
291ff9c1e55SRichard Henderson     case TYPE_LONGLONG:
292ff9c1e55SRichard Henderson         qemu_log("%" PRId64, tswap64(*(uint64_t *)arg));
293ff9c1e55SRichard Henderson         break;
294ff9c1e55SRichard Henderson     case TYPE_ULONGLONG:
295ff9c1e55SRichard Henderson         qemu_log("%" PRIu64, tswap64(*(uint64_t *)arg));
296ff9c1e55SRichard Henderson         break;
297ff9c1e55SRichard Henderson #if HOST_LONG_BITS == 32 && TARGET_ABI_BITS == 32
298ff9c1e55SRichard Henderson     case TYPE_PTRVOID:
299ff9c1e55SRichard Henderson         qemu_log("0x%" PRIx32, tswap32(*(uint32_t *)arg));
300ff9c1e55SRichard Henderson         break;
301ff9c1e55SRichard Henderson     case TYPE_LONG:
302ff9c1e55SRichard Henderson         qemu_log("%" PRId32, tswap32(*(uint32_t *)arg));
303ff9c1e55SRichard Henderson         break;
304ff9c1e55SRichard Henderson     case TYPE_ULONG:
305ff9c1e55SRichard Henderson         qemu_log("%" PRIu32, tswap32(*(uint32_t *)arg));
306ff9c1e55SRichard Henderson         break;
307ff9c1e55SRichard Henderson #elif HOST_LONG_BITS == 64 && TARGET_ABI_BITS == 32
308ff9c1e55SRichard Henderson     case TYPE_PTRVOID:
309ff9c1e55SRichard Henderson         qemu_log("0x%" PRIx32, tswap32(*(uint64_t *)arg & 0xffffffff));
310ff9c1e55SRichard Henderson         break;
311ff9c1e55SRichard Henderson     case TYPE_LONG:
312ff9c1e55SRichard Henderson         qemu_log("%" PRId32, tswap32(*(uint64_t *)arg & 0xffffffff));
313ff9c1e55SRichard Henderson         break;
314ff9c1e55SRichard Henderson     case TYPE_ULONG:
315ff9c1e55SRichard Henderson         qemu_log("%" PRIu32, tswap32(*(uint64_t *)arg & 0xffffffff));
316ff9c1e55SRichard Henderson         break;
317ff9c1e55SRichard Henderson #elif HOST_LONG_BITS == 64 && TARGET_ABI_BITS == 64
318ff9c1e55SRichard Henderson     case TYPE_PTRVOID:
319ff9c1e55SRichard Henderson         qemu_log("0x%" PRIx64, tswap64(*(uint64_t *)arg));
320ff9c1e55SRichard Henderson         break;
321ff9c1e55SRichard Henderson     case TYPE_LONG:
322ff9c1e55SRichard Henderson         qemu_log("%" PRId64, tswap64(*(uint64_t *)arg));
323ff9c1e55SRichard Henderson         break;
324ff9c1e55SRichard Henderson     case TYPE_ULONG:
325ff9c1e55SRichard Henderson         qemu_log("%" PRIu64, tswap64(*(uint64_t *)arg));
326ff9c1e55SRichard Henderson         break;
327ff9c1e55SRichard Henderson #else
328ff9c1e55SRichard Henderson     case TYPE_PTRVOID:
329ff9c1e55SRichard Henderson         qemu_log("0x%" PRIx64, tswap64(*(uint64_t *)arg));
330ff9c1e55SRichard Henderson         break;
331ff9c1e55SRichard Henderson     case TYPE_LONG:
332ff9c1e55SRichard Henderson         qemu_log("%" PRId64, tswap64(*(uint64_t *)arg));
333ff9c1e55SRichard Henderson         break;
334ff9c1e55SRichard Henderson     case TYPE_ULONG:
335ff9c1e55SRichard Henderson         qemu_log("%" PRIu64, tswap64(*(uint64_t *)arg));
336ff9c1e55SRichard Henderson         break;
337ff9c1e55SRichard Henderson #endif
338ff9c1e55SRichard Henderson     case TYPE_OLDDEVT:
339ff9c1e55SRichard Henderson     {
340ff9c1e55SRichard Henderson         uint64_t val = 0;
341ff9c1e55SRichard Henderson         switch (thunk_type_size(type_ptr - 1, 1)) {
342ff9c1e55SRichard Henderson         case 2:
343ff9c1e55SRichard Henderson             val = *(uint16_t *)arg;
344ff9c1e55SRichard Henderson             break;
345ff9c1e55SRichard Henderson         case 4:
346ff9c1e55SRichard Henderson             val = *(uint32_t *)arg;
347ff9c1e55SRichard Henderson             break;
348ff9c1e55SRichard Henderson         case 8:
349ff9c1e55SRichard Henderson             val = *(uint64_t *)arg;
350ff9c1e55SRichard Henderson             break;
351ff9c1e55SRichard Henderson         }
352ff9c1e55SRichard Henderson         switch (thunk_type_size(type_ptr - 1, 0)) {
353ff9c1e55SRichard Henderson         case 2:
354ff9c1e55SRichard Henderson             qemu_log("%" PRIu16, tswap16(val));
355ff9c1e55SRichard Henderson             break;
356ff9c1e55SRichard Henderson         case 4:
357ff9c1e55SRichard Henderson             qemu_log("%" PRIu32, tswap32(val));
358ff9c1e55SRichard Henderson             break;
359ff9c1e55SRichard Henderson         case 8:
360ff9c1e55SRichard Henderson             qemu_log("%" PRIu64, tswap64(val));
361ff9c1e55SRichard Henderson             break;
362ff9c1e55SRichard Henderson         }
363ff9c1e55SRichard Henderson     }
364ff9c1e55SRichard Henderson     break;
365ff9c1e55SRichard Henderson     case TYPE_ARRAY:
366ff9c1e55SRichard Henderson         {
367ff9c1e55SRichard Henderson             int i, array_length, arg_size;
368ff9c1e55SRichard Henderson             uint8_t *a;
369ff9c1e55SRichard Henderson             int is_string = 0;
370ff9c1e55SRichard Henderson 
371ff9c1e55SRichard Henderson             array_length = *type_ptr++;
372ff9c1e55SRichard Henderson             arg_size = thunk_type_size(type_ptr, 0);
373ff9c1e55SRichard Henderson             a = arg;
374ff9c1e55SRichard Henderson 
375ff9c1e55SRichard Henderson             if (*type_ptr == TYPE_CHAR) {
376ff9c1e55SRichard Henderson                 qemu_log("\"");
377ff9c1e55SRichard Henderson                 is_string = 1;
378ff9c1e55SRichard Henderson             } else {
379ff9c1e55SRichard Henderson                 qemu_log("[");
380ff9c1e55SRichard Henderson             }
381ff9c1e55SRichard Henderson 
382ff9c1e55SRichard Henderson             for (i = 0; i < array_length; i++) {
383ff9c1e55SRichard Henderson                 if (i > 0 && !is_string) {
384ff9c1e55SRichard Henderson                     qemu_log(",");
385ff9c1e55SRichard Henderson                 }
386ff9c1e55SRichard Henderson                 thunk_print(a, type_ptr);
387ff9c1e55SRichard Henderson                 a += arg_size;
388ff9c1e55SRichard Henderson             }
389ff9c1e55SRichard Henderson 
390ff9c1e55SRichard Henderson             if (is_string) {
391ff9c1e55SRichard Henderson                 qemu_log("\"");
392ff9c1e55SRichard Henderson             } else {
393ff9c1e55SRichard Henderson                 qemu_log("]");
394ff9c1e55SRichard Henderson             }
395ff9c1e55SRichard Henderson 
396ff9c1e55SRichard Henderson             type_ptr = thunk_type_next(type_ptr);
397ff9c1e55SRichard Henderson         }
398ff9c1e55SRichard Henderson         break;
399ff9c1e55SRichard Henderson     case TYPE_STRUCT:
400ff9c1e55SRichard Henderson         {
401ff9c1e55SRichard Henderson             int i;
402ff9c1e55SRichard Henderson             const StructEntry *se;
403ff9c1e55SRichard Henderson             uint8_t  *a;
404ff9c1e55SRichard Henderson             const argtype *field_types;
405ff9c1e55SRichard Henderson             const int *arg_offsets;
406ff9c1e55SRichard Henderson 
407ff9c1e55SRichard Henderson             se = struct_entries + *type_ptr++;
408ff9c1e55SRichard Henderson 
409ff9c1e55SRichard Henderson             if (se->print != NULL) {
410ff9c1e55SRichard Henderson                 se->print(arg);
411ff9c1e55SRichard Henderson             } else {
412ff9c1e55SRichard Henderson                 a = arg;
413ff9c1e55SRichard Henderson 
414ff9c1e55SRichard Henderson                 field_types = se->field_types;
415ff9c1e55SRichard Henderson                 arg_offsets = se->field_offsets[0];
416ff9c1e55SRichard Henderson 
417ff9c1e55SRichard Henderson                 qemu_log("{");
418ff9c1e55SRichard Henderson                 for (i = 0; i < se->nb_fields; i++) {
419ff9c1e55SRichard Henderson                     if (i > 0) {
420ff9c1e55SRichard Henderson                         qemu_log(",");
421ff9c1e55SRichard Henderson                     }
422ff9c1e55SRichard Henderson                     field_types = thunk_print(a + arg_offsets[i], field_types);
423ff9c1e55SRichard Henderson                 }
424ff9c1e55SRichard Henderson                 qemu_log("}");
425ff9c1e55SRichard Henderson             }
426ff9c1e55SRichard Henderson         }
427ff9c1e55SRichard Henderson         break;
428ff9c1e55SRichard Henderson     default:
429ff9c1e55SRichard Henderson         g_assert_not_reached();
430ff9c1e55SRichard Henderson     }
431ff9c1e55SRichard Henderson     return type_ptr;
432ff9c1e55SRichard Henderson }
433ff9c1e55SRichard Henderson 
434ff9c1e55SRichard Henderson /* from em86 */
435ff9c1e55SRichard Henderson 
436ff9c1e55SRichard Henderson /* Utility function: Table-driven functions to translate bitmasks
437ff9c1e55SRichard Henderson  * between host and target formats
438ff9c1e55SRichard Henderson  */
target_to_host_bitmask_len(unsigned int target_mask,const bitmask_transtbl * tbl,size_t len)439a05cee93SRichard Henderson unsigned int target_to_host_bitmask_len(unsigned int target_mask,
440a05cee93SRichard Henderson                                         const bitmask_transtbl *tbl,
441a05cee93SRichard Henderson                                         size_t len)
442ff9c1e55SRichard Henderson {
443ff9c1e55SRichard Henderson     unsigned int host_mask = 0;
444ff9c1e55SRichard Henderson 
445a05cee93SRichard Henderson     for (size_t i = 0; i < len; ++i) {
446a05cee93SRichard Henderson         if ((target_mask & tbl[i].target_mask) == tbl[i].target_bits) {
447a05cee93SRichard Henderson             host_mask |= tbl[i].host_bits;
448ff9c1e55SRichard Henderson         }
449ff9c1e55SRichard Henderson     }
450ff9c1e55SRichard Henderson     return host_mask;
451ff9c1e55SRichard Henderson }
452ff9c1e55SRichard Henderson 
host_to_target_bitmask_len(unsigned int host_mask,const bitmask_transtbl * tbl,size_t len)453a05cee93SRichard Henderson unsigned int host_to_target_bitmask_len(unsigned int host_mask,
454a05cee93SRichard Henderson                                         const bitmask_transtbl *tbl,
455a05cee93SRichard Henderson                                         size_t len)
456ff9c1e55SRichard Henderson {
457ff9c1e55SRichard Henderson     unsigned int target_mask = 0;
458ff9c1e55SRichard Henderson 
459a05cee93SRichard Henderson     for (size_t i = 0; i < len; ++i) {
460a05cee93SRichard Henderson         if ((host_mask & tbl[i].host_mask) == tbl[i].host_bits) {
461a05cee93SRichard Henderson             target_mask |= tbl[i].target_bits;
462ff9c1e55SRichard Henderson         }
463ff9c1e55SRichard Henderson     }
464ff9c1e55SRichard Henderson     return target_mask;
465ff9c1e55SRichard Henderson }
466ff9c1e55SRichard Henderson 
thunk_type_size_array(const argtype * type_ptr,int is_host)467ff9c1e55SRichard Henderson int thunk_type_size_array(const argtype *type_ptr, int is_host)
468ff9c1e55SRichard Henderson {
469ff9c1e55SRichard Henderson     return thunk_type_size(type_ptr, is_host);
470ff9c1e55SRichard Henderson }
471ff9c1e55SRichard Henderson 
thunk_type_align_array(const argtype * type_ptr,int is_host)472ff9c1e55SRichard Henderson int thunk_type_align_array(const argtype *type_ptr, int is_host)
473ff9c1e55SRichard Henderson {
474ff9c1e55SRichard Henderson     return thunk_type_align(type_ptr, is_host);
475ff9c1e55SRichard Henderson }
476ff9c1e55SRichard Henderson 
thunk_init(unsigned int max_structs)477ff9c1e55SRichard Henderson void thunk_init(unsigned int max_structs)
478ff9c1e55SRichard Henderson {
479ff9c1e55SRichard Henderson     max_struct_entries = max_structs;
480ff9c1e55SRichard Henderson     struct_entries = g_new0(StructEntry, max_structs);
481ff9c1e55SRichard Henderson }
482