symbian-qemu-0.9.1-12/qemu-symbian-svp/thunk.c
changeset 1 2fb8b9db1c86
equal deleted inserted replaced
0:ffa851df0825 1:2fb8b9db1c86
       
     1 /*
       
     2  *  Generic thunking code to convert data between host and target CPU
       
     3  *
       
     4  *  Copyright (c) 2003 Fabrice Bellard
       
     5  *
       
     6  * This library is free software; you can redistribute it and/or
       
     7  * modify it under the terms of the GNU Lesser General Public
       
     8  * License as published by the Free Software Foundation; either
       
     9  * version 2 of the License, or (at your option) any later version.
       
    10  *
       
    11  * This library is distributed in the hope that it will be useful,
       
    12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
       
    13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
       
    14  * Lesser General Public License for more details.
       
    15  *
       
    16  * You should have received a copy of the GNU Lesser General Public
       
    17  * License along with this library; if not, write to the Free Software
       
    18  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
       
    19  */
       
    20 #include <stdlib.h>
       
    21 #include <stdio.h>
       
    22 #include <stdarg.h>
       
    23 
       
    24 #include "qemu.h"
       
    25 #include "thunk.h"
       
    26 
       
    27 //#define DEBUG
       
    28 
       
    29 #define MAX_STRUCTS 128
       
    30 
       
    31 /* XXX: make it dynamic */
       
    32 StructEntry struct_entries[MAX_STRUCTS];
       
    33 
       
    34 static const argtype *thunk_type_next_ptr(const argtype *type_ptr);
       
    35 
       
    36 static inline const argtype *thunk_type_next(const argtype *type_ptr)
       
    37 {
       
    38     int type;
       
    39 
       
    40     type = *type_ptr++;
       
    41     switch(type) {
       
    42     case TYPE_CHAR:
       
    43     case TYPE_SHORT:
       
    44     case TYPE_INT:
       
    45     case TYPE_LONGLONG:
       
    46     case TYPE_ULONGLONG:
       
    47     case TYPE_LONG:
       
    48     case TYPE_ULONG:
       
    49     case TYPE_PTRVOID:
       
    50         return type_ptr;
       
    51     case TYPE_PTR:
       
    52         return thunk_type_next_ptr(type_ptr);
       
    53     case TYPE_ARRAY:
       
    54         return thunk_type_next_ptr(type_ptr + 1);
       
    55     case TYPE_STRUCT:
       
    56         return type_ptr + 1;
       
    57     default:
       
    58         return NULL;
       
    59     }
       
    60 }
       
    61 
       
    62 static const argtype *thunk_type_next_ptr(const argtype *type_ptr)
       
    63 {
       
    64     return thunk_type_next(type_ptr);
       
    65 }
       
    66 
       
    67 void thunk_register_struct(int id, const char *name, const argtype *types)
       
    68 {
       
    69     const argtype *type_ptr;
       
    70     StructEntry *se;
       
    71     int nb_fields, offset, max_align, align, size, i, j;
       
    72 
       
    73     se = struct_entries + id;
       
    74 
       
    75     /* first we count the number of fields */
       
    76     type_ptr = types;
       
    77     nb_fields = 0;
       
    78     while (*type_ptr != TYPE_NULL) {
       
    79         type_ptr = thunk_type_next(type_ptr);
       
    80         nb_fields++;
       
    81     }
       
    82     se->field_types = types;
       
    83     se->nb_fields = nb_fields;
       
    84     se->name = name;
       
    85 #ifdef DEBUG
       
    86     printf("struct %s: id=%d nb_fields=%d\n",
       
    87            se->name, id, se->nb_fields);
       
    88 #endif
       
    89     /* now we can alloc the data */
       
    90 
       
    91     for(i = 0;i < 2; i++) {
       
    92         offset = 0;
       
    93         max_align = 1;
       
    94         se->field_offsets[i] = malloc(nb_fields * sizeof(int));
       
    95         type_ptr = se->field_types;
       
    96         for(j = 0;j < nb_fields; j++) {
       
    97             size = thunk_type_size(type_ptr, i);
       
    98             align = thunk_type_align(type_ptr, i);
       
    99             offset = (offset + align - 1) & ~(align - 1);
       
   100             se->field_offsets[i][j] = offset;
       
   101             offset += size;
       
   102             if (align > max_align)
       
   103                 max_align = align;
       
   104             type_ptr = thunk_type_next(type_ptr);
       
   105         }
       
   106         offset = (offset + max_align - 1) & ~(max_align - 1);
       
   107         se->size[i] = offset;
       
   108         se->align[i] = max_align;
       
   109 #ifdef DEBUG
       
   110         printf("%s: size=%d align=%d\n",
       
   111                i == THUNK_HOST ? "host" : "target", offset, max_align);
       
   112 #endif
       
   113     }
       
   114 }
       
   115 
       
   116 void thunk_register_struct_direct(int id, const char *name,
       
   117                                   const StructEntry *se1)
       
   118 {
       
   119     StructEntry *se;
       
   120     se = struct_entries + id;
       
   121     *se = *se1;
       
   122     se->name = name;
       
   123 }
       
   124 
       
   125 
       
   126 /* now we can define the main conversion functions */
       
   127 const argtype *thunk_convert(void *dst, const void *src,
       
   128                              const argtype *type_ptr, int to_host)
       
   129 {
       
   130     int type;
       
   131 
       
   132     type = *type_ptr++;
       
   133     switch(type) {
       
   134     case TYPE_CHAR:
       
   135         *(uint8_t *)dst = *(uint8_t *)src;
       
   136         break;
       
   137     case TYPE_SHORT:
       
   138         *(uint16_t *)dst = tswap16(*(uint16_t *)src);
       
   139         break;
       
   140     case TYPE_INT:
       
   141         *(uint32_t *)dst = tswap32(*(uint32_t *)src);
       
   142         break;
       
   143     case TYPE_LONGLONG:
       
   144     case TYPE_ULONGLONG:
       
   145         *(uint64_t *)dst = tswap64(*(uint64_t *)src);
       
   146         break;
       
   147 #if HOST_LONG_BITS == 32 && TARGET_ABI_BITS == 32
       
   148     case TYPE_LONG:
       
   149     case TYPE_ULONG:
       
   150     case TYPE_PTRVOID:
       
   151         *(uint32_t *)dst = tswap32(*(uint32_t *)src);
       
   152         break;
       
   153 #elif HOST_LONG_BITS == 64 && TARGET_ABI_BITS == 32
       
   154     case TYPE_LONG:
       
   155     case TYPE_ULONG:
       
   156     case TYPE_PTRVOID:
       
   157         if (to_host) {
       
   158             if (type == TYPE_LONG) {
       
   159                 /* sign extension */
       
   160                 *(uint64_t *)dst = (int32_t)tswap32(*(uint32_t *)src);
       
   161             } else {
       
   162                 *(uint64_t *)dst = tswap32(*(uint32_t *)src);
       
   163             }
       
   164         } else {
       
   165             *(uint32_t *)dst = tswap32(*(uint64_t *)src & 0xffffffff);
       
   166         }
       
   167         break;
       
   168 #elif HOST_LONG_BITS == 64 && TARGET_ABI_BITS == 64
       
   169     case TYPE_LONG:
       
   170     case TYPE_ULONG:
       
   171     case TYPE_PTRVOID:
       
   172         *(uint64_t *)dst = tswap64(*(uint64_t *)src);
       
   173         break;
       
   174 #elif HOST_LONG_BITS == 32 && TARGET_ABI_BITS == 64
       
   175     case TYPE_LONG:
       
   176     case TYPE_ULONG:
       
   177     case TYPE_PTRVOID:
       
   178         if (to_host) {
       
   179             *(uint32_t *)dst = tswap64(*(uint64_t *)src);
       
   180         } else {
       
   181             if (type == TYPE_LONG) {
       
   182                 /* sign extension */
       
   183                 *(uint64_t *)dst = tswap64(*(int32_t *)src);
       
   184             } else {
       
   185                 *(uint64_t *)dst = tswap64(*(uint32_t *)src);
       
   186             }
       
   187         }
       
   188         break;
       
   189 #else
       
   190 #warning unsupported conversion
       
   191 #endif
       
   192     case TYPE_ARRAY:
       
   193         {
       
   194             int array_length, i, dst_size, src_size;
       
   195             const uint8_t *s;
       
   196             uint8_t  *d;
       
   197 
       
   198             array_length = *type_ptr++;
       
   199             dst_size = thunk_type_size(type_ptr, to_host);
       
   200             src_size = thunk_type_size(type_ptr, 1 - to_host);
       
   201             d = dst;
       
   202             s = src;
       
   203             for(i = 0;i < array_length; i++) {
       
   204                 thunk_convert(d, s, type_ptr, to_host);
       
   205                 d += dst_size;
       
   206                 s += src_size;
       
   207             }
       
   208             type_ptr = thunk_type_next(type_ptr);
       
   209         }
       
   210         break;
       
   211     case TYPE_STRUCT:
       
   212         {
       
   213             int i;
       
   214             const StructEntry *se;
       
   215             const uint8_t *s;
       
   216             uint8_t  *d;
       
   217             const argtype *field_types;
       
   218             const int *dst_offsets, *src_offsets;
       
   219 
       
   220             se = struct_entries + *type_ptr++;
       
   221             if (se->convert[0] != NULL) {
       
   222                 /* specific conversion is needed */
       
   223                 (*se->convert[to_host])(dst, src);
       
   224             } else {
       
   225                 /* standard struct conversion */
       
   226                 field_types = se->field_types;
       
   227                 dst_offsets = se->field_offsets[to_host];
       
   228                 src_offsets = se->field_offsets[1 - to_host];
       
   229                 d = dst;
       
   230                 s = src;
       
   231                 for(i = 0;i < se->nb_fields; i++) {
       
   232                     field_types = thunk_convert(d + dst_offsets[i],
       
   233                                                 s + src_offsets[i],
       
   234                                                 field_types, to_host);
       
   235                 }
       
   236             }
       
   237         }
       
   238         break;
       
   239     default:
       
   240         fprintf(stderr, "Invalid type 0x%x\n", type);
       
   241         break;
       
   242     }
       
   243     return type_ptr;
       
   244 }
       
   245 
       
   246 /* from em86 */
       
   247 
       
   248 /* Utility function: Table-driven functions to translate bitmasks
       
   249  * between X86 and Alpha formats...
       
   250  */
       
   251 unsigned int target_to_host_bitmask(unsigned int x86_mask,
       
   252                                     const bitmask_transtbl * trans_tbl)
       
   253 {
       
   254     const bitmask_transtbl *btp;
       
   255     unsigned int	alpha_mask = 0;
       
   256 
       
   257     for(btp = trans_tbl; btp->x86_mask && btp->alpha_mask; btp++) {
       
   258 	if((x86_mask & btp->x86_mask) == btp->x86_bits) {
       
   259 	    alpha_mask |= btp->alpha_bits;
       
   260 	}
       
   261     }
       
   262     return(alpha_mask);
       
   263 }
       
   264 
       
   265 unsigned int host_to_target_bitmask(unsigned int alpha_mask,
       
   266                                     const bitmask_transtbl * trans_tbl)
       
   267 {
       
   268     const bitmask_transtbl *btp;
       
   269     unsigned int	x86_mask = 0;
       
   270 
       
   271     for(btp = trans_tbl; btp->x86_mask && btp->alpha_mask; btp++) {
       
   272 	if((alpha_mask & btp->alpha_mask) == btp->alpha_bits) {
       
   273 	    x86_mask |= btp->x86_bits;
       
   274 	}
       
   275     }
       
   276     return(x86_mask);
       
   277 }
       
   278 
       
   279 #ifndef NO_THUNK_TYPE_SIZE
       
   280 int thunk_type_size_array(const argtype *type_ptr, int is_host)
       
   281 {
       
   282     return thunk_type_size(type_ptr, is_host);
       
   283 }
       
   284 
       
   285 int thunk_type_align_array(const argtype *type_ptr, int is_host)
       
   286 {
       
   287     return thunk_type_align(type_ptr, is_host);
       
   288 }
       
   289 #endif /* ndef NO_THUNK_TYPE_SIZE */