diff options
author | Richard Henderson <richard.henderson@linaro.org> | 2021-11-17 16:26:14 +0100 |
---|---|---|
committer | Richard Henderson <richard.henderson@linaro.org> | 2021-12-20 10:12:29 -0800 |
commit | ff9c1e5500141df7be15446ccfbdc66752812a9a (patch) | |
tree | 18af3b172428c7a91d7fa89e0102ee1ea8c44001 /thunk.c | |
parent | 5bfd125ec8ba8aab04f3a636dcea39f6c4075ced (diff) |
linux-user: Move thunk.c from top-level
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 <imp@bsdimp.com>
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
Diffstat (limited to 'thunk.c')
-rw-r--r-- | thunk.c | 481 |
1 files changed, 0 insertions, 481 deletions
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 <http://www.gnu.org/licenses/>. - */ -#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); -} |