File:  [Qemu by Fabrice Bellard] / qemu / thunk.c
Revision 1.1.1.3 (vendor branch): download - view: text, annotated - select for diffs
Tue Apr 24 16:51:04 2018 UTC (3 years, 1 month ago) by root
Branches: qemu, MAIN
CVS tags: qemu0105, qemu0104, qemu0103, qemu0102, qemu0101, qemu0100, HEAD
qemu 0.10.0

    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., 51 Franklin Street, Fifth Floor, Boston MA  02110-1301 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 */

unix.superglobalmegacorp.com