diff options
Diffstat (limited to 'qemu/include/exec/user')
-rw-r--r-- | qemu/include/exec/user/abitypes.h | 66 | ||||
-rw-r--r-- | qemu/include/exec/user/thunk.h | 191 |
2 files changed, 257 insertions, 0 deletions
diff --git a/qemu/include/exec/user/abitypes.h b/qemu/include/exec/user/abitypes.h new file mode 100644 index 000000000..80eedaccf --- /dev/null +++ b/qemu/include/exec/user/abitypes.h @@ -0,0 +1,66 @@ +#ifndef QEMU_TYPES_H +#define QEMU_TYPES_H +#include "cpu.h" + +#ifdef TARGET_ABI32 +#define TARGET_ABI_BITS 32 +#else +#define TARGET_ABI_BITS TARGET_LONG_BITS +#endif + +#ifdef TARGET_M68K +#define ABI_INT_ALIGNMENT 2 +#define ABI_LONG_ALIGNMENT 2 +#define ABI_LLONG_ALIGNMENT 2 +#endif + +#ifndef ABI_SHORT_ALIGNMENT +#define ABI_SHORT_ALIGNMENT 2 +#endif +#ifndef ABI_INT_ALIGNMENT +#define ABI_INT_ALIGNMENT 4 +#endif +#ifndef ABI_LONG_ALIGNMENT +#define ABI_LONG_ALIGNMENT (TARGET_ABI_BITS / 8) +#endif +#ifndef ABI_LLONG_ALIGNMENT +#define ABI_LLONG_ALIGNMENT 8 +#endif + +typedef int16_t abi_short __attribute__ ((aligned(ABI_SHORT_ALIGNMENT))); +typedef uint16_t abi_ushort __attribute__((aligned(ABI_SHORT_ALIGNMENT))); +typedef int32_t abi_int __attribute__((aligned(ABI_INT_ALIGNMENT))); +typedef uint32_t abi_uint __attribute__((aligned(ABI_INT_ALIGNMENT))); +typedef int64_t abi_llong __attribute__((aligned(ABI_LLONG_ALIGNMENT))); +typedef uint64_t abi_ullong __attribute__((aligned(ABI_LLONG_ALIGNMENT))); + +#ifdef TARGET_ABI32 +typedef uint32_t abi_ulong __attribute__((aligned(ABI_LONG_ALIGNMENT))); +typedef int32_t abi_long __attribute__((aligned(ABI_LONG_ALIGNMENT))); +#define TARGET_ABI_FMT_lx "%08x" +#define TARGET_ABI_FMT_ld "%d" +#define TARGET_ABI_FMT_lu "%u" + +static inline abi_ulong tswapal(abi_ulong v) +{ + return tswap32(v); +} + +#else +typedef target_ulong abi_ulong __attribute__((aligned(ABI_LONG_ALIGNMENT))); +typedef target_long abi_long __attribute__((aligned(ABI_LONG_ALIGNMENT))); +#define TARGET_ABI_FMT_lx TARGET_FMT_lx +#define TARGET_ABI_FMT_ld TARGET_FMT_ld +#define TARGET_ABI_FMT_lu TARGET_FMT_lu +/* for consistency, define ABI32 too */ +#if TARGET_ABI_BITS == 32 +#define TARGET_ABI32 1 +#endif + +static inline abi_ulong tswapal(abi_ulong v) +{ + return tswapl(v); +} + +#endif +#endif diff --git a/qemu/include/exec/user/thunk.h b/qemu/include/exec/user/thunk.h new file mode 100644 index 000000000..3b6746272 --- /dev/null +++ b/qemu/include/exec/user/thunk.h @@ -0,0 +1,191 @@ +/* + * 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 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/>. + */ +#ifndef THUNK_H +#define THUNK_H + +#include <inttypes.h> +#include "cpu.h" + +/* types enums definitions */ + +typedef enum argtype { + TYPE_NULL, + TYPE_CHAR, + TYPE_SHORT, + TYPE_INT, + TYPE_LONG, + TYPE_ULONG, + TYPE_PTRVOID, /* pointer on unknown data */ + TYPE_LONGLONG, + TYPE_ULONGLONG, + TYPE_PTR, + TYPE_ARRAY, + TYPE_STRUCT, + TYPE_OLDDEVT, +} argtype; + +#define MK_PTR(type) TYPE_PTR, type +#define MK_ARRAY(type, size) TYPE_ARRAY, size, type +#define MK_STRUCT(id) TYPE_STRUCT, id + +#define THUNK_TARGET 0 +#define THUNK_HOST 1 + +typedef struct { + /* standard struct handling */ + const argtype *field_types; + int nb_fields; + int *field_offsets[2]; + /* special handling */ + void (*convert[2])(void *dst, const void *src); + int size[2]; + int align[2]; + const char *name; +} StructEntry; + +/* Translation table for bitmasks... */ +typedef struct bitmask_transtbl { + unsigned int x86_mask; + unsigned int x86_bits; + unsigned int alpha_mask; + unsigned int alpha_bits; +} bitmask_transtbl; + +void thunk_register_struct(int id, const char *name, const argtype *types); +void thunk_register_struct_direct(int id, const char *name, + const StructEntry *se1); +const argtype *thunk_convert(void *dst, const void *src, + const argtype *type_ptr, int to_host); +#ifndef NO_THUNK_TYPE_SIZE + +extern StructEntry *struct_entries; + +int thunk_type_size_array(const argtype *type_ptr, int is_host); +int thunk_type_align_array(const argtype *type_ptr, int is_host); + +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 sizeof(void *); + } else { + return TARGET_ABI_BITS / 8; + } + break; + case TYPE_OLDDEVT: + if (is_host) { +#if defined(HOST_X86_64) + return 8; +#elif defined(HOST_ALPHA) || defined(HOST_IA64) || defined(HOST_MIPS) || \ + defined(HOST_PARISC) || defined(HOST_SPARC64) + return 4; +#elif defined(HOST_PPC) + return sizeof(void *); +#else + return 2; +#endif + } else { +#if defined(TARGET_X86_64) + return 8; +#elif defined(TARGET_ALPHA) || defined(TARGET_IA64) || defined(TARGET_MIPS) || \ + defined(TARGET_PARISC) || defined(TARGET_SPARC64) + return 4; +#elif defined(TARGET_PPC) + return TARGET_ABI_BITS / 8; +#else + return 2; +#endif + } + break; + case TYPE_ARRAY: + size = type_ptr[1]; + return size * thunk_type_size_array(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 sizeof(void *); + } else { + return TARGET_ABI_BITS / 8; + } + break; + case TYPE_OLDDEVT: + return thunk_type_size(type_ptr, is_host); + case TYPE_ARRAY: + return thunk_type_align_array(type_ptr + 2, is_host); + case TYPE_STRUCT: + se = struct_entries + type_ptr[1]; + return se->align[is_host]; + default: + return -1; + } +} + +#endif /* NO_THUNK_TYPE_SIZE */ + +unsigned int target_to_host_bitmask(unsigned int x86_mask, + const bitmask_transtbl * trans_tbl); +unsigned int host_to_target_bitmask(unsigned int alpha_mask, + const bitmask_transtbl * trans_tbl); + +void thunk_init(unsigned int max_structs); + +#endif |