X-Git-Url: https://git.proxmox.com/?a=blobdiff_plain;f=thunk.c;h=2dac36666de47c74477dc42ff897497e1440fc5a;hb=93587e3af3a259deac89c12863d93653d69d22b8;hp=c2fd44caeefaba3f323da4a4255ef8323e2188d3;hpb=3ef693a03205217a5def9318b443c8cb6de17217;p=mirror_qemu.git diff --git a/thunk.c b/thunk.c index c2fd44caee..2dac36666d 100644 --- a/thunk.c +++ b/thunk.c @@ -1,6 +1,6 @@ /* * 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 @@ -14,95 +14,19 @@ * 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, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * License along with this library; if not, see . */ -#include -#include -#include +#include "qemu/osdep.h" #include "qemu.h" -#include "thunk.h" +#include "exec/user/thunk.h" //#define DEBUG -#define MAX_STRUCTS 128 - -/* XXX: make it dynamic */ -static StructEntry struct_entries[MAX_STRUCTS]; +static unsigned int max_struct_entries; +StructEntry *struct_entries; -static inline int thunk_type_size(const argtype *type_ptr, int is_host) -{ - int type, size; - const StructEntry *se; - - type = *type_ptr; - switch(type) { - case TYPE_CHAR: - return 1; - case TYPE_SHORT: - return 2; - case TYPE_INT: - return 4; - case TYPE_LONGLONG: - case TYPE_ULONGLONG: - return 8; - case TYPE_LONG: - case TYPE_ULONG: - case TYPE_PTRVOID: - case TYPE_PTR: - if (is_host) { - return HOST_LONG_SIZE; - } else { - return TARGET_LONG_SIZE; - } - break; - case TYPE_ARRAY: - size = type_ptr[1]; - return size * thunk_type_size(type_ptr + 2, is_host); - case TYPE_STRUCT: - se = struct_entries + type_ptr[1]; - return se->size[is_host]; - default: - return -1; - } -} - -static inline int thunk_type_align(const argtype *type_ptr, int is_host) -{ - int type; - const StructEntry *se; - - type = *type_ptr; - switch(type) { - case TYPE_CHAR: - return 1; - case TYPE_SHORT: - return 2; - case TYPE_INT: - return 4; - case TYPE_LONGLONG: - case TYPE_ULONGLONG: - return 8; - case TYPE_LONG: - case TYPE_ULONG: - case TYPE_PTRVOID: - case TYPE_PTR: - if (is_host) { - return HOST_LONG_SIZE; - } else { - return TARGET_LONG_SIZE; - } - break; - case TYPE_ARRAY: - return thunk_type_align(type_ptr + 2, is_host); - case TYPE_STRUCT: - se = struct_entries + type_ptr[1]; - return se->align[is_host]; - default: - return -1; - } -} +static const argtype *thunk_type_next_ptr(const argtype *type_ptr); static inline const argtype *thunk_type_next(const argtype *type_ptr) { @@ -118,11 +42,12 @@ static inline const argtype *thunk_type_next(const argtype *type_ptr) case TYPE_LONG: case TYPE_ULONG: case TYPE_PTRVOID: + case TYPE_OLDDEVT: return type_ptr; case TYPE_PTR: - return thunk_type_next(type_ptr); + return thunk_type_next_ptr(type_ptr); case TYPE_ARRAY: - return thunk_type_next(type_ptr + 1); + return thunk_type_next_ptr(type_ptr + 1); case TYPE_STRUCT: return type_ptr + 1; default: @@ -130,14 +55,20 @@ static inline const argtype *thunk_type_next(const argtype *type_ptr) } } +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); se = struct_entries + id; - + /* first we count the number of fields */ type_ptr = types; nb_fields = 0; @@ -149,7 +80,7 @@ void thunk_register_struct(int id, const char *name, const argtype *types) se->nb_fields = nb_fields; se->name = name; #ifdef DEBUG - printf("struct %s: id=%d nb_fields=%d\n", + printf("struct %s: id=%d nb_fields=%d\n", se->name, id, se->nb_fields); #endif /* now we can alloc the data */ @@ -167,20 +98,24 @@ void thunk_register_struct(int id, const char *name, const argtype *types) 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", + 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, StructEntry *se1) +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; @@ -188,7 +123,7 @@ void thunk_register_struct_direct(int id, const char *name, StructEntry *se1) /* now we can define the main conversion functions */ -const argtype *thunk_convert(void *dst, const void *src, +const argtype *thunk_convert(void *dst, const void *src, const argtype *type_ptr, int to_host) { int type; @@ -208,25 +143,78 @@ const argtype *thunk_convert(void *dst, const void *src, case TYPE_ULONGLONG: *(uint64_t *)dst = tswap64(*(uint64_t *)src); break; -#if HOST_LONG_BITS == 32 && TARGET_LONG_BITS == 32 +#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_LONG_BITS == 32 +#elif HOST_LONG_BITS == 64 && TARGET_ABI_BITS == 32 case TYPE_LONG: case TYPE_ULONG: case TYPE_PTRVOID: - if (target_to_host) { - *(uint64_t *)dst = tswap32(*(uint32_t *)src); + 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 -#error unsupported conversion +#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; @@ -254,7 +242,8 @@ const argtype *thunk_convert(void *dst, const void *src, 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 */ @@ -267,8 +256,8 @@ const argtype *thunk_convert(void *dst, const void *src, 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 = thunk_convert(d + dst_offsets[i], + s + src_offsets[i], field_types, to_host); } } @@ -284,32 +273,48 @@ const argtype *thunk_convert(void *dst, const void *src, /* from em86 */ /* Utility function: Table-driven functions to translate bitmasks - * between X86 and Alpha formats... + * between host and target formats */ -unsigned int target_to_host_bitmask(unsigned int x86_mask, - bitmask_transtbl * trans_tbl) +unsigned int target_to_host_bitmask(unsigned int target_mask, + const bitmask_transtbl * trans_tbl) { - bitmask_transtbl * btp; - unsigned int alpha_mask = 0; + const bitmask_transtbl *btp; + unsigned int host_mask = 0; - for(btp = trans_tbl; btp->x86_mask && btp->alpha_mask; btp++) { - if((x86_mask & btp->x86_mask) == btp->x86_bits) { - alpha_mask |= btp->alpha_bits; - } + 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(alpha_mask); + return host_mask; } -unsigned int host_to_target_bitmask(unsigned int alpha_mask, - bitmask_transtbl * trans_tbl) +unsigned int host_to_target_bitmask(unsigned int host_mask, + const bitmask_transtbl * trans_tbl) { - bitmask_transtbl * btp; - unsigned int x86_mask = 0; + const bitmask_transtbl *btp; + unsigned int target_mask = 0; - for(btp = trans_tbl; btp->x86_mask && btp->alpha_mask; btp++) { - if((alpha_mask & btp->alpha_mask) == btp->alpha_bits) { - x86_mask |= btp->x86_mask; - } + 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(x86_mask); + 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); }