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 #ifndef THUNK_H 20 #define THUNK_H 21 22 #include "cpu.h" 23 24 /* types enums definitions */ 25 26 typedef enum argtype { 27 TYPE_NULL, 28 TYPE_CHAR, 29 TYPE_SHORT, 30 TYPE_INT, 31 TYPE_LONG, 32 TYPE_ULONG, 33 TYPE_PTRVOID, /* pointer on unknown data */ 34 TYPE_LONGLONG, 35 TYPE_ULONGLONG, 36 TYPE_PTR, 37 TYPE_ARRAY, 38 TYPE_STRUCT, 39 TYPE_OLDDEVT, 40 } argtype; 41 42 #define MK_PTR(type) TYPE_PTR, type 43 #define MK_ARRAY(type, size) TYPE_ARRAY, size, type 44 #define MK_STRUCT(id) TYPE_STRUCT, id 45 46 #define THUNK_TARGET 0 47 #define THUNK_HOST 1 48 49 typedef struct { 50 /* standard struct handling */ 51 const argtype *field_types; 52 int nb_fields; 53 int *field_offsets[2]; 54 /* special handling */ 55 void (*convert[2])(void *dst, const void *src); 56 int size[2]; 57 int align[2]; 58 const char *name; 59 } StructEntry; 60 61 /* Translation table for bitmasks... */ 62 typedef struct bitmask_transtbl { 63 unsigned int target_mask; 64 unsigned int target_bits; 65 unsigned int host_mask; 66 unsigned int host_bits; 67 } bitmask_transtbl; 68 69 void thunk_register_struct(int id, const char *name, const argtype *types); 70 void thunk_register_struct_direct(int id, const char *name, 71 const StructEntry *se1); 72 const argtype *thunk_convert(void *dst, const void *src, 73 const argtype *type_ptr, int to_host); 74 75 extern StructEntry *struct_entries; 76 77 int thunk_type_size_array(const argtype *type_ptr, int is_host); 78 int thunk_type_align_array(const argtype *type_ptr, int is_host); 79 80 static inline int thunk_type_size(const argtype *type_ptr, int is_host) 81 { 82 int type, size; 83 const StructEntry *se; 84 85 type = *type_ptr; 86 switch(type) { 87 case TYPE_CHAR: 88 return 1; 89 case TYPE_SHORT: 90 return 2; 91 case TYPE_INT: 92 return 4; 93 case TYPE_LONGLONG: 94 case TYPE_ULONGLONG: 95 return 8; 96 case TYPE_LONG: 97 case TYPE_ULONG: 98 case TYPE_PTRVOID: 99 case TYPE_PTR: 100 if (is_host) { 101 return sizeof(void *); 102 } else { 103 return TARGET_ABI_BITS / 8; 104 } 105 break; 106 case TYPE_OLDDEVT: 107 if (is_host) { 108 #if defined(HOST_X86_64) 109 return 8; 110 #elif defined(HOST_ALPHA) || defined(HOST_IA64) || defined(HOST_MIPS) || \ 111 defined(HOST_PARISC) || defined(HOST_SPARC64) 112 return 4; 113 #elif defined(HOST_PPC) 114 return sizeof(void *); 115 #else 116 return 2; 117 #endif 118 } else { 119 #if defined(TARGET_X86_64) 120 return 8; 121 #elif defined(TARGET_ALPHA) || defined(TARGET_IA64) || defined(TARGET_MIPS) || \ 122 defined(TARGET_PARISC) || defined(TARGET_SPARC64) 123 return 4; 124 #elif defined(TARGET_PPC) 125 return TARGET_ABI_BITS / 8; 126 #else 127 return 2; 128 #endif 129 } 130 break; 131 case TYPE_ARRAY: 132 size = type_ptr[1]; 133 return size * thunk_type_size_array(type_ptr + 2, is_host); 134 case TYPE_STRUCT: 135 se = struct_entries + type_ptr[1]; 136 return se->size[is_host]; 137 default: 138 return -1; 139 } 140 } 141 142 static inline int thunk_type_align(const argtype *type_ptr, int is_host) 143 { 144 int type; 145 const StructEntry *se; 146 147 type = *type_ptr; 148 switch(type) { 149 case TYPE_CHAR: 150 return 1; 151 case TYPE_SHORT: 152 return 2; 153 case TYPE_INT: 154 return 4; 155 case TYPE_LONGLONG: 156 case TYPE_ULONGLONG: 157 return 8; 158 case TYPE_LONG: 159 case TYPE_ULONG: 160 case TYPE_PTRVOID: 161 case TYPE_PTR: 162 if (is_host) { 163 return sizeof(void *); 164 } else { 165 return TARGET_ABI_BITS / 8; 166 } 167 break; 168 case TYPE_OLDDEVT: 169 return thunk_type_size(type_ptr, is_host); 170 case TYPE_ARRAY: 171 return thunk_type_align_array(type_ptr + 2, is_host); 172 case TYPE_STRUCT: 173 se = struct_entries + type_ptr[1]; 174 return se->align[is_host]; 175 default: 176 return -1; 177 } 178 } 179 180 unsigned int target_to_host_bitmask(unsigned int target_mask, 181 const bitmask_transtbl * trans_tbl); 182 unsigned int host_to_target_bitmask(unsigned int host_mask, 183 const bitmask_transtbl * trans_tbl); 184 185 void thunk_init(unsigned int max_structs); 186 187 #endif 188