From ff9c1e5500141df7be15446ccfbdc66752812a9a Mon Sep 17 00:00:00 2001 From: Richard Henderson Date: Wed, 17 Nov 2021 16:26:14 +0100 Subject: linux-user: Move thunk.c from top-level MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit So far, linux-user is the only user of these functions. Clean up the build machinery by restricting it to linux-user. Reviewed-by: Warner Losh Reviewed-by: Philippe Mathieu-Daudé Signed-off-by: Richard Henderson --- MAINTAINERS | 1 - linux-user/meson.build | 1 + linux-user/thunk.c | 481 +++++++++++++++++++++++++++++++++++++++++++++++++ meson.build | 1 - thunk.c | 481 ------------------------------------------------- 5 files changed, 482 insertions(+), 483 deletions(-) create mode 100644 linux-user/thunk.c delete mode 100644 thunk.c diff --git a/MAINTAINERS b/MAINTAINERS index be8fc57538..1de6ce6e44 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -3077,7 +3077,6 @@ Usermode Emulation Overall usermode emulation M: Riku Voipio S: Maintained -F: thunk.c F: accel/tcg/user-exec*.c F: include/user/ F: common-user/ diff --git a/linux-user/meson.build b/linux-user/meson.build index eef1dd68bd..ca8b86f209 100644 --- a/linux-user/meson.build +++ b/linux-user/meson.build @@ -15,6 +15,7 @@ linux_user_ss.add(files( 'signal.c', 'strace.c', 'syscall.c', + 'thunk.c', 'uaccess.c', 'uname.c', )) diff --git a/linux-user/thunk.c b/linux-user/thunk.c new file mode 100644 index 0000000000..dac4bf11c6 --- /dev/null +++ b/linux-user/thunk.c @@ -0,0 +1,481 @@ +/* + * Generic thunking code to convert data between host and target CPU + * + * Copyright (c) 2003 Fabrice Bellard + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, see . + */ +#include "qemu/osdep.h" +#include "qemu/log.h" + +#include "qemu.h" +#include "exec/user/thunk.h" + +//#define DEBUG + +static unsigned int max_struct_entries; +StructEntry *struct_entries; + +static const argtype *thunk_type_next_ptr(const argtype *type_ptr); + +static inline const argtype *thunk_type_next(const argtype *type_ptr) +{ + int type; + + type = *type_ptr++; + switch(type) { + case TYPE_CHAR: + case TYPE_SHORT: + case TYPE_INT: + case TYPE_LONGLONG: + case TYPE_ULONGLONG: + case TYPE_LONG: + case TYPE_ULONG: + case TYPE_PTRVOID: + case TYPE_OLDDEVT: + return type_ptr; + case TYPE_PTR: + return thunk_type_next_ptr(type_ptr); + case TYPE_ARRAY: + return thunk_type_next_ptr(type_ptr + 1); + case TYPE_STRUCT: + return type_ptr + 1; + default: + return NULL; + } +} + +static const argtype *thunk_type_next_ptr(const argtype *type_ptr) +{ + return thunk_type_next(type_ptr); +} + +void thunk_register_struct(int id, const char *name, const argtype *types) +{ + const argtype *type_ptr; + StructEntry *se; + int nb_fields, offset, max_align, align, size, i, j; + + assert(id < max_struct_entries); + + /* first we count the number of fields */ + type_ptr = types; + nb_fields = 0; + while (*type_ptr != TYPE_NULL) { + type_ptr = thunk_type_next(type_ptr); + nb_fields++; + } + assert(nb_fields > 0); + se = struct_entries + id; + se->field_types = types; + se->nb_fields = nb_fields; + se->name = name; +#ifdef DEBUG + printf("struct %s: id=%d nb_fields=%d\n", + se->name, id, se->nb_fields); +#endif + /* now we can alloc the data */ + + for (i = 0; i < ARRAY_SIZE(se->field_offsets); i++) { + offset = 0; + max_align = 1; + se->field_offsets[i] = g_new(int, nb_fields); + type_ptr = se->field_types; + for(j = 0;j < nb_fields; j++) { + size = thunk_type_size(type_ptr, i); + align = thunk_type_align(type_ptr, i); + offset = (offset + align - 1) & ~(align - 1); + se->field_offsets[i][j] = offset; + offset += size; + if (align > max_align) + max_align = align; + type_ptr = thunk_type_next(type_ptr); + } + offset = (offset + max_align - 1) & ~(max_align - 1); + se->size[i] = offset; + se->align[i] = max_align; +#ifdef DEBUG + printf("%s: size=%d align=%d\n", + i == THUNK_HOST ? "host" : "target", offset, max_align); +#endif + } +} + +void thunk_register_struct_direct(int id, const char *name, + const StructEntry *se1) +{ + StructEntry *se; + + assert(id < max_struct_entries); + se = struct_entries + id; + *se = *se1; + se->name = name; +} + + +/* now we can define the main conversion functions */ +const argtype *thunk_convert(void *dst, const void *src, + const argtype *type_ptr, int to_host) +{ + int type; + + type = *type_ptr++; + switch(type) { + case TYPE_CHAR: + *(uint8_t *)dst = *(uint8_t *)src; + break; + case TYPE_SHORT: + *(uint16_t *)dst = tswap16(*(uint16_t *)src); + break; + case TYPE_INT: + *(uint32_t *)dst = tswap32(*(uint32_t *)src); + break; + case TYPE_LONGLONG: + case TYPE_ULONGLONG: + *(uint64_t *)dst = tswap64(*(uint64_t *)src); + break; +#if HOST_LONG_BITS == 32 && TARGET_ABI_BITS == 32 + case TYPE_LONG: + case TYPE_ULONG: + case TYPE_PTRVOID: + *(uint32_t *)dst = tswap32(*(uint32_t *)src); + break; +#elif HOST_LONG_BITS == 64 && TARGET_ABI_BITS == 32 + case TYPE_LONG: + case TYPE_ULONG: + case TYPE_PTRVOID: + if (to_host) { + if (type == TYPE_LONG) { + /* sign extension */ + *(uint64_t *)dst = (int32_t)tswap32(*(uint32_t *)src); + } else { + *(uint64_t *)dst = tswap32(*(uint32_t *)src); + } + } else { + *(uint32_t *)dst = tswap32(*(uint64_t *)src & 0xffffffff); + } + break; +#elif HOST_LONG_BITS == 64 && TARGET_ABI_BITS == 64 + case TYPE_LONG: + case TYPE_ULONG: + case TYPE_PTRVOID: + *(uint64_t *)dst = tswap64(*(uint64_t *)src); + break; +#elif HOST_LONG_BITS == 32 && TARGET_ABI_BITS == 64 + case TYPE_LONG: + case TYPE_ULONG: + case TYPE_PTRVOID: + if (to_host) { + *(uint32_t *)dst = tswap64(*(uint64_t *)src); + } else { + if (type == TYPE_LONG) { + /* sign extension */ + *(uint64_t *)dst = tswap64(*(int32_t *)src); + } else { + *(uint64_t *)dst = tswap64(*(uint32_t *)src); + } + } + break; +#else +#warning unsupported conversion +#endif + case TYPE_OLDDEVT: + { + uint64_t val = 0; + switch (thunk_type_size(type_ptr - 1, !to_host)) { + case 2: + val = *(uint16_t *)src; + break; + case 4: + val = *(uint32_t *)src; + break; + case 8: + val = *(uint64_t *)src; + break; + } + switch (thunk_type_size(type_ptr - 1, to_host)) { + case 2: + *(uint16_t *)dst = tswap16(val); + break; + case 4: + *(uint32_t *)dst = tswap32(val); + break; + case 8: + *(uint64_t *)dst = tswap64(val); + break; + } + break; + } + case TYPE_ARRAY: + { + int array_length, i, dst_size, src_size; + const uint8_t *s; + uint8_t *d; + + array_length = *type_ptr++; + dst_size = thunk_type_size(type_ptr, to_host); + src_size = thunk_type_size(type_ptr, 1 - to_host); + d = dst; + s = src; + for(i = 0;i < array_length; i++) { + thunk_convert(d, s, type_ptr, to_host); + d += dst_size; + s += src_size; + } + type_ptr = thunk_type_next(type_ptr); + } + break; + case TYPE_STRUCT: + { + int i; + const StructEntry *se; + const uint8_t *s; + uint8_t *d; + const argtype *field_types; + const int *dst_offsets, *src_offsets; + + assert(*type_ptr < max_struct_entries); + se = struct_entries + *type_ptr++; + if (se->convert[0] != NULL) { + /* specific conversion is needed */ + (*se->convert[to_host])(dst, src); + } else { + /* standard struct conversion */ + field_types = se->field_types; + dst_offsets = se->field_offsets[to_host]; + src_offsets = se->field_offsets[1 - to_host]; + d = dst; + s = src; + for(i = 0;i < se->nb_fields; i++) { + field_types = thunk_convert(d + dst_offsets[i], + s + src_offsets[i], + field_types, to_host); + } + } + } + break; + default: + fprintf(stderr, "Invalid type 0x%x\n", type); + break; + } + return type_ptr; +} + +const argtype *thunk_print(void *arg, const argtype *type_ptr) +{ + int type; + + type = *type_ptr++; + + switch (type) { + case TYPE_CHAR: + qemu_log("%c", *(uint8_t *)arg); + break; + case TYPE_SHORT: + qemu_log("%" PRId16, tswap16(*(uint16_t *)arg)); + break; + case TYPE_INT: + qemu_log("%" PRId32, tswap32(*(uint32_t *)arg)); + break; + case TYPE_LONGLONG: + qemu_log("%" PRId64, tswap64(*(uint64_t *)arg)); + break; + case TYPE_ULONGLONG: + qemu_log("%" PRIu64, tswap64(*(uint64_t *)arg)); + break; +#if HOST_LONG_BITS == 32 && TARGET_ABI_BITS == 32 + case TYPE_PTRVOID: + qemu_log("0x%" PRIx32, tswap32(*(uint32_t *)arg)); + break; + case TYPE_LONG: + qemu_log("%" PRId32, tswap32(*(uint32_t *)arg)); + break; + case TYPE_ULONG: + qemu_log("%" PRIu32, tswap32(*(uint32_t *)arg)); + break; +#elif HOST_LONG_BITS == 64 && TARGET_ABI_BITS == 32 + case TYPE_PTRVOID: + qemu_log("0x%" PRIx32, tswap32(*(uint64_t *)arg & 0xffffffff)); + break; + case TYPE_LONG: + qemu_log("%" PRId32, tswap32(*(uint64_t *)arg & 0xffffffff)); + break; + case TYPE_ULONG: + qemu_log("%" PRIu32, tswap32(*(uint64_t *)arg & 0xffffffff)); + break; +#elif HOST_LONG_BITS == 64 && TARGET_ABI_BITS == 64 + case TYPE_PTRVOID: + qemu_log("0x%" PRIx64, tswap64(*(uint64_t *)arg)); + break; + case TYPE_LONG: + qemu_log("%" PRId64, tswap64(*(uint64_t *)arg)); + break; + case TYPE_ULONG: + qemu_log("%" PRIu64, tswap64(*(uint64_t *)arg)); + break; +#else + case TYPE_PTRVOID: + qemu_log("0x%" PRIx64, tswap64(*(uint64_t *)arg)); + break; + case TYPE_LONG: + qemu_log("%" PRId64, tswap64(*(uint64_t *)arg)); + break; + case TYPE_ULONG: + qemu_log("%" PRIu64, tswap64(*(uint64_t *)arg)); + break; +#endif + case TYPE_OLDDEVT: + { + uint64_t val = 0; + switch (thunk_type_size(type_ptr - 1, 1)) { + case 2: + val = *(uint16_t *)arg; + break; + case 4: + val = *(uint32_t *)arg; + break; + case 8: + val = *(uint64_t *)arg; + break; + } + switch (thunk_type_size(type_ptr - 1, 0)) { + case 2: + qemu_log("%" PRIu16, tswap16(val)); + break; + case 4: + qemu_log("%" PRIu32, tswap32(val)); + break; + case 8: + qemu_log("%" PRIu64, tswap64(val)); + break; + } + } + break; + case TYPE_ARRAY: + { + int i, array_length, arg_size; + uint8_t *a; + int is_string = 0; + + array_length = *type_ptr++; + arg_size = thunk_type_size(type_ptr, 0); + a = arg; + + if (*type_ptr == TYPE_CHAR) { + qemu_log("\""); + is_string = 1; + } else { + qemu_log("["); + } + + for (i = 0; i < array_length; i++) { + if (i > 0 && !is_string) { + qemu_log(","); + } + thunk_print(a, type_ptr); + a += arg_size; + } + + if (is_string) { + qemu_log("\""); + } else { + qemu_log("]"); + } + + type_ptr = thunk_type_next(type_ptr); + } + break; + case TYPE_STRUCT: + { + int i; + const StructEntry *se; + uint8_t *a; + const argtype *field_types; + const int *arg_offsets; + + se = struct_entries + *type_ptr++; + + if (se->print != NULL) { + se->print(arg); + } else { + a = arg; + + field_types = se->field_types; + arg_offsets = se->field_offsets[0]; + + qemu_log("{"); + for (i = 0; i < se->nb_fields; i++) { + if (i > 0) { + qemu_log(","); + } + field_types = thunk_print(a + arg_offsets[i], field_types); + } + qemu_log("}"); + } + } + break; + default: + g_assert_not_reached(); + } + return type_ptr; +} + +/* from em86 */ + +/* Utility function: Table-driven functions to translate bitmasks + * between host and target formats + */ +unsigned int target_to_host_bitmask(unsigned int target_mask, + const bitmask_transtbl * trans_tbl) +{ + const bitmask_transtbl *btp; + unsigned int host_mask = 0; + + for (btp = trans_tbl; btp->target_mask && btp->host_mask; btp++) { + if ((target_mask & btp->target_mask) == btp->target_bits) { + host_mask |= btp->host_bits; + } + } + return host_mask; +} + +unsigned int host_to_target_bitmask(unsigned int host_mask, + const bitmask_transtbl * trans_tbl) +{ + const bitmask_transtbl *btp; + unsigned int target_mask = 0; + + for (btp = trans_tbl; btp->target_mask && btp->host_mask; btp++) { + if ((host_mask & btp->host_mask) == btp->host_bits) { + target_mask |= btp->target_bits; + } + } + return target_mask; +} + +int thunk_type_size_array(const argtype *type_ptr, int is_host) +{ + return thunk_type_size(type_ptr, is_host); +} + +int thunk_type_align_array(const argtype *type_ptr, int is_host) +{ + return thunk_type_align(type_ptr, is_host); +} + +void thunk_init(unsigned int max_structs) +{ + max_struct_entries = max_structs; + struct_entries = g_new0(StructEntry, max_structs); +} diff --git a/meson.build b/meson.build index 4e0a8033f7..eebeaab9ce 100644 --- a/meson.build +++ b/meson.build @@ -2633,7 +2633,6 @@ subdir('linux-user') specific_ss.add_all(when: 'CONFIG_BSD_USER', if_true: bsd_user_ss) -linux_user_ss.add(files('thunk.c')) specific_ss.add_all(when: 'CONFIG_LINUX_USER', if_true: linux_user_ss) common_user_ss = common_user_ss.apply(config_all, strict: false) diff --git a/thunk.c b/thunk.c deleted file mode 100644 index dac4bf11c6..0000000000 --- a/thunk.c +++ /dev/null @@ -1,481 +0,0 @@ -/* - * Generic thunking code to convert data between host and target CPU - * - * Copyright (c) 2003 Fabrice Bellard - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, see . - */ -#include "qemu/osdep.h" -#include "qemu/log.h" - -#include "qemu.h" -#include "exec/user/thunk.h" - -//#define DEBUG - -static unsigned int max_struct_entries; -StructEntry *struct_entries; - -static const argtype *thunk_type_next_ptr(const argtype *type_ptr); - -static inline const argtype *thunk_type_next(const argtype *type_ptr) -{ - int type; - - type = *type_ptr++; - switch(type) { - case TYPE_CHAR: - case TYPE_SHORT: - case TYPE_INT: - case TYPE_LONGLONG: - case TYPE_ULONGLONG: - case TYPE_LONG: - case TYPE_ULONG: - case TYPE_PTRVOID: - case TYPE_OLDDEVT: - return type_ptr; - case TYPE_PTR: - return thunk_type_next_ptr(type_ptr); - case TYPE_ARRAY: - return thunk_type_next_ptr(type_ptr + 1); - case TYPE_STRUCT: - return type_ptr + 1; - default: - return NULL; - } -} - -static const argtype *thunk_type_next_ptr(const argtype *type_ptr) -{ - return thunk_type_next(type_ptr); -} - -void thunk_register_struct(int id, const char *name, const argtype *types) -{ - const argtype *type_ptr; - StructEntry *se; - int nb_fields, offset, max_align, align, size, i, j; - - assert(id < max_struct_entries); - - /* first we count the number of fields */ - type_ptr = types; - nb_fields = 0; - while (*type_ptr != TYPE_NULL) { - type_ptr = thunk_type_next(type_ptr); - nb_fields++; - } - assert(nb_fields > 0); - se = struct_entries + id; - se->field_types = types; - se->nb_fields = nb_fields; - se->name = name; -#ifdef DEBUG - printf("struct %s: id=%d nb_fields=%d\n", - se->name, id, se->nb_fields); -#endif - /* now we can alloc the data */ - - for (i = 0; i < ARRAY_SIZE(se->field_offsets); i++) { - offset = 0; - max_align = 1; - se->field_offsets[i] = g_new(int, nb_fields); - type_ptr = se->field_types; - for(j = 0;j < nb_fields; j++) { - size = thunk_type_size(type_ptr, i); - align = thunk_type_align(type_ptr, i); - offset = (offset + align - 1) & ~(align - 1); - se->field_offsets[i][j] = offset; - offset += size; - if (align > max_align) - max_align = align; - type_ptr = thunk_type_next(type_ptr); - } - offset = (offset + max_align - 1) & ~(max_align - 1); - se->size[i] = offset; - se->align[i] = max_align; -#ifdef DEBUG - printf("%s: size=%d align=%d\n", - i == THUNK_HOST ? "host" : "target", offset, max_align); -#endif - } -} - -void thunk_register_struct_direct(int id, const char *name, - const StructEntry *se1) -{ - StructEntry *se; - - assert(id < max_struct_entries); - se = struct_entries + id; - *se = *se1; - se->name = name; -} - - -/* now we can define the main conversion functions */ -const argtype *thunk_convert(void *dst, const void *src, - const argtype *type_ptr, int to_host) -{ - int type; - - type = *type_ptr++; - switch(type) { - case TYPE_CHAR: - *(uint8_t *)dst = *(uint8_t *)src; - break; - case TYPE_SHORT: - *(uint16_t *)dst = tswap16(*(uint16_t *)src); - break; - case TYPE_INT: - *(uint32_t *)dst = tswap32(*(uint32_t *)src); - break; - case TYPE_LONGLONG: - case TYPE_ULONGLONG: - *(uint64_t *)dst = tswap64(*(uint64_t *)src); - break; -#if HOST_LONG_BITS == 32 && TARGET_ABI_BITS == 32 - case TYPE_LONG: - case TYPE_ULONG: - case TYPE_PTRVOID: - *(uint32_t *)dst = tswap32(*(uint32_t *)src); - break; -#elif HOST_LONG_BITS == 64 && TARGET_ABI_BITS == 32 - case TYPE_LONG: - case TYPE_ULONG: - case TYPE_PTRVOID: - if (to_host) { - if (type == TYPE_LONG) { - /* sign extension */ - *(uint64_t *)dst = (int32_t)tswap32(*(uint32_t *)src); - } else { - *(uint64_t *)dst = tswap32(*(uint32_t *)src); - } - } else { - *(uint32_t *)dst = tswap32(*(uint64_t *)src & 0xffffffff); - } - break; -#elif HOST_LONG_BITS == 64 && TARGET_ABI_BITS == 64 - case TYPE_LONG: - case TYPE_ULONG: - case TYPE_PTRVOID: - *(uint64_t *)dst = tswap64(*(uint64_t *)src); - break; -#elif HOST_LONG_BITS == 32 && TARGET_ABI_BITS == 64 - case TYPE_LONG: - case TYPE_ULONG: - case TYPE_PTRVOID: - if (to_host) { - *(uint32_t *)dst = tswap64(*(uint64_t *)src); - } else { - if (type == TYPE_LONG) { - /* sign extension */ - *(uint64_t *)dst = tswap64(*(int32_t *)src); - } else { - *(uint64_t *)dst = tswap64(*(uint32_t *)src); - } - } - break; -#else -#warning unsupported conversion -#endif - case TYPE_OLDDEVT: - { - uint64_t val = 0; - switch (thunk_type_size(type_ptr - 1, !to_host)) { - case 2: - val = *(uint16_t *)src; - break; - case 4: - val = *(uint32_t *)src; - break; - case 8: - val = *(uint64_t *)src; - break; - } - switch (thunk_type_size(type_ptr - 1, to_host)) { - case 2: - *(uint16_t *)dst = tswap16(val); - break; - case 4: - *(uint32_t *)dst = tswap32(val); - break; - case 8: - *(uint64_t *)dst = tswap64(val); - break; - } - break; - } - case TYPE_ARRAY: - { - int array_length, i, dst_size, src_size; - const uint8_t *s; - uint8_t *d; - - array_length = *type_ptr++; - dst_size = thunk_type_size(type_ptr, to_host); - src_size = thunk_type_size(type_ptr, 1 - to_host); - d = dst; - s = src; - for(i = 0;i < array_length; i++) { - thunk_convert(d, s, type_ptr, to_host); - d += dst_size; - s += src_size; - } - type_ptr = thunk_type_next(type_ptr); - } - break; - case TYPE_STRUCT: - { - int i; - const StructEntry *se; - const uint8_t *s; - uint8_t *d; - const argtype *field_types; - const int *dst_offsets, *src_offsets; - - assert(*type_ptr < max_struct_entries); - se = struct_entries + *type_ptr++; - if (se->convert[0] != NULL) { - /* specific conversion is needed */ - (*se->convert[to_host])(dst, src); - } else { - /* standard struct conversion */ - field_types = se->field_types; - dst_offsets = se->field_offsets[to_host]; - src_offsets = se->field_offsets[1 - to_host]; - d = dst; - s = src; - for(i = 0;i < se->nb_fields; i++) { - field_types = thunk_convert(d + dst_offsets[i], - s + src_offsets[i], - field_types, to_host); - } - } - } - break; - default: - fprintf(stderr, "Invalid type 0x%x\n", type); - break; - } - return type_ptr; -} - -const argtype *thunk_print(void *arg, const argtype *type_ptr) -{ - int type; - - type = *type_ptr++; - - switch (type) { - case TYPE_CHAR: - qemu_log("%c", *(uint8_t *)arg); - break; - case TYPE_SHORT: - qemu_log("%" PRId16, tswap16(*(uint16_t *)arg)); - break; - case TYPE_INT: - qemu_log("%" PRId32, tswap32(*(uint32_t *)arg)); - break; - case TYPE_LONGLONG: - qemu_log("%" PRId64, tswap64(*(uint64_t *)arg)); - break; - case TYPE_ULONGLONG: - qemu_log("%" PRIu64, tswap64(*(uint64_t *)arg)); - break; -#if HOST_LONG_BITS == 32 && TARGET_ABI_BITS == 32 - case TYPE_PTRVOID: - qemu_log("0x%" PRIx32, tswap32(*(uint32_t *)arg)); - break; - case TYPE_LONG: - qemu_log("%" PRId32, tswap32(*(uint32_t *)arg)); - break; - case TYPE_ULONG: - qemu_log("%" PRIu32, tswap32(*(uint32_t *)arg)); - break; -#elif HOST_LONG_BITS == 64 && TARGET_ABI_BITS == 32 - case TYPE_PTRVOID: - qemu_log("0x%" PRIx32, tswap32(*(uint64_t *)arg & 0xffffffff)); - break; - case TYPE_LONG: - qemu_log("%" PRId32, tswap32(*(uint64_t *)arg & 0xffffffff)); - break; - case TYPE_ULONG: - qemu_log("%" PRIu32, tswap32(*(uint64_t *)arg & 0xffffffff)); - break; -#elif HOST_LONG_BITS == 64 && TARGET_ABI_BITS == 64 - case TYPE_PTRVOID: - qemu_log("0x%" PRIx64, tswap64(*(uint64_t *)arg)); - break; - case TYPE_LONG: - qemu_log("%" PRId64, tswap64(*(uint64_t *)arg)); - break; - case TYPE_ULONG: - qemu_log("%" PRIu64, tswap64(*(uint64_t *)arg)); - break; -#else - case TYPE_PTRVOID: - qemu_log("0x%" PRIx64, tswap64(*(uint64_t *)arg)); - break; - case TYPE_LONG: - qemu_log("%" PRId64, tswap64(*(uint64_t *)arg)); - break; - case TYPE_ULONG: - qemu_log("%" PRIu64, tswap64(*(uint64_t *)arg)); - break; -#endif - case TYPE_OLDDEVT: - { - uint64_t val = 0; - switch (thunk_type_size(type_ptr - 1, 1)) { - case 2: - val = *(uint16_t *)arg; - break; - case 4: - val = *(uint32_t *)arg; - break; - case 8: - val = *(uint64_t *)arg; - break; - } - switch (thunk_type_size(type_ptr - 1, 0)) { - case 2: - qemu_log("%" PRIu16, tswap16(val)); - break; - case 4: - qemu_log("%" PRIu32, tswap32(val)); - break; - case 8: - qemu_log("%" PRIu64, tswap64(val)); - break; - } - } - break; - case TYPE_ARRAY: - { - int i, array_length, arg_size; - uint8_t *a; - int is_string = 0; - - array_length = *type_ptr++; - arg_size = thunk_type_size(type_ptr, 0); - a = arg; - - if (*type_ptr == TYPE_CHAR) { - qemu_log("\""); - is_string = 1; - } else { - qemu_log("["); - } - - for (i = 0; i < array_length; i++) { - if (i > 0 && !is_string) { - qemu_log(","); - } - thunk_print(a, type_ptr); - a += arg_size; - } - - if (is_string) { - qemu_log("\""); - } else { - qemu_log("]"); - } - - type_ptr = thunk_type_next(type_ptr); - } - break; - case TYPE_STRUCT: - { - int i; - const StructEntry *se; - uint8_t *a; - const argtype *field_types; - const int *arg_offsets; - - se = struct_entries + *type_ptr++; - - if (se->print != NULL) { - se->print(arg); - } else { - a = arg; - - field_types = se->field_types; - arg_offsets = se->field_offsets[0]; - - qemu_log("{"); - for (i = 0; i < se->nb_fields; i++) { - if (i > 0) { - qemu_log(","); - } - field_types = thunk_print(a + arg_offsets[i], field_types); - } - qemu_log("}"); - } - } - break; - default: - g_assert_not_reached(); - } - return type_ptr; -} - -/* from em86 */ - -/* Utility function: Table-driven functions to translate bitmasks - * between host and target formats - */ -unsigned int target_to_host_bitmask(unsigned int target_mask, - const bitmask_transtbl * trans_tbl) -{ - const bitmask_transtbl *btp; - unsigned int host_mask = 0; - - for (btp = trans_tbl; btp->target_mask && btp->host_mask; btp++) { - if ((target_mask & btp->target_mask) == btp->target_bits) { - host_mask |= btp->host_bits; - } - } - return host_mask; -} - -unsigned int host_to_target_bitmask(unsigned int host_mask, - const bitmask_transtbl * trans_tbl) -{ - const bitmask_transtbl *btp; - unsigned int target_mask = 0; - - for (btp = trans_tbl; btp->target_mask && btp->host_mask; btp++) { - if ((host_mask & btp->host_mask) == btp->host_bits) { - target_mask |= btp->target_bits; - } - } - return target_mask; -} - -int thunk_type_size_array(const argtype *type_ptr, int is_host) -{ - return thunk_type_size(type_ptr, is_host); -} - -int thunk_type_align_array(const argtype *type_ptr, int is_host) -{ - return thunk_type_align(type_ptr, is_host); -} - -void thunk_init(unsigned int max_structs) -{ - max_struct_entries = max_structs; - struct_entries = g_new0(StructEntry, max_structs); -} -- cgit v1.2.3