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