Annotation of qemu/thunk.c, revision 1.1.1.3

1.1       root        1: /*
                      2:  *  Generic thunking code to convert data between host and target CPU
1.1.1.2   root        3:  *
1.1       root        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
1.1.1.3 ! root       18:  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA  02110-1301 USA
1.1       root       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: 
1.1.1.2   root       34: static const argtype *thunk_type_next_ptr(const argtype *type_ptr);
                     35: 
1.1       root       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:
1.1.1.2   root       52:         return thunk_type_next_ptr(type_ptr);
1.1       root       53:     case TYPE_ARRAY:
1.1.1.2   root       54:         return thunk_type_next_ptr(type_ptr + 1);
1.1       root       55:     case TYPE_STRUCT:
                     56:         return type_ptr + 1;
                     57:     default:
                     58:         return NULL;
                     59:     }
                     60: }
                     61: 
1.1.1.2   root       62: static const argtype *thunk_type_next_ptr(const argtype *type_ptr)
                     63: {
                     64:     return thunk_type_next(type_ptr);
                     65: }
                     66: 
1.1       root       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;
1.1.1.2   root       74: 
1.1       root       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
1.1.1.2   root       86:     printf("struct %s: id=%d nb_fields=%d\n",
1.1       root       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
1.1.1.2   root      110:         printf("%s: size=%d align=%d\n",
1.1       root      111:                i == THUNK_HOST ? "host" : "target", offset, max_align);
                    112: #endif
                    113:     }
                    114: }
                    115: 
1.1.1.3 ! root      116: void thunk_register_struct_direct(int id, const char *name,
        !           117:                                   const StructEntry *se1)
1.1       root      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 */
1.1.1.2   root      127: const argtype *thunk_convert(void *dst, const void *src,
1.1       root      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;
1.1.1.2   root      147: #if HOST_LONG_BITS == 32 && TARGET_ABI_BITS == 32
1.1       root      148:     case TYPE_LONG:
                    149:     case TYPE_ULONG:
                    150:     case TYPE_PTRVOID:
                    151:         *(uint32_t *)dst = tswap32(*(uint32_t *)src);
                    152:         break;
1.1.1.2   root      153: #elif HOST_LONG_BITS == 64 && TARGET_ABI_BITS == 32
1.1       root      154:     case TYPE_LONG:
                    155:     case TYPE_ULONG:
                    156:     case TYPE_PTRVOID:
                    157:         if (to_host) {
1.1.1.2   root      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:             }
1.1       root      164:         } else {
                    165:             *(uint32_t *)dst = tswap32(*(uint64_t *)src & 0xffffffff);
                    166:         }
                    167:         break;
1.1.1.2   root      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;
1.1       root      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;
1.1.1.2   root      219: 
1.1       root      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++) {
1.1.1.2   root      232:                     field_types = thunk_convert(d + dst_offsets[i],
                    233:                                                 s + src_offsets[i],
1.1       root      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:  */
1.1.1.2   root      251: unsigned int target_to_host_bitmask(unsigned int x86_mask,
1.1.1.3 ! root      252:                                     const bitmask_transtbl * trans_tbl)
1.1       root      253: {
1.1.1.3 ! root      254:     const bitmask_transtbl *btp;
1.1       root      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: 
1.1.1.2   root      265: unsigned int host_to_target_bitmask(unsigned int alpha_mask,
1.1.1.3 ! root      266:                                     const bitmask_transtbl * trans_tbl)
1.1       root      267: {
1.1.1.3 ! root      268:     const bitmask_transtbl *btp;
1.1       root      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: }
1.1.1.2   root      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 */

unix.superglobalmegacorp.com