* 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.
+ * 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
* 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 <stdlib.h>
-#include <stdio.h>
-#include <stdarg.h>
+#include "qemu/osdep.h"
+#include "qemu/log.h"
#include "qemu.h"
-#include "thunk.h"
+#include "exec/user/thunk.h"
//#define DEBUG
-#define MAX_STRUCTS 128
-
-/* XXX: make it dynamic */
-StructEntry struct_entries[MAX_STRUCTS];
+static unsigned int max_struct_entries;
+StructEntry *struct_entries;
static const argtype *thunk_type_next_ptr(const argtype *type_ptr);
StructEntry *se;
int nb_fields, offset, max_align, align, size, i, j;
- se = struct_entries + id;
+ assert(id < max_struct_entries);
/* first we count the number of fields */
type_ptr = types;
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;
#endif
/* now we can alloc the data */
- for(i = 0;i < 2; i++) {
+ for (i = 0; i < ARRAY_SIZE(se->field_offsets); i++) {
offset = 0;
max_align = 1;
- se->field_offsets[i] = malloc(nb_fields * sizeof(int));
+ 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);
const StructEntry *se1)
{
StructEntry *se;
+
+ assert(id < max_struct_entries);
se = struct_entries + id;
*se = *se1;
se->name = name;
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 */
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 X86 and Alpha formats...
+ * between host and target formats
*/
-unsigned int target_to_host_bitmask(unsigned int x86_mask,
+unsigned int target_to_host_bitmask(unsigned int target_mask,
const bitmask_transtbl * trans_tbl)
{
const bitmask_transtbl *btp;
- unsigned int alpha_mask = 0;
+ 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,
+unsigned int host_to_target_bitmask(unsigned int host_mask,
const bitmask_transtbl * trans_tbl)
{
const bitmask_transtbl *btp;
- unsigned int x86_mask = 0;
+ 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_bits;
- }
+ 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;
}
-#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);
{
return thunk_type_align(type_ptr, is_host);
}
-#endif /* ndef NO_THUNK_TYPE_SIZE */
+
+void thunk_init(unsigned int max_structs)
+{
+ max_struct_entries = max_structs;
+ struct_entries = g_new0(StructEntry, max_structs);
+}