]> git.proxmox.com Git - qemu.git/blobdiff - thunk.c
Open 2.0 development tree
[qemu.git] / thunk.c
diff --git a/thunk.c b/thunk.c
index 62520a2976dd7333db354bec186f98c0993a395f..3cca047509e7483da2f45701b16055eb9f028cf6 100644 (file)
--- a/thunk.c
+++ b/thunk.c
 /*
  *  Generic thunking code to convert data between host and target CPU
- * 
+ *
  *  Copyright (c) 2003 Fabrice Bellard
  *
- *  This program is free software; you can redistribute it and/or modify
- *  it under the terms of the GNU 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 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 program 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 General Public License for more details.
+ * 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 General Public License
- *  along with this program; if not, write to the Free Software
- *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ * 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 "gemu.h"
-#include "thunk.h"
+#include "qemu.h"
+#include "exec/user/thunk.h"
 
 //#define DEBUG
 
 #define MAX_STRUCTS 128
 
 /* XXX: make it dynamic */
-static StructEntry struct_entries[MAX_STRUCTS];
-
-static inline int thunk_type_size(const argtype *type_ptr, int is_host)
-{
-    int type, size;
-    const StructEntry *se;
+StructEntry struct_entries[MAX_STRUCTS];
 
-    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 +46,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,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;
@@ -137,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;
@@ -149,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 */
@@ -167,18 +101,20 @@ 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;
     se = struct_entries + id;
@@ -188,7 +124,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 +144,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 +243,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 */
@@ -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);
                 }
             }
@@ -286,10 +275,10 @@ 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, 
-                                    bitmask_transtbl * trans_tbl)
+unsigned int target_to_host_bitmask(unsigned int x86_mask,
+                                    const bitmask_transtbl * trans_tbl)
 {
-    bitmask_transtbl * btp;
+    const bitmask_transtbl *btp;
     unsigned int       alpha_mask = 0;
 
     for(btp = trans_tbl; btp->x86_mask && btp->alpha_mask; btp++) {
@@ -300,16 +289,28 @@ unsigned int target_to_host_bitmask(unsigned int x86_mask,
     return(alpha_mask);
 }
 
-unsigned int host_to_target_bitmask(unsigned int alpha_mask, 
-                                    bitmask_transtbl * trans_tbl)
+unsigned int host_to_target_bitmask(unsigned int alpha_mask,
+                                    const bitmask_transtbl * trans_tbl)
 {
-    bitmask_transtbl * btp;
+    const bitmask_transtbl *btp;
     unsigned int       x86_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;
+           x86_mask |= btp->x86_bits;
        }
     }
     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 */