File:  [Qemu by Fabrice Bellard] / qemu / thunk.c
Revision 1.1.1.4 (vendor branch): download - view: text, annotated - select for diffs
Tue Apr 24 17:21:29 2018 UTC (3 years, 1 month ago) by root
Branches: qemu, MAIN
CVS tags: qemu1001, qemu1000, qemu0151, qemu0150, qemu0141, qemu0140, qemu0130, qemu0125, qemu0124, qemu0123, qemu0122, qemu0121, qemu0120, qemu0111, qemu0110, HEAD
qemu 0.11.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, see <http://www.gnu.org/licenses/>.
   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: 
   33: static const argtype *thunk_type_next_ptr(const argtype *type_ptr);
   34: 
   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:
   49:         return type_ptr;
   50:     case TYPE_PTR:
   51:         return thunk_type_next_ptr(type_ptr);
   52:     case TYPE_ARRAY:
   53:         return thunk_type_next_ptr(type_ptr + 1);
   54:     case TYPE_STRUCT:
   55:         return type_ptr + 1;
   56:     default:
   57:         return NULL;
   58:     }
   59: }
   60: 
   61: static const argtype *thunk_type_next_ptr(const argtype *type_ptr)
   62: {
   63:     return thunk_type_next(type_ptr);
   64: }
   65: 
   66: void thunk_register_struct(int id, const char *name, const argtype *types)
   67: {
   68:     const argtype *type_ptr;
   69:     StructEntry *se;
   70:     int nb_fields, offset, max_align, align, size, i, j;
   71: 
   72:     se = struct_entries + id;
   73: 
   74:     /* first we count the number of fields */
   75:     type_ptr = types;
   76:     nb_fields = 0;
   77:     while (*type_ptr != TYPE_NULL) {
   78:         type_ptr = thunk_type_next(type_ptr);
   79:         nb_fields++;
   80:     }
   81:     se->field_types = types;
   82:     se->nb_fields = nb_fields;
   83:     se->name = name;
   84: #ifdef DEBUG
   85:     printf("struct %s: id=%d nb_fields=%d\n",
   86:            se->name, id, se->nb_fields);
   87: #endif
   88:     /* now we can alloc the data */
   89: 
   90:     for(i = 0;i < 2; i++) {
   91:         offset = 0;
   92:         max_align = 1;
   93:         se->field_offsets[i] = malloc(nb_fields * sizeof(int));
   94:         type_ptr = se->field_types;
   95:         for(j = 0;j < nb_fields; j++) {
   96:             size = thunk_type_size(type_ptr, i);
   97:             align = thunk_type_align(type_ptr, i);
   98:             offset = (offset + align - 1) & ~(align - 1);
   99:             se->field_offsets[i][j] = offset;
  100:             offset += size;
  101:             if (align > max_align)
  102:                 max_align = align;
  103:             type_ptr = thunk_type_next(type_ptr);
  104:         }
  105:         offset = (offset + max_align - 1) & ~(max_align - 1);
  106:         se->size[i] = offset;
  107:         se->align[i] = max_align;
  108: #ifdef DEBUG
  109:         printf("%s: size=%d align=%d\n",
  110:                i == THUNK_HOST ? "host" : "target", offset, max_align);
  111: #endif
  112:     }
  113: }
  114: 
  115: void thunk_register_struct_direct(int id, const char *name,
  116:                                   const StructEntry *se1)
  117: {
  118:     StructEntry *se;
  119:     se = struct_entries + id;
  120:     *se = *se1;
  121:     se->name = name;
  122: }
  123: 
  124: 
  125: /* now we can define the main conversion functions */
  126: const argtype *thunk_convert(void *dst, const void *src,
  127:                              const argtype *type_ptr, int to_host)
  128: {
  129:     int type;
  130: 
  131:     type = *type_ptr++;
  132:     switch(type) {
  133:     case TYPE_CHAR:
  134:         *(uint8_t *)dst = *(uint8_t *)src;
  135:         break;
  136:     case TYPE_SHORT:
  137:         *(uint16_t *)dst = tswap16(*(uint16_t *)src);
  138:         break;
  139:     case TYPE_INT:
  140:         *(uint32_t *)dst = tswap32(*(uint32_t *)src);
  141:         break;
  142:     case TYPE_LONGLONG:
  143:     case TYPE_ULONGLONG:
  144:         *(uint64_t *)dst = tswap64(*(uint64_t *)src);
  145:         break;
  146: #if HOST_LONG_BITS == 32 && TARGET_ABI_BITS == 32
  147:     case TYPE_LONG:
  148:     case TYPE_ULONG:
  149:     case TYPE_PTRVOID:
  150:         *(uint32_t *)dst = tswap32(*(uint32_t *)src);
  151:         break;
  152: #elif HOST_LONG_BITS == 64 && TARGET_ABI_BITS == 32
  153:     case TYPE_LONG:
  154:     case TYPE_ULONG:
  155:     case TYPE_PTRVOID:
  156:         if (to_host) {
  157:             if (type == TYPE_LONG) {
  158:                 /* sign extension */
  159:                 *(uint64_t *)dst = (int32_t)tswap32(*(uint32_t *)src);
  160:             } else {
  161:                 *(uint64_t *)dst = tswap32(*(uint32_t *)src);
  162:             }
  163:         } else {
  164:             *(uint32_t *)dst = tswap32(*(uint64_t *)src & 0xffffffff);
  165:         }
  166:         break;
  167: #elif HOST_LONG_BITS == 64 && TARGET_ABI_BITS == 64
  168:     case TYPE_LONG:
  169:     case TYPE_ULONG:
  170:     case TYPE_PTRVOID:
  171:         *(uint64_t *)dst = tswap64(*(uint64_t *)src);
  172:         break;
  173: #elif HOST_LONG_BITS == 32 && TARGET_ABI_BITS == 64
  174:     case TYPE_LONG:
  175:     case TYPE_ULONG:
  176:     case TYPE_PTRVOID:
  177:         if (to_host) {
  178:             *(uint32_t *)dst = tswap64(*(uint64_t *)src);
  179:         } else {
  180:             if (type == TYPE_LONG) {
  181:                 /* sign extension */
  182:                 *(uint64_t *)dst = tswap64(*(int32_t *)src);
  183:             } else {
  184:                 *(uint64_t *)dst = tswap64(*(uint32_t *)src);
  185:             }
  186:         }
  187:         break;
  188: #else
  189: #warning unsupported conversion
  190: #endif
  191:     case TYPE_ARRAY:
  192:         {
  193:             int array_length, i, dst_size, src_size;
  194:             const uint8_t *s;
  195:             uint8_t  *d;
  196: 
  197:             array_length = *type_ptr++;
  198:             dst_size = thunk_type_size(type_ptr, to_host);
  199:             src_size = thunk_type_size(type_ptr, 1 - to_host);
  200:             d = dst;
  201:             s = src;
  202:             for(i = 0;i < array_length; i++) {
  203:                 thunk_convert(d, s, type_ptr, to_host);
  204:                 d += dst_size;
  205:                 s += src_size;
  206:             }
  207:             type_ptr = thunk_type_next(type_ptr);
  208:         }
  209:         break;
  210:     case TYPE_STRUCT:
  211:         {
  212:             int i;
  213:             const StructEntry *se;
  214:             const uint8_t *s;
  215:             uint8_t  *d;
  216:             const argtype *field_types;
  217:             const int *dst_offsets, *src_offsets;
  218: 
  219:             se = struct_entries + *type_ptr++;
  220:             if (se->convert[0] != NULL) {
  221:                 /* specific conversion is needed */
  222:                 (*se->convert[to_host])(dst, src);
  223:             } else {
  224:                 /* standard struct conversion */
  225:                 field_types = se->field_types;
  226:                 dst_offsets = se->field_offsets[to_host];
  227:                 src_offsets = se->field_offsets[1 - to_host];
  228:                 d = dst;
  229:                 s = src;
  230:                 for(i = 0;i < se->nb_fields; i++) {
  231:                     field_types = thunk_convert(d + dst_offsets[i],
  232:                                                 s + src_offsets[i],
  233:                                                 field_types, to_host);
  234:                 }
  235:             }
  236:         }
  237:         break;
  238:     default:
  239:         fprintf(stderr, "Invalid type 0x%x\n", type);
  240:         break;
  241:     }
  242:     return type_ptr;
  243: }
  244: 
  245: /* from em86 */
  246: 
  247: /* Utility function: Table-driven functions to translate bitmasks
  248:  * between X86 and Alpha formats...
  249:  */
  250: unsigned int target_to_host_bitmask(unsigned int x86_mask,
  251:                                     const bitmask_transtbl * trans_tbl)
  252: {
  253:     const bitmask_transtbl *btp;
  254:     unsigned int	alpha_mask = 0;
  255: 
  256:     for(btp = trans_tbl; btp->x86_mask && btp->alpha_mask; btp++) {
  257: 	if((x86_mask & btp->x86_mask) == btp->x86_bits) {
  258: 	    alpha_mask |= btp->alpha_bits;
  259: 	}
  260:     }
  261:     return(alpha_mask);
  262: }
  263: 
  264: unsigned int host_to_target_bitmask(unsigned int alpha_mask,
  265:                                     const bitmask_transtbl * trans_tbl)
  266: {
  267:     const bitmask_transtbl *btp;
  268:     unsigned int	x86_mask = 0;
  269: 
  270:     for(btp = trans_tbl; btp->x86_mask && btp->alpha_mask; btp++) {
  271: 	if((alpha_mask & btp->alpha_mask) == btp->alpha_bits) {
  272: 	    x86_mask |= btp->x86_bits;
  273: 	}
  274:     }
  275:     return(x86_mask);
  276: }
  277: 
  278: #ifndef NO_THUNK_TYPE_SIZE
  279: int thunk_type_size_array(const argtype *type_ptr, int is_host)
  280: {
  281:     return thunk_type_size(type_ptr, is_host);
  282: }
  283: 
  284: int thunk_type_align_array(const argtype *type_ptr, int is_host)
  285: {
  286:     return thunk_type_align(type_ptr, is_host);
  287: }
  288: #endif /* ndef NO_THUNK_TYPE_SIZE */

unix.superglobalmegacorp.com