]> git.proxmox.com Git - mirror_qemu.git/blobdiff - thunk.c
Merge remote-tracking branch 'remotes/bonzini/tags/for-upstream' into staging
[mirror_qemu.git] / thunk.c
diff --git a/thunk.c b/thunk.c
index 0347d6d049d47c0a5f2152d4cec318729556b54d..7f31cffe0968c87a83d59b27ecab2f1f79e78d99 100644 (file)
--- a/thunk.c
+++ b/thunk.c
  * 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
+ * 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.h"
-#include "thunk.h"
+#include "exec/user/thunk.h"
 
 //#define DEBUG
 
-#define MAX_STRUCTS 128
+static unsigned int max_struct_entries;
+StructEntry *struct_entries;
 
-/* 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)
 {
@@ -45,11 +42,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:
@@ -57,13 +55,18 @@ 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;
     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;
@@ -72,6 +75,8 @@ void thunk_register_struct(int id, const char *name, const argtype *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;
@@ -81,10 +86,10 @@ void thunk_register_struct(int id, const char *name, const argtype *types)
 #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);
@@ -106,9 +111,12 @@ void thunk_register_struct(int id, const char *name, const argtype *types)
     }
 }
 
-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;
+
+    assert(id < max_struct_entries);
     se = struct_entries + id;
     *se = *se1;
     se->name = name;
@@ -147,14 +155,67 @@ const argtype *thunk_convert(void *dst, const void *src,
     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
+    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;
@@ -183,6 +244,7 @@ const argtype *thunk_convert(void *dst, const void *src,
             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 */
@@ -212,32 +274,48 @@ const argtype *thunk_convert(void *dst, const void *src,
 /* 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,
-                                    bitmask_transtbl * trans_tbl)
+unsigned int target_to_host_bitmask(unsigned int target_mask,
+                                    const bitmask_transtbl * trans_tbl)
 {
-    bitmask_transtbl * btp;
-    unsigned int       alpha_mask = 0;
+    const bitmask_transtbl *btp;
+    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,
-                                    bitmask_transtbl * trans_tbl)
+unsigned int host_to_target_bitmask(unsigned int host_mask,
+                                    const bitmask_transtbl * trans_tbl)
 {
-    bitmask_transtbl * btp;
-    unsigned int       x86_mask = 0;
+    const bitmask_transtbl *btp;
+    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;
+}
+
+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);
+}
+
+void thunk_init(unsigned int max_structs)
+{
+    max_struct_entries = max_structs;
+    struct_entries = g_new0(StructEntry, max_structs);
 }