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