+/*
+ * 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, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
#ifndef THUNK_H
#define THUNK_H
#include <inttypes.h>
-#include <endian.h>
+#include "config.h"
#ifdef HAVE_BYTESWAP_H
#include <byteswap.h>
#define bswap_64(x) \
({ \
- __u64 __x = (x); \
- ((__u64)( \
- (__u64)(((__u64)(__x) & (__u64)0x00000000000000ffULL) << 56) | \
- (__u64)(((__u64)(__x) & (__u64)0x000000000000ff00ULL) << 40) | \
- (__u64)(((__u64)(__x) & (__u64)0x0000000000ff0000ULL) << 24) | \
- (__u64)(((__u64)(__x) & (__u64)0x00000000ff000000ULL) << 8) | \
- (__u64)(((__u64)(__x) & (__u64)0x000000ff00000000ULL) >> 8) | \
- (__u64)(((__u64)(__x) & (__u64)0x0000ff0000000000ULL) >> 24) | \
- (__u64)(((__u64)(__x) & (__u64)0x00ff000000000000ULL) >> 40) | \
- (__u64)(((__u64)(__x) & (__u64)0xff00000000000000ULL) >> 56) )); \
+ uint64_t __x = (x); \
+ ((uint64_t)( \
+ (uint64_t)(((uint64_t)(__x) & (uint64_t)0x00000000000000ffULL) << 56) | \
+ (uint64_t)(((uint64_t)(__x) & (uint64_t)0x000000000000ff00ULL) << 40) | \
+ (uint64_t)(((uint64_t)(__x) & (uint64_t)0x0000000000ff0000ULL) << 24) | \
+ (uint64_t)(((uint64_t)(__x) & (uint64_t)0x00000000ff000000ULL) << 8) | \
+ (uint64_t)(((uint64_t)(__x) & (uint64_t)0x000000ff00000000ULL) >> 8) | \
+ (uint64_t)(((uint64_t)(__x) & (uint64_t)0x0000ff0000000000ULL) >> 24) | \
+ (uint64_t)(((uint64_t)(__x) & (uint64_t)0x00ff000000000000ULL) >> 40) | \
+ (uint64_t)(((uint64_t)(__x) & (uint64_t)0xff00000000000000ULL) >> 56) )); \
})
#endif
-#undef WORDS_BIGENDIAN
-#if __BYTE_ORDER == __BIG_ENDIAN
-#define WORDS_BIGENDIAN
-#endif
-
-#ifdef WORDS_BIGENDIAN
+#if defined(WORDS_BIGENDIAN) != defined(TARGET_WORDS_BIGENDIAN)
#define BSWAP_NEEDED
#endif
-/* XXX: auto autoconf */
-#define TARGET_I386
+/* XXX: autoconf */
#define TARGET_LONG_BITS 32
-
-#if defined(__alpha__)
+#if defined(__alpha__) || defined (__ia64__)
#define HOST_LONG_BITS 64
#else
#define HOST_LONG_BITS 32
#endif
#define TARGET_LONG_SIZE (TARGET_LONG_BITS / 8)
-#define HOST_LONG_SIZE (TARGET_LONG_BITS / 8)
+#define HOST_LONG_SIZE (HOST_LONG_BITS / 8)
static inline uint16_t bswap16(uint16_t x)
{
return bswap_64(x);
}
-static void inline bswap16s(uint16_t *s)
+static inline void bswap16s(uint16_t *s)
{
*s = bswap16(*s);
}
-static void inline bswap32s(uint32_t *s)
+static inline void bswap32s(uint32_t *s)
{
*s = bswap32(*s);
}
-static void inline bswap64s(uint64_t *s)
+static inline void bswap64s(uint64_t *s)
{
*s = bswap64(*s);
}
return bswap64(s);
}
-static void inline tswap16s(uint16_t *s)
+static inline void tswap16s(uint16_t *s)
{
*s = bswap16(*s);
}
-static void inline tswap32s(uint32_t *s)
+static inline void tswap32s(uint32_t *s)
{
*s = bswap32(*s);
}
-static void inline tswap64s(uint64_t *s)
+static inline void tswap64s(uint64_t *s)
{
*s = bswap64(*s);
}
return s;
}
-static void inline tswap16s(uint16_t *s)
+static inline void tswap16s(uint16_t *s)
{
}
-static void inline tswap32s(uint32_t *s)
+static inline void tswap32s(uint32_t *s)
{
}
-static void inline tswap64s(uint64_t *s)
+static inline void tswap64s(uint64_t *s)
{
}
const argtype *thunk_convert(void *dst, const void *src,
const argtype *type_ptr, int to_host);
+extern 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;
+ }
+}
+
unsigned int target_to_host_bitmask(unsigned int x86_mask,
bitmask_transtbl * trans_tbl);
unsigned int host_to_target_bitmask(unsigned int alpha_mask,