aboutsummaryrefslogtreecommitdiffstats
path: root/thunk.c
diff options
context:
space:
mode:
authorThe Android Open Source Project <initial-contribution@android.com>2009-02-10 15:43:59 -0800
committerThe Android Open Source Project <initial-contribution@android.com>2009-02-10 15:43:59 -0800
commitc27f813900a3c114562efbb8df1065e94766fc48 (patch)
treed95919283707dcab61009e27007374a745c9541e /thunk.c
parent0852ad57fa372f9b2854e4df685eaba8d8ef6790 (diff)
downloadexternal_qemu-c27f813900a3c114562efbb8df1065e94766fc48.zip
external_qemu-c27f813900a3c114562efbb8df1065e94766fc48.tar.gz
external_qemu-c27f813900a3c114562efbb8df1065e94766fc48.tar.bz2
auto import from //branches/cupcake/...@130745
Diffstat (limited to 'thunk.c')
-rw-r--r--thunk.c75
1 files changed, 60 insertions, 15 deletions
diff --git a/thunk.c b/thunk.c
index bc9bd28..7331aeb 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
@@ -31,6 +31,8 @@
/* XXX: make it dynamic */
StructEntry struct_entries[MAX_STRUCTS];
+static const argtype *thunk_type_next_ptr(const argtype *type_ptr);
+
static inline const argtype *thunk_type_next(const argtype *type_ptr)
{
int type;
@@ -47,9 +49,9 @@ static inline const argtype *thunk_type_next(const argtype *type_ptr)
case TYPE_PTRVOID:
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:
@@ -57,6 +59,11 @@ 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;
@@ -64,7 +71,7 @@ void thunk_register_struct(int id, const char *name, const argtype *types)
int nb_fields, offset, max_align, align, size, i, j;
se = struct_entries + id;
-
+
/* first we count the number of fields */
type_ptr = types;
nb_fields = 0;
@@ -76,7 +83,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 */
@@ -100,7 +107,7 @@ void thunk_register_struct(int id, const char *name, const argtype *types)
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
}
@@ -116,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;
@@ -136,22 +143,48 @@ 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 (to_host) {
- *(uint64_t *)dst = tswap32(*(uint32_t *)src);
+ 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
@@ -182,7 +215,7 @@ const argtype *thunk_convert(void *dst, const void *src,
uint8_t *d;
const argtype *field_types;
const int *dst_offsets, *src_offsets;
-
+
se = struct_entries + *type_ptr++;
if (se->convert[0] != NULL) {
/* specific conversion is needed */
@@ -195,8 +228,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);
}
}
@@ -214,7 +247,7 @@ const argtype *thunk_convert(void *dst, const void *src,
/* Utility function: Table-driven functions to translate bitmasks
* between X86 and Alpha formats...
*/
-unsigned int target_to_host_bitmask(unsigned int x86_mask,
+unsigned int target_to_host_bitmask(unsigned int x86_mask,
bitmask_transtbl * trans_tbl)
{
bitmask_transtbl * btp;
@@ -228,7 +261,7 @@ unsigned int target_to_host_bitmask(unsigned int x86_mask,
return(alpha_mask);
}
-unsigned int host_to_target_bitmask(unsigned int alpha_mask,
+unsigned int host_to_target_bitmask(unsigned int alpha_mask,
bitmask_transtbl * trans_tbl)
{
bitmask_transtbl * btp;
@@ -241,3 +274,15 @@ unsigned int host_to_target_bitmask(unsigned int alpha_mask,
}
return(x86_mask);
}
+
+#ifndef NO_THUNK_TYPE_SIZE
+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);
+}
+#endif /* ndef NO_THUNK_TYPE_SIZE */