Annotation of qemu/thunk.c, revision 1.1.1.5

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
1.1.1.4   root       17:  * License along with this library; if not, see <http://www.gnu.org/licenses/>.
1.1       root       18:  */
                     19: #include <stdlib.h>
                     20: #include <stdio.h>
                     21: #include <stdarg.h>
                     22: 
                     23: #include "qemu.h"
                     24: #include "thunk.h"
                     25: 
                     26: //#define DEBUG
                     27: 
                     28: #define MAX_STRUCTS 128
                     29: 
                     30: /* XXX: make it dynamic */
                     31: StructEntry struct_entries[MAX_STRUCTS];
                     32: 
1.1.1.2   root       33: static const argtype *thunk_type_next_ptr(const argtype *type_ptr);
                     34: 
1.1       root       35: static inline const argtype *thunk_type_next(const argtype *type_ptr)
                     36: {
                     37:     int type;
                     38: 
                     39:     type = *type_ptr++;
                     40:     switch(type) {
                     41:     case TYPE_CHAR:
                     42:     case TYPE_SHORT:
                     43:     case TYPE_INT:
                     44:     case TYPE_LONGLONG:
                     45:     case TYPE_ULONGLONG:
                     46:     case TYPE_LONG:
                     47:     case TYPE_ULONG:
                     48:     case TYPE_PTRVOID:
1.1.1.5 ! root       49:     case TYPE_OLDDEVT:
1.1       root       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
1.1.1.5 ! root      192:     case TYPE_OLDDEVT:
        !           193:     {
        !           194:         uint64_t val = 0;
        !           195:         switch (thunk_type_size(type_ptr - 1, !to_host)) {
        !           196:         case 2:
        !           197:             val = *(uint16_t *)src;
        !           198:             break;
        !           199:         case 4:
        !           200:             val = *(uint32_t *)src;
        !           201:             break;
        !           202:         case 8:
        !           203:             val = *(uint64_t *)src;
        !           204:             break;
        !           205:         }
        !           206:         switch (thunk_type_size(type_ptr - 1, to_host)) {
        !           207:         case 2:
        !           208:             *(uint16_t *)dst = tswap16(val);
        !           209:             break;
        !           210:         case 4:
        !           211:             *(uint32_t *)dst = tswap32(val);
        !           212:             break;
        !           213:         case 8:
        !           214:             *(uint64_t *)dst = tswap64(val);
        !           215:             break;
        !           216:         }
        !           217:         break;
        !           218:     }
1.1       root      219:     case TYPE_ARRAY:
                    220:         {
                    221:             int array_length, i, dst_size, src_size;
                    222:             const uint8_t *s;
                    223:             uint8_t  *d;
                    224: 
                    225:             array_length = *type_ptr++;
                    226:             dst_size = thunk_type_size(type_ptr, to_host);
                    227:             src_size = thunk_type_size(type_ptr, 1 - to_host);
                    228:             d = dst;
                    229:             s = src;
                    230:             for(i = 0;i < array_length; i++) {
                    231:                 thunk_convert(d, s, type_ptr, to_host);
                    232:                 d += dst_size;
                    233:                 s += src_size;
                    234:             }
                    235:             type_ptr = thunk_type_next(type_ptr);
                    236:         }
                    237:         break;
                    238:     case TYPE_STRUCT:
                    239:         {
                    240:             int i;
                    241:             const StructEntry *se;
                    242:             const uint8_t *s;
                    243:             uint8_t  *d;
                    244:             const argtype *field_types;
                    245:             const int *dst_offsets, *src_offsets;
1.1.1.2   root      246: 
1.1       root      247:             se = struct_entries + *type_ptr++;
                    248:             if (se->convert[0] != NULL) {
                    249:                 /* specific conversion is needed */
                    250:                 (*se->convert[to_host])(dst, src);
                    251:             } else {
                    252:                 /* standard struct conversion */
                    253:                 field_types = se->field_types;
                    254:                 dst_offsets = se->field_offsets[to_host];
                    255:                 src_offsets = se->field_offsets[1 - to_host];
                    256:                 d = dst;
                    257:                 s = src;
                    258:                 for(i = 0;i < se->nb_fields; i++) {
1.1.1.2   root      259:                     field_types = thunk_convert(d + dst_offsets[i],
                    260:                                                 s + src_offsets[i],
1.1       root      261:                                                 field_types, to_host);
                    262:                 }
                    263:             }
                    264:         }
                    265:         break;
                    266:     default:
                    267:         fprintf(stderr, "Invalid type 0x%x\n", type);
                    268:         break;
                    269:     }
                    270:     return type_ptr;
                    271: }
                    272: 
                    273: /* from em86 */
                    274: 
                    275: /* Utility function: Table-driven functions to translate bitmasks
                    276:  * between X86 and Alpha formats...
                    277:  */
1.1.1.2   root      278: unsigned int target_to_host_bitmask(unsigned int x86_mask,
1.1.1.3   root      279:                                     const bitmask_transtbl * trans_tbl)
1.1       root      280: {
1.1.1.3   root      281:     const bitmask_transtbl *btp;
1.1       root      282:     unsigned int       alpha_mask = 0;
                    283: 
                    284:     for(btp = trans_tbl; btp->x86_mask && btp->alpha_mask; btp++) {
                    285:        if((x86_mask & btp->x86_mask) == btp->x86_bits) {
                    286:            alpha_mask |= btp->alpha_bits;
                    287:        }
                    288:     }
                    289:     return(alpha_mask);
                    290: }
                    291: 
1.1.1.2   root      292: unsigned int host_to_target_bitmask(unsigned int alpha_mask,
1.1.1.3   root      293:                                     const bitmask_transtbl * trans_tbl)
1.1       root      294: {
1.1.1.3   root      295:     const bitmask_transtbl *btp;
1.1       root      296:     unsigned int       x86_mask = 0;
                    297: 
                    298:     for(btp = trans_tbl; btp->x86_mask && btp->alpha_mask; btp++) {
                    299:        if((alpha_mask & btp->alpha_mask) == btp->alpha_bits) {
                    300:            x86_mask |= btp->x86_bits;
                    301:        }
                    302:     }
                    303:     return(x86_mask);
                    304: }
1.1.1.2   root      305: 
                    306: #ifndef NO_THUNK_TYPE_SIZE
                    307: int thunk_type_size_array(const argtype *type_ptr, int is_host)
                    308: {
                    309:     return thunk_type_size(type_ptr, is_host);
                    310: }
                    311: 
                    312: int thunk_type_align_array(const argtype *type_ptr, int is_host)
                    313: {
                    314:     return thunk_type_align(type_ptr, is_host);
                    315: }
                    316: #endif /* ndef NO_THUNK_TYPE_SIZE */

unix.superglobalmegacorp.com